BookmarkSubscribeRSS Feed

External Binary Access to CAS: Manual Configuration

Started 8 hours ago by
Modified 8 hours ago by
Views 46

Welcome to the third installment of the series presenting how to enable external binary access to SAS Cloud Analytics Services (CAS).

 

This final article focuses on external binary connectivity to CAS where Kubernetes cannot provision load balancers automatically, such as on‑prem or tightly controlled environments. In these cases, you can expose CAS externally with a manually controlled NodePort service, integrated with an external network load balancer, and aligned TLS certificate settings.

 

You can reference the first article for a description of the architecture, requirements and preliminary checks; the second article walks you through an implementation that leverages the automation provided by the CAS Operator to provision a Kubernetes LoadBalancer Service in cloud environments.

 

Here you can learn how to plan the external network load balancer endpoint, create a NodePort service, and ensure that CAS certificates include the correct external alias and IP address.

 

The article ends with a structured troubleshooting guide for common connectivity issues, such as CA trust failures, SAN mismatches, or missing routes, reflecting real‑world scenarios.

 

Core goal: Address the reality that on‑prem environments often have less automation and more stakeholder boundaries, requiring stricter collaboration between IT infrastructure teams, Kubernetes administrators, and SAS administrators.

 

 

Reality Calls

 

The steps presented in the previous article are based on official SAS Viya documentation, which assumes that you can leverage the integrated automation of your cloud provider, Kubernetes cluster and SAS Viya platform to configure external binary access to CAS with simple declarative entries in a configuration file.

 

A customer reached out to us asking how to obtain the same result in their environment, based on an OpenShift cluster deployed on physical hardware in an on-prem datacenter. Their IT team manages the creation and configuration of network artifacts such as the frontend load balancer and DNS aliases. They require the CAS service to listen on a pre-defined, static port number, so that the frontend load balancer can be configured to redirect incoming connections from external CAS clients to that internal known port.

 

You might remember from the previous article that, when leveraging the CAS Operator automation, you cannot customize many details of the new CAS service that gets created. The name sas-cas-server-default-bin and the frontend port 5570 are fixed by the CAS Operator. The internal service port is randomly assigned by the Kubernetes cluster and cannot be specified, as well.

 

All these requirements and constraints can be solved with a customized approach.

 

The detailed steps might vary from cluster to cluster, according to the environment, company policies, etc.

 

The rest of this article walks through one sample manual implementation where you bypass CAS Operator automation and perform the same configuration steps as you would with any other Kubernetes service.

 

 

Ownership Boundaries

 

The steps described in this article show that it is possible to configure external binary access to CAS even when you have to manually configure all the required components. You might have to involve different teams to support you with the configuration and changes to the infrastructure.

 

  • The OpenShift administrator creates a Kubernetes service for the CAS binary port.
  • The IT department creates or configures the frontend networking infrastructure, such as an external network load balancer, so that it routes clients that connect to the external IP address to the listening address of the Kubernetes service.
  • The IT department is also in charge of configuring your DNS server to properly resolve the external alias hostname.
  • The SAS Viya administrator configures the CAS TLS certificate with the new external alias hostname and IP address.

 

 

High-level steps

 

Use the following sequence to plan the manual configuration, validate prerequisites, and confirm external CAS connectivity end to end.

 

  1. Plan the external endpoint, service name, and NodePort settings required by your environment.
  2. Verify that the external DNS alias resolves to the correct frontend IP address.
  3. Create the Kubernetes NodePort service that exposes the CAS binary port.
  4. Update the CAS TLS certificate so that it includes the external DNS alias and IP address.
  5. Validate the certificate and test the connection from an external client.

 

 

Plan

 

Before touching any configuration files, you will need to retrieve some parameters or decide their value. Here is a high-level list, with some sample choices that we made in our test OpenShift environment.

 

  • Verify that your IT department has provisioned the external load balancing infrastructure. Its configuration is beyond the scope of this article. In our test case, we decided to reuse the frontend load balancer already configured to manage the OpenShift default ingress route.
  • Decide or retrieve the DNS alias and IP address of that external load balancer. This is the endpoint that external CAS clients will specify in their connection details. In our case, we decided to connect to CAS using the alias "cas-server-test" within the base SAS Viya domain “viya.example.com” (i.e. cas-server-test.viya.example.com). We also decided to reuse the existing external IP address of the OpenShift default ingress route. For this reason, we asked our IT team to define a DNS alias that maps the alias we chose to that IP address.
  • Decide the internal name of the service. While you are free to choose whatever service name you want, for the sake of simplicity, keep it aligned to the external DNS alias; in our case, that’s “cas-server-test”.
  • Decide if the internal service will listen on a pre-determined and fixed port. Kubernetes services of type NodePort let you choose a pre-determined port number (see Choosing your own port). This might be useful when the external load balancer requires a known port number to route incoming connections to cluster nodes listening on that port. As the official Kubernetes documentation reminds us, in this case you need to take care of possible port collisions yourself. The chosen port number must be available and reserved for the CAS service on all the cluster nodes where the CAS server controller pod could run. In our test cluster, the external load balancer has been configured with a new rule to route incoming clients that connect to port 5570 to a service NodePort 30076.

 

