Chapter 3. Configuring certificates


3.1. Replacing the default ingress certificate

To allow external clients to connect securely to applications under the .apps subdomain in OpenShift Container Platform, you can replace the default wildcard ingress certificate with one issued by a trusted public CA.

3.1.1. Understand the default ingress certificate

You can replace the default ingress certificate with a certificate from a public CA so that external clients connect securely to your applications.

The default ingress certificate in OpenShift Container Platform is a wildcard certificate that the Ingress Operator issues from an internal CA for the web console, CLI, and applications under the .apps subdomain.

3.1.2. Replace the default ingress certificate

To secure the web console, CLI, and all applications under the .apps subdomain in OpenShift Container Platform, you can replace the default ingress certificate by creating a TLS secret with your wildcard certificate and updating the Ingress Controller and cluster proxy configuration.

Note

Before using the procedure, ensure you understand the following Ingress Controller behaviors:

  • When certificates are renewed or rotated by using external certificate management tools, only the contents of the secret, such as the certificate and key, are updated. The secret name remains unchanged. Kubelet automatically propagates these updates to the mounted volume, allowing the router to detect the file changes and hot-reload the new certificate and key. As a result, no rolling update of the router deployment is triggered or required.
  • For secret renewal or rotation, the cert-manager Operator changes the secret content, such as a cert/key pair, but does not change the secret name. This happens because kubelet automatically propagates changes to the secret in the volume mount. The router pod detects the file change and then hot reloads the new cert/key pair. Updating the secret content does not trigger rolling update.

Prerequisites

  • You must have a wildcard certificate for the fully qualified .apps subdomain and its corresponding private key. Each should be in a separate PEM format file.
  • The private key must be unencrypted. If your key is encrypted, decrypt it before importing it into OpenShift Container Platform.
  • The certificate must include the subjectAltName extension showing *.apps.<clustername>.<domain>.
  • The certificate file can contain one or more certificates in a chain. The file must list the wildcard certificate as the first certificate, followed by other intermediate certificates, and then ending with the root CA certificate.
  • Copy the root CA certificate into an additional PEM format file.
  • Verify that all certificates which include -----END CERTIFICATE----- also end with one carriage return after that line.

Procedure

  1. Create a config map that includes only the root CA certificate that is used to sign the wildcard certificate:

    $ oc create configmap custom-ca \
         --from-file=ca-bundle.crt=</path/to/example-ca.crt> \
         -n openshift-config

    where

    </path/to/example-ca.crt>
    The path to the root CA certificate file on your local file system. For example, /etc/pki/ca-trust/source/anchors.
  2. Update the cluster-wide proxy configuration with the newly created config map:

    $ oc patch proxy/cluster \
         --type=merge \
         --patch='{"spec":{"trustedCA":{"name":"custom-ca"}}}'
    Note

    If you update only the trusted CA for your cluster, the MCO updates the /etc/pki/ca-trust/source/anchors/openshift-config-user-ca-bundle.crt file and the Machine Config Controller (MCC) applies the trusted CA update to each node so that a node reboot is not required. However, with these changes, the Machine Config Daemon (MCD) restarts critical services on each node, such as kubelet and CRI-O. These service restarts cause each node to briefly enter the NotReady state until the service is fully restarted.

    If you change any other parameter in the openshift-config-user-ca-bundle.crt file, such as noproxy, the MCO reboots each node in your cluster.

  3. Create a secret that contains the wildcard certificate chain and key:

    $ oc create secret tls <secret> \
         --cert=</path/to/cert.crt> \
         --key=</path/to/cert.key> \
         -n openshift-ingress

    where:

    <secret>
    Specifies the name of the secret that will contain the certificate chain and private key.
    </path/to/cert.crt>
    Specifies the path to the certificate chain on your local file system.
    </path/to/cert.key>
    Specifies the path to the private key associated with this certificate.
  4. Update the Ingress Controller configuration with the newly created secret:

    $ oc patch ingresscontroller.operator default \
         --type=merge -p \
         '{"spec":{"defaultCertificate": {"name": "<secret>"}}}' \
         -n openshift-ingress-operator
    • <secret>:: Specifies the name used for the secret. Replace <secret> with the name used for the secret.

3.2. Adding API server certificates

