Manage TLS encryption and certificates

Configure and manage TLS encryption and certificates to protect data in transit and ensure that your environment complies with your organization’s security policies.

In RHOSO 18.0, TLS everywhere (TLS-e) cannot be disabled after it is enabled. Certificate lifecycle management is handled by the cert-manager Operator, which replaces FreeIPA, certmonger, and tripleo-ipa from Red Hat OpenStack Platform (RHOSP) 17.1. In RHOSO 18.0, there is no undercloud, no novajoin, or no IdM integration to configure. Certificates are issued, renewed, and rotated automatically.

TLS default configuration and custom certificates

When you deploy your cloud environment, most API connections are protected by TLS by default. You can customize these settings to apply trusted certificates from your own internal certificate authority (CA) to comply with your organization’s security requirements.

Note
TLS is not currently available for the internal Alert Manager Web UI service endpoint.

You might be required to protect public APIs by using your own internal certificate authority(CA). To replace the automatically generated certificates you must create a secret that contains your additional CA certs, including all certificates in needed chains of trust.

You can apply trusted certificates from your own internal CA to public interfaces on RHOSO. The public interface is where ingress traffic meets the service’s route. Do not attempt to manage encryption on internal pod-level interfaces.

If you decide to apply trusted certificates from your own internal CA, you will need the following information:

DNS names

For each service you apply your own custom certificate to, you will need its DNS hostname for the process of generating the certificate. You can get a list of public hostnames by using the command: oc get -n openstack routes.

Note
To use a single certificate for two or more services, use a wildcard in the DNS name field, or list multiple DNS names in the subject alt names field. If you do not use a wildcard, then you must update the certificate if a route hostname changes.
Duration
To update a service’s certificate in OpenShift, the service must be restarted. The duration for the certificate is the longest amount of time a service can stay live without being restarted, subject to your internal security policies.
Usages
You must include - key encipherment, digital signature, and server auth within the list of usages in your certificate.

Updating TLS to use custom certificates requires edits to both the control plane and the data plane.

The following are the default TLS settings that are used if not annotated and changed:

apiVersion: core.openstack.org/v1beta1
kind: OpenStackControlPlane
metadata:
  name: myctlplane
spec:
  tls:
    ingress:
      ca:
        duration: 87600h
      cert:
        duration: 43800h
      enabled: true
    podLevel:
      enabled: true
      internal:
        ca:
          duration: 87600h
        cert:
          duration: 43800h
      libvirt:
        ca:
          duration: 87600h
        cert:
          duration: 43800h
      ovn:
        ca:
          duration: 87600h
        cert:
          duration: 43800h

Add custom CA certificates to the control plane

Add custom certificate authority (CA) certificates to the control plane so that OpenStack services can validate certificates from your internal CA or third-party providers.

About this task

To validate custom CA certificates on your control plane, you must add your custom CA certificate into a bundle that includes all certificates that OpenStack services can verify against.

Note
If TLS is not enabled on each node set, then it must be enabled, which requires deploying the data plane.

