Configuring security services


Red Hat OpenStack Services on OpenShift 18.0

Configuring the security features for Red Hat OpenStack Services on OpenShift

OpenStack Documentation Team

Abstract

Customize security features for Red Hat OpenStack Services on OpenShift based on the requirements of your environment.

Providing feedback on Red Hat documentation

We appreciate your input on our documentation. Tell us how we can make it better.

Use the Create Issue form to provide feedback on the documentation for Red Hat OpenStack Services on OpenShift (RHOSO) or earlier releases of Red Hat OpenStack Platform (RHOSP). When you create an issue for RHOSO or RHOSP documents, the issue is recorded in the RHOSO Jira project, where you can track the progress of your feedback.

To complete the Create Issue form, ensure that you are logged in to Jira. If you do not have a Red Hat Jira account, you can create an account at https://issues.redhat.com.

  1. Click the following link to open a Create Issue page: Create Issue
  2. Complete the Summary and Description fields. In the Description field, include the documentation URL, chapter or section number, and a detailed description of the issue. Do not modify any other fields in the form.
  3. Click Create.

Chapter 1. Scheduling fernet key rotation

For security purposes, the fernet keys in your Red Hat OpenStack Services on OpenShift (RHOSO) environment are automatically rotated. To meet the unique security requirements of your environment, you can modify the frequency with which fernet key rotations occur as well as the number of old decryption keys kept after each rotation.

1.1. Updating fernet key rotation frequency

As of Red Hat OpenStack Services on OpenShift (RHOSO), you can update the frequency with which the Identity service (keystone) rotates its fernet keys.

Procedure

  1. Edit the OpenStackControlPlane custom resource (CR) for editing:

    oc edit openstackcontrolplane openstack-control-plane
    Copy to Clipboard Toggle word wrap
  2. Under the properties field under the Identity service (keystone) configuration, add the following:

                  fernetMaxActiveKeys:
                    default: <active_keys>
                    description: FernetMaxActiveKeys - Maximum number of fernet token
                      keys after rotation
                    type: int
                  fernetRotationDays:
                    default: <days>
    Copy to Clipboard Toggle word wrap
    • Replace <active_keys> with the number of keys to keep active. The default is 5.
    • Replace <days> with the frequency with which to rotate your fernet keys.

When you deploy Red Hat OpenStack Services on OpenShift (RHOSO), TLS-e (TLS everywhere) is enabled by default. TLS is handled by cert-manager, which applies both ingress (public) encryption, as well as reencryption to each pod. Currently, disabling TLS on RHOSO is not supported.

When you deploy Red Hat OpenStack Services on OpenShift (RHOSO), most API connections are protected by TLS.

Note

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

