This is the second post on running SingleStore Studio in the Kubernetes cluster, within the SAS Viya namespace. In this post we will examine configuring TLS encryption for the SingleStore Studio (S2 Studio) application and will discuss the use of secure connections to the SingleStore (memsql) cluster.
This builds on the configuration described in Part 1, see here.
One of the advantages of deploying SingleStore Studio within the SAS Viya namespace is that you can make use of the SAS Viya secrets for the S2 Studio TLS configuration.
TL;DR
From a security perspective, the “cleanest” implementation is probably to run S2 Studio within the SAS Viya namespace with a full-stack TLS configuration, utilizing a connection profile using port 3306 and the internal DDL service name.
Let’s examine this configuration and some of the architecture (deployment) considerations.
Using the SAS Viya terminology, we will look at creating a “Front-door” TLS configuration and a “Full-stack” TLS configuration. See the SAS documentation: SAS Viya Platform Encryption Modes
The TLS configuration can be addressed at two levels, at the ingress and within the S2 Studio configuration. Hence, the two configuration options.
As described in Part 1, the ingress needs a host name that resolves to the pod running the S2 Studio application. In this example, I needed a DNS wildcard for: *.camel-a20280-rg.gelenable.sas.com
‘camel-a20280-rg.gelenable.sas.com’ was the DNS name for my ingress. Having the DNS wildcard would allow me to use a host name of: s2studio.camel-a20280-rg.gelenable.sas.com
As stated in the introduction, I wanted to make use of the SAS Viya certificates. For the TLS configuration I wanted to use the ingress certificate, the sas-ingress-certificate secret. Therefore, this certificate must have a Subject Alternate Name (SAN) definition that covers my proposed host name. The TLS certificate must have a wildcard definition as shown above.
To confirm if this was possible, I used the following command:
kubectl -n namespace get secret sas-ingress-certificate -o jsonpath="{.data['tls\.crt']}" |
base64 -d | openssl x509 -text
The command decodes the secret which is base64 encoded. For my environment, it provided the following output.
Select any image to see a larger version.
Mobile users: To view the images, select the "Full" version at the bottom of the page.
Here you can see that the Subject CN is: sas-viya-openssl-ingress-certificate. In the second highlighted block, you can see that the certificate has a number of SAN names defined. Most importantly it has a wildcard for: *.camel-a20280-rg.gelenable.sas.com
To implement TLS for the S2 Studio application, the ingress definition for S2 Studio must contain a TLS (tls:) block. The ‘tls:’ block needs to specify the hostname or DNS alias for your environment and the secrets (certificate and key) to be used by the ingress. For example, my configuration needed the following definition:
spec:
tls:
- hosts:
- s2studio.camel-a20280-rg.gelenable.sas.com
secretName: sas-ingress-certificate
Now let’s look at creating the TLS configurations.
The Front-door configuration refers to enabling TLS for the ingress only. The SingleStore Studio (S2 Studio) application is still using HTTP to receive communication from the Ingress. The configuration is illustrated below.
In the diagram, the green line highlights the HTTPS session flow. The service and S2 Studio deployments remain as detailed in the Part 1 post.
The following is an example of the Front-door ingress definition (using Kubernetes 1.27).
# Front-door ingress definition
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: s2studio-front-door-ingress
labels:
app.kubernetes.io/name: s2studio-front-door-ingress
spec:
ingressClassName: nginx
tls:
- hosts:
- s2studio.camel-a20280-rg.gelenable.sas.com
secretName: sas-ingress-certificate
rules:
- host: s2studio.camel-a20280-rg.gelenable.sas.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: s2studio-http-svc
port:
number: 80
Here you can see that the TLS block refers to the secret (TLS certificate and key) sas-ingres-certificate, and the backend service (s2studio-http-svc) is using (listening on) port 80.
Here is the ‘s2studio-http-svc’ yaml definition.
---
apiVersion: v1
kind: Service
metadata:
name: s2studio-http-svc
labels:
app.kubernetes.io/name: s2studio-http-svc
spec:
selector:
app.kubernetes.io/name: singlestore-tools
ports:
- name: s2studio-http
port: 80
protocol: TCP
targetPort: 8080
type: ClusterIP
Once again you can see that the service is mapping port 80 to port 8080 on the container.
With the Kubernetes configuration completed, let’s examine the S2 Studio configuration.
Remember there are two configuration files, the ‘studio.hcl’ contains the profile definitions for the memsql clusters connections and the ‘singlestoredb-studio.hcl’ file which is used for the S2 Studio server configuration.
In this example I used the following studio.hcl file.
version = 1
cluster "ViyaS2Profile" {
name = "SAS Viya DDL Connection"
description = "Connection using port 3306"
hostname = "svc-sas-singlestore-cluster-ddl"
port = 3306
profile = "PRODUCTION"
websocket = false
websocketSSL = false
kerberosAutologin = false
}
With the Front-door TLS configuration, the default singlestoredb-studio.hcl configuration can be used, with the S2 Studio application listening on port 8080.
You can confirm the S2 Studio configuration using the following command:
kubectl -n namespace logs pod_name
You will see output similar to the following, showing that the S2 Studio server is using an HTTP configuration listening on port 8080.
2023/11/21 03:53:14 env.go:90 Log Opened
2023/11/21 03:53:14 server.go:74 Listening on 0.0.0.0:8080
2023/11/21 03:53:14 server.go:93 HTTPS configuration was not detected, serving with HTTP
When we connect to the S2 Studio application we can now see that the ingress is using the Viya TLS certificate.
Note, with the latest version of Chrome you no longer see the padlock to indicate that a session is secure. It is assumed that all sites use HTTPS.
Viewing the certificate details, we can see that the session is using the sas-viya-openssl-ingress certificate.
Now that we have seen the Front-door configuration, let’s look at the Full-stack configuration.
The Full-stack configuration refers to enabling TLS for the Ingress and the S2 Studio application. This configuration is illustrated below.
For this configuration we must update the ingress, service and the S2 Studio deployment configuration. Therefore, this could be viewed as more complicated to implement than the Front-door configuration.
We will start by looking at the ingress configuration. This is shown below, the configurations changes are highlighted.
# Full-stack ingress definition
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: s2studio-ingress
annotations:
nginx.ingress.kubernetes.io/backend-protocol: HTTPS
labels:
app.kubernetes.io/name: s2studio-full-stack-ingress
spec:
ingressClassName: nginx
tls:
- hosts:
- s2studio.camel-a20280-rg.gelenable.sas.com
secretName: sas-ingress-certificate
rules:
- host: s2studio.camel-a20280-rg.gelenable.sas.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: s2studio-https-svc
port:
number: 443
A key part of this configuration is the annotation to enable the TLS (HTTPS) connection to the backend service:
nginx.ingress.kubernetes.io/backend-protocol: HTTPS
This time you can see that the s2studio-https-svc service is being used, and it is listening on port 443.
The service configuration is shown below.
---
apiVersion: v1
kind: Service
metadata:
name: s2studio-https-svc
labels:
app.kubernetes.io/name: s2studio-https-svc
spec:
selector:
app.kubernetes.io/name: singlestore-tools
ports:
- name: s2studio-https
port: 443
protocol: TCP
targetPort: 8443
type: ClusterIP
Here you can see that the service is mapping port 443 to port 8443 on the S2 Studio container (pod).
That completes the ingress and service configuration. The next step is to update the S2 Studio deployment for the TLS configuration. With the “Front-door” configuration this step isn’t required.
The S2 Studio deployment needs to be updated for the following:
The deployment configuration is shown below. Again, the key changes are highlighted.
---
# Create the deployment YAML file
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app.kubernetes.io/name: singlestore-tools
workload.sas.com/class: singlestore
name: singlestore-tools
spec:
replicas: 2
selector:
matchLabels:
app.kubernetes.io/name: singlestore-tools
template:
metadata:
labels:
app: singlestore-tools
app.kubernetes.io/name: singlestore-tools
workload.sas.com/class: singlestore
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.azure.com/mode
operator: NotIn
values:
- system
- key: workload.sas.com/class
operator: In
values:
- stateful
containers:
- image: myregistry.azurecr.io/singlestore-tools:latest
imagePullPolicy: Always # IfNotPresent or Always
name: s2tools
resources:
requests: # Minimum amount of resources requested
cpu: 1
memory: 128Mi
limits: # Maximum amount of resources requested
cpu: 2
memory: 256Mi
ports:
- containerPort: 8443 # The container exposes this port
name: https # Name the port "https"
volumeMounts:
- name: studio-files-volume
mountPath: /tmp/s2studio-files
- name: tls-volume
mountPath: /tmp/viya-secrets
lifecycle:
postStart:
exec:
command:
- /bin/sh
- '-c'
- |
cp /tmp/s2studio-files/studio.hcl /var/lib/singlestoredb-studio/studio.hcl
cp /tmp/s2studio-files/singlestoredb-studio.hcl /etc/singlestore/singlestoredb-studio.hcl
cp /tmp/viya-secrets/tls.* /var/lib/singlestoredb-studio/
tolerations:
- effect: NoSchedule
key: workload.sas.com/class
operator: Equal
value: stateful
volumes:
- name: studio-files-volume
configMap:
name: studio-files
- name: tls-volume
secret:
secretName: sas-ingress-certificate
Here you can see that the container(s) has been configured to use port 8443. The TLS secrets (certificate and key) have been mounted as a volume called ‘tls-volume’; this is mapped to path ‘/tmp/viya-secrets’ within the container.
The last part of the configuration I wish to highlight is under the ‘lifecycle:’ block. Here the singlestoredb-studio.hcl file is copied into the S2 Studio application configuration, and the secrets (Viya ingress certificate and key) are copied into the configuration.
The copy statements are shown below:
cp /tmp/s2studio-files/singlestoredb-studio.hcl /etc/singlestore/singlestoredb-studio.hcl
cp /tmp/viya-secrets/tls.* /var/lib/singlestoredb-studio/
To enable TLS for the S2 Studio application, the singlestoredb-studio.hcl file needs to be updated. The following changes are required:
Reading the SingleStore documentation it is possible to limit the TLS version and cipher suites being used, see here. Similarly, the SAS documentation lists the supported TLS Versions and Cipher Suites. This is also shown in the example below.
The singlestoredb-studio.hcl configuration.
# This is the IP address that SingleStore DB Studio will bind to.
host = "0.0.0.0"
# This is the port that SingleStore DB Studio will bind to.
port = 8443
# This is the path to the state file of SingleStore DB Studio.
statePath = "/var/lib/singlestoredb-studio/studio.hcl"
# This is the path to the log file of SingleStore DB Studio.
logPath = "/var/lib/singlestoredb-studio/studio.log"
HTTPSCertificateFile = "/var/lib/singlestoredb-studio/tls.crt"
HTTPSCertificateKeyFile = "/var/lib/singlestoredb-studio/tls.key"
TLSVersions = ["TLSv1.2", "TLSv1.3"]
TLSCipherSuites = ["TLS_AES_128_GCM_SHA256", "TLS_AES_256_GCM_SHA384", "TLS_CHACHA20_POLY1305_SHA256", "ECDHE-ECDSA-AES128-GCM-SHA256", "ECDHE-ECDSA-AES256-GCM-SHA384", "ECDHE-RSA-AES128-GCM-SHA256", "ECDHE-RSA-AES256-GCM-SHA384"]
Note: The TLSCipherSuites property cannot be used when TLSv1.3 is selected for a TLS handshake. TLSv1.3 uses three predefined cipher suites that cannot be modified using the TLSCipherSuites property.
The configuration is loaded using a ConfigMap. Again, I wasn’t using an inline configuration for the ConfigMap (as discussed in Part 1). Once the singlestoredb-studio.hcl file has been created the ConfigMap must be updated to include it. It is possible to load multiple files into a ConfigMap using the following command:
kubectl -n namespace create configmap studio-files --from-file=./
For this configuration it loads the studio.hcl and singlestoredb-studio.hcl files.
With the new deployment configuration and ConfigMap in place the S2 Studio application can be deployed.
Once the singlestore-tools (S2 Studio) deployment has started, the TLS configuration can be confirmed by viewing the logs for one of the running S2 Studio pods. An example is show below.
2023/11/21 02:23:32 env.go:90 Log Opened
2023/11/21 02:23:32 env.go: 138 Minimum/Maximum TLS versions: TLSv1.2/TLSv1.3
2023/11/21 02:23:32 server.go:74 Listening on 0.0.0.0:8443
2023/11/21 02:23:32 server.go:80 HTTPS configuration detected, serving with HTTPS
Here you can see that the TLS (HTTPS) configuration was detected and that port 8443 is being used. You can also see the TLS versions that are supported using this configuration. It has been limited to TLS v1.2 and v1.3.
As I hadn’t updated the ‘studio.hcl’ file, at this point the S2 Studio home page looks the same as in the Front-door example shown above.
I could probably finish the post here, but I want to take a moment to discuss using a secure connection to the SingleStore (memsql) cluster.
The S2 Studio application uses a WebSocket implementation for a secure connection to the memsql cluster. This is detailed in the SingleStore documentation and is discussed in the SAS manuals, see:
SAS Help Center: Managing the SingleStore Cluster
Reviewing the SAS documentation, you will see that the cluster side of the WebSocket Proxy configuration is performed automatically when you configure the SAS Viya platform for front-door or full-stack TLS encryption, you do not need to follow the steps in the SingleStore documentation. The SAS Viya deployment makes the following changes in the SingleStore cluster configuration:
Given the configuration changes made as part of the SAS Viya deployment, to create a connection profile for a secure connection (in the studio.hcl file), you must set the port to 443 and set the websocket and websocketSSL entries to true. This must be done by manually editing the profile, you can’t create the profile using the S2 Studio user interface.
This is shown in the example studio.hcl configuration below. The second profile (SecureProfile) illustrates the secure connection configuration for my environment.
Example studio.hcl file.
version = 1
cluster "ViyaS2Profile" {
name = "SAS Viya DDL Connection"
description = "Connection using port 3306"
hostname = "svc-sas-singlestore-cluster-ddl"
port = 3306
profile = "PRODUCTION"
websocket = false
websocketSSL = false
kerberosAutologin = false
}
cluster "SecureProfile" {
name = "Secure DDL Connection"
description = "Connection using port 443 and Public IP"
hostname = "ddl-camel-a20280.gelenable.sas.com"
port = 443
profile = "STAGING"
websocket = true
websocketSSL = true
kerberosAutologin = false
}
At this point it is important to understand how the secure connection works. The secure connection requires two browser sessions, a connection to the S2 Studio application service and a direct connection from the browser to the WebSocket proxy of the SingleStore database cluster’s DDL service, to the SingleStore Master Aggregator (MemSQL MA).
See the SingleStoreDB Studio WebSocket Proxy Documentation
Source: SingleStore documentation (please ignore the port numbers shown in the diagram).
Hence, the hostname must refer to the public IP address for the DDL service. In my case I had a DNS alias for the DDL service called: ‘ddl-camel-a20280.gelenable.sas.com’
The S2 Studio home page for this configuration is shown below.
When using port 3306 to connect to the memsql cluster all communication is via the S2 Studio server application. This is shown above as the ‘SAS Viya DDL Connection’ profile.
This is one of the key benefits of running S2 Studio within the Kubernetes cluster and within the SAS Viya namespace. All communication from the browser is via the ingress, and the backend communication to the memsql cluster is contained to within the Kubernetes cluster. There is no secondary browser connection to the backend.
Therefore, from a security perspective, the “cleanest” implementation is probably to run S2 Studio within the SAS Viya namespace with a full-stack TLS configuration, utilising a connection profile using port 3306 and the internal DDL service name (svc-sas-singlestore-cluster-ddl).
Here we have looked at how to implement TLS for the S2 Studio application using the SAS Viya secrets. A benefit of this approach is that it piggybacks on the SAS Viya configuration, simplifying the S2 Studio configuration.
While SingleStore don’t provide a container image to only run the S2 Studio application, I suggest that the effort to create the image is worthwhile and can provide a better overall environment for SAS Viya with SingleStore (this offering is now called SAS SpeedyStore).
From a security perspective, running the S2 Studio application within the Kubernetes cluster allows the use of the DDL service with the internal IP address, thus keeping all the communication from the S2 Studio application to the memsql cluster within the Kubernetes cluster.
Finally, as stated in Part 1, it is important to remember that the SingleStore Studio application is not maintained by SAS, and it is not shipped with the SAS SpeedyStore order. As such, SAS Technical Support do not support SingleStore Studio and will not provide support for this type of deployment.
I hope this is helpful and thanks for reading…
Find more articles from SAS Global Enablement and Learning here.
It's finally time to hack! Remember to visit the SAS Hacker's Hub regularly for news and updates.
The rapid growth of AI technologies is driving an AI skills gap and demand for AI talent. Ready to grow your AI literacy? SAS offers free ways to get started for beginners, business leaders, and analytics professionals of all skill levels. Your future self will thank you.