Procedure

  1. Create a PEM-formatted bundle, for example, mybundle.pem. Include all the CA certificates that you want OpenStack to trust.
  2. Create a manifest file called cacerts.yaml that includes the mybundle.pem created in the previous step. Include all the certificates in chains of trust if applicable:
    apiVersion: v1
    kind: Secret
    metadata:
      name: cacerts
      namespace: openstack
    type: Opaque
    data:
      myBundleExample: <cat mybundle.pem | base64 -w0>
      CACertExample: <cat cacert.pem | base64 -w0>

    where:

    mybundle.pem
    Specifies the name of your certificate or certificate bundle. The results are pasted as the value of the myBundleExample field.
    cacert.pem
    Specifies the name of your CA certificate.
  3. Create the secret from the manifest file:
    $ oc apply -f cacerts.yaml
  4. Edit the openstack_control_plane.yaml custom resource (CR) file and add your bundle as the parameter for caBundleSecretName:
    apiVersion: core.openstack.org/v1beta1
    kind: OpenStackControlPlane
    metadata:
      name: myctlplane
    spec:
      tls:
        podLevel:
          enabled: true
        caBundleSecretName: cacerts
  5. Apply the control plane changes:
    $ oc apply -f openstack_control_plane.yaml
  6. Determine if TLS is enabled on each node set, by running the following command, which returns true if TLS is enabled on the specified node set:
    $ oc get openstackdataplanenodeset <node_set_name> -n <namespace> -o json | jq .items[0].spec.tlsEnabled

    where:

    <node_set_name>
    Specifies the name of the OpenStackDataPlaneNodeSet CR that the node belongs to.
    <namespace>
    Specifies the namespace of the required Red Hat OpenStack Services on OpenShift (RHOSO) environment, for example, openstack.
  7. If TLS is not enabled, you must enable it:
    1. Open the OpenStackDataPlaneNodeSet CR file for each node on the data plane, and enable TLS in each:
      apiVersion: dataplane.openstack.org/v1beta1
      kind: OpenStackDataPlaneNodeSet
      metadata:
        name: <node_set_name>
        namespace: openstack
      spec:
        tlsEnabled: true
    2. Save the updated OpenStackDataPlaneNodeSet CR files and apply the updates:
      $ oc apply -f openstack_data_plane.yaml -n <namespace>
  8. Create a separate file on your workstation to define the OpenStackDataPlaneDeployment CR:
    apiVersion: dataplane.openstack.org/v1beta1
    kind: OpenStackDataPlaneDeployment
    metadata:
      name: <node_set_deployment_name>

    where:

    <node_set_deployment_name>
    Specifies the name of the OpenStackDataPlaneDeployment CR. This name must be unique, must consist of lower case alphanumeric characters, - (hyphen) or . (period), and must start and end with an alphanumeric character.
  9. Add the OpenStackDataPlaneNodeSet CRs to the OpenStackDataPlaneDeployment CR file:
    spec:
      ...
      nodeSets:
        - <node_set_name>
  10. Save the OpenStackDataPlaneDeployment CR deployment file.
  11. Deploy the modified OpenStackDataPlaneNodeSet CRs:
    $ oc create -f openstack_data_plane_deploy.yaml -n <namespace>

    You can view the Ansible logs while the deployment executes:

    $ oc get pod -l app=openstackansibleee -w
    $ oc logs -l app=openstackansibleee -f --max-log-requests 10

    If the oc logs command returns an error similar to the following error, increase the --max-log-requests value:

    error: you are attempting to follow 19 log streams, but maximum allowed concurrency is 10, use --max-log-requests to increase the limit
  12. Verify that the modified OpenStackDataPlaneNodeSet CRs are deployed:
    $ oc get openstackdataplanedeployment -n <namespace>
    NAME             	STATUS   MESSAGE
    openstack-data-plane   True     Setup Complete
    
    
    $ oc get openstackdataplanenodeset -n <namespace>
    NAME             	STATUS   MESSAGE
    openstack-data-plane   True     NodeSet Ready

    For information about the meaning of the returned status, see Data plane conditions and states .

    If the status indicates that the data plane has not been deployed, then troubleshoot the deployment. For information, see Troubleshoot data plane creation and deployment .

Apply custom certificates to public service endpoints

Apply signed certificates from your own certificate authority (CA) to public service endpoints to replace automatically generated route certificates and meet your organization’s security requirements.

Before you begin

  • You have a list of each of the public services for which to apply your custom service certificates. You can get this list using the oc route list -n openstack command. Use this information for the number of certificates you must create, the DNS names for those certificates, and finding the relevant services to edit in the openstack_control_plane.yaml custom resource (CR).
  • You have a service certificate for the public services.