To allow clients outside of the cluster to verify the API server’s certificate, you can replace the default API server certificate with one that is issued by a CA that clients trust.

By default, the API server certificate is issued by an internal OpenShift Container Platform cluster CA. As a result, clients outside of the cluster cannot verify the API server’s certificate.

Note

In hosted control plane clusters, you can add as many custom certificates to your Kubernetes API Server as you need. However, do not add a certificate for the endpoint that worker nodes use to communicate with the control plane.

The default API server certificate is issued by an internal OpenShift Container Platform cluster Certificate Authority (CA).

You can add alternative certificates that the API server will return based on the fully qualified domain name (FQDN) requested by the client, for example when a reverse proxy or load balancer is used.

Note

Adding a custom API server named certificate for the first time triggers the kube-apiserver-operator to roll out a new revision of the API server pods. Node reboots are not required.

Prerequisites

  • You must have a certificate for the FQDN and its corresponding private key. Each should be in a separate PEM format file.
  • The private key must be unencrypted.
  • The certificate must include the subjectAltName extension showing the FQDN.
  • The certificate file can contain one or more certificates in a chain. The certificate for the API server FQDN must be the first certificate in the file, followed by intermediate certificates, and ending with the root CA certificate.
Warning

Do not provide a named certificate for the internal load balancer (host name api-int.<cluster_name>.<base_domain>). Doing so will leave your cluster in a degraded state.

Procedure

  1. Log in to the CLI as the kubeadmin user:

    $ oc login -u kubeadmin -p <password> https://<fqdn>:6443

    where:

    <password>
    Specifies your cluster administrative password.
    <fqdn>
    Specifies the fully qualified domain name of the internal cluster API endpoint.
  2. Create a secret that contains the certificate chain and private key in the openshift-config namespace:

    $ oc create secret tls <secret_name> \
         --cert=<path_to_certificate_file> \
         --key=<path_to_private_key_file> \
         -n openshift-config

    where:

    <secret_name>
    Specifies the name of the new secret resource that will contain the cryptographic key pair.
    <path_to_certificate_file>
    Specifies the absolute local path to your custom certificate chain file.
    <path_to_private_key_file>
    Specifies the absolute local path to the unencrypted private key file associated with the certificate.
  3. Update the API server to reference the created secret resource:

    $ oc patch apiserver cluster --type=merge -p '
    {
      "spec": {
        "servingCerts": {
          "namedCertificates": [
            {
              "names": ["<fqdn>"],
              "servingCertificate": {
                "name": "<secret_name>"
              }
            }
          ]
        }
      }
    }'

    where:

    <fqdn>
    Specifies the fully qualified domain name for which the API server serves this custom certificate. Do not include a port number.
    <secret_name>
    Specifies the name of the secret you created in the previous step.
  4. Verify that a new revision of the Kubernetes API server rolls out by checking the operator status:

    $ oc get clusteroperators kube-apiserver
    Note

    The PROGRESSING status column will change to True while the API server operator deploys the new pod revision configured with your custom certificate. Do not interrupt the process or apply additional configuration updates while the rollout is underway. Continue only after the status returns to False and AVAILABLE reads True.

Update or renew an expired or expiring named certificate that has already been configured in your cluster to avoid API availability issues. The API server pods dynamically detect and reload the updated certificate asset without disruption.

Note

When an existing API server named certificate is renewed by updating its corresponding secret, a new revision of the Kubernetes API server pods does not roll out. Node reboots are not required.

Warning

If the renewed certificate is signed by a different root CA than the previous certificate, internal applications or custom pods that communicate with the API server might encounter X509 certificate validation errors. If these client workloads do not automatically hot-reload their truststores, you must manually restart them to force them to pick up the new certificate chain.

Prerequisites

  • You have the renewed certificate chain and private key files in PEM format.
  • The secret containing the old certificate already exists in the openshift-config namespace and is actively referenced by the apiserver/cluster configuration.