Coordination note: This manual approach might involve different owners for load balancer configuration, firewall rules, DNS record provisioning, etc. This can add additional delays to your SAS Viya project timeline.

 

 

Validate the service DNS alias

 

You need to make sure that the desired DNS alias resolves to the expected IP address. In our case, we use the following code to verify that it maps to the IP address of our OpenShift default router:

 

CUSTOM_SVC_NAME="cas-server-test"
MY_SUBDOMAIN="viya.example.com"
echo "Looking for IP address of: ${CUSTOM_SVC_NAME}.${MY_SUBDOMAIN}
    It should be the same IP address as the OpenShift default router:
    $(oc -n openshift-ingress get service router-default -o json | jq -r .status.loadBalancer.ingress[0].ip)"

dig +short "${CUSTOM_SVC_NAME}.${MY_SUBDOMAIN}"

 

This prints a confirmation like the following:

 

Looking for IP address of: cas-server-test.viya.example.com
    It should be the same IP address as the OpenShift default router:
    52.232.224.221

router.apps.viya.example.com.
52.232.224.221

 

 

Create and verify the Kubernetes NodePort service

 

Create the new NodePort service. You can use this sample code; notice that it is mostly a copy of the original sas-cas-server-default-bin service that the CAS Operator creates when using automation:

 

CUSTOM_NODE_PORT=30076
CUSTOM_SVC_NAME="cas-server-test"

# delete the service if it was previously defined
kubectl -n ${NS} delete service ${CUSTOM_SVC_NAME} --ignore-not-found

# Create the new service on a custom node port
echo "---
apiVersion: v1
kind: Service
metadata:
    labels:
        app.kubernetes.io/instance: default
        app.kubernetes.io/name: sas-cas-server
        casoperator.sas.com/instance: default
        casoperator.sas.com/server: default
        casoperator.sas.com/tenant: shared
        sas.com/deployment: sas-viya
        sas.com/tenant: shared
    name: ${CUSTOM_SVC_NAME}
spec:
    type: NodePort
    selector:
        casoperator.sas.com/controller-active: '1'
        casoperator.sas.com/node-type: controller
        casoperator.sas.com/server: default
    ports:
        - name: cal
          protocol: TCP
          port: 5570
          targetPort: 5570
          nodePort: ${CUSTOM_NODE_PORT}
" | kubectl -n ${NS} create -f -

 

After the new service gets created, verify it with the following command:

 

kubectl -n ${NS} get service ${CUSTOM_SVC_NAME}

 

Your output should be similar to the following. Notice that NodePort services do not have an external IP.

 

NAME              TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
cas-server-test   NodePort   172.30.218.136   none          5570:30076/TCP   48s

 

This is different than when using automation: this time we are able to specify the service name cas-server-test and both its frontend and backend  ports, 5570 and 30076.

 

 

Update the CAS TLS certificate

 

Following the steps described in SAS Viya documentation, copy the sample file to your working directory, and change its permissions so that you can modify it:

 

cd $deploy
cp ./sas-bases/examples/security/customer-provided-merge-sas-certframe-configmap.yaml \
   ./site-config/customer-provided-merge-sas-certframe-configmap.yaml
chmod +w ./site-config/customer-provided-merge-sas-certframe-configmap.yaml

 

Now add the DNS alias and the external IP address to the file, while removing other example placeholders. You can submit the following code to do it automatically using sed:

 

cd $deploy
MY_ALIAS="cas-server-test.viya.example.com"
MY_IP="$(oc -n openshift-ingress get service router-default -o json | jq -r .status.loadBalancer.ingress[0].ip)"
sed -i -e "s/{{ ADDITIONAL-SAN-DNS-ENTRIES }}/${MY_ALIAS}/g" \
       -e "s/{{ ADDITIONAL-SAN-IP-ENTRIES }}/${MY_IP}/g" \
       -e "/{{ CERTIFICATE-GENERATOR }}/d" \
       -e "/{{ CERTIFICATE-DURATION }}/d" \
       -e "/{{ EXCLUDE-MOZILLA-CERTS }}/d" \
       ./site-config/customer-provided-merge-sas-certframe-configmap.yaml

 