Procedure

  1. Create a manifest file called cacerts.yaml that includes all CA certificates. Include all certificates in chains of trust if applicable:
    apiVersion: v1
    kind: Secret
    metadata:
      name: cacerts
      namespace: openstack
    type: Opaque
    data:
      myBundleExample: <cat mybundle.pem | base64 -w0>
      CACertExample: <cat cacert.pem | base64 -w0>

    where:

    mybundle.pem
    Specifies the name of your certificate or certificate bundle. The results are pasted as the value of the myBundleExample field.
    cacert.pem
    Specifies the name of your CA certificate.
  2. Create the secret from the manifest file:
    $ oc apply -f cacerts.yaml
  3. Create a manifest file for each secret named api_certificate_<service>_secret.yaml:
    apiVersion: v1
    kind: Secret
    metadata:
      name: api_certificate_<service>_secret
      namespace: openstack
    type: kubernetes.io/tls
    data:
      tls.crt: <cat tlscrt.pem | base64 -w0>
      tls.key: <cat tlskey.pem | base64 -w0>
      ca.crt: <cat cacrt.pem | base64 -w0>

    where:

    <service>
    Specifies the name of the service that this secret is for.
    tlscrt.pem
    Specifies the name of your signed certificate.
    tlskey.pem
    Specifies the name of your private key.
    cacrt.pem
    Specifies the name of your CA certificate.
  4. Create the secret
    $ oc apply -f api_certificate_<service>_secret.yaml
  5. Edit the openstack_control_plane.yaml custom resource and add your bundle as the parameter for caBundleSecretName:
    apiVersion: core.openstack.org/v1beta1
    kind: OpenStackControlPlane
    metadata:
      name: myctlplane
    spec:
      tls:
        podLevel:
          enabled: true
        caBundleSecretName: cacerts
  6. Apply the secret service certificates to each of the public services under the apiOverride field. For example enter the following for the Identity service (keystone):
    apiVersion: core.openstack.org/v1beta1
    kind: OpenStackControlPlane
    metadata:
      name: myctlplane
      namespace: openstack
    spec:
      ...
      keystone:
        apiOverride:
          tls:
            secretName: api_certificate_keystone_secret

    The edits for the Compute service (nova) and noVNCProxy appear as the following:

    apiVersion: core.openstack.org/v1beta1
    kind: OpenStackControlPlane
    metadata:
      name: myctlplane
      namespace: openstack
    spec:
    ...
      nova:
        apiOverride:
          tls:
            secretName: api_certificate_nova_secret
          route: {}
        cellOverride:
          cell1:
            noVNCProxy:
              tls:
                secretName: api_certificate_novavncproxy_secret

    The edits for the Image service (Glance) appear as the following:

    apiVersion: core.openstack.org/v1beta1
    kind: OpenStackControlPlane
    metadata:
      name: myctlplane
      namespace: openstack
    spec:
    ...
      glance:
        apiOverrides:
          defaultAPI1:
            tls:
              secretName: api_certificate_glance_secret
            route: {}
          defaultAPI2:
            tls:
              secretName: api_certificate_glance_secret
            route: {}
        template:
          glanceAPIs:
            defaultAPI1:
              replicas: 3
        ...
            defaultAPI2:
              replicas: 1
        ...
  7. Apply the control plane changes
    $ oc apply -f openstack_control_plane.yaml

Update the control plane with a single custom certificate

Apply a single shared certificate from your own certificate authority (CA) to all public service endpoints to simplify certificate management and replace the automatically generated route certificates.

Before you begin

  • You have a list of each of the public services for which to apply your custom service certificate. You can get this list by using the oc route list -n openstack command. Use this information for the DNS names for the certificate, and for finding the relevant services to edit in the openstack_control_plane.yaml custom resource (CR).