You might be required to protect public APIs using your own internal certificate authority. In order 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 certificate authority (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 certificate authority (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 using the following 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 in the event of a route hostname change.

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 is the default TLS settings that are used if not annotated and changed:

apiVersion: core.openstack.org/v1beta1
kind: OpenStackControlPlane
metadata:
  name: myctlplane
spec:
  tls:
    default:
      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
Copy to Clipboard Toggle word wrap

You might be required to protect public APIs by using your own internal certificate authority (CA). To replace the automatically generated route certificates with common signed certificates from your CA, you must create a secret that contains your additional CA certificate, and all certificates in the chain of trust.

Prerequisites

  • 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, as well as 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> 
    1
    
      CACertExample: <cat cacert.pem | base64 -w0>     
    2
    Copy to Clipboard Toggle word wrap
    1
    Run this command, replacing mybundle.pem with the name of your certificate or certificate bundle. The results are pasted as the value of the myBundleExample field.
    2
    Run this command, replacing cacert.pem with the name of your CA certificate.
  2. Create the secret from the manifest file:

    oc apply -f cacerts.yaml
    Copy to Clipboard Toggle word wrap
  3. Create a manifest file for each secret named api_certificate_<service>_secret.yaml:

    apiVersion: v1
    kind: Secret
    metadata:
      name: api_certificate_<service>_secret 
    1
    
      namespace: openstack
    type: kubernetes.io/tls
    data:
      tls.crt: <cat tlscrt.pem | base64 -w0> 
    2
    
      tls.key: <cat tlskey.pem | base64 -w0> 
    3
    
      ca.crt: <cat cacrt.pem | base64 -w0>   
    4
    Copy to Clipboard Toggle word wrap
    1
    Replace <service> with the name of the service that this secret is for.
    2
    Run this command, replacing tlscrt.pem with the name of your signed certificate.
    3
    Run this command, replacing tlskey.pem with the name of your private key.
    4
    Run this command, replacing cacrt.pem with the name of your CA certificate.
  4. Create the secret

    oc apply -f api_certificate_<service>_secret.yaml
    Copy to Clipboard Toggle word wrap
  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
    Copy to Clipboard Toggle word wrap
  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
    Copy to Clipboard Toggle word wrap

    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
    Copy to Clipboard Toggle word wrap
  7. Apply the control plane changes

    oc apply -f openstack_control_plane.yaml
    Copy to Clipboard Toggle word wrap

You might be required to protect public APIs by using your own internal certificate authority (CA). To replace the automatically generated route certificates with a common signed certificate from your CA, you must create a secret that contains your CA certificate, and all certificates in the chain of trust.

Prerequisites

  • 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, as well as 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
    Copy to Clipboard Toggle word wrap
  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> 
    1
    
      CACertExample: <cat cacert.pem | base64 -w0>     
    2
    Copy to Clipboard Toggle word wrap
    1
    Run this command, replacing mybundle.pem with the name of your certificate or certificate bundle. The results are pasted as the value of the myBundleExample field.
    2
    Run this command, replacing cacert.pem with the name of your CA certificate.
  3. Create the secret from the manifest file:

    oc apply -f cacerts.yaml
    Copy to Clipboard Toggle word wrap
  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> 
    1
    
      tls.key: <cat tlskey.pem | base64 -w0> 
    2
    
      ca.crt: <cat cacrt.pem | base64 -w0>   
    3
    Copy to Clipboard Toggle word wrap
    1
    Run this command, replacing tlscrt.pem with the name of your signed certificate.
    2
    Run this command, replacing tlskey.pem with the name of your private key.
    3
    Run this command, replacing cacrt.pem with the name of your CA certificate.
  5. Create the secret

    oc apply -f certificate-secret.yaml
    Copy to Clipboard Toggle word wrap
  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
    Copy to Clipboard Toggle word wrap
  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
    Copy to Clipboard Toggle word wrap

    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
    Copy to Clipboard Toggle word wrap
  8. Apply the control plane changes

    oc apply -f openstack_control_plane.yaml
    Copy to Clipboard Toggle word wrap

2.4. Using your CA certs on remote clients

If you do not use a trusted CA from a public entity, openstack client commands fail with an SSL verification error, requiring the --insecure command option to succeed. You can securely communicate with OpenStack API using a private certificate authority using the following steps.

Prerequisites

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

Procedure

  1. Log onto OpenShift with global administrative permissions.
  2. Extract the ca cert 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
    Copy to Clipboard Toggle word wrap
  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>
      Copy to Clipboard Toggle word wrap
      • Replace </path/to/ca.crt> with 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 CACERT variable:

      export OC_CACERT=</path/to/ca.crt>
      Copy to Clipboard Toggle word wrap
      • Replace </path/to/ca.crt> with the absolute path and name of the CA cert on your system.

Chapter 3. Custom issuers for cert-manager

An issuer is a resource that acts as a certificate authority for a specific namespace, and is managed by the cert-manager Operator. TLS-e (TLS everywhere) is enabled in Red Hat OpenStack Services on OpenShift (RHOSO) environments, and it uses the following issuers by default:

  • rootca-internal
  • rootca-libvirt
  • rootca-ovn
  • rootca-public

3.1. Creating a custom issuer

You can create custom ingress as well as custom internal issuers. To create and manage your own certificates for internal endpoints, you must create a custom internal issuer.

Procedure

  1. Create a custom issuer in a file named rootca-custom.yaml:

    apiVersion: cert-manager.io/v1
    kind: Issuer
    metadata:
      name: <issuer_name>
    spec:
      ca:
        secretName: <secret_name>
    Copy to Clipboard Toggle word wrap
    • Replace <issuer_name> with the name of your custom issuer, for example, rootca-ingress-custom.
    • Replace <secret_name> with the name of the Secret CR used by the certificate for your custom issuer. If you do not include a secret, one is created automatically.
  2. Create a certificate in a file named ca-issuer-certificate.yaml:

    apiVersion: cert-manager.io/v1
    kind: Certificate
    metadata:
      name: <issuer_name>
    spec:
      commonName: <issuer_name>
      isCA: true
      duration: <hours>
      privateKey:
        algorithm: RSA
        size: 3072
      issuerRef:
        name: selfsigned-issuer
        kind: Issuer
      secretName: <secret-name>
    Copy to Clipboard Toggle word wrap
    • Replace <issuer_name> with the name of your custom issuer. This matches the issuer created in the first step.
    • Replace <hours> with the duration in hours, for example, a value of 87600h is equivalent to 3650 days, or about 10 years.
    • Replace <secret_name> with the name of the Secret CR used by the certificate for your custom issuer. If you do not include a secret, one is created automatically.
  3. Create the issuer and certificate:

    $ oc create -f rootca-custom.yaml
    $ oc create -f ca-issuer-certificate.yaml
    Copy to Clipboard Toggle word wrap
  4. Add the custom issuer to the TLS service definition in the control plane CR file.

    1. If your custom issuer is an ingress issuer, the customer issuer is defined under the ingress attribute as shown below:

      apiVersion: core.openstack.org/v1beta1
      kind: OpenStackControlPlane
      metadata:
        name: openstack-control-plane
      spec:
        tls:
           ingress:
             enabled: true
             ca:
               customIssuer: <issuer_name>
         ...
      Copy to Clipboard Toggle word wrap
      • Replace <issuer_name> with the name of your custom issuer. This matches the issuer created in the first step.
    2. If your custom issuer is an internal issuer, the custom issuer is defined at the pod level under the internal attribute as shown below:

      apiVersion: core.openstack.org/v1beta1
      kind: OpenStackControlPlane
      metadata:
        name: myctlplane
      spec:
        tls:
           ingress:
             enabled: true
           podLevel:
             enabled: true
             internal:
               ca:
                 customIssuer: <issuer_name>
      Copy to Clipboard Toggle word wrap
      • Replace <issuer_name> with the name of your custom issuer. This matches the issuer created in the first step.

TLS is enabled by default in Red Hat OpenStack Services on OpenShift (RHOSO) environments. If you disabled TLS when you deployed your RHOSO environment, or if you adopted your Red Hat OpenStack Platform 17.1 deployment to a RHOSO environment, then you can reenable TLS after deployment.

Important
  • Enabling TLS on a deployed RHOSO environment involves some data plane downtime when connectivity to Rabbitmq and OVS from the control plane is lost during the redeployment.

    • If your deployment uses the default configuration where no floating IP connectivity is directed through the control plane, then this downtime does not affect the workload hosted on the RHOSO environment.
    • If your deployment routes traffic through the control plane, then the downtime will impact the workload hosted on the RHOSO environment.
  • New workloads cannot be created and existing workloads cannot be managed with the OpenStack API while the control plane and data plane are being updated.

The following error messages are logged when the connectivity to Rabbitmq and OVS is lost from the control plane during the redeployment to enable TLS:

  • Extract from the nova-compute log:

    Aug 09 11:35:49 edpm-compute-0 nova_compute[105613]: 2024-08-09 11:35:49.037 2 ERROR oslo.messaging._drivers.impl_rabbit [-] [98752a36-cf06-4d26-aee8-f5b21bf55aef] AMQP server on rabbitmq-cell1.openstack.svc:5672 is unreachable: <RecoverableConnectionError: unknown error>. Trying again in 1 seconds.: amqp.exceptions.RecoverableConnectionError: <RecoverableConnectionError: unknown error>
    Aug 09 11:35:49 edpm-compute-0 nova_compute[105613]: 2024-08-09 11:35:49.566 2 ERROR oslo.messaging._drivers.impl_rabbit [-] [8c795961-cb17-4a6d-82ee-25c862316b40] AMQP server on rabbitmq-cell1.openstack.svc:5672 is unreachable: timed out. Trying again in 32 seconds.: socket.timeout: timed out
    Copy to Clipboard Toggle word wrap
  • Extract from the OVN controller log:

    ovn_controller[55433]: 2024-08-09T11:35:47Z|00452|reconnect|INFO|tcp:ovsdbserver-sb.openstack.svc:6642: connected Aug 09 11:35:47 edpm-compute-0
    ovn_controller[55433]: 2024-08-09T11:35:47Z|00453|jsonrpc|WARN|tcp:ovsdbserver-sb.openstack.svc:6642: error parsing stream: line 0, column 0, byte 0: invalid character U+0015 Aug 09 11:35:47 edpm-compute-0
    ovn_controller[55433]: 2024-08-09T11:35:47Z|00454|reconnect|WARN|tcp:ovsdbserver-sb.openstack.svc:6642: connection dropped (Protocol error)
    Copy to Clipboard Toggle word wrap

If TLS is disabled in your deployed Red Hat OpenStack Services on OpenShift (RHOSO) environment, you can reenable it on a operational RHOSO environment with minimal disruption.

Prerequisites

  • The RHOSO environment is deployed on a Red Hat OpenShift Container Platform (RHOCP) cluster. For more information, see Deploying Red Hat OpenStack Services on OpenShift.
  • You are logged on to a workstation that has access to the RHOCP cluster as a user with cluster-admin privileges.

Procedure

  1. Open your OpenStackControlPlane custom resource (CR) file, openstack_control_plane.yaml, on your workstation.
  2. Add the following tls configuration to the spec configuration, if not already present:

    spec:
      tls:
        ingress:
          ca:
            duration: 87600h0m0s
          cert:
            duration: 43800h0m0s
          enabled: true
        podLevel:
          enabled: true 
    1
    
          internal:
            ca:
              duration: 87600h0m0s
            cert:
              duration: 43800h0m0s
          libvirt:
            ca:
              duration: 87600h0m0s
            cert:
              duration: 43800h0m0s
          ovn:
            ca:
              duration: 87600h0m0s
            cert:
              duration: 43800h0m0s
    Copy to Clipboard Toggle word wrap
    1
    If the tls configuration is already present in the definition file, then ensure the`podLevel` is enabled.
  3. Update the control plane:

    $ oc apply -f openstack_control_plane.yaml -n <namespace>
    Copy to Clipboard Toggle word wrap
  4. The rabbitmq pods cannot change the TLS configuration on an operating environment, therefore you must delete the existing rabbitmq pods to update the control plane with the new rabbitmq pods that have TLS enabled:

    $ oc delete pod -n openstack -l app.kubernetes.io/component=rabbitmq
    Copy to Clipboard Toggle word wrap
  5. Wait for the control plane to be ready:

    $ oc wait openstackcontrolplane -n <namespace> --for=condition=Ready --timeout=400s -l core.openstack.org/openstackcontrolplane
    Copy to Clipboard Toggle word wrap

    While waiting for the control plane to be ready, new workloads cannot be created and existing workloads cannot be managed with the OpenStack API. The nova-compute service on the data plane nodes cannot connect to the cell1 rabbitmq and reports as down:

    $ oc rsh openstackclient
    $ openstack compute service list -c Binary -c Host -c Status -c State
    +----------------+-------------------------------------+---------+-------+
    | Binary         | Host                                | Status  | State |
    +----------------+-------------------------------------+---------+-------+
    | nova-conductor | nova-cell0-conductor-0              | enabled | up    |
    | nova-scheduler | nova-scheduler-0                    | enabled | up    |
    | nova-conductor | nova-cell1-conductor-0              | enabled | up    |
    | nova-compute   | edpm-compute-0.ctlplane.example.com | enabled | down  |
    | nova-compute   | edpm-compute-1.ctlplane.example.com | enabled | down  |
    +----------------+-------------------------------------+---------+-------+
    Copy to Clipboard Toggle word wrap

    The OVN controller and the OVN metadata agent cannot connect to the southbound database:

    $ openstack network agent list -c 'Agent Type' -c Host -c Alive -c State
    +------------------------------+-------------------------------------+-------+-------+
    | Agent Type                   | Host                                | Alive | State |
    +------------------------------+-------------------------------------+-------+-------+
    | OVN Controller Gateway agent | crc                                 | :-)   | UP    |
    | OVN Controller agent         | edpm-compute-1.ctlplane.example.com | XXX   | UP    |
    | OVN Metadata agent           | edpm-compute-1.ctlplane.example.com | XXX   | UP    |
    | OVN Controller agent         | edpm-compute-0.ctlplane.example.com | XXX   | UP    |
    | OVN Metadata agent           | edpm-compute-0.ctlplane.example.com | XXX   | UP    |
    +------------------------------+-------------------------------------+-------+-------+
    Copy to Clipboard Toggle word wrap
    Note

    The existing workload is not impacted if workload traffic is not routed through the control plane.

  6. Open the OpenStackDataPlaneNodeSet CR definition 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
    Copy to Clipboard Toggle word wrap
  7. Save the updated OpenStackDataPlaneNodeSet CR definition files and apply the updates:

    $ oc apply -f openstack_data_plane.yaml -n <namespace>
    Copy to Clipboard Toggle word wrap
  8. Check that TLS is enabled on each node set:

    $ oc get openstackdataplanenodeset <node_set_name> -n <namespace> -o json | jq .items[0].spec.tlsEnabled
    true
    Copy to Clipboard Toggle word wrap
  9. Create a file on your workstation to define the OpenStackDataPlaneDeployment CR:

    apiVersion: dataplane.openstack.org/v1beta1
    kind: OpenStackDataPlaneDeployment
    metadata:
      name: <node_set_deployment_name>
    Copy to Clipboard Toggle word wrap
    • Replace <node_set_deployment_name> with the name of the OpenStackDataPlaneDeployment CR. The name must be unique, must consist of lower case alphanumeric characters, - (hyphen) or . (period), and must start and end with an alphanumeric character.
    Tip

    Give the definition file and the OpenStackDataPlaneDeployment CR unique and descriptive names that indicate the purpose of the modified node set.

  10. Add the OpenStackDataPlaneNodeSet CRs that you modified to enable TLS:

    spec:
      nodeSets:
        - <nodeSet_name>
    Copy to Clipboard Toggle word wrap
  11. Save the OpenStackDataPlaneDeployment CR deployment file.
  12. Deploy the modified OpenStackDataPlaneNodeSet CRs:

    $ oc create -f openstack_data_plane_deploy.yaml -n <namespace>
    Copy to Clipboard Toggle word wrap

    You can view the Ansible logs while the deployment executes:

    $ oc get pod -l app=openstackansibleee -n <namespace> -w
    $ oc logs -l app=openstackansibleee -f --max-log-requests 10 -n <namespace>
    Copy to Clipboard Toggle word wrap

    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
    Copy to Clipboard Toggle word wrap
  13. 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
    Copy to Clipboard Toggle word wrap

    For information about the returned status, see Data plane conditions and states in the Deploying Red Hat OpenStack Services on OpenShift guide.

    If the status indicates that the data plane has not been deployed, then troubleshoot the deployment. For information, see Troubleshooting the data plane creation and deployment in the Deploying Red Hat OpenStack Services on OpenShift guide.

  14. Verify that the nova-compute service is connected again to TLS rabbitmq:

    $ oc rsh openstackclient
    $ openstack compute service list -c Binary -c Host -c Status -c State
    +----------------+-------------------------------------+---------+-------+
    | Binary         | Host                                | Status  | State |
    +----------------+-------------------------------------+---------+-------+
    | nova-conductor | nova-cell0-conductor-0              | enabled | up    |
    | nova-scheduler | nova-scheduler-0                    | enabled | up    |
    | nova-conductor | nova-cell1-conductor-0              | enabled | up    |
    | nova-compute   | edpm-compute-0.ctlplane.example.com | enabled | up    |
    | nova-compute   | edpm-compute-1.ctlplane.example.com | enabled | up    |
    +----------------+-------------------------------------+---------+-------+
    Copy to Clipboard Toggle word wrap
  15. Verify that the OVN agents are running again:

    $ openstack network agent list -c 'Agent Type' -c Host -c Alive -c State
    +------------------------------+-------------------------------------+-------+-------+
    | Agent Type                   | Host                                | Alive | State |
    +------------------------------+-------------------------------------+-------+-------+
    | OVN Controller Gateway agent | crc                                 | :-)   | UP    |
    | OVN Controller agent         | edpm-compute-1.ctlplane.example.com | :-)   | UP    |
    | OVN Metadata agent           | edpm-compute-1.ctlplane.example.com | :-)   | UP    |
    | OVN Controller agent         | edpm-compute-0.ctlplane.example.com | :-)   | UP    |
    | OVN Metadata agent           | edpm-compute-0.ctlplane.example.com | :-)   | UP    |
    +------------------------------+-------------------------------------+-------+-------+
    Copy to Clipboard Toggle word wrap