Procedure

  1. Log in to the CLI as the kubeadmin user.
  2. Update the existing secret resource in the openshift-config namespace with the newly issued certificate and private key:

    $ oc create secret tls <existing_secret_name> \
         --cert=<path_to_new_cert>.crt \
         --key=<path_to_new_key>.key \
         -n openshift-config \
         --dry-run=client -o yaml | oc replace -f -

    where:

    <existing_secret_name>
    Specifies the target name of the existing active secret that you are replacing.
    <path_to_new_cert>.crt
    Specifies the absolute local file system path to the renewed certificate chain file.
    <path_to_new_key>.key
    Specifies the absolute local file system path to the corresponding unencrypted private key file.
  3. Verify that the kube-apiserver pods successfully hot-reload the updated assets without initiating a new cluster deployment revision:

    $ oc get clusteroperators kube-apiserver

    Confirm that the PROGRESSING status column remains False. If the status changes to True, verify that your underlying apiserver/cluster resource parameters were not modified structural layout changes during the substitution.

Service serving certificates provide automatic TLS encryption for service-to-service communication. Configure certificates for services, ConfigMaps, APIServices, CRDs, and webhooks to secure internal cluster traffic.

3.3.1. Understand service serving certificates

Service serving certificates are TLS web server certificates that OpenShift Container Platform issues for middleware applications that require encryption. The service-ca controller stores the certificate and key in a secret and automatically replaces them near expiration.

The service-ca controller uses the x509.SHA256WithRSA signature algorithm to generate service certificates.

The generated certificate and key are in PEM format, stored in tls.crt and tls.key respectively, within a created secret. The certificate and key are automatically replaced when they get close to expiration.

The service Certificate Authority (CA) certificate, which issues the service certificates, is valid for 26 months and is automatically rotated when there is less than 13 months validity left. After rotation, the previous service CA configuration is still trusted until its expiration. This allows a grace period for all affected services to refresh their key material before the expiration. If you do not upgrade your cluster during this grace period, which restarts services and refreshes their key material, you might need to manually restart services to avoid failures after the previous service CA expires.

Note

You can use the following command to manually restart all pods in the cluster. Be aware that running this command causes a service interruption, because it deletes every running pod in every namespace. These pods will automatically restart after they are deleted.

$ for I in $(oc get ns -o jsonpath='{range .items[*]} {.metadata.name}{"\n"} {end}'); \
      do oc delete pods --all -n $I; \
      sleep 1; \
      done

3.3.2. Add a service certificate

To secure internal communication to a service in OpenShift Container Platform, you can annotate the service to generate a signed serving certificate and key pair into a secret in the same namespace.

The generated certificate is only valid for the internal service DNS name <service.name>.<service.namespace>.svc, and is only valid for internal communications. If your service is a headless service (no clusterIP value set), the generated certificate also contains a wildcard subject in the format of *.<service.name>.<service.namespace>.svc.

Important

Because the generated certificates contain wildcard subjects for headless services, you must not use the service Certificate Authority (CA) if your client must differentiate between individual pods. In this case:

  • Generate individual TLS certificates by using a different CA.
  • Do not accept the service CA as a trusted CA for connections that are directed to individual pods and must not be impersonated by other pods. These connections must be configured to trust the CA that was used to generate the individual TLS certificates.

Prerequisites

  • You must have a service defined.

Procedure

  1. Annotate the service with service.beta.openshift.io/serving-cert-secret-name:

    $ oc annotate service <service_name> \
         service.beta.openshift.io/serving-cert-secret-name=<secret_name>
    • Replace <service_name> with the name of the service to secure.
    • <secret_name> will be the name of the generated secret containing the certificate and key pair.

      Note

      For convenience, it is recommended that this value be the same as <service_name>.

      For example, use the following command to annotate the service test1:

      $ oc annotate service test1 service.beta.openshift.io/serving-cert-secret-name=test1
  2. Examine the service to confirm that the annotations are present:

    $ oc describe service <service_name>

    Example output

    ...
    Annotations:              service.beta.openshift.io/serving-cert-secret-name: <service_name>
                              service.beta.openshift.io/serving-cert-signed-by: openshift-service-serving-signer@1556850837
    ...

  3. After the cluster generates a secret for your service, your Pod spec can mount it, and the pod will run after it becomes available.

3.3.3. Add the service CA bundle to a config map

To verify TLS connections to services that use serving certificates in OpenShift Container Platform, you can inject the service Certificate Authority (CA) certificate into a config map. Annotate the config map so that pods can mount the CA bundle from the service-ca.crt key.