Procedure

  1. Create a signed certificate that includes the hostname for every service in the alt_names section:
    [alt_names]
    DNS.1 = barbican-public-openstack.apps.ocp.openstack.lab
    DNS.2 = cinder-public-openstack.apps.ocp.openstack.lab
    DNS.3 = glance-default-public-openstack.apps.ocp.openstack.lab
    DNS.4 = horizon-openstack.apps.ocp.openstack.lab
    DNS.5 = keystone-public-openstack.apps.ocp.openstack.lab
    DNS.6 = manila-public-openstack.apps.ocp.openstack.lab
    DNS.7 = neutron-public-openstack.apps.ocp.openstack.lab
    DNS.8 = nova-novncproxy-cell1-public-openstack.apps.ocp.openstack.lab
    DNS.9 = nova-public-openstack.apps.ocp.openstack.lab
    DNS.10 = placement-public-openstack.apps.ocp.openstack.lab
  2. Create a manifest file called cacerts.yaml that includes all CA certificates. Include all certificates in chains of trust if applicable:
    apiVersion: v1
    kind: Secret
    metadata:
      name: cacerts
      namespace: openstack
    type: Opaque
    data:
      myBundleExample: <cat mybundle.pem | base64 -w0>
      CACertExample: <cat cacert.pem | base64 -w0>

    where:

    mybundle.pem
    Specifies the name of your certificate or certificate bundle. The results are pasted as the value of the myBundleExample field.
    cacert.pem
    Specifies the name of your CA certificate.
  3. Create the secret from the manifest file:
    $ oc apply -f cacerts.yaml
  4. Create a manifest file for a secret named certificate-secret.yaml:
    apiVersion: v1
    kind: Secret
    metadata:
      name: certificate-secret
      namespace: openstack
    type: kubernetes.io/tls
    data:
      tls.crt: <cat tlscrt.pem | base64 -w0>
      tls.key: <cat tlskey.pem | base64 -w0>
      ca.crt: <cat cacrt.pem | base64 -w0>

    where:

    tlscrt.pem
    Specifies the name of your signed certificate.
    tlskey.pem
    Specifies the name of your private key.
    cacrt.pem
    Specifies the name of your CA certificate.
  5. Create the secret
    $ oc apply -f certificate-secret.yaml
  6. Edit the openstack_control_plane.yaml custom resource and add your bundle as the parameter for caBundleSecretName:
    apiVersion: core.openstack.org/v1beta1
    kind: OpenStackControlPlane
    metadata:
      name: myctlplane
    spec:
      tls:
        podLevel:
          enabled: true
        caBundleSecretName: cacerts
  7. Apply the secret service certificates to each of the public services under the apiOverride field. For example, enter the following for the Identity service (keystone):
    apiVersion: core.openstack.org/v1beta1
    kind: OpenStackControlPlane
    metadata:
      name: myctlplane
      namespace: openstack
    spec:
      ...
      keystone:
        apiOverride:
          tls:
            secretName: certificate-secret

    The edits for the Compute service (nova) and noVNCProxy appear as the following:

    apiVersion: core.openstack.org/v1beta1
    kind: OpenStackControlPlane
    metadata:
      name: myctlplane
      namespace: openstack
    spec:
    ...
      nova:
        apiOverride:
          tls:
            secretName: certificate-secret
          route: {}
        cellOverride:
          cell1:
            noVNCProxy:
              tls:
                secretName: certificate-secret

    The edits for the Image service (Glance) appear as the following:

    apiVersion: core.openstack.org/v1beta1
    kind: OpenStackControlPlane
    metadata:
      name: myctlplane
      namespace: openstack
    spec:
    ...
      glance:
        apiOverrides:
          defaultAPI1:
            tls:
              secretName: api_certificate_glance_secret
            route: {}
          defaultAPI2:
            tls:
              secretName: api_certificate_glance_secret
            route: {}
        template:
          glanceAPIs:
            defaultAPI1:
              replicas: 3
        ...
            defaultAPI2:
              replicas: 1
        ...
  8. Apply the control plane changes:
    $ oc apply -f openstack_control_plane.yaml

Use your CA certificates on remote clients

Configure remote clients to trust the certificate authority (CA) used by your deployment so that OpenStack CLI commands authenticate securely without SSL verification errors.

Before you begin

  • You have deployed RHOSO with default certificates, or have used custom certificates that are not signed by a public certificate authority.

Procedure

  1. Log on to OpenShift with global administrative permissions.
  2. Extract the CA certificate ca.crt for the public endpoints from the rootca-public secret.
    $ oc get secret rootca-public -o json | jq -r '.data."ca.crt"' | base64 -d > ca.crt
  3. Transfer the ca.crt file to the client that accesses the OpenStack API.
  4. Update your authentication file with the path to ca.crt.
    1. If you use a clouds.yml authentication file, add the cacert parameter:
      clouds:
          secure:
              cacert: </path/to/ca.crt>

      where:

      </path/to/ca.crt>
      Specifies the absolute path and name of the CA cert on your system.
    2. If you use a resource credentials file, update the file with the exported OS_CACERT variable:
      $ export OS_CACERT=</path/to/ca.crt>