4.3. Deploying RHOSO with TLS disabled

TLS is enabled, by default, when you deploy Red Hat OpenStack Services on OpenShift (RHOSO). But you can disable TLS, if you need to.

Note

You can re-enable TLS on a operational RHOSO environment with minimal disruption.

Procedure

  1. Open your OpenStackControlPlane custom resource (CR) file, openstack_control_plane.yaml, on your workstation.
  2. Add the following tls configuration to the spec configuration, if not already present:

    spec:
      tls:
        ingress:
          enabled: false
        podLevel:
          enabled: false
    Copy to Clipboard Toggle word wrap
  3. Update the control plane:

    $ oc apply -f openstack_control_plane.yaml -n openstack
    Copy to Clipboard Toggle word wrap
  4. Open the OpenStackDataPlaneNodeSet CR file for each node on the data plane, and disable TLS by setting spec.tlsEnabled to false:

    apiVersion: dataplane.openstack.org/v1beta1
    kind: OpenStackDataPlaneNodeSet
    metadata:
      name: <node_set_name>
      namespace: openstack
    spec:
      tlsEnabled: false
    Copy to Clipboard Toggle word wrap
    • Replace <node_set_name> with the name of the OpenStackDataPlaneNodeSet CR that the node belongs to.
  5. Save the updated OpenStackDataPlaneNodeSet CR files and apply the updates:

    $ oc apply -f openstack_data_plane.yaml -n openstack
    Copy to Clipboard Toggle word wrap
  6. Verify that TLS is disabled on every node set:

    $ oc get openstackdataplanenodeset <node_set_name> -n openstack -o json | jq .items[0].spec.tlsEnabled
    Copy to Clipboard Toggle word wrap

Chapter 5. Configuring LDAP on RHOSO

To connect Red Hat OpenStack Services on OpenShift to LDAP so that your OpenStack users authenticate by using pre-established LDAP identities, do the following:

  1. Use the OpenStack CLI to create the domain.
  2. Use RHOSO to create a secret that contains the required configuration.
  3. Mount the secret to the service by using the OpenStackControlPlane custom resource file.

5.1. Configuring LDAP by using Red Hat Identity

Use the OpenStack CLI or the OpenStack Dashboard (horizon) to create OpenStack domains.

Prerequisites

  • A pre-established Red Hat Identity server.

Procedure

  1. Create an OpenStack domain:

    $ openstack domain create <name>
    Copy to Clipboard Toggle word wrap
    • Replace <name> with the name of your OpenStack domain.
  2. Create a keystone-domains secret called keystone-domains.yaml. This secret is mounted into the /etc/keystone/domains configuration directory:

    apiVersion: v1
    kind: Secret
    metadata:
      name: keystone-domains
      namespace: openstack
    type: Opaque
    stringData:
        keystone.<domain_name>.conf: |
            [identity]
            driver = ldap
            [ldap]
            url = ldaps://localhost
            user = =openstack,ou=Users,dc=director,dc=example,dc=com
            password = RedactedComplexPassword
            suffix = dc=domain,dc=example,dc=com
            user_tree_dn = ou=Users,dc=domain,dc=example,dc=com
            user_objectclass = person
            group_tree_dn = ou=Groups,dc=example,dc=org
            group_objectclass = groupOfNames
            use_tls = True
    Copy to Clipboard Toggle word wrap
  3. Create the secret:

    $ oc apply -f keystone-domain-name.yaml
    Copy to Clipboard Toggle word wrap
  4. Open your OpenStackCustomResource custom resource (CR) file and add the secret by using the extraMounts field:

    apiVersion: core.openstack.org/v1beta1
    kind: OpenStackControlPlane
    metadata:
      name: openstack
    spec:
      keystone:
        template:
          customServiceConfig: |
            [identity]
            domain_specific_drivers_enabled = True
          extraMounts:
          - name: v1
            region: r1
              extraVol:
                - propagation:
                  - Keystone
                  extraVolType: Conf
                  volumes:
                  - name: keystone-domains
                    secret:
                      secretName: keystone-domains
                  mounts:
                  - name: keystone-domains
                    mountPath: "/etc/keystone/domains"
                    readOnly: true
    Copy to Clipboard Toggle word wrap
  5. Apply the changes to your OpenStack control plane CR:

    $ oc apply -f openstackcontrolplane
    Copy to Clipboard Toggle word wrap

When you install Red Hat OpenStack Services on OpenShift (RHOSO), you have the option of using the Key Manager service with either a default SimpleCrypto back end, or using it with a Luna hardware security module (HSM). Using a hardware security module provides hardened protection for storing keys.

When you use a Luna HSM, the Key Manager service communicates with the Luna HSM by using a PKCS #11 interface to load libraries provided by Thales. To integrate your RHOSO deployment with a Luna HSM, you must complete the following steps:

Build a new image for the Key Manager service that integrates required Thales software. You must repeat this step when you update RHOSO.

Creating an ansible playbook to build this image simplifies the process of configuring RHOSO for your Luna HSM. The ansible-role-rhoso-luna-hsm RPM, which is part of the RHOSO repository, contains roles that are required for this playbook.

The following playbook automates downloading the barbican-api and barbican-worker images from the Red Hat source repository, adding the Luna client software, and storing the resulting image in your destination repository.

The following steps are run from any system from which you can execute Ansible playbooks.

Prerequisites

