Provide your own internal TLS certificates
By default, the operator generates a self-signed CA and per-service certificates for internal mutual TLS (mTLS). You can replace these with certificates from your own certificate authority (CA) when your organization requires it.
Before you begin
- You have cluster administrator access to the OpenShift namespace where automation orchestrator is deployed.
- You have installed and authenticated the
ocCLI. - You have installed OpenSSL 1.1.1 or later.
- You have a CA certificate and key, or you plan to generate a new CA for internal use.
About this task
For the required Secrets, DNS Subject Alternative Names (SANs), and certificate specifications, see Internal TLS.
If you already have certificates that meet the requirements, skip to step 5.
Procedure
-
Set shell variables to match your deployment:
$ INSTANCE_NAME=my-orchestrator $ NAMESPACE=automation-orchestrator $ CERT_DIR=$(mktemp -d) -
Generate the CA:
$ openssl req -x509 -newkey rsa:2048 -nodes \ -keyout "${CERT_DIR}/ca.key" \ -out "${CERT_DIR}/ca.crt" \ -days 3650 \ -subj "/CN=my-internal-ca" -
Generate a certificate for each component.
The following script creates all five:
$ for COMPONENT in backend worker background-worker temporal ui; do cat > "${CERT_DIR}/${COMPONENT}.cnf" <<EOF [req] req_extensions = v3_req distinguished_name = req_dn prompt = no [req_dn] CN = ${COMPONENT}.ao.svc [v3_req] keyUsage = digitalSignature, keyEncipherment extendedKeyUsage = serverAuth, clientAuth subjectAltName = @alt_names [alt_names] DNS.1 = ${INSTANCE_NAME}-${COMPONENT}.${NAMESPACE}.svc.cluster.local DNS.2 = ${INSTANCE_NAME}-${COMPONENT} DNS.3 = localhost IP.1 = 127.0.0.1 EOF openssl req -newkey rsa:2048 -nodes \ -keyout "${CERT_DIR}/${COMPONENT}.key" \ -out "${CERT_DIR}/${COMPONENT}.csr" \ -config "${CERT_DIR}/${COMPONENT}.cnf" openssl x509 -req \ -in "${CERT_DIR}/${COMPONENT}.csr" \ -CA "${CERT_DIR}/ca.crt" \ -CAkey "${CERT_DIR}/ca.key" \ -CAcreateserial \ -out "${CERT_DIR}/${COMPONENT}.crt" \ -days 3650 \ -extensions v3_req \ -extfile "${CERT_DIR}/${COMPONENT}.cnf" done -
Verify that each certificate is signed by your CA and has the correct SANs and extended key usage (EKU):
$ for COMPONENT in backend worker background-worker temporal ui; do echo "=== ${COMPONENT} ===" openssl verify -CAfile "${CERT_DIR}/ca.crt" "${CERT_DIR}/${COMPONENT}.crt" openssl x509 -in "${CERT_DIR}/${COMPONENT}.crt" -noout -text \ | grep -A1 "Subject Alternative Name" openssl x509 -in "${CERT_DIR}/${COMPONENT}.crt" -noout -text \ | grep -A1 "Extended Key Usage" echo doneEach certificate should show:
- Verification:
OK - SANs: the three DNS names and
127.0.0.1 - Extended Key Usage:
TLS Web Server Authentication, TLS Web Client Authentication
- Verification:
-
Create the Kubernetes Secrets.
Create the CA Secret as an
OpaqueSecret:$ oc create secret generic my-internal-ca \ --from-file=ca.crt="${CERT_DIR}/ca.crt" \ -n "${NAMESPACE}"Create the service certificate Secrets as
kubernetes.io/tlsSecrets:$ oc create secret tls my-backend-tls \ --cert="${CERT_DIR}/backend.crt" \ --key="${CERT_DIR}/backend.key" \ -n "${NAMESPACE}" $ oc create secret tls my-worker-tls \ --cert="${CERT_DIR}/worker.crt" \ --key="${CERT_DIR}/worker.key" \ -n "${NAMESPACE}" $ oc create secret tls my-background-worker-tls \ --cert="${CERT_DIR}/background-worker.crt" \ --key="${CERT_DIR}/background-worker.key" \ -n "${NAMESPACE}" $ oc create secret tls my-temporal-tls \ --cert="${CERT_DIR}/temporal.crt" \ --key="${CERT_DIR}/temporal.key" \ -n "${NAMESPACE}" $ oc create secret tls my-ui-tls \ --cert="${CERT_DIR}/ui.crt" \ --key="${CERT_DIR}/ui.key" \ -n "${NAMESPACE}" -
Add the
spec.tlsblock to your AutomationOrchestrator custom resource, referencing the Secrets you created:apiVersion: aap.ansible.com/v1alpha1 kind: AutomationOrchestrator metadata: name: my-orchestrator namespace: automation-orchestrator spec: tls: caSecretRef: name: my-internal-ca backendCertSecretRef: name: my-backend-tls workerCertSecretRef: name: my-worker-tls backgroundWorkerCertSecretRef: name: my-background-worker-tls temporalCertSecretRef: name: my-temporal-tls uiCertSecretRef: name: my-ui-tls # ... other spec fields -
Apply the custom resource:
$ oc apply -f orchestrator-cr.yamlThe operator validates that all six Secrets exist and contain the required keys before deploying. If any Secret is missing or incomplete, the operator sets
ConfigurationValid=Falseand does not proceed. -
Verify the deployment.
- Confirm that
TLSReadyshows"True"with reason"CustomerCertificates":$ oc get automationorchestrator my-orchestrator -n automation-orchestrator \ -o jsonpath='{.status.conditions[?(@.type=="TLSReady")]}' | jq .If the reason shows
SelfSignedCertificates, the operator did not detectspec.tls.caSecretRefand fell back to auto-generated certificates. IfTLSReadyisFalse, check themessagefield to identify which Secret is unhealthy. - Confirm that
ConfigurationValidandReadyare alsoTrue:$ oc get automationorchestrator my-orchestrator -n automation-orchestrator \ -o jsonpath='{.status.conditions}' | jq . - Verify that all pods are running:
$ oc get pods -n automation-orchestrator -l app.kubernetes.io/instance=my-orchestrator - Verify that the backend certificate issuer matches your CA, not the default
automation-orchestrator-internal-ca. Run this command from your workstation because the backend container image does not include the OpenSSL CLI.$ oc get secret my-backend-tls -n automation-orchestrator \ -o jsonpath='{.data.tls\.crt}' | base64 -d | openssl x509 -noout -issuer - Log in to the web interface and run a workflow to confirm end-to-end functionality.
- Confirm that