Important

After adding this annotation to a config map, the OpenShift Service CA Operator deletes all the data in the config map. Consider using a separate config map to contain the service-ca.crt, instead of using the same config map that stores your pod configuration.

Procedure

  1. Annotate the config map with the service.beta.openshift.io/inject-cabundle=true annotation by entering the following command:

    $ oc annotate configmap <config_map_name> \
         service.beta.openshift.io/inject-cabundle=true
    • Replace <config_map_name> with the name of the config map to annotate.

      Note

      Explicitly referencing the service-ca.crt key in a volume mount prevents a pod from starting until the config map has been injected with the CA bundle. You can override this behavior by setting the optional parameter to true in the serving certificate configuration of the volume.

  2. View the config map to ensure that the service CA bundle has been injected:

    $ oc get configmap <config_map_name> -o yaml

    The CA bundle is displayed as the value of the service-ca.crt key in the YAML output:

    apiVersion: v1
    data:
      service-ca.crt: |
        -----BEGIN CERTIFICATE-----
    ...
  3. Mount the config map as a volume to each container that exists in a pod by configuring your Deployment object.

    Example Deployment object that defines the volume for the mounted config map

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: my-example-custom-ca-deployment
      namespace: my-example-custom-ca-ns
    spec:
      ...
        spec:
          ...
          containers:
            - name: my-container-that-needs-custom-ca
              volumeMounts:
              - name: trusted-ca
                mountPath: /etc/pki/ca-trust/extracted/pem
                readOnly: true
          volumes:
          - name: trusted-ca
            configMap:
              name: <config_map_name>
              items:
                - key: ca-bundle.crt
                  path: tls-ca-bundle.pem
    # ...

    where:

    <config_map_name>
    Specifies the name of the config map that you annotated in an earlier step of the procedure.
    ca-bundle.crt
    Specifies the ConfigMap key. This is required.
    tls-ca-bundle.pem
    Specifies the ConfigMap path. This is required.

3.3.4. Add the service CA bundle to an API service

To allow the Kubernetes API server in OpenShift Container Platform to validate the service Certificate Authority (CA) certificate that secures an API service endpoint, you can annotate an APIService object to inject the service CA bundle into the spec.caBundle field.

Procedure

  1. Annotate the API service with service.beta.openshift.io/inject-cabundle=true:

    $ oc annotate apiservice <api_service_name> \
         service.beta.openshift.io/inject-cabundle=true
    • Replace <api_service_name> with the name of the API service to annotate.

      For example, use the following command to annotate the API service test1:

      $ oc annotate apiservice test1 service.beta.openshift.io/inject-cabundle=true
  2. View the API service to ensure that the service CA bundle has been injected:

    $ oc get apiservice <api_service_name> -o yaml

    The CA bundle is displayed in the spec.caBundle field in the YAML output:

    apiVersion: apiregistration.k8s.io/v1
    kind: APIService
    metadata:
      annotations:
        service.beta.openshift.io/inject-cabundle: "true"
    ...
    spec:
      caBundle: <CA_BUNDLE>
    ...

You can annotate a CustomResourceDefinition (CRD) object with service.beta.openshift.io/inject-cabundle=true to have its spec.conversion.webhook.clientConfig.caBundle field populated with the service Certificate Authority (CA) bundle.

This allows the Kubernetes API server to validate the service CA certificate used to secure the targeted endpoint.

Note

The service CA bundle will only be injected into the CRD if the CRD is configured to use a webhook for conversion. It is only useful to inject the service CA bundle if a CRD’s webhook is secured with a service CA certificate.

Procedure

  1. Annotate the CRD with service.beta.openshift.io/inject-cabundle=true:

    $ oc annotate crd <crd_name> \
         service.beta.openshift.io/inject-cabundle=true
    • Replace <crd_name> with the name of the CRD to annotate.

      For example, use the following command to annotate the CRD test1:

      $ oc annotate crd test1 service.beta.openshift.io/inject-cabundle=true
  2. View the CRD to ensure that the service CA bundle has been injected:

    $ oc get crd <crd_name> -o yaml

    The CA bundle is displayed in the spec.conversion.webhook.clientConfig.caBundle field in the YAML output:

    apiVersion: apiextensions.k8s.io/v1
    kind: CustomResourceDefinition
    metadata:
      annotations:
        service.beta.openshift.io/inject-cabundle: "true"
    ...
    spec:
      conversion:
        strategy: Webhook
        webhook:
          clientConfig:
            caBundle: <CA_BUNDLE>
    ...

