Switchover: No Auth → OAuth¶
This example configures the gateway to accept unauthenticated client connections and authenticate to Confluent Cloud using OAuth.
Environment Variables¶
| Variable | Description |
|---|---|
KUBECTL_NAMESPACE |
Kubernetes namespace for the gateway |
JKS_PASSWORD |
Password for JKS truststores |
JAVA_HOME |
Path to JDK installation |
OAUTH_CLIENT_ID |
OAuth client ID from your identity provider |
OAUTH_CLIENT_SECRET |
OAuth client secret from your identity provider |
CCLOUD_LOGICAL_CLUSTER |
Confluent Cloud logical cluster ID (e.g., lkc-xxxxx) |
CCLOUD_IDENTITY_POOL_ID |
Confluent Cloud identity pool ID (e.g., pool-xxxxx) |
Secrets Setup¶
| Secret | Purpose |
|---|---|
tls |
JKS truststore for verifying Confluent Cloud's server certificate (switchover state) |
file-store-idp-credentials |
Maps the ANONYMOUS identity to IdP OAuth client credentials (switchover state) |
file-store-config |
File store separator configuration |
oauth-jaas |
OAuth JAAS config for gateway-to-CCloud authentication (switchover state) |
1. Confluent Cloud TLS truststore¶
cp $JAVA_HOME/lib/security/cacerts ccloud-truststore.jks
echo "jksPassword=${JKS_PASSWORD}" > ccloud-jksPassword.txt
kubectl create secret generic tls \
--from-file=truststore.jks=ccloud-truststore.jks \
--from-file=jksPassword.txt=ccloud-jksPassword.txt \
-n ${KUBECTL_NAMESPACE}
2. File store credential mapping¶
Maps ANONYMOUS to OAuth client credentials:
kubectl create secret generic file-store-idp-credentials \
--from-literal=ANONYMOUS="${OAUTH_CLIENT_ID}/${OAUTH_CLIENT_SECRET}" \
-n ${KUBECTL_NAMESPACE}
3. File store config¶
kubectl create secret generic file-store-config \
--from-literal=separator="/" \
-n ${KUBECTL_NAMESPACE}
4. OAuth JAAS config¶
Important: The secret key must be oauth-jass.conf (single 'a'), not oauth-jaas.conf.
kubectl create secret generic oauth-jaas \
--from-literal=oauth-jass.conf="org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginModule required clientId=\"%s\" clientSecret=\"%s\" extension_logicalCluster=\"${CCLOUD_LOGICAL_CLUSTER}\" extension_identityPoolId=\"${CCLOUD_IDENTITY_POOL_ID}\";" \
-n ${KUBECTL_NAMESPACE}
Note: Set CCLOUD_LOGICAL_CLUSTER and CCLOUD_IDENTITY_POOL_ID environment variables to your Confluent Cloud values before running this command. These IDs link the OAuth token to your CCloud identity pool.
Confluent Cloud Identity Provider Setup¶
Before deploying the gateway, configure an OAuth-compatible identity provider on Confluent Cloud:
https://docs.confluent.io/cloud/current/security/authenticate/workload-identities/identity-providers/oauth/overview.html
Key steps:
1. Create an identity provider pointing to your IdP's JWKS endpoint
2. Create an identity pool that maps token claims to a CCloud identity
3. Note the logical cluster ID (lkc-xxxxx) and identity pool ID (pool-xxxxx) — these go into the oauth-jaas secret
Gateway YAMLs¶
gateway_init.yaml¶
apiVersion: platform.confluent.io/v1beta1
kind: Gateway
metadata:
labels:
app.kubernetes.io/name: confluent-for-kubernetes
app.kubernetes.io/managed-by: kustomize
name: migration-gateway
spec:
replicas: 3
image:
application: <gateway-image>
init: confluentinc/confluent-init-container:3.1.0
podTemplate:
envVars:
- name: GATEWAY_ROOT_LOG_LEVEL
value: DEBUG # Can be changed to INFO for production
streamingDomains:
- name: source-kafka-cluster
type: kafka
kafkaCluster:
bootstrapServers:
- id: UNAUTHED
# Replace with your MSK bootstrap server (plaintext port 9092 for unauthenticated access)
endpoint: PLAINTEXT://<msk-bootstrap-server>:9092
nodeIdRanges:
- name: pool-1
start: 1
end: 3
routes:
- name: migration-route
endpoint: <gateway-lb-hostname>:9595
brokerIdentificationStrategy:
type: port
streamingDomain:
name: source-kafka-cluster
bootstrapServerId: UNAUTHED
security:
client:
authentication:
type: none
auth: passthrough
externalAccess:
type: loadBalancer
loadBalancer:
domain: <gateway-lb-hostname>
gateway_fenced.yaml¶
apiVersion: platform.confluent.io/v1beta1
kind: Gateway
metadata:
labels:
app.kubernetes.io/name: confluent-for-kubernetes
app.kubernetes.io/managed-by: kustomize
name: migration-gateway
spec:
replicas: 3
image:
application: <gateway-image>
init: confluentinc/confluent-init-container:3.1.0
podTemplate:
envVars:
- name: GATEWAY_ROOT_LOG_LEVEL
value: DEBUG # Can be changed to INFO for production
streamingDomains:
- name: source-kafka-cluster
type: kafka
kafkaCluster:
bootstrapServers:
- id: UNAUTHED
endpoint: PLAINTEXT://<msk-bootstrap-server>:9092
nodeIdRanges:
- name: pool-1
start: 1
end: 3
routes:
- name: migration-route
endpoint: <gateway-lb-hostname>:9595
fence:
scope: ALL
errorCode: BROKER_NOT_AVAILABLE
brokerIdentificationStrategy:
type: port
streamingDomain:
name: source-kafka-cluster
bootstrapServerId: UNAUTHED
security:
client:
authentication:
type: none
auth: passthrough
externalAccess:
type: loadBalancer
loadBalancer:
domain: <gateway-lb-hostname>
gateway_switchover.yaml¶
apiVersion: platform.confluent.io/v1beta1
kind: Gateway
metadata:
labels:
app.kubernetes.io/name: confluent-for-kubernetes
app.kubernetes.io/managed-by: kustomize
name: migration-gateway
spec:
replicas: 3
image:
application: <gateway-image>
init: confluentinc/confluent-init-container:3.1.0
podTemplate:
envVars:
- name: GATEWAY_ROOT_LOG_LEVEL
value: DEBUG # Can be changed to INFO for production
- name: GATEWAY_OPTS
# Replace with your token endpoint URI (must match tokenEndpointUri below)
value: "-Dorg.apache.kafka.sasl.oauthbearer.allowed.urls=<token-endpoint-uri>"
secretStores:
- name: file-store
provider:
type: File
configSecretRef: file-store-config
clientCredentialsRef: file-store-idp-credentials
streamingDomains:
- name: confluent-cloud
type: kafka
kafkaCluster:
bootstrapServers:
- id: OAUTH
# Replace with your Confluent Cloud bootstrap server
endpoint: SASL_SSL://<ccloud-bootstrap-server>:9092
tls:
secretRef: tls
nodeIdRanges:
- name: pool-1
start: 0
end: 17
routes:
- name: migration-route
endpoint: <gateway-lb-hostname>:9595
brokerIdentificationStrategy:
type: port
streamingDomain:
name: confluent-cloud
bootstrapServerId: OAUTH
security:
auth: swap
secretStore: file-store
client:
authentication:
type: none
cluster:
authentication:
type: oauth
jaasConfigPassThrough:
secretRef: oauth-jaas
oauthSettings:
# Replace with your token endpoint URI (must match tokenEndpointUri below)
tokenEndpointUri: <token-endpoint-uri>
externalAccess:
type: loadBalancer
loadBalancer:
domain: <gateway-lb-hostname>
Important: <token-endpoint-uri> appears in two places and both must be set to the same value:
1. spec.podTemplate.envVars[GATEWAY_OPTS].value
2. spec.routes[0].security.cluster.authentication.oauthSettings.tokenEndpointUri
Client Configuration¶
No client configuration needed. Client authentication is none — clients connect without credentials.