Enable RBAC in Running Confluent Platform Environment Using Ansible Playbooks

You can enable role-based access control (RBAC) on a Confluent Platform deployment that was originally configured without RBAC enabled.

The following are the options to enable RBAC using Confluent Ansible:

Enable RBAC with ACL authorizer

This section describes the workflow to enable RBAC in non-RBAC or ACL-based Confluent Platform deployments using an ACL authorizer.

You can reference the sample inventory files for example non-RBAC to RBAC migration setups.

If your clusters have an authorizer and all required ACLs, you can start at Step 4.

For clusters without an authorizer, Steps 1-3 are needed to first enable authorization. Then you can migrate to RBAC.

  1. Configure ACL authorizer and add super users for broker principals.

    If an ACL authorizer was already configured, you do not need to do a rolling restart.

    For KRaft-based clusters, an authorizer must be added in both the KRaft controller and broker.

    kafka_broker_custom_properties:
      authorizer.class.name: org.apache.kafka.metadata.authorizer.StandardAuthorizer
      allow.everyone.if.no.acl.found: "true"
      super.users: "User:admin"
    
    kafka_controller_custom_properties:
      authorizer.class.name: org.apache.kafka.metadata.authorizer.StandardAuthorizer
      allow.everyone.if.no.acl.found: "true"
      super.users: "User:admin"
    
    • allow.everyone.if.no.acl.found=true is set for zero downtime after enabling the authorizer.

      Caution

      If someone adds an ACL while allow.everyone.if.no.acl.found is set to true, all the users who previously had access will lose that access.

    • You need to add broker’s principal in super.users. The admin user is used as a broker principal example in the above snippet.

  2. Perform a rolling restart of the KRaft controllers and Kafka brokers.

    ansible-playbook -i <your hosts file> confluent.platform.all \
      --skip-tags package \
      -e deployment_strategy=rolling \
      --tags kafka_controller,kafka_broker
    

    You can skip this step if ACLs are already enabled in the cluster.

  3. Create ACLs for broker principals and user principals of all applications, including Confluent Platform components.

    When a new ACL is added, all the users who previously had access will lose access to that resource since it was previously set to allow all before the new ACL is added.

    There might be downtime for clients here between adding an authorizer and adding ACLs.

  4. Add the custom broker listener and update all Confluent Platform components to communicate on that listener.

    An example snippet:

    kafka_broker_custom_listeners:
        internal_client_listener:
          name: CUSTOM_LISTENER
          port: 9095
          ssl_enabled: false
          sasl_protocol: plain
    
    schema_registry_kafka_listener_name: internal_client_listener
    kafka_connect_kafka_listener_name: internal_client_listener
    kafka_rest_kafka_listener_name: internal_client_listener
    ksql_kafka_listener_name: internal_client_listener
    control_center_kafka_listener_name: internal_client_listener
    
  5. Run the following command to update the listener used for Kafka to Confluent Platform communication:

    ansible-playbook -i <your hosts file> confluent.platform.all \
      --skip-tags package \
      -e deployment_strategy=rolling
    
  6. Enable RBAC and Metadata Service (MDS) on Kafka brokers.

    1. Remove the simple authorizer properties added in Step 1.

    2. Comment out the *_kafka_listener_name variables set in step 4. This will ensure Kafka to Confluent Platform communication via OAuthbearer on the internal listener once RBAC is enabled.

    3. Add the variables to enable RBAC.

      Example snippet of RBAC with OAuth:

      rbac_enabled: true
      auth_mode: oauth
      oauth_superuser_client_id: superuser
      oauth_superuser_client_password: my-secret
      
      oauth_sub_claim: client_id
      oauth_groups_claim: groups
      oauth_token_uri: https://oauth1:8443/realms/cp-ansible-realm/protocol/openid-connect/token
      oauth_issuer_url: https://oauth1:8443/realms/cp-ansible-realm
      oauth_jwks_uri: https://oauth1:8443/realms/cp-ansible-realm/protocol/openid-connect/certs
      oauth_expected_audience: Confluent,account,api://default
      
      schema_registry_oauth_user: schema_registry
      schema_registry_oauth_password: my-secret
      
      kafka_rest_oauth_user: kafka_rest
      kafka_rest_oauth_password: my-secret
      
    4. Run the command to enable RBAC in all Confluent Platform components.

      ansible-playbook -i <your hosts file> confluent.platform.all \
        --skip-tags package \
        -e deployment_strategy=rolling
      
  7. Configure RBAC role bindings for resources of other components. This includes all the external Kafka clients and the clients of Confluent Platform components.