Procedure

  1. Use DNF to install ansible-role-rhoso-luna-hsm:

    $ sudo dnf -y install ansible-role-rhoso-luna-hsm
    Copy to Clipboard Toggle word wrap
  2. Place the Luna minimal client image for Linux in a known location. In this procedure, the image is placed in /opt/luna.
  3. Move a copy of the Luna minimal client for Linux tarball to /opt/luna:

    $ mv <LunaClinet-Minimal-10.7.2.x86_64.tar> /opt/luna
    Copy to Clipboard Toggle word wrap
    • Replace <LunaClinet-Minimal-10.7.2.x86_64.tar> with the name of your Luna Minimal client for Linux tarball.
  4. Create a playbook called custom-image.yaml that creates the custom Key Manager image:

    ---
    - name: Create and upload the custom Key Manager image
      ansible.builtin.include_role:
        name: rhoso_luna_hsm
        tasks_from: create_image
      vars:
        barbican_src_image_registry: "quay.io:5001"
        barbican_src_image_namespace: "openstack-k8s-operators"
        barbican_src_image_tag: "latest"
        barbican_dest_image_registry: "<my_registry_url>:5001" 
    1
    
        barbican_dest_image_namespace: "openstack-k8s-operators"
        barbican_dest_image_tag: "luna-custom"
        image_registry_verify_tls: "<true|false>" 
    2
    
        luna_minclient_src: "file:///opt/luna/<filename>" 
    3
    
    ---
    Copy to Clipboard Toggle word wrap
    1
    Replace <my_registry_url> with the URL for your registry.
    2
    Replace <true|false> with either true or false based on the requirements of your image registry.
    3
    Replace <filename> with the name of your source image, for example: LunaClinet-Minimal-10.7.2.x86_64.tar
  5. Run the playbook:

    $ ansible-playbook custom-image.yaml
    Copy to Clipboard Toggle word wrap

6.2. Creating secrets for the Key Manager service

The following steps use keys, certificates, and configuration for your Luna HSM to create two secrets. One is called login_secret, which contains your HSM partition password. The other secret is called luna_data_secret, and it contains your certificates, keys, and chrystoki.conf configuration file. These secrets are required in your Red Hat OpenShift Container Platform environment to enable secure communication between the Key Manager service and your HSM. You create an Ansible playbook to identify the client certs to be copied in.

Prerequisites

  • The client cert for your Luna HSM. For more information see Comparing NTLS and STC.
  • You must disable ntls ipcheck on your Luna HSM, for more information see ntls ipcheck.

Procedure

  1. Place the Luna certificate and key into the /opt/luna directory tree:

    $ cp <luna_client_name>.pem /opt/luna
    $ cp <luna_client_name>Key.pem /opt/luna
    Copy to Clipboard Toggle word wrap
    • Replace <luna_client_name> with the name of your Luna certificate.
  2. Download the server certificate from the HSM device:

    $ scp -O <hsm-device.examle.com:server.pem> /opt/luna/
    Copy to Clipboard Toggle word wrap
  3. Optional: If you have more than one HSM for HA, get every cert from the HSM and concatenate them into a single file:

    $ scp -O <hsm-device-01.examle.com:server-01.pem> /opt/luna/
    $ scp -O <hsm-device-02.examle.com:server-02.pem> /opt/luna/
    $ cat /opt/luna/cert/server-01.pem > /opt/luna/CAFile.pem
    $ cat /opt/luna/cert/server-02.pem >> /opt/luna/CAFile.pem
    Copy to Clipboard Toggle word wrap
  4. Update your Crystoki.conf file to look similar to the following:

    Note

    The contents from the LunaClient-Minimal tarball is extracted to the /usr/local/luna/ directory in the Key Manager container. You must update the paths in your Crystoki.conf file to match this example.

    Chrystoki2 = {
      LibUNIX = /usr/local/luna/libs/64/libCryptoki2.so;
      LibUNIX64 = /usr/local/luna/libs/64/libCryptoki2.so;
    }
    
    Luna = {
      DefaultTimeOut = 500000;
      PEDTimeout1 = 100000;
      PEDTimeout2 = 200000;
      PEDTimeout3 = 10000;
      KeypairGenTimeOut = 2700000;
      CloningCommandTimeOut = 300000;
      CommandTimeOutPedSet = 720000;
    }
    
    CardReader = {
      RemoteCommand = 1;
    }
    
    Misc = {
      PE1746Enabled = 0;
      ToolsDir = ./bin/64;
      PartitionPolicyTemplatePath = ./ppt/partition_policy_templates;
      ProtectedAuthenticationPathFlagStatus = 0;
      MutexFolder = ./lock;
    }
    
    LunaSA Client = {
      ReceiveTimeout = 20000;
      SSLConfigFile = /usr/local/luna/openssl.cnf;
      ClientPrivKeyFile = /usr/local/luna/<luna_client_name>Key.pem;
      ClientCertFile = /usr/local/luna/<luna_client_name>.pem;
      ServerCAFile = /usr/local/luna/CAFile.pem;
      NetClient = 1;
      TCPKeepAlive = 1;
      ServerName00 = <ip_address>;
      ServerPort00 = 1792;
      ServerHtl00 = 0;
    }
    Copy to Clipboard Toggle word wrap
    • Replace <luna_client_name> with the name of your Luna certificate.
    • Replace <ip_address> with the IP address of your Luna HSM.
  5. Optional: If you are configuring HA, you must include additional entries for the IP addresses of each HSM, as well as configurations for the VirtualToken, HASynchronize, and HAConfigurations parameters:

    ...
      ServerName00 = <ip_address>;
      ServerPort00 = 1792;
      ServerHtl00 = 0;
      ServerName01 = <ip_address>;
      ServerPort01 = 1792;
      ServerHtl01 = 0;
    }
    
    VirtualToken = {
      VirtualToken00Label = myHAGroup;
      VirtualToken00SN = <virtual_token_sn>;
      VirtualToken00Members = <virtual_token_member>,<virtual_token_member>;
    }
    
    HASynchronize = {
      myHAGroup = 1;
    }
    
    HAConfiguration = {
      haLogStatus = enabled;
    }
    Copy to Clipboard Toggle word wrap
    • Replace <virtual_token_sn> with the serial number of your first partition prepended by a 1. For example, for partition 545000014, use a value of 1545000014
    • Replace <virtual_token_member> with the serial numbers of the partitions from the HSMs you are using.
  6. Move the chrystoki.conf configuration file to /opt/luna:

    $ mv chrystoki.conf /opt/luna
    Copy to Clipboard Toggle word wrap
  7. Create an Ansible playbook called create-luna-secrets.yaml to create the required secrets:

    ---
    - name: Create secrets with the HSM certs and hsm-login credentials
    ansible.builtin.include_role:
        name: rhoso_luna_hsm
        tasks_from: create_secrets
    vars:
        luna_client_name: <luna_client_name> 
    1
    
        chrystoki_conf_src: "/opt/luna/chrystoki.conf"
        luna_server_cert_src: "/opt/luna/<server.pem>" 
    2
    
        luna_client_cert_src: "/opt/luna/"
        luna_partition_password: "<my_partion_password>" 
    3
    
        kubeconfig_path: "<kubeconfig_path>" 
    4
    
        oc_dir: "<path_to_oc>" 
    5
    
        luna_data_secret: "luna_data_secret"
        login_secret: "login_secret"
    ---
    Copy to Clipboard Toggle word wrap
    1
    Replace <luna_client_name> with the name of your Luna certificate.
    2
    Replace <server.pem> with the name of your server certificate.
    3
    Replace <my_partion_password> with your HSM partition password.
    4
    Replace <kubeconfig_path> with the path to your .kube configuration file. For example: $HOME/.kube/config.
    5
    Replace <path_to_oc> with the output of which oc.
  8. Run the Ansible play book:

    ansible-playbook create-luna-secrets.yaml
    Copy to Clipboard Toggle word wrap

Change OpenStack version. The following procedure shows the OpenStackVersion custom resource (CR) that defines the custom container image.

Procedure

  1. Create a CR file with the following contents:

    apiVersion: core.openstack.org/v1beta1
    kind: OpenStackVersion
    metadata:
      name: openstack-galera-network-isolation
      namespace: openstack
    spec:
      customContainerImages:
          barbicanAPIImage: <api_image> 
    1
    
          barbicanWorkerImage: <worker_image> 
    2
    Copy to Clipboard Toggle word wrap
    1
    Replace <api_image> with the registry and path to the custom barbicanAPIImage.
    2
    Replace <worker_image> with the registry and path to the custom barbicanWorkerImage.
  2. Apply the OpenStackVersion CR:

    $ oc apply -f <filename>
    Copy to Clipboard Toggle word wrap

You must modify the Key Manager (barbican) service section of the OpenStackControl custom resource (CR) to fully integrate your Luna HSM with Red Hat OpenStack Services on OpenShift (RHOSO).