To allow the Kubernetes API server in OpenShift Container Platform to validate the service Certificate Authority (CA) certificate that secures a mutating webhook endpoint, you can annotate a MutatingWebhookConfiguration object to inject the service CA bundle into each webhook clientConfig.caBundle field.

Note

Do not set this annotation for admission webhook configurations that need to specify different CA bundles for different webhooks. If you do, then the service CA bundle will be injected for all webhooks.

Procedure

  1. Annotate the mutating webhook configuration with service.beta.openshift.io/inject-cabundle=true:

    $ oc annotate mutatingwebhookconfigurations <mutating_webhook_name> \
         service.beta.openshift.io/inject-cabundle=true
    • Replace <mutating_webhook_name> with the name of the mutating webhook configuration to annotate.

      For example, use the following command to annotate the mutating webhook configuration test1:

      $ oc annotate mutatingwebhookconfigurations test1 service.beta.openshift.io/inject-cabundle=true
  2. View the mutating webhook configuration to ensure that the service CA bundle has been injected:

    $ oc get mutatingwebhookconfigurations <mutating_webhook_name> -o yaml

    The CA bundle is displayed in the clientConfig.caBundle field of all webhooks in the YAML output:

    apiVersion: admissionregistration.k8s.io/v1
    kind: MutatingWebhookConfiguration
    metadata:
      annotations:
        service.beta.openshift.io/inject-cabundle: "true"
    ...
    webhooks:
    - myWebhook:
      - v1beta1
      clientConfig:
        caBundle: <CA_BUNDLE>
    ...

To allow the Kubernetes API server in OpenShift Container Platform to validate the service Certificate Authority (CA) certificate that secures a validating webhook endpoint, you can annotate a ValidatingWebhookConfiguration object to inject the service CA bundle into each webhook clientConfig.caBundle field.

Note

Do not set this annotation for admission webhook configurations that need to specify different CA bundles for different webhooks. If you do, then the service CA bundle will be injected for all webhooks.

Procedure

  1. Annotate the validating webhook configuration with service.beta.openshift.io/inject-cabundle=true:

    $ oc annotate validatingwebhookconfigurations <validating_webhook_name> \
         service.beta.openshift.io/inject-cabundle=true
    • Replace <validating_webhook_name> with the name of the validating webhook configuration to annotate.

      For example, use the following command to annotate the validating webhook configuration test1:

      $ oc annotate validatingwebhookconfigurations test1 service.beta.openshift.io/inject-cabundle=true
  2. View the validating webhook configuration to ensure that the service CA bundle has been injected:

    $ oc get validatingwebhookconfigurations <validating_webhook_name> -o yaml

    The CA bundle is displayed in the clientConfig.caBundle field of all webhooks in the YAML output:

    apiVersion: admissionregistration.k8s.io/v1
    kind: ValidatingWebhookConfiguration
    metadata:
      annotations:
        service.beta.openshift.io/inject-cabundle: "true"
    ...
    webhooks:
    - myWebhook:
      - v1beta1
      clientConfig:
        caBundle: <CA_BUNDLE>
    ...

To replace a generated service serving certificate in OpenShift Container Platform, you can delete the TLS secret named in the service serving-cert-secret-name annotation. A new secret and certificate pair are created automatically.

Prerequisites

  • A secret containing the certificate and key pair must have been generated for the service.

Procedure

  1. Examine the service to determine the secret containing the certificate. This is found in the serving-cert-secret-name annotation, as seen below.

    $ oc describe service <service_name>

    Example output

    ...
    service.beta.openshift.io/serving-cert-secret-name: <secret>
    ...

  2. Delete the generated secret for the service. This process will automatically recreate the secret.

    $ oc delete secret <secret>
    • Replace <secret> with the name of the secret from the previous step.
  3. Confirm that the certificate has been recreated by obtaining the new secret and examining the AGE.

    $ oc get secret <service_name>

    Example output

    NAME              TYPE                DATA   AGE
    <service.name>    kubernetes.io/tls   2      1s