Troubleshooting

Known issue: Confluent Ansible uses the first broker (the first node set in the mds_bootstrap_server_urls variable) up and running to make MDS API calls, assuming the first broker is running with MDS. This might fail when enabling RBAC in an Ansible cluster, and the first broker node to enable RBAC does not match the first value of mds_bootstrap_server_urls.

This will lead to an error similar to:

TASK [confluent.platform.common : Get Authorization Token from MDS]
fatal: [kafka-broker2]: FAILED! => {"attempts": 30, "cache_control": "must-revalidate,no-cache,no-store", "changed": false, "connection": "close", "content":
...
HTTP Error 404: status": 404, "url": "https://kafka-broker1:8090/security/1.0/authenticate"}

Solution: Set mds_bootstrap_server_urls[0] in your inventory file, with the first value pointing to the broker node that was upgraded first.

For example, in the above case with the error message, since kafka-broker2 was the first node to enable RBAC, add the node to mds_bootstrap_server_urls as following:

mds_bootstrap_server_urls=https://kafka-broker2:8090,https://kafka-broker1:8090,https://kafka-broker3:8090

Enable RBAC with parallel restart of Confluent Platform

  1. Set the following and provide the required properties for RBAC in your hosts inventory file:

    rbac_enabled: true
    

    For a list of all the RBAC-related properties and their, refer to Role-based access control.

    Below is an example snippet:

    all:
      vars:
        ssl_enabled: true
        rbac_enabled: true
        mds_ssl_mutual_auth_enabled: true
        # super user credentials for bootstrapping RBAC within Confluent Platform
        mds_super_user: mds
        mds_super_user_password: password
        # LDAP users for Confluent Platform components
        kafka_broker_ldap_user: kafka_broker
        kafka_broker_ldap_password: password
        schema_registry_ldap_user: schema_registry
        schema_registry_ldap_password: password
        kafka_connect_ldap_user: connect_worker
        kafka_connect_ldap_password: password
        ksql_ldap_user: ksql
        ksql_ldap_password: password
        kafka_rest_ldap_user: rest_proxy
        kafka_rest_ldap_password: password
        control_center_ldap_user: control_center
        control_center_ldap_password: password
    
    kafka_broker:
      vars:
        kafka_broker_custom_properties:
          ldap.java.naming.factory.initial: com.sun.jndi.ldap.LdapCtxFactory
          ldap.com.sun.jndi.ldap.read.timeout: 3000
          ldap.java.naming.provider.url: ldap://ldap1:389
          ldap.java.naming.security.principal: uid=mds,OU=rbac,DC=example,DC=com
          ldap.java.naming.security.credentials: password
          ldap.java.naming.security.authentication: simple
          ldap.user.search.base: OU=rbac,DC=example,DC=com
          ldap.group.search.base: OU=rbac,DC=example,DC=com
          ldap.user.name.attribute: uid
          ldap.user.memberof.attribute.pattern: CN=(.*),OU=rbac,DC=example,DC=com
          ldap.group.name.attribute: cn
          ldap.group.member.attribute.pattern: CN=(.*),OU=rbac,DC=example,DC=com
          ldap.user.object.class: account
    
  2. Run the confluent.platform.all playbook:

    ansible-playbook -i <your hosts file> confluent.platform.all \
      --skip-tags package \
      -e deployment_strategy=parallel
    

    Include the --skip-tags package option to skip the package installation tasks and to ensure no upgrade happens. The option also speeds up the reconfiguration process.