Procedure

  1. Configure the OpenStackControlPlane CR:

    1. Optional: If you have saved secrets that are using RHOSO Key Manager simple_crypto, keep those secrets available by enabling multiple back ends:

      …
      spec:
        barbican:
          apiOverride:
            route: {}
          enabled: true
          template:
            globalDefaultSecretStore: pkcs11
            enabledSecretStores:
              - pkcs11
              - simple_crypto
      Copy to Clipboard Toggle word wrap
    2. Configure the Key Manager service for use with the Luna HSM:

      spec:
        barbican:
          apiOverride:
            route: {}
          enabled: true
          template:
            globalDefaultSecretStore: pkcs11
            enabledSecretStores:
              - pkcs11
              - simple_crypto
            apiTimeout: 90
            barbicanAPI:
              apiTimeout: 0
              customServiceConfig: |
                [secretstore:pkcs11]
                secret_store_plugin = store_crypto
                crypto_plugin = p11_crypto
                [p11_crypto_plugin]
                plugin_name = PKCS11
                library_path = /usr/local/luna/lib/libCryptoki2.so
                token_serial_number = <serial_number> 
      1
      
                mkek_label = <mkek_label> 
      2
      
                hmac_label = <hmac_label> 
      3
      
                encryption_mechanism = CKM_AES_GCM
                aes_gcm_generate_iv = true
                hmac_key_type = CKK_GENERIC_SECRET
                hmac_keygen_mechanism = CKM_GENERIC_SECRET_KEY_GEN
                hmac_keywrap_mechanism = CKM_AES_KEY_WRAP_KWP
                key_wrap_mechanism = true
                key_wrap_generate_iv = true
                always_set_cka_sensitive = true
                os_locking_ok = false
              pkcs11:
                loginSecret: "login_secret"
                clientDataSecret: "luna_data_secret"
                clientDataPath: /usr/local/luna/config
      Copy to Clipboard Toggle word wrap
      1
      Replace <serial_number> with the token serial number of your HSM. If you are using HA, you must replace <serial_number> with the virtual token serial number. For more information, see Creating secrets for the Key Manager service.
      2
      Replace <mkek_label> with a user-defined label. If you have already defined this label, you must use the same one.
      3
      Replace <hmac_label> with a user-defined label. If you have already set this up, you must use the same label.
      Note

      Use one of the following options to identify the HSM that you can use. These options are mutually exclusive and have the following order of precedence:

      Expand

      Parameter

      Value

      Precedence

      token_serial_number

      <serial_number>

      1 - Highest

      token_labels

      Comma delimited lists

      2 - Middle

      slot-id

      <slot_id>

      3 - Lowest

  2. Deploy the OpenStackControlPlane CR:

    $ oc apply -f openstack_control_plane.yaml
    Copy to Clipboard Toggle word wrap

When you install Red Hat OpenStack Services on OpenShift (RHOSO), you have the option of using the Key Manager (barbican) service with either a default SimpleCrypto back end, or using it with a hardware security module (HSM). Using a hardware security module provides hardened protection for storing keys.

When you use a Trustway HSM, the Key Manager service communicates with the Trustway HSM by using a PKCS #11 interface to load libraries provided by Eviden. To integrate your RHOSO deployment with a Proteccio HSM, you must complete the following steps:

The following table details the versions of software tested by Red Hat.

Expand
SoftwareVersion

cryptoki

2.20

CRYPTO

167

Firmware

147, 167

FPGA

-1596587865

library

3.17

MCS

65539

Build a new image for the Key Manager service that integrates the required Proteccio software. You must repeat this step when you update RHOSO. Creating an ansible playbook to build this image simplifies the process of configuring RHOSO for your Trustway HSM. The ansible-role-rhoso-Trustway-hsm RPM, which is part of the RHOSO repository, contains roles that are required for this playbook. The following playbook automates required tasks for configuring the Trustway HSM back end to work with the RHOSO Key Manager service:

  • Downloads the barbican-api and barbican-worker images from the Red Hat source repository
  • Adds the Trustway client software, to the images
  • Stores the resulting images in your destination repository
  • Creates OpenShift secrets for the Key Manager service

The playbook uses keys, certificates, and configuration for your Trustway HSM to create two secrets. One is called login_secret, which contains your HSM password or PIN. The other secret is called proteccio_data_secret, and it contains your certificates, keys, and the proteccio.rc configuration file. These secrets are required in your Red Hat OpenShift Container Platform (RHOCP) environment to enable secure communication between the Key Manager service and your HSM. You can use an Ansible playbook to identify the client certificates to be copied in.

Prerequisites

  • The Trustway client image for Linux. For information about obtaining this software, contact Eviden.
  • An available image service, such as an internally available Quay service, or an account with quay.io. For more information, see Deploying the Red Hat Quay Operator on OpenShift Container Platform.
  • The client certificate and the key for your Trustway HSM.
  • The Trustway HSM certificate file.
  • You are running commands on a workstation on which you can run Ansible playbooks.

Procedure

  1. Use DNF to install ansible-role-rhoso-proteccio-hsm:

    $ sudo dnf -y install ansible-role-rhoso-proteccio-hsm
    Copy to Clipboard Toggle word wrap
  2. Place the Trustway client image for Linux, as well as the client cert and the client key into the /opt/proteccio directory tree.

    $ cp <trustway_client_cert>.crt /opt/proteccio
    $ cp <Trustway_client_key>.key /opt/proteccio
    $ cp  <Proteccio3.06.05.iso> /opt/proteccio
    Copy to Clipboard Toggle word wrap
    • Replace <trustway_client_cert> with the file name of your client certificate.
    • Replace <trustway_client_key> with the file name of your client key.
    • Replace <Proteccio3.06.05.iso> with the name of your Trustway client for Linux ISO.
  3. Retrieve the server certificate from the HSM device, and copy it to the /opt/proceccio directory. For more information on retrieving the server certificate from your Proteccio HSM, see the vendor documentation.
  4. Optional: If you have more than one HSM for HA, get every certificate for each of the HSMs and put them altogether in the /opt/proteccio directory.
  5. Update your proteccio.rc file to look similar to the following:

    [PROTECCIO]
    IPaddr=<Trustway_HSM_IP_address>
    SSL=1
    SrvCert=<HSM_Certificate_Name>.CRT
    
    [CLIENT]
    Mode=0
    LoggingLevel=7
    LogFile=/var/log/barbican/proteccio.log
    StatusFile=/var/log/barbican/HSM_Status.log
    ClntKey=<Client_Certificate_Name>.key
    ClntCert=<Client_Certificate_Name>.crt
    Copy to Clipboard Toggle word wrap
    • Replace <Trustway_HSM_IP_Address> with the IP address of your Trustway HSM.
    • Replace <HSM_Certificate_Name> with the name of your Trustway certificate.
    • In the file above, Mode=0 means that only a single HSM device is in place.
    • Replace <Client_Certificate_Name> with your client certificate name.
  6. Optional: If you are configuring HA, you must include additional entries for the IP addresses of each HSM. Each new HSM must be inside of a [PROTECCIO] section. Additionally, you much change the Mode parameter inside the [CLIENT] to a value of either 1 or 2. For more information, see the official Eviden documentation.

    [PROTECCIO]
    IPaddr=<Trustway_HSM-2_IP_address>
    SSL=1
    SrvCert=<HSM-2_Certificate_Name>.CRT
    
    [CLIENT]
    Mode=2
    Copy to Clipboard Toggle word wrap
    • Replace <Trustway_HSM-2_IP_Address> with the IP address of your second Trustway HSM.
    • Create a new [PROTECCIO] section with the corresponding parameters for every subsequent Trustway unit you have in your environment.
  7. Move the proteccio.rc configuration file to /opt/proteccio:

    $ mv proteccio.rc /opt/proteccio
    Copy to Clipboard Toggle word wrap
  8. Create a playbook called ansible-proteccio.yaml with the following contents:

      vars:
        Trustway_client_name: <name>
        Trustway_server_cert_src: "/opt/trustway/<server.pem>"
        Trustway_partition_password: "<password>"
        Trustway_data_secret: "Trustway_data_secret"
        login_secret: "login_secret"
        barbican_dest_image_namespace: "<namespace>"
        proteccio_client_src: "file:///opt/proteccio/<iso_file>"
        proteccio_password: "{{ PIN to log into proteccio }}"
        kubeconfig_path: "<kubeconfig_path"
        oc_dir: "<directory>"
      roles:
        - rhoso_proteccio_hsm
    Copy to Clipboard Toggle word wrap
    • Replace <name> with the name of your Trustway certificate.
    • Replace <server.pem> with the name of your server certificate.
    • Replace <password> with your HSM partition password.
    • Replace <namespace> with your account name for Quay.io or other container registry.
    • Replace the contents of <iso_file> with the name of the Proteccio client ISO file.
    • Replace the contents of <kubeconfig_path> with the full path to your OpenShift’s configuration file.
    • Replace <directory> with the full path to the OpenShift Client location.
  9. Run the playbook:

    $ ansible-playbook ansible-proteccio.yaml
    Copy to Clipboard Toggle word wrap

Update the OpenStack version by using the OpenStackVersion custom resource (CR). The following procedure shows the CR that defines the custom container image.

Procedure

  1. Create a CR file with the following contents:

    apiVersion: core.openstack.org/v1beta1
    kind: OpenStackVersion
    metadata:
      name: openstack-galera-network-isolation
      namespace: openstack
    spec:
      customContainerImages:
          barbicanAPIImage: <api_image>
          barbicanWorkerImage: <worker_image>
    Copy to Clipboard Toggle word wrap
    • Replace <api_image> with the registry and path to the custom barbicanAPIImage.
    • Replace <worker_image> with the registry and path to the custom barbicanWorkerImage.
  2. Apply the OpenStackVersion CR:

    $ oc apply -f <filename>
    Copy to Clipboard Toggle word wrap

You must modify the Key Manager (barbican) service section of the OpenStackControl custom resource (CR) to fully integrate your Trustway HSM with Red Hat OpenStack Services on OpenShift (RHOSO).

