<a id="ansible-rbac-enable"></a>

# 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:

- [Use the ACL authorizer](#ansible-rbac-enable-using-acl)

  This is the  recommended method.
- [Parallel restart after enabling RBAC](#ansible-rbac-enable-parallel)

  Parallel restarts lead to downtime, and this approach is not recommended for
  production deployments.

<a id="ansible-rbac-enable-using-acl"></a>

## 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](https://github.com/confluentinc/cp-ansible/tree/master/docs/sample_inventories)
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.
   ```yaml
   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.
   * 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.
   ```bash
   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:
   ```yaml
   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_next_gen_kafka_listener_name: internal_client_listener
   ```
5. Run the following command to update the listener used for Kafka to Confluent Platform
   communication:
   ```bash
   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:
      ```yaml
      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.
      ```bash
      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:

```text
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:

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

<a id="ansible-rbac-enable-parallel"></a>

## Enable RBAC with parallel restart of Confluent Platform

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

   For a list of all the RBAC-related properties, refer to
   [Role-based access control](ansible-authorize.md#ansible-authz-rbac).

   Below is an example snippet:
   ```yaml
   all:
     vars:
       ssl_enabled: true
       rbac_enabled: true
       mds_ssl_client_authentication: required
       # 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_next_gen_ldap_user: control_center
       control_center_next_gen_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:
   ```bash
   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.
