Why is it useful?
(IPIC is used as an example to illustrate the requirement, but the requirement extends to any Keystores that may be required by a z/OS Connect API server.)
IPIC security is an important consideration when deploying z/OS Connect API servers as Linux containers, particularly bind-time (transport) security which will prevent an unauthorised client system from connecting to CICS. IPIC bind-time (transport) security is implemented by configuring the connection to use TLS client authentication.
Container images are designed to be immutable, and this applies to both application content (e.g. .war files) and configuration (e.g. server.xml snippets). An example of an immutable secure IPIC connection config that could be used unchanged from development (z/OS Connect Designer) through to production (z/OS Connect API server):
<zosconnect_cicsIpicConnection id="cicsConn"
zosConnectNetworkid="${BAQ_NETWORK}"
zosConnectApplid="${BAQ_APPLID}"
host="${CICS_HOST}"
port="${CICS_PORT}"
sslRef="ipicSSLConfig" />
<ssl id="ipicSSLConfig"
keyStoreRef="ipicKeyStore"
trustStoreRef="ipicTrustStore" />
<keyStore id="ipicKeyStore"
location="${server.config.dir}/resources/security/${KEYSTORE}"
password="${KEYSTORE_PASSWORD}"
type="PKCS12" />
<keyStore id="ipicTrustStore"
location="${server.config.dir}/resources/security/${TRUSTSTORE}"
password="${TRUSTSTORE_PASSWORD}"
type="PKCS12" />
Docker, Podman, etc. provide a simple mechanism for mounting Keystores into a z/OS Connect Designer container; for example using a docker-compose.yaml file:
version: "3.2"
services:
zosConnect:
image: icr.io/zosconnect/ibm-zcon-designer:3.0.75
environment:
- BAQ_NETWORK=BAQCA
- BAQ_APPLID=BAQCA
- CICS_HOST=10.242.64.200
- CICS_PORT=57027
- KEYSTORE=ipic-dev-keystore.p12
- KEYSTORE_PASSWORD=${KPASS}
- TRUSTSTORE=ipic-dev-truststore.p12
- TRUSTSTORE_PASSWORD=${TPASS}
- HTTPS_PORT=9443
ports:
- "9443:9443"
volumes:
- ../zc-pot-api:/workspace/project
- ./logs/:/logs/
- ./certs:/config/resources/security/:ro
- ./defaults:/config/configDropins/defaults:ro
In a Kubernetes environment (where z/OS Connect API servers are deployed), the same result is achieved using ConfigMaps, Secrets, Volumes and volumeMounts. However, the z/OS Connect Operator and associated Custom Resource (CR) do not currently support all of the k8s objects required to mount keystores into a Liberty server, making it difficult for customers to design and build immutable z/OS Connect API server container images. Currently, a customer would have to do something like this:
(Keystores and truststores would be pre-deployed as k8s Secrets.)
1) Build a z/OS Connect API server image containing a secure IPIC connection server.xml snippet (similar to example above)
2) Create a ZosConnect CR instance, which will in turn create a Deployment, which will in turn start a z/OS Connect API server in a container
3) The z/OS Connect API server will fail to start with "keystore not found" type errors
4) Patch the Deployment in order to mount the keystores; example patch-file:
spec:
template:
spec:
containers:
- name: zc
volumeMounts:
- mountPath: "/opt/ibm/wlp/usr/servers/defaultServer/resources/security/ipic-prod-truststore.p12"
name: zc-truststore
readOnly: true
subPath: ipic-prod-truststore.p12
- mountPath: "/opt/ibm/wlp/usr/servers/defaultServer/resources/security/ipic-prod-keystore.p12"
name: zc-keystore
readOnly: true
subPath: ipic-prod-keystore.p12
volumes:
- name: zc-truststore
secret:
defaultMode: 420
secretName: zc-truststore
- name: zc-keystore
secret:
defaultMode: 420
secretName: zc-keystore
5) k8s will create a new Pod / z/OS Connect API server; it will start successfully and the old Pod / API server will be deleted
Who would benefit?
All customers deploying z/OS Connect API servers to Kubernetes.
How would it work?
The ZosConnect Custom Resource (CR) schema would be enhanced to support all of the k8s objects required to mount keystores into a Liberty server. Optionally, the z/OS Connect Operator UI would be similarly enhanced, but in the meantime, it would be sufficient to support an enhanced ZosConnect CR in yaml format.