Procedure

  1. Configure the Key Manager service within your OpenStackControlPlane CR for use with the Trustway HSM:

    spec:
      barbican:
        apiOverride:
          route: {}
        enabled: true
        template:
          globalDefaultSecretStore: pkcs11
          enabledSecretStores:
            - pkcs11
            - simple_crypto
          apiTimeout: 90
          barbicanAPI:
            apiTimeout: 0
            customServiceConfig: |
              [secretstore:pkcs11]
              secret_store_plugin = store_crypto
              crypto_plugin = p11_crypto
              [p11_crypto_plugin]
              plugin_name = PKCS11
              library_path = /opt/tw_proteccio/lib/libnethsm.so
              token_labels = <token_label>
              mkek_label = <mkek_label>
              hmac_label = <hmac_label>
              encryption_mechanism = CKM_AES_CBC
              hmac_key_type = CKK_GENERIC_SECRET
              hmac_keygen_mechanism = CKM_GENERIC_SECRET_KEY_GEN
              hmac_mechanism = CKM_SHA256_HMAC
              key_wrap_mechanism = CKM_AES_CBC_PAD
              key_wrap_generate_iv = true
              always_set_cka_sensitive = true
              os_locking_ok = false
    
            pkcs11:
              loginSecret: "login_secret"
              clientDataSecret: "proteccio-data"
              clientDataPath: /etc/proteccio
    Copy to Clipboard Toggle word wrap
    • Replace <token_label> with the token label of your HSM. If you are using HA, you must replace <token_label> with the virtual token serial number.
    • Replace <mkek_label> with a user-defined label. If you have already defined this label, you must use the same one.
    • Replace <hmac_label> with a user-defined label. If you have already set this up, you must use the same label.

      Note

      Use one of the following options to identify the HSM that you can use. These options are mutually exclusive and have the following order of precedence:

      Expand

      Parameter

      Value

      Precedence

      token_serial_number

      <serial_number>

      1 - Highest

      token_labels

      Comma delimited lists

      2 - Middle

      slot-id

      <slot_id>

      3 - Lowest

  2. Optional: If you have saved secrets that are using RHOSO Key Manager simple_crypto, keep those secrets available by enabling multiple back ends:

    spec:
      barbican:
        apiOverride:
          route: {}
        enabled: true
        template:
          globalDefaultSecretStore: pkcs11
          enabledSecretStores:
            - pkcs11
            - simple_crypto
    Copy to Clipboard Toggle word wrap
  3. Deploy the OpenStackControlPlane CR:

    $ oc apply -f openstack_control_plane.yaml
    Copy to Clipboard Toggle word wrap

Red Hat supports only Red Hat’s single sign-on (SSO) technology as the identity provider for Red Hat OpenStack Services on OpenShift (RHOSO). If you use another vendor, contact Red Hat Support for a support exception.

Federation allows users to log in to the OpenStack Dashboard (horizon) by using Red Hat’s single sign-on (SSO) technology.

Note

By default, users who log out of the OpenStack Dashboard are not logged out of SSO.

Making use of a single sign-on federated solution requires modifications of the Identity service (keystone). You can use a secret to configure Red Hat OpenStack Services on OpenShift (RHOSO) Identity service to be integrated into your federated authentication solution.

Note

Your federation client must have implicit flow enabled.

Prerequisites

  • You have installed RHOSO.
  • You have a SSO federated solution in your environment.

Procedure

  1. Retrieve the Identity service (keystone) endpoint:

    oc get keystoneapis.keystone.openstack.org -o json | jq '.items[0].status.apiEndpoints.public'
    Copy to Clipboard Toggle word wrap
  2. Provide your SSO administrator with the following redirect URIs as well as the web origin.

    https://<keystoneURL>/v3/auth/OS-FEDERATION/identity_providers/<idp_name>/protocols/openid/websso/
    https://<keystoneURL>/v3/auth/OS-FEDERATION/websso/openid
    
    webOrigins: https://<keystoneURL>
    Copy to Clipboard Toggle word wrap
    • Replace <keystoneURL> with the URL retrieved in step 1. This url must end in a trailing /.
    • Replace <idp_name> with a value of your choosing, for example, kcipaIDP.

      In response, your SSO administrator provides you with a ClientID and a ClientSecret.

      Note

      The chosen <idp_name> value must match all referenced <idp_name> values in this procedure.

  3. Retrieve the Memcached hostname:

    1. For an IPv4 deployment run the following command:

      oc get memcacheds.memcached.openstack.org -n openstack -o json | jq -r '.items[0].status.serverList[0] | split(":")[0]'
      Copy to Clipboard Toggle word wrap
    2. For an IPv6 deployment, run the following command:

      oc get memcacheds.memcached.openstack.org -n openstack -o json | jq -r '.items[0].status.serverListWithInet[0]'
      Copy to Clipboard Toggle word wrap
  4. Create a keystone-httpd-override.yaml CR file and add the following configuration:

    apiVersion: v1
    kind: Secret
    metadata:
      name: keystone-httpd-override
      namespace: openstack
    type: Opaque
    stringData:
      federation.conf: |
        # Example OIDC directives for the *public* endpoint
        OIDCClaimPrefix "OIDC-"
        OIDCScope "openid email profile"
        OIDCClaimDelimiter ";"
        OIDCPassUserInfoAs "claims"
        OIDCPassClaimsAs "both"
        OIDCClientID "<my_client_id>" 
    1
    
        OIDCClientSecret "<my_client_secret>" 
    2
    
        OIDCCryptoPassphrase "<crypto_pass>" 
    3
    
        OIDCProviderMetadataURL <metadata_url> 
    4
    
        OIDCResponseType "id_token" 
    5
    
        OIDCOAuthClientID "my_oauth_client_id"
        OIDCOAuthClientSecret "12345678"
        OIDCOAuthIntrospectionEndpoint "<https://my_oauth_introspection_endpoint>" 
    6
    
        OIDCRedirectURI "{{ .KeystoneEndpointPublic }}/v3/auth/OS-FEDERATION/identity_providers/<idp_name>/protocols/openid/websso/" 
    7
    
    
        <LocationMatch "/v3/auth/OS-FEDERATION/identity_providers/<idp_name>/protocols/openid/websso">
            AuthType "openid-connect"
            Require valid-user
        </LocationMatch>
    
        <Location ~ "/v3/OS-FEDERATION/identity_providers/<idp_name>/protocols/openid/auth">
            AuthType oauth20
            Require valid-user
        </Location>
    
        <LocationMatch "/v3/auth/OS-FEDERATION/websso/openid">
            AuthType "openid-connect"
            Require valid-user
        </LocationMatch>
    Copy to Clipboard Toggle word wrap
    1
    Replace <my_client_id> with your client ID to use for the OpenID Connect provider handshake. You must get this from your SSO administrator.
    2
    Replace <my_client_secret> with the client secret to use for the OpenID Connect provider handshake. You must get this from your SSO administrator after providing your redirect URLs.
    3
    Replace <crypto_pass> with a secure passphrase to use when encrypting data for the OpenID Connect handshake. This is a user-defined value.
    4
    Replace <metadata_url> with the URL that points to your OpenID Connect provider metadata. Use the format: "https://<FQDN>/realms/<realm>/.well-known/openid-configuration. The SSO administrator will provide the requisite <FQDN> and organization-specific <realm> name for your OpenID provider.
    5
    The response type expected from the OpenID Connect provider.
    6
    Replace https://my_oauth_introspection_endpoint with a value provided by the SSO administrator.
    7
    Replace <idp_name> with your chosen string that creates unique redirect URL, for example, kcipaIDP. This value must be replaced for the keystoneFederationIdentityProviderName parameter and the LocationMatch and Location directive arguments.
    Important

    The full value for the OIDCRedirectURI parameter must end in a trailing /.

  5. Create the secret:

    oc create -f keystone-httpd-override.yaml
    Copy to Clipboard Toggle word wrap
  6. Get the URL for the OpenStack Dashboard:

    oc get horizons.horizon.openstack.org -o json | jq -r '.items[0].status.endpoint'
    Copy to Clipboard Toggle word wrap
  7. Edit the keystone section of the OpenStackControlPlane CR file and add the secret:

    keystone:
      template:
        customServiceConfig: |
          [federation]
          trusted_dashboard=<horizon_endpoint>/dashboard/auth/websso/ 
    1
    
          [openid]
          remote_id_attribute=HTTP_OIDC_ISS
          [auth]
          methods = password,token,oauth1,mapped,application_credential,openid 
    2
    
        httpdCustomization:
          customConfigSecret: keystone-httpd-override 
    3
    Copy to Clipboard Toggle word wrap
    1
    Replace <horizon_endpoint> with the value you retrieved in step 6.
    2
    Ensure that external is removed from this list of values.
    3
    Add the customConfigSecret parameter under httpdCustomization and set its value to the key created in the keystone-httpd-override.yaml CR file.
  8. Edit the horizon section of the OpenStackControlPlane CR file to configure the OpenStack Dashboard (horizon):

    horizon:
      template:
        customServiceConfig: |
          # Point Horizon to the Keystone public endpoint
          OPENSTACK_KEYSTONE_URL = "<keystone_endpoint>/v3" 
    1
    
    
          # Enable WebSSO in Horizon
          WEBSSO_ENABLED = True
    
          # Provide login options in Horizon's dropdown menu
          WEBSSO_CHOICES = (
            ("credentials", _("Keystone Credentials")),
            ("OIDC", _("OpenID Connect")),
          )
    
          # Map Horizon's "OIDC" choice to the Keystone IDP and protocol
          WEBSSO_IDP_MAPPING = {
            "OIDC": ("<idp_name>", "openid"), 
    2
    
          }
    Copy to Clipboard Toggle word wrap
    1
    Replace <keystone_endpoint> with the value you retrieved in the first step.
    2
    Replace <idp_name> with your chosen string that creates a unique redirect URL, for example, kcipaIDP.
  9. Update the control plane:

    $ oc apply -f openstack_control_plane.yaml -n openstack
    Copy to Clipboard Toggle word wrap