You can look at the resulting file (using grep to remove comments and yq to color the output):

 

grep -v '#' ./site-config/customer-provided-merge-sas-certframe-configmap.yaml | yq

 

Your file should be similar to the following - possibly with different DNS and IP values. Since it is a YAML file, double check that the lines are indented correctly:

 

---
apiVersion: builtin
kind: ConfigMapGenerator
metadata:
  name: sas-certframe-user-config
behavior: merge
literals:
  - SAS_CERTIFICATE_ADDITIONAL_SAN_DNS=cas-server-test.viya.example.com
  - SAS_CERTIFICATE_ADDITIONAL_SAN_IP=52.232.224.221

 

After customizing the new ConfigMapGenerator file, update the kustomization.yaml manifest to reference it. Add the following line beneath the existing content in the generators section:

 

site-config/customer-provided-merge-sas-certframe-configmap.yaml

 

Finally, redeploy SAS Viya using the same steps as your initial deployment.

 

Just like with the automated case, when the new settings are in place, you must restart the CAS server pods so that CAS picks up the updated TLS certificate.

 

 

Validate the DNS name in the service TLS certificate

 

We have already validated that the DNS alias resolves to the correct IP address; now we have to check that the new CAS certificate includes both.

 

Use the following command to list all the aliases defined in the CAS server certificate

 

kubectl -n ${NS} get secret sas-cas-server-default-controller -o jsonpath="{.data['tls\.crt']}" \
    | base64 -d \
    | openssl x509 -text -noout \
    | grep -B 1 "cas-server-test"

 

You should get a result similar to the following. Note that it includes both the full DNS alias and the external IP of the cas-server-test service (in this example, cas-server-test.viya.example.com and 52.232.224.221) :

 

X509v3 Subject Alternative Name:
    DNS:banjo-p41772-worker-1, DNS:cas-server-test, DNS:cas-server-test.viya.example.com, DNS:controller, DNS:controller.sas-cas-server-default, DNS:controller.sas-cas-server-default.viya, DNS:controller.sas-cas-server-default.viya.svc.cluster.local, DNS:viya.apps.viya.example.com, DNS:localhost, DNS:sas-cas-server-default, DNS:sas-cas-server-default-client, DNS:sas-cas-server-default-controller, IP Address:10.0.1.5, IP Address:10.128.2.232, IP Address:127.0.0.1, IP Address:172.30.110.241, IP Address:172.30.231.168, IP Address:52.232.224.221

 

 

Test a connection from a Windows client

 

After all the configuration and verification steps have been performed, you can finally connect from an external client. Let’s use the same sample steps as in the previous article.

 

  1. Launch Windows PowerShell from the Windows Start menu
  2. If you do not have it yet, install the python swat package, which provides the required classes to connect to SAS Viya: pip install swat
  3. Launch python and submit the following code, making sure to fill in the server variable the DNS name of the load balancer verified above (i.e. cas-server-test.viya.example.com)

 

import swat
username = "MyUserName"
password = "MySecretPassword"
### Insert your DNS alias here!
server = "cas-server-test.viya.example.com"
### Connect to CAS
if server == "cas-server-test.viya.example.com":
    raise ValueError(f"Please enter *your* DNS server alias in the server variable and try again")
else:
    conn = swat.CAS(server, 5570, username, password)
    print(conn.serverStatus())

 

If you get a printout similar to the following, you have a successful connection:

 

NOTE: Grid node action status report: 3 nodes, 8 total actions executed.

[About]
{'CAS': 'Cloud Analytic Services', 'Version': '4.00', 'VersionLong': 'V.04.00M0P09082025', 'Viya Release': '20260214.1771047480056', 'Viya Version': 'Long-Term Support 2025.09', 'Copyright': 'Copyright © 2014-2025 SAS Institute Inc. All Rights Reserved.', 'ServerTime': '2026-02-16T17:22:51Z', 'System': {'Hostname': 'controller.sas-cas-server-default.gelcorp.svc.cluster.local', 'OS Name': 'Linux', 'OS Family': 'LIN X64', 'OS Release': '5.14.0-427.107.1.el9_4.x86_64', 'OS Version': '#1 SMP PREEMPT_DYNAMIC Wed Jan 14 07:05:59 EST 2026', 'Model Number': 'x86_64', 'Linux Distribution': 'Red Hat Enterprise Linux release 8.10 (Ootpa)'}, 'license': {'site': '(SIMPLE) THIS ORDER IS FOR SAS INTERNAL USE ONLY', 'siteNum': 70180938, 'expires': '20Mar2026:00:00:00', 'gracePeriod': 0, 'warningPeriod': 15}, 'CASHostAccountRequired': 'OPTIONAL', 'Transferred': 'NO', 'GlobalReadOnlyMode': 'NO', 'CASCacheLocation': 'CAS Disk Cache'}