3.3.9. Manually rotate the service CA certificate

To refresh the service Certificate Authority (CA) certificate in OpenShift Container Platform outside the automatic renewal cycle, you can delete the signing-key secret in the openshift-service-ca namespace. Restart pods so that services use certificates signed by the new CA.

The service CA is valid for 26 months and is automatically refreshed when less than 13 months of validity remain.

Warning

A manually-rotated service CA does not maintain trust with the previous service CA. You might experience a temporary service disruption until the pods in the cluster are restarted, which ensures that pods are using service serving certificates issued by the new service CA.

Prerequisites

  • You must be logged in as a cluster admin.

Procedure

  1. View the expiration date of the current service CA certificate by using the following command.

    $ oc get secrets/signing-key -n openshift-service-ca \
         -o template='{{index .data "tls.crt"}}' \
         | base64 --decode \
         | openssl x509 -noout -enddate
  2. Manually rotate the service CA. This process generates a new service CA which will be used to sign the new service certificates.

    $ oc delete secret/signing-key -n openshift-service-ca
  3. To apply the new certificates to all services, restart all the pods in your cluster. This command ensures that all services use the updated certificates.

    $ for I in $(oc get ns -o jsonpath='{range .items[*]} {.metadata.name}{"\n"} {end}'); \
          do oc delete pods --all -n $I; \
          sleep 1; \
          done
    Warning

    This command will cause a service interruption, as it goes through and deletes every running pod in every namespace. These pods will automatically restart after they are deleted.

3.4. Updating the CA bundle

To trust custom certificate authorities for egress connections in OpenShift Container Platform, you can update the CA bundle by specifying custom CA certificates in the cluster-wide proxy configuration.

3.4.1. Understand the CA Bundle certificate

Proxy certificates allow users to specify one or more custom certificate authority (CA) used by platform components when making egress connections.

The trustedCA field of the Proxy object is a reference to a config map that contains a user-provided trusted certificate authority (CA) bundle. This bundle is merged with the Red Hat Enterprise Linux CoreOS (RHCOS) trust bundle and injected into the trust store of platform components that make egress HTTPS calls. For example, image-registry-operator calls an external image registry to download images. If trustedCA is not specified, only the RHCOS trust bundle is used for proxied HTTPS connections. Provide custom CA certificates to the RHCOS trust bundle if you want to use your own certificate infrastructure.

The trustedCA field should only be consumed by a proxy validator. The validator is responsible for reading the certificate bundle from required key ca-bundle.crt and copying it to a config map named trusted-ca-bundle in the openshift-config-managed namespace. The namespace for the config map referenced by trustedCA is openshift-config:

apiVersion: v1
kind: ConfigMap
metadata:
  name: user-ca-bundle
  namespace: openshift-config
data:
  ca-bundle.crt: |
    -----BEGIN CERTIFICATE-----
    Custom CA certificate bundle.
    -----END CERTIFICATE-----

3.4.2. Replace the CA Bundle certificate

To trust a custom certificate authority for egress connections in OpenShift Container Platform, you can replace the CA bundle by creating a config map with your root CA certificate and updating the cluster proxy configuration.

Procedure

  1. Create a config map that includes the root CA certificate used to sign the wildcard certificate:

    $ oc create configmap custom-ca \
         --from-file=ca-bundle.crt=</path/to/example-ca.crt> \
         -n openshift-config

    </path/to/example-ca.crt> is the path to the CA certificate bundle on your local file system.

  2. Update the cluster-wide proxy configuration with the newly created config map:

    $ oc patch proxy/cluster \
         --type=merge \
         --patch='{"spec":{"trustedCA":{"name":"custom-ca"}}}'
Red Hat logoGithubRedditYoutubeTwitter

Learn

Try, buy, & sell

Communities

About Red Hat

We deliver hardened solutions that make it easier for enterprises to work across platforms and environments, from the core datacenter to the network edge.

Making open source more inclusive

Red Hat is committed to replacing problematic language in our code, documentation, and web properties. For more details, see the Red Hat Blog.

About Red Hat Documentation

Legal Notice

Theme

© 2026 Red Hat
Back to top