After you deploy Red Hat OpenStack Services on OpenShift (RHOSO) with Red Hat’s single sign-on (SSO) technology for federation, you must integrate SSO with RHOSO.

Procedure

  1. Create a federated domain:

    $ openstack domain create <federated_domain_name>
    Copy to Clipboard Toggle word wrap
    • Replace <federated_domain_name> with the name of the domain you are managing with your identity provider, for example, my_domain.

      Example output:

      +-------------+----------------------------------+
      | Field       | Value                            |
      +-------------+----------------------------------+
      | description |                                  |
      | enabled     | True                             |
      | id          | b493634c9dbf4546a2d1988af181d7c9 |
      | name        | my_domain                        |
      | options     | {}                               |
      | tags        | []                               |
      +-------------+----------------------------------+
      Copy to Clipboard Toggle word wrap
  2. Set up the federation identity provider:

    $ openstack identity provider create --remote-id https://<sso_fqdn>:9443/realms/<realm> --domain <federated_domain_name> <idp_name>
    Copy to Clipboard Toggle word wrap
    • Replace <sso_fqdn> with the fully qualified domain name for your SSO identity provider.
    • Replace <realm> with the SSO realm. The default realm is master.
    • Replace <federated_domain_name> with the name of the federated domain that you created in step 1, for example, my_domain.
    • Replace <idp_name> with the string that you chose when deploying SSO to create the unique redirect URL, for example, kcipaIDP.

      Example output:

      +-------------------+-----------------------------------------------------+
      | Field             | Value                                               |
      +-------------------+-----------------------------------------------------+
      | authorization_ttl | None                                                |
      | description       | None                                                |
      | domain_id         | b493634c9dbf4546a2d1988af181d7c9                    |
      | enabled           | True                                                |
      | id                | kcipaIDP                                            |
      | remote_ids        | https://sso.fqdn.local:9443/realms/master           |
      +-------------------+-----------------------------------------------------+
      Copy to Clipboard Toggle word wrap
  3. Create a mapping file that is unique to the identity needs of your cloud:

     cat > mapping.json << EOF
    [
    	{
        	"local": [
            	{
                	"user": {
                 	"name": "{0}"
                	},
                	"group": {
                    	"domain": {
                     	"name": "<federated_domain_name>" 
    1
    
                    	},
                    	"name": "<federated_group_name>" 
    2
    
                	}
            	}
        	],
        	"remote": [
            	{
                	"type": "OIDC-preferred_username"
            	}
        	]
    	}
    ]
    EOF
    Copy to Clipboard Toggle word wrap
    1
    Replace <federated_domain_name> with the domain you created in step 1, for example, my_domain.
    2
    Replace <federated_group_name> with the name of the federated group that you create in a later step, for example, my_fed_group.
  4. Use the mapping file to create the federation mapping rules for RHOSO:

    $ openstack mapping create --rules <mapping_file> <mapping_rules>
    Copy to Clipboard Toggle word wrap
    • Replace <mapping_file> with the name of the mapping file that you created in the previous step, for example, mapping.json.
    • Replace <mapping_rules> with the name of the mapping rules created from this file, for example, IPAmap.
  5. Create a federated group:

    $ openstack group create --domain <federated_domain_name> <federated_group_name>
    Copy to Clipboard Toggle word wrap
    • Replace <federated_domain_name> with the name of the domain that you created in step 1, for example, my_domain.
    • Replace <federated_group_name> with the name of the federated group that have specified in the mapping file, for example, my_fed_group.
  6. Create an Identity service (keystone) project:

    $ openstack project create --domain <federated_domain_name> <federated_project_name>
    Copy to Clipboard Toggle word wrap
    • Replace <federation_project_name> with the name of the Identity service project.
  7. Add the Identity service federation group to a role:

    $ openstack role add --group <federated_group_name> --group-domain <federated_domain_name> --project <federated_project_name> --project-domain <federated_domain_name> member
    Copy to Clipboard Toggle word wrap
  8. Create the OpenID federation protocol:

    $ openstack federation protocol create openid --mapping <mapping_rules> --identity-provider <idp_name>
    Copy to Clipboard Toggle word wrap
    • Replace <mapping_rules> with the name of the mapping rules you created from your mapping file, for example, IPAmap.
    • Replace <idp_name> with your chosen string that creates the unique redirect URL, for example, kcipaIDP.

You can configure Red Hat OpenStack Services on OpenShift (RHOSO) Identity service (keystone) and Dashboard (horizon) to provide multi-realm federated authentication using OpenID Connect (OIDC) as the protocol. Multi-realm federation allows users to log in to the OpenStack Dashboard by using single sign-on (SSO) and select from one of several external Identity Providers (IdPs).

Multi-realm federation allows users to log in to the Red Hat OpenStack Services on OpenShift (RHOSO) Dashboard by using single sign-on (SSO) and select from one of several external Identity Providers (IdPs).

Note

The RHOSO deployment of multiple federated IdPs implements the Web SSO authentication flow because the OpenStack CLI does not support multiple IdPs.

Prerequisites

  • You have installed RHOSO.
  • You have multiple external OpenID Connect (OIDC) IdPs configured in your environment.