[server]
Server Status
nodes  actions
0      3        8

[nodestatus]
Node Status
                                               name        role  uptime  running  stalled
0  worker-0.sas-cas-server-default.gelcorp.svc.c...      worker  34.958        0        0
1  worker-1.sas-cas-server-default.gelcorp.svc.c...      worker  34.958        0        0
2  controller.sas-cas-server-default.gelcorp.svc...  controller  35.016        0        0

+ Elapsed: 0.00614s, user: 0.00141s, sys: 0.00145s, mem: 1.05mb

 

 

Troubleshooting playbook

 

To simplify troubleshooting, we have collected a few common errors that you may receive when testing from the client, together with possible solutions. You might notice how this section aligns with the earlier validation steps. This troubleshooting applies to both the automation case presented in the previous article, and to the manual case in this article.

 

In general, when troubleshooting, we suggest following this order:

 

(1) CAS Service endpoint exists, (2) DNS resolves, (3) SAN in CAS TLS certificate matches, (4) client trusts SAS Viya CA, (5) authentication is valid, (6) network configuration is in place (firewalls/load balancing rules).

 

The client does not trust the SAS Viya CA

ERROR:

 

NOTE: The TCP/IP negClientSSL support routine failed with status 807ff008, hostname 20.80.228.0 port 5570 NOTE: Encryption run-time execution error ERROR: Failed to connect to host 'sas-cas-server-default-bin.myviya.example.com', port 5570.

 

CAUSE: The client is rejecting the CAS server certificate because it does not trust the SAS Viya CA. SOLUTION: Review the steps in the first article to ensure that the client’s TLS trust chain works.

 

Invalid certificate

ERROR:

 

NOTE: The TCP/IP negClientSSL support routine failed with status 807ff019, hostname 20.80.228.0 port 5570 NOTE: SSL Error: Invalid subject name in partner's certificate. Subject name must match machine name. ERROR: Failed to connect to host 'sas-cas-server-default-bin.myviya.example.com', port 5570.

 

CAUSE: The TLS certificate presented by CAS does not include the external hostname or DNS alias used to connect to the server.

SOLUTION: Review the validation in the section Validate the DNS name in the service TLS certificate. If using automation, check the value used in the field publishExtHostnameSuffix of the cas-enable-external-services.yaml file. In the manual case, check the value of SAS_CERTIFICATE_ADDITIONAL_SAN_DNS in the customer-provided-merge-sas-certframe-configmap.yaml file.

 

Invalid server name

ERROR:

 

ERROR: The host name 'sas-cas-server-default-bin.myviya.example.com' could not be found.

 

CAUSE: There is an error with the DNS hostname resolution. SOLUTION: Verify that the client connection string is correct (any typo?), and that the DNS entry has been properly created.

 

Invalid authentication

ERROR:

 

ERROR: Connection failed. Server returned: SAS Logon Manager authentication failed: Access denied.

 

CAUSE: Authentication failure.

SOLUTION: Verify the username and password entered in the connection string.

 

Generic connection error

ERROR:

 

ERROR: Failed to connect to host 'sas-cas-server-default-bin.myviya.example.com', port 5570.

 

CAUSE: Without any further error messages, this ERROR alone means that there is a generic connection issue between the client and CAS.

SOLUTION: Verify that the CAS server is running, that the LoadBalancer or NodePort service has been created, that the networking load balancer has been configured to route external connections to SAS Viya, and that there are no firewalls or other networking issues blocking the connection.

 

 

Summary

 

Manual external binary access to CAS is entirely achievable in environments where Kubernetes cannot provision load balancers automatically, but it succeeds only when service exposure, DNS, and TLS configuration are aligned. In practice, this means creating a NodePort service that the network team can route to, ensuring that the external alias resolves correctly, and updating the CAS certificate so that it matches the hostname and IP address used by clients.

 

This approach also requires deliberate coordination across teams. The platform administrator owns the Kubernetes service, the infrastructure team owns external routing and DNS, and the SAS Viya administrator owns the CAS certificate updates and client trust validation. When those responsibilities are planned early and validated in order, you can deliver reliable external CAS connectivity even in tightly controlled on-premises environments.

 

 

Find more articles from SAS Global Enablement and Learning here.

Contributors
Version history
Last update:
8 hours ago
Updated by:

Viya Copilot Motion Graphic.gif

Ready to see what SAS Viya Copilot can do?

Visit the Tips & Tricks page for setup guidance, demos, and practical examples that show how Copilot supports your workflows.

Get Started →

SAS AI and Machine Learning Courses

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.

Get started

Article Tags