Migrate user permissions and credentials to Confluent Platform as described in the following sections:
- Migrating access control lists: Export ACLs by using the Event Streams CLI and import them by using the Confluent REST Proxy.
- Migrating mutual TLS users: Make existing mTLS certificates available to Confluent for Kubernetes (CFK) or issue new certificates.
- Migrating SCRAM-SHA-512 credentials to SASL/PLAIN: Recreate SCRAM-SHA-512 user credentials as SASL/PLAIN secrets in CFK.
- Migrating OAuth server and client configuration: Update client configuration to point to the new CFK listener endpoints.
Migrating access control lists
Access control lists (ACLs) are not automatically transferred as part of topic data replication. You can migrate ACLs by exporting them in a Confluent-compatible format by using the Event Streams CLI and then importing them directly to the Confluent Platform cluster by using the Confluent REST Proxy.
Before you begin
Complete the following steps before you start the migration:
- Install and initialize the Event Streams CLI by following the instructions in logging in.
- If you have logged in to the Event Streams CLI by using SCRAM, ensure that your SCRAM user has
cluster.alterandcluster.describepermissions required to export ACLs. - Deploy a REST Proxy server and enable external access by following the instructions in the Confluent documentation.
- Ensure that the user that the REST Proxy uses to authenticate to Kafka has
cluster.alterpermission required to create and manage ACLs in Confluent.
Migrating ACLs
To migrate ACLs to Confluent Platform, complete the following steps:
-
Export ACLs by running the following Event Streams CLI command. The command returns all the ACLs that are present in your Event Streams instance in a JSON file:
kubectl es acls-ccompat-export --output <export-filename>Where:
<export-filename>is the name of the JSON file where the exported ACLs are stored.
Note: You can export ACLs for a specific user or topic by using the flags provided in the command. Run the command with the
--helpoption to list all the flags and understand their usage. -
Run the following curl command to import the ACLs to Confluent Platform by using the REST Proxy:
curl -X POST \ -H "Content-Type: application/json" \ -d @<export-filename> \ https://<rest-proxy-host>:<rest-proxy-port>/v3/clusters/<cluster-id>/acls:batchFor more information about the
acls:batchendpoint, see the REST proxy API documentation.Where:
<rest-proxy-host>is the host address of the REST Proxy server.<rest-proxy-port>is the port of the server.<cluster-id>is your Kafka cluster ID. Run the following command to retrieve it:
CLUSTER_ID=$(curl "https://<rest-proxy-host>:<rest-proxy-port>/v3/clusters" | jq -r '.data[0].cluster_id')
Note: Enable authentication and encryption in your REST proxy server to secure access to your endpoints by following the instructions in the Confluent documentation. Use curl flags to pass credentials and certificates in your requests.
Note: Kafka supports a maximum of 10,000 ACL entries in a single batch upload. If your export file contains more than 10,000 ACL entries, split the entries across multiple files and use those files to add the ACLs to the Confluent Platform cluster in smaller batches by using the Confluent REST Proxy.
Migrating mutual TLS users
To migrate mTLS-authenticated Kafka users from Event Streams to Confluent Platform, issue new client certificates and update each client application to connect to CFK. For detailed instructions, see migrating mTLS users.
Migrating SCRAM-SHA-512 credentials to SASL/PLAIN
CFK reads SASL/PLAIN credentials from a Kubernetes secret that contains a plain-users.json key. Add your SCRAM credentials inside the JSON referenced by this key to configure them as SASL/PLAIN credentials.
Note: Before you begin, ensure that the jq command-line utility is installed.
To migrate all the SCRAM credentials at once, complete the following steps:
- Log in to your Kubernetes cluster as a cluster administrator by setting your
kubectlcontext. -
In the namespace where your Confluent Platform cluster is installed, run the following command to create a secret to store plain user credentials if it does not already exist:
kubectl create secret generic <secret-name> --from-literal=plain-users.json='{}' -n <confluent-namespace>Where:
<secret-name>is the name of the Kubernetes secret for plain user credentials.<confluent-namespace>is the namespace where Confluent Platform is installed.
-
Run the following command to switch to the namespace where your Event Streams instance is installed:
kubectl config set-context --current --namespace=<eventstreams-namespace>Where:
<eventstreams-namespace>is the namespace where Event Streams is installed.
-
Create a shell script that contains the following commands:
PLAIN_USERS_JSON='{}' for username in $(kubectl get kafkausers.eventstreams.ibm.com -o jsonpath='{.items[?(@.spec.authentication.type=="scram-sha-512")].metadata.name}'); do printf 'Migrating credentials for user %s\n' "$username" if printf '%s' "$PLAIN_USERS_JSON" | jq -e --arg u "$username" 'has($u)' > /dev/null; then printf 'Username key %s is already present in the json, skipping adding %s to the json\n' "$username" "$username" continue fi SECRET_NAME=$(kubectl get kafkausers.eventstreams.ibm.com "$username" -o jsonpath='{.status.secret}') PASSWORD=$(kubectl get secret "$SECRET_NAME" -o jsonpath='{.data.password}' | base64 --decode) if [ -z "$PASSWORD" ]; then echo "Secret not found, skipping adding $username to the json" continue fi JQ_FILTER='. += {($u): $p}' PLAIN_USERS_JSON=$(printf '%s' "$PLAIN_USERS_JSON" | jq --arg u "$username" --arg p "$PASSWORD" "$JQ_FILTER") done echo "$PLAIN_USERS_JSON"Note: If credentials already exist in the
plain-userssecret, initializePLAIN_USERS_JSONwith the existing credentials so that the migrated credentials are appended to them:PLAIN_USERS_JSON=$(kubectl get secret <secret-name> -n <confluent-namespace> -o jsonpath='{.data.plain-users\.json}' | base64 --decode) -
Run the script and store the output in a variable:
OUTPUT_JSON=$(./<script-name>.sh)The script outputs a JSON with the credentials to be migrated.
-
Verify the output. Run the following command to update the
plain-userssecret with the JSON containing the credentials to be migrated:kubectl create secret generic <secret-name> \ --from-literal=plain-users.json="$OUTPUT_JSON" \ --dry-run=client -o yaml -n <confluent-namespace> | kubectl apply -f - -n <confluent-namespace>
Migrating OAuth server and client configuration
OAuth server credentials do not require migration. Your applications continue to authenticate with the same identity provider. After you set up Confluent Platform, update the following configuration in your client applications:
- Kafka bootstrap address: Update with the CFK OAuth listener bootstrap address.
ssl.truststore.locationproperty: Update with the location of the truststore file containing the CA certificate to verify the CFK OAuth listener certificate.- OAuth settings: Update
sasl.oauthbearer.token.endpoint.urland any related OAuth properties to match the CFK listener configuration. - OAuth client credentials properties: Use the top-level
sasl.oauthbearer.client.credentials.*andsasl.oauthbearer.scopeproperties, which are the Kafka 4.1 preferred form. SettingclientId,clientSecret, andscopeinsidesasl.jaas.configis deprecated in Kafka 4.1 and will be removed in a future version. The top-level properties take precedence if both are set. sasl.login.callback.handler.class: If your client applications use the Strimzi OAuth library (io.strimzi.kafka.oauth.client.JaasClientOauthLoginCallbackHandler), update the handler class to the native Kafka handler (org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginCallbackHandler).
The following example shows a complete client properties file for connecting to the CFK OAuth listener:
security.protocol=SASL_SSL
sasl.mechanism=OAUTHBEARER
sasl.login.callback.handler.class=org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginCallbackHandler
sasl.login.connect.timeout.ms=15000
sasl.oauthbearer.token.endpoint.url=https://<oauth-server-host>:<oauth-server-port>/<realm-name>/protocol/openid-connect/token
sasl.oauthbearer.client.credentials.client.id=kafka-client
sasl.oauthbearer.client.credentials.client.secret=<kafka-client-secret>
sasl.oauthbearer.scope=openid
sasl.jaas.config=org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginModule required ;
ssl.truststore.location=./oauth-server-ca.crt
ssl.truststore.type=PEM
Where:
<oauth-server-host>is the hostname of your OAuth server.<oauth-server-port>is the port that your OAuth server is listening on.<realm-name>is the realm or tenant name configured in your OAuth server.<kafka-client-secret>is the client secret for thekafka-clientretrieved from your OAuth server.
Note: The sasl.oauthbearer.client.credentials.* and sasl.oauthbearer.scope properties are the Kafka 4.1 preferred form. In Kafka 4.1, setting clientId, clientSecret, and scope inside sasl.jaas.config is deprecated. Those JAAS options remain supported for backward compatibility but will be removed in a future version. The top-level properties take precedence if both are set.
Important: If you are migrating from Event Streams, update sasl.login.callback.handler.class from io.strimzi.kafka.oauth.client.JaasClientOauthLoginCallbackHandler to org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginCallbackHandler. In addition, move oauth.token.endpoint.uri, oauth.client.id, and oauth.client.secret out of sasl.jaas.config and into the top-level sasl.oauthbearer.* properties shown previously.
Run the following command to set the Java option so that the Kafka client can access the OAuth server token and JWKS endpoints:
export KAFKA_OPTS="-Dorg.apache.kafka.sasl.oauthbearer.allowed.urls=https://<oauth-server-host>:<oauth-server-port>/<realm-name>/protocol/openid-connect/token,https://<oauth-server-host>:<oauth-server-port>/<realm-name>/protocol/openid-connect/certs"
Configuring OAuth authentication
Configure an OAuth listener in CFK to authenticate your Kafka clients after migrating from Event Streams.
Prerequisites
Complete the following steps before you configure the OAuth listener:
-
Extract the CA certificate from your existing OAuth server TLS secret and create a Kubernetes secret in the
confluentnamespace by running the following commands:kubectl get secret <oauth-server-tls-secret> -n <oauth-server-namespace> \ -o jsonpath='{.data.ca\.crt}' | base64 -d > oauth-server-ca.crt kubectl create secret generic oauth-server-ca \ --from-file=tls.crt=oauth-server-ca.crt \ -n <cp-namespace>Where:
<oauth-server-tls-secret>is the name of your OAuth server TLS secret.<oauth-server-namespace>is the namespace where your OAuth server is deployed.
-
Add the following
mountedSecretsconfiguration to your CFK Kafka CR so that the broker mounts the OAuth server CA and accesses the OAuth server token introspection endpoint over TLS:mountedSecrets: - secretRef: oauth-server-ca
Configuring the OAuth listener
To configure the OAuth listener, complete the following steps:
-
Create the CFK OAuth JAAS secret by completing the following steps:
a. Retrieve the
clientIdandclientSecretof your existing Kafka broker OAuth client from your OAuth server.b. Create
oauth.txtwith the following content, by using your Kafka broker OAuth client credentials:clientId=<your-broker-client> clientSecret=<your-broker-client-secret>Where:
<your-broker-client>is the client ID of your Kafka broker OAuth client.<your-broker-client-secret>is the client secret retrieved from your OAuth server.
c. Run the following command to create the Kubernetes secret:
kubectl create secret generic oauth-jaas \ --from-file=oauth.txt=oauth.txt \ -n <cp-namespace>Reference this secret in the
jaasConfigsection of the CFK Kafka CR as follows:jaasConfig: secretRef: oauth-jaas -
Configure the Kafka OAuth listener in your CFK Kafka CR. For the properties and their expected values, see the CFK OAuth/OIDC authentication documentation.
Important: When configuring
oauthSettings, setsubClaimName: azp. This setting instructs the CFK broker to extract theazp(“authorized party”) claim from the JWT and use it as the Kafka principal. In an OAuth client credentials flow,azpis set to theclient_idof the client that requested the token. Whenkafka-clientretrieves a token, the broker resolves the principal asUser:kafka-client. If you change the client ID, update your ACL principal or role binding to match. -
If you use OAuth server RBAC rules for authorization in Event Streams, create ACLs or a Confluent role binding to grant the client access to Kafka resources.
Next steps
- If you have mutual TLS (mTLS) users, see migrating mTLS users.
- To migrate schemas, see migrating schemas.