Procedure

  1. Choose a name to uniquely identify each IdP.

    In this example there are two IdPs, whose names are referenced as <idp_name_1> and <idp_name_2>.

  2. Obtain the following settings from each IdP administrator:

    • The FQDN for each IdP that is referenced in this procedure as <fqdn_1> and <fqdn_2>.
    • The federation Realm Name for each IdP that is referenced in this procedure as <realm_name_1> and <realm_name_2>.
    • The Client ID for each IdP that is referenced in this procedure as <client_id_1> and <client_id_2>.
    • The Client Secret for each IdP that is referenced in this procedure as <client_secret_1> and <client_secret_2>.
    • The Provider Metadata URL for each IdP that is referenced in this procedure as <provider_metadata_url_1> and <provider_metadata_url_2>.
  3. Retrieve the Identity service (keystone) public endpoint:

    $ oc get keystoneapis.keystone.openstack.org -o json | jq '.items[0].status.apiEndpoints.public'
    Copy to Clipboard Toggle word wrap

    This Identity service endpoint is referenced in this procedure as <keystone_url>.

  4. Provide the IdP administrators with the following information:

    • Web origin:

      https://<keystone_url>
      Copy to Clipboard Toggle word wrap
    • Redirect URIs:

      https://<keystone_url>/v3/auth/OS-FEDERATION/websso/openid
      Copy to Clipboard Toggle word wrap

      Provide a URI for each IdP containing their unique IdP name, which must end in a trailing /. You must send each URI to their respective IdP administrator:

      https://<keystone_url>/v3/auth/OS-FEDERATION/identity_providers/<idp_name_1>/protocols/openid/websso/
      https://<keystone_url>/v3/auth/OS-FEDERATION/identity_providers/<idp_name_2>/protocols/openid/websso/
      Copy to Clipboard Toggle word wrap
    • Each federation client must have Implicit flow enabled and not Authorization code flow.
  5. Create a custom resource (CR) file for a secret called keystone-httpd-override:

    apiVersion: v1
    kind: Secret
    metadata:
     name: keystone-httpd-override
     namespace: openstack
    type: Opaque
    stringData:
     federation.conf: |
       # Example OIDC directives for the *public* endpoint
       OIDCClaimPrefix "OIDC-"
       OIDCResponseType "id_token"
       OIDCScope "openid email profile"
       OIDCClaimDelimiter ";"
       OIDCPassUserInfoAs "claims"
       OIDCPassClaimsAs "both"
       OIDCCryptoPassphrase "<crypto_pass>"
       OIDCRedirectURI "<keystone_url>/v3/redirect_uri/"
                            OIDCMetadataDir "/var/lib/httpd/metadata"
       OIDCAuthRequestParams "prompt=login"
       <IfModule headers_module>
         <Location "/v3/local-logout/clear">
           Header always add Set-Cookie "mod_auth_openidc_session=deleted; Path=/; Max-Age=0; HttpOnly; Secure; SameSite=None"
         </Location>
       </IfModule>
    
       RewriteEngine On
    
       RewriteRule ^/v3/auth/OS-FEDERATION/identity_providers/(<idp_name_1>|<idp_name_2>)/protocols/openid/websso$ \
         /v3/local-logout/clear [R=302,L]
    
       RewriteRule ^/v3/local-logout/clear$ \
         /v3/auth/OS-FEDERATION/websso/openid [R=302,L,QSA,NE]
    
       <Location "/v3/auth/OS-FEDERATION/websso/openid">
         AuthType openid-connect
         Require  valid-user
       </Location>
    
       <Location "/v3/redirect_uri">
         AuthType openid-connect
         Require  valid-user
       </Location>
    Copy to Clipboard Toggle word wrap
    Important

    The full value of the OIDCRedirectURI parameter must end in a trailing /.

    • Replace <crypto_pass> with a user-defined passphrase to use when encrypting data for the OpenID Connect handshake.
    • Replace <keystone_url> with the Identity service endpoint value that you retrieved in step 3.
    • Replace <idp_name_1> and <idp_name_2> with their unique IdP names that you specified in step 1.
    • The following OIDC parameter and associated Apache configuration is designed to provide the most failsafe solution that supports the login of users from multiple IdPs. Consequently, previous sessions are not saved and users must reauthenticate themselves after they log out of the Dashboard:

       OIDCAuthRequestParams "prompt=login"
      
      
       <IfModule headers_module>
         <Location "/v3/local-logout/clear">
           Header always add Set-Cookie "mod_auth_openidc_session=deleted; Path=/; Max-Age=0; HttpOnly; Secure; SameSite=None"
         </Location>
       </IfModule>
        RewriteEngine On
        RewriteRule ^/v3/auth/OS-FEDERATION/identity_providers/(<idp_name_1>|<idp_name_2>)/protocols/openid/websso$ \
         /v3/local-logout/clear [R=302,L]
        RewriteRule ^/v3/local-logout/clear$ \
         /v3/auth/OS-FEDERATION/websso/openid [R=302,L,QSA,NE]
      Copy to Clipboard Toggle word wrap

      If users in your multiple federated IdP deployment do not belong to more than one IdP then you can allow users to reopen the Dashboard they have closed without providing any authentication. In this case, you must remove this OIDC parameter and provide a different Apache LocationMatch configuration to save the previous sessions.

  6. Create the keystone-httpd-override secret:

    $ oc create -f keystone-httpd-override.yaml
    Copy to Clipboard Toggle word wrap
  7. Retrieve the URL for the Dashboard:

    $ oc get horizons.horizon.openstack.org -o json | jq -r '.items[0].status.endpoint'
    Copy to Clipboard Toggle word wrap
  8. Use the following Ansible playbook to create a secret called federation-realm-data:

    - name: Download realm1 OpenID configuration
      ansible.builtin.uri:
        url: "<provider_metadata_url_1>"
        method: GET
        return_content: true
        validate_certs: false
      register: openid_wellknown_config1
    
    
    - name: Download realm2 OpenID configuration
      ansible.builtin.uri:
        url: "<provider_metadata_url_2>"
        method: GET
        return_content: true
        validate_certs: false
      register: openid_wellknown_config2
    
    
    - name: Set federation_config_items
      ansible.builtin.set_fact:
        federation_config_items:
          - filename: "<fqdn_1>%2Fauth%2Frealms%2F<realm_name_1>.conf"
            contents: |
              {
                "scope" : "openid email profile"
              }
          - filename: "<fqdn_1>%2Fauth%2Frealms%2F<realm_name_1>.client"
            contents: "{{ {'client_id': <client_id_1>, 'client_secret': <client_secret_1> } | to_json }}"
          - filename: "<fqdn_1>%2Fauth%2Frealms%2F<realm_name_1>.provider"
            contents: |
              {{ openid_wellknown_config1.content }}
          - filename: "<fqdn_2>%2Fauth%2Frealms%2F<realm_name_2>.conf"
            contents: |
              {
                "scope" : "openid email profile"
              }
          - filename: "<fqdn_2>%2Fauth%2Frealms%2F<realm_name_2>.client"
            contents: "{{ {'client_id': <client_id_2>, 'client_secret': <client_secret_2>} | to_json }}"
          - filename: "<fqdn_2>%2Fauth%2Frealms%2F<realm_name_2>.provider"
            contents: |
              {{ openid_wellknown_config2.content }}
    - name: Generate the final federation_config.json string (as a dictionary)
      ansible.builtin.set_fact:
        _raw_federation_config_json_value: |
          {
          {% for item in federation_config_items %}
            "{{ item.filename }}": {{ item.contents }}{% if not loop.last %},{% endif %}
          {% endfor %}
          }
    - name: Final JSON string for Secret stringData
      ansible.builtin.set_fact:
        federation_config_json_string: "{{ _raw_federation_config_json_value }}"
    
    
    - name: Create a Kubernetes Secret with federation metadata
      kubernetes.core.k8s:
        state: present
        definition:
          apiVersion: v1
          kind: Secret
          type: Opaque
          metadata:
            name: federation-realm-data
            namespace: openstack
          stringData:
            federation-config.json: "{{ federation_config_json_string }}"
    Copy to Clipboard Toggle word wrap
    • Replace the IdP variables with the values you obtained from the IdP administrators in step 2.
  9. Open your OpenStackControlPlane custom resource (CR) file, openstack_control_plane.yaml, on your workstation.
  10. Edit the keystone section of the OpenStackControlPlane CR:

    keystone:
     template:
       customServiceConfig: |
         [federation]
         trusted_dashboard=<horizon_endpoint>/dashboard/auth/websso/
         [openid]
         remote_id_attribute=HTTP_OIDC_ISS
         [auth]
         methods = password,token,oauth1,mapped,application_credential,openid
       httpdCustomization:
         customConfigSecret: keystone-httpd-override
         federatedRealmConfig: federation-realm-data
    Copy to Clipboard Toggle word wrap
    • Replace <horizon_endpoint> with the Dashboard URL you retrieved in step 7.
    • Remove external from the methods = comma delimited list.
    • Add the customConfigSecret parameter under httpdCustomization and set this value to the key created in the keystone-httpd-override.yaml CR file in step 5.
    • Add the federatedRealmConfig parameter and set this value to the federation-realm-data secret created by the Ansible Playbook in step 8.
  11. Edit the horizon section of the OpenStackControlPlane CR:

    horizon:
     template:
     customServiceConfig: |
       # Point horizon to the keystone public endpoint
       OPENSTACK_KEYSTONE_URL = "<keystone_endpoint>/v3"
    
    
       # Enable WebSSO in horizon
       WEBSSO_ENABLED = True
    
    
       # Provide login options in the horizon dropdown menu
       WEBSSO_CHOICES = (
         ("credentials", _("Keystone Credentials")),
         ("OIDC1", _("OpenID Connect IdP1")),
         ("OIDC2", _("OpenID Connect IdP2")),
       )
    
    
       # Map the "OIDC" choice of horizon to the keystone IDP and protocol
       WEBSSO_IDP_MAPPING = {
         "OIDC1": ("<idp_name1>", "openid"),
         "OIDC2": ("<idp_name2>", "openid"),
       }
    Copy to Clipboard Toggle word wrap
  12. Update the control plane:

    $ oc apply -f openstack_control_plane.yaml -n openstack
    Copy to Clipboard Toggle word wrap

Legal Notice

Copyright © 2025 Red Hat, Inc.
The text of and illustrations in this document are licensed by Red Hat under a Creative Commons Attribution–Share Alike 3.0 Unported license ("CC-BY-SA"). An explanation of CC-BY-SA is available at http://creativecommons.org/licenses/by-sa/3.0/. In accordance with CC-BY-SA, if you distribute this document or an adaptation of it, you must provide the URL for the original version.
Red Hat, as the licensor of this document, waives the right to enforce, and agrees not to assert, Section 4d of CC-BY-SA to the fullest extent permitted by applicable law.
Red Hat, Red Hat Enterprise Linux, the Shadowman logo, the Red Hat logo, JBoss, OpenShift, Fedora, the Infinity logo, and RHCE are trademarks of Red Hat, Inc., registered in the United States and other countries.
Linux® is the registered trademark of Linus Torvalds in the United States and other countries.
Java® is a registered trademark of Oracle and/or its affiliates.
XFS® is a trademark of Silicon Graphics International Corp. or its subsidiaries in the United States and/or other countries.
MySQL® is a registered trademark of MySQL AB in the United States, the European Union and other countries.
Node.js® is an official trademark of Joyent. Red Hat is not formally related to or endorsed by the official Joyent Node.js open source or commercial project.
The OpenStack® Word Mark and OpenStack logo are either registered trademarks/service marks or trademarks/service marks of the OpenStack Foundation, in the United States and other countries and are used with the OpenStack Foundation's permission. We are not affiliated with, endorsed or sponsored by the OpenStack Foundation, or the OpenStack community.
All other trademarks are the property of their respective owners.
Back to top
Red Hat logoGithubredditYoutubeTwitter

Learn

Try, buy, & sell

Communities

About Red Hat Documentation

We help Red Hat users innovate and achieve their goals with our products and services with content they can trust. Explore our recent updates.

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

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

Theme

© 2025 Red Hat