Configure Security for Confluent Gateway using Confluent for Kubernetes

Configure security for Confluent Gateway deployed with Confluent for Kubernetes (CFK). Because Confluent Gateway sits between your Apache Kafka® clients and clusters, the Confluent Gateway controls how clients authenticate, how it encrypts traffic in transit, and how it stores credentials. Configure authentication, TLS/SSL, passwords, and secret stores to protect client connections and the credentials Confluent Gateway uses to reach your brokers.

Confluent Gateway supports the following security configurations with CFK:

Security best practices

Confluent Gateway deployments have two authentication layers:

  • Client to Confluent Gateway: Clients authenticate to Confluent Gateway using SASL/PLAIN, SASL/SCRAM, mTLS, or NONE.

  • Confluent Gateway to broker: Confluent Gateway authenticates to the backing Kafka cluster using SASL/PLAIN, SASL/OAUTHBEARER, or NONE. Store these credentials in AWS Secrets Manager, HashiCorp Vault, Azure Key Vault, or a local directory.

To secure both layers, follow these authentication best practices:

  • Use a dedicated credential for each client. Give every client its own Confluent Gateway-to-broker SASL credential. Don’t map multiple clients to a single credential or share static credentials across clients, so that you can audit and revoke access for each client independently.

  • Prefer SASL/SCRAM over SASL/PLAIN. Unlike SASL/PLAIN, SASL/SCRAM doesn’t send passwords in cleartext and protects against dictionary attacks using salted hashes.

Configure authentication for Confluent Gateway

Confluent Gateway supports the following modes for forwarding client traffic to Kafka clusters. Use security.client to set how clients authenticate to Confluent Gateway. This setting applies to the whole route. Use security.cluster to set the mode for each streaming domain that the route is bound to, with the streaming domain name as the key. If a bound streaming domain has no entry, Confluent Gateway uses identity passthrough for it.

To update a Confluent Gateway CR that uses the CFK 3.3 settings, see Update Confluent Gateway security settings before you upgrade to 3.4.

Note

Route authentication, which includes the security.client and security.cluster settings, is an Early Access feature that is part of topic-based routing in Confluent Gateway 1.4 and CFK 3.4. Property names and YAML structure might change before General Availability (GA), and the changes might not be backward compatible.

  • Identity passthrough: Confluent Gateway forwards client credentials directly to Kafka clusters without modification.

    Use identity passthrough when the authentication method is uniform across clients and you want Confluent Gateway to forward credentials to brokers unchanged.

    Identity passthrough supports all SASL authentication mechanisms, such as SASL/PLAIN, SASL/SCRAM, and SASL/OAUTHBEARER.

  • Authentication swapping: Confluent Gateway transforms client credentials into different credentials before connecting to Kafka clusters.

    When you enable this mode, Confluent Gateway authenticates incoming clients, optionally using a different authentication mechanism than the backing Kafka cluster. Confluent Gateway then swaps the client identity and credentials as it forwards requests to brokers.

    With authentication swapping:

    • For client-to-Confluent Gateway authentication, Confluent Gateway supports SASL/PLAIN, SASL/SCRAM, SASL/OAUTHBEARER, mTLS, or NONE.

    • For Confluent Gateway-to-Kafka cluster authentication, Confluent Gateway supports SASL/PLAIN, SASL/OAUTHBEARER, or NONE.

    Use authentication swapping when you need to:

    • Migrate clients between source and destination clusters that have different authentication requirements, without modifying client applications.

    • Share cluster access with external clients while maintaining your internal authentication standards, even when you cannot enforce those standards directly on the client side.

    The following diagram shows a sample authentication swapping flow:

    Authentication swapping illustration from client through Confluent Gateway to Kafka in a CFK setup.

Consider the following when you select the authentication mode in Confluent Gateway:

  • You configure identity passthrough or authentication swapping for each streaming domain that a route is bound to. A route that is bound to more than one streaming domain, such as a dynamic route that uses topic-based routing, can swap credentials for one streaming domain and pass them through for another.

  • Clients authenticate to the route one way, regardless of the streaming domain they read from or write to. You cannot configure multiple client authentication mechanisms for the same route.

  • You cannot use identity passthrough for mTLS because TLS terminates at Confluent Gateway. Authentication swapping is mandatory for mTLS clients.

  • Authentication swapping requires more configuration, such as identity stores, key management systems (KMS), and mappings, but adds flexibility and supports more complex enterprise scenarios.

  • Authentication swapping with multi-cluster streaming domains requires identical user identities and role-based access control (RBAC) policies across all clusters. If clusters have different authentication systems or user permissions, use separate streaming domains instead.

Configure identity passthrough

When you configure a route for identity passthrough, Confluent Gateway forwards unaltered authentication information directly to Kafka brokers and does not authenticate incoming clients itself. The brokers perform authentication and authorization checks.

Identity passthrough supports SASL authentication mechanisms, such as SASL/PLAIN, SASL/SCRAM, and SASL/OAUTHBEARER.

To configure a route for identity passthrough in CFK:

kind: Gateway
spec:
  routes:
    - name:
      security:
        client:
          authentication:
            type: oauth                --- [1]
            mtls:
              sslClientAuthentication: --- [2]
          tls:                         --- [3]
        cluster:                       --- [4]
          <streaming-domain-name>:     --- [5]
            auth: passthrough          --- [6]
            extensionHeaders:          --- [7]
              logicalCluster:
  • [1] To have Confluent Gateway inject SASL extension headers (see [7]) into an OAUTHBEARER client’s authentication request before forwarding it to the backing Kafka cluster, set the client authentication type to oauth. Use this when clients authenticate to Confluent Cloud with SASL/OAUTHBEARER and you want Confluent Gateway to set the logical cluster (lkc) extension on their behalf. This keeps client configurations independent of the active cluster, so authentication continues to succeed after a failover.

    A passthrough entry doesn’t need oauthSettings. Confluent Gateway forwards the client’s token unmodified.

  • [2] If using TLS, set sslClientAuthentication to required to require clients to present their certificates. Set to requested for optional certificate presentation.

  • [3] The TLS configuration for the client to Confluent Gateway communication. For more information, see TLS/SSL configuration.

  • [4] How Confluent Gateway authenticates to each streaming domain that the route is bound to. A streaming domain with no entry uses passthrough, so you can omit security.cluster when every bound streaming domain uses identity passthrough.

  • [5] The name of a streaming domain that the route is bound to. Must match a spec.streamingDomains[].name.

  • [6] The authentication mode for the streaming domain. passthrough is the default. Don’t set secretStore on a passthrough entry.

  • [7] One or more SASL extension headers that Confluent Gateway adds to the client’s OAUTHBEARER authentication request to the backing Kafka cluster. Each header is a key-value pair. Set logicalCluster to the target cluster ID, for example, lkc-abc123. Confluent Gateway honors extensionHeaders only when auth is passthrough and the client authentication type is oauth.

Sample configurations for identity passthrough

The following example configures TLS for the client-to-Confluent Gateway connection:

kind: Gateway
spec:
  routes:
    - name:
      security:
        client:
          authentication:
            type: plain
          tls:
            secretRef: my-tls-secret

The following example configures TLS for the client-to-Confluent Gateway connection and requires client certificates:

kind: Gateway
spec:
  routes:
    - name:
      security:
        client:
          authentication:
            type: plain
            mtls:
              sslClientAuthentication: "required"
          tls:
            secretRef: my-tls-secret

The following example injects a logical cluster header for SASL/OAUTHBEARER identity passthrough:

kind: Gateway
spec:
  routes:
    - name:
      security:
        client:
          authentication:
            type: oauth
        cluster:
          ccloud-active:
            auth: passthrough
            extensionHeaders:
              logicalCluster: 'lkc-abc123'

Setting extensionHeaders on a security.cluster entry requires client.authentication.type: oauth and auth: passthrough for that entry.

OAUTHBEARER passthrough limitation

In CFK 3.3, a Confluent Gateway passthrough route that sets cluster.extensionHeaders is rejected at admission unless you set placeholder values for oauthSettings.jwksEndpointUri and oauthSettings.audience. This limitation doesn’t apply to CFK 3.4, which doesn’t require oauthSettings on a passthrough entry.

Configure authentication swapping

When you configure a streaming domain for authentication swapping, Confluent Gateway authenticates incoming clients, optionally using a different authentication mechanism than the backing Kafka cluster. Confluent Gateway then swaps the client identity and credentials as it forwards requests to Kafka brokers.

Authentication swapping requires identity mapping, which integrates with external KMS or secret stores.

Confluent Gateway supports the following secret stores for fetching credentials:

  • HashiCorp Vault

  • AWS Secrets Manager

  • Azure Key Vault

To configure a route for authentication swapping in CFK:

kind: Gateway
spec:
  routes:
    - name:                       --- [1]
      security:
        client:                   --- [2]
        cluster:                  --- [3]
          <streaming-domain-name>:  --- [4]
            auth: swap            --- [5]
            secretStore:          --- [6]
            authentication:       --- [7]
  • [1] The unique name for the route.

  • [2] How clients authenticate to Confluent Gateway. You configure it once for the route. For more information, see Client authentication for authentication swapping.

  • [3] How Confluent Gateway authenticates to each streaming domain that the route is bound to. Add one entry for each streaming domain that you want to swap credentials for. A streaming domain with no entry uses identity passthrough. CFK ignores an entry that names a streaming domain that the route isn’t bound to.

  • [4] The name of a streaming domain that the route is bound to. Must match a spec.streamingDomains[].name.

  • [5] The authentication mode for the streaming domain. Set to swap to enable authentication swapping.

  • [6] Reference to a secret store for exchanging credentials. For more information, see Secret store configuration. Allowed only when auth is swap.

  • [7] Required when auth is swap. How Confluent Gateway authenticates to the Kafka cluster after swapping. For more information, see Cluster authentication for authentication swapping.

If a client authentication type is oauth and any security.cluster entry uses auth: swap, security.client.authentication.oauthSettings must set jwksEndpointUri.

Client authentication for authentication swapping

Configure how clients authenticate to Confluent Gateway for authentication swapping. You configure client authentication in security.client once for the route. Set auth: swap on a security.cluster entry (Configure authentication swapping) to enable swapping for a streaming domain. Examples that show only security.client and secretStore omit the authentication block that each swap entry also requires. For more information, see Cluster authentication for authentication swapping.

You can use SASL/PLAIN, SASL/SCRAM, SASL/OAUTHBEARER, mTLS, or NONE authentication methods.

SASL authentication

kind: Gateway
spec:
  routes:
    - name:
      security:
        client:
          authentication:
            type:                      --- [1]
            jaasConfig:                --- [2]
              secretRef:               --- [3]
            jaasConfigPassThrough:     --- [4]
              secretRef:               --- [5]
              directoryPathInContainer: -- [6]
          connectionsMaxReauthMs:      --- [7]
  • [1] The SASL mechanism to use. Set to plain for SASL/PLAIN authentication.

  • [2] jaasConfig provides the SASL credentials for client authentication. Specify either jaasConfig or jaasConfigPassThrough, not both.

  • [3] The Kubernetes secret that holds the jaasConfig credentials.

    To learn more about creating the JAAS configuration secret, see Create client-side SASL/PLAIN credentials using JAAS configuration.

  • [4] jaasConfigPassThrough is an alternative to jaasConfig ([2]) that supplies the JAAS configuration directly, from a secret ([5]) or a mounted directory ([6]).

  • [5] The Kubernetes secret that holds the jaasConfigPassThrough credentials.

    To learn more about creating the JAAS Passthrough credentials, see Create client-side SASL/PLAIN JAAS pass-through credentials.

  • [6] The directory path in the container that contains the JAAS configuration file.

    To learn more about creating the JAAS Passthrough credentials, see Create client-side SASL/PLAIN JAAS pass-through credentials.

  • [7] Maximum time in milliseconds before requiring client reauthentication. If the client does not reauthenticate within this time frame, the connection is closed. Default is 0.

SASL/SCRAM authentication

Confluent Gateway supports SASL/SCRAM authentication for client-to-Confluent Gateway connections. When you use SCRAM with authentication swapping, you have three options for managing SCRAM credentials:

  • Store SCRAM credentials in the same secret store as authentication swapping: Confluent Gateway stores SCRAM credentials in the route’s secret store.

  • Store SCRAM credentials in a SCRAM-specific secret store: Confluent Gateway stores SCRAM credentials in a separate secret store from other authentication swap credentials.

  • Manage SCRAM credentials with the Kafka administrator API: Confluent Gateway automatically manages SCRAM credentials by creating and updating SCRAM user credentials through the Kafka administrator API.

kind: Gateway
spec:
  routes:
    - name:
      security:
        client:
          authentication:
            type: scram                    --- [2]
            scram:
              alterScramCredentials:       --- [3]
              scramCredentialsTtlMs:       --- [4]
              secretStore:                 --- [5]
              admin:
                secretRef:                 --- [6]
        cluster:
          <streaming-domain-name>:
            auth: swap
            secretStore:                   --- [1]
  • [1] The secret store reference for authentication swapping, set on the security.cluster entry. For more information, see Secret store configuration.

  • [2] The authentication type. Set to scram to enable SCRAM authentication for clients.

  • [3] Optional. When set to true, enables Confluent Gateway to manage SCRAM user credentials by creating and updating them through the Kafka administrator API. This field requires administrator credentials. The default is false.

  • [4] Optional. The time-to-live, in milliseconds, for cached SCRAM credentials. The default is 600000 (10 minutes).

  • [5] Optional. Refers to a SCRAM-specific secret store. If not specified, the field uses the secret store defined in secretStore ([1]).

  • [6] Required when alterScramCredentials: true. Refers to administrator credentials in the secret store that Confluent Gateway uses to perform SCRAM credential operations. Ensure these credentials are present in the secret store and that the administrator user has the required permissions to alter and describe SCRAM credentials.

When type is scram, set the scram block. If you use the defaults, set scram: {}.

Configuration scenario 1: Using the same secret store as authentication swapping

In this configuration, you store SCRAM credentials in the route’s secret store.

kind: Gateway
spec:
  routes:
    - name: gateway-route
      security:
        client:
          authentication:
            type: scram
            scram: {}
        cluster:
          payments:
            auth: swap
            secretStore: vault-store

Configuration scenario 2: Using a SCRAM-specific secret store

In this configuration, you store SCRAM credentials in a separate secret store from other authentication swap credentials.

kind: Gateway
spec:
  routes:
    - name: gateway-route
      security:
        client:
          authentication:
            type: scram
            scram:
              secretStore: scram-secret-store
        cluster:
          payments:
            auth: swap
            secretStore: vault-store

Configuration scenario 3: Managing SCRAM credentials from Confluent Gateway

In this configuration, you enable Confluent Gateway to automatically create and update SCRAM user credentials through the Kafka administrator API. Ensure that:

  • secretRef contains the username and password.

  • The administrator user has the necessary permissions to perform AlterUserScramCredentials and DescribeUserScramCredentials operations on the Kafka cluster.

kind: Gateway
spec:
  routes:
    - name: gateway-route
      security:
        client:
          authentication:
            type: scram
            scram:
              alterScramCredentials: true
              admin:
                secretRef: scram-admin-credentials
        cluster:
          payments:
            auth: swap
            secretStore: vault-store

Note

When you set alterScramCredentials: true, ensure that Confluent Gateway has the necessary permissions to create, update, and delete secrets. For required permissions, see Secret store configuration.

SASL/OAUTHBEARER authentication

Confluent Gateway supports SASL/OAUTHBEARER authentication for client-to-Confluent Gateway connections. The client presents an OAuth bearer token (a JSON Web Token, or JWT), and Confluent Gateway validates it against your identity provider’s JSON Web Key Set (JWKS) endpoint.

After validation, Confluent Gateway reads the client principal from a claim in the token (the sub claim by default) and uses it as the key to look up the swapped credentials in the secret store. Confluent Gateway then uses those credentials to authenticate to the Kafka cluster.

kind: Gateway
spec:
  routes:
    - name:
      security:
        client:
          authentication:
            type: oauth                --- [2]
            jaasConfigPassThrough:
              secretRef:                --- [3]
            oauthSettings:
              jwksEndpointUri:         --- [4]
              audience:                --- [5]
              expectedIssuer:          --- [6]
              subClaimName:            --- [7]
          connectionsMaxReauthMs:      --- [8]
        cluster:
          <streaming-domain-name>:
            auth: swap
            secretStore:               --- [1]
  • [1] The secret store reference for authentication swapping, set on the security.cluster entry. For more information, see Secret store configuration.

  • [2] The authentication type. Set to oauth to enable SASL/OAUTHBEARER authentication for clients.

  • [3] The Kubernetes secret that holds the JAAS configuration for the client inbound authentication.

  • [4] Required when any security.cluster entry uses auth: swap. The JWKS endpoint URI that Confluent Gateway uses to validate the signature of the inbound token.

  • [5] The expected audience (aud claim) in the token. Confluent Gateway rejects tokens whose audience does not match this value.

  • [6] Optional. The expected issuer (iss claim) in the token.

  • [7] Optional. The token claim that Confluent Gateway uses as the client principal and the secret store lookup key. The default is sub.

  • [8] Optional. Maximum time in milliseconds (ms) before requiring client reauthentication. The default is 0 (no reauthentication required).

Note

When you set type: oauth and any security.cluster entry uses auth: swap, oauthSettings.jwksEndpointUri is required. CFK rejects the Confluent Gateway custom resource at admission if it is missing.

mTLS authentication

kind: Gateway
spec:
  routes:
    - name:
      security:
        client:
          authentication:
            type:                      --- [1]
            mtls:
              principalMappingRules:   --- [2]
              sslClientAuthentication: --- [3]
          tls:
            secretRef:
  • [1] The client authentication mechanism to use. Set to mtls for mTLS authentication.

  • [2] The pattern to read principal name from the certificates. Required for authentication swapping with mTLS authentication.

  • [3] The SSL client authentication mode. Set to "required" to enable mandatory mTLS authentication from the client side and to enforce certificate presentation. Valid values are "requested" and "required".

NONE authentication

kind: Gateway
spec:
  routes:
    - name:
      security:
        client:
          authentication:
            type: none                   --- [1]
  • [1] The client authentication mechanism to use. Set to none to use NONE client authentication.

When you use none, Confluent Gateway identifies all incoming clients as anonymous and assigns the client ID ANONYMOUS. Configure the swapped credentials for the ANONYMOUS user in the associated secret store.

Cluster authentication for authentication swapping

Configure how Confluent Gateway authenticates to the Kafka cluster for authentication swapping. You configure it for each streaming domain in security.cluster. Authentication swapping requires security.client.authentication.

You can use SASL/PLAIN, SASL/OAUTHBEARER, or NONE authentication methods.

SASL authentication

kind: Gateway
spec:
  routes:
    - name:
      security:
        cluster:
          payments:
            auth: swap
            secretStore:                            --- [7]
            authentication:
              type:                                 --- [1]
              jaasConfigPassThrough:                --- [2]
                secretRef:                          --- [3]
                directoryPathInContainer:           --- [4]
              oauthSettings:                        --- [5]
                tokenEndpointUri:                   --- [6]
  • [1] The SASL mechanism to use. Set to plain for SASL/PLAIN authentication, or oauth for SASL/OAUTHBEARER authentication.

  • [2] Required for SASL/PLAIN authentication. Only jaasConfigPassThrough is supported for cluster authentication.

  • [3] The Kubernetes secret that holds the credentials. Specify either secretRef or directoryPathInContainer ([4]), not both.

    The secret file content must use the following format:

    org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginModule required clientId="%s" clientSecret="%s";
    
  • [4] The directory path in the container that contains the JAAS Passthrough configuration file.

    To learn more about creating the JAAS Passthrough credentials, see Create client-side SASL/PLAIN JAAS pass-through credentials.

  • [5] The OAuth settings for cluster authentication, such as the token endpoint URI ([6]). Required only if the entry’s authentication.type is oauth ([1]).

  • [6] The URI for the OAuth token endpoint.

    You must also configure the GATEWAY_OPTS environment variable in podTemplate.envVars to set the org.apache.kafka.sasl.oauthbearer.allowed.urls JVM system property to this URL. Without this, Confluent Gateway authentication fails with a ConfigException indicating the URL is not allowed.

  • [7] The name of the secret store that holds the credentials that Confluent Gateway uses for this streaming domain. Must match a spec.secretStores[].name. For more information, see Secret store configuration.

NONE authentication

The NONE authentication method disables authentication between Confluent Gateway and the cluster. When you use this method, Confluent Gateway ignores the client ID and bypasses cluster authentication.

Because Confluent Gateway doesn’t perform a secret lookup, don’t configure a secret store.

kind: Gateway
spec:
  routes:
    - name:
      security:
        cluster:
          payments:
            auth: swap
            authentication:
              type: none                   --- [1]
  • [1] The cluster authentication mechanism to use. Set to none to use NONE cluster authentication.

Sample configurations for authentication swapping

When you use SASL/OAUTHBEARER for cluster authentication, update the following in your Confluent Gateway configuration:

  1. Set bootstrapServers in the streamingDomains section to your Kafka cluster’s OAuth listener. For example, SASL_SSL://kafka.example.com:9093. For more information, see Configure streaming domains.

  2. Set tokenEndpointUri in the security.cluster entry’s authentication.oauthSettings to your OAuth token endpoint URL. For example, https://<your-oauth-server.com>/oauth2/token.

  3. Set GATEWAY_OPTS in podTemplate.envVars to the same OAuth token endpoint URL to configure the org.apache.kafka.sasl.oauthbearer.allowed.urls JVM system property, which allows the OAuth token endpoint. Without this, Confluent Gateway authentication fails with a ConfigException indicating the URL is not allowed.

SASL/PLAIN to SASL/OAUTHBEARER example:

kind: Gateway
spec:
  podTemplate:
    envVars:
      - name: GATEWAY_OPTS
        value: "-Dorg.apache.kafka.sasl.oauthbearer.allowed.urls=https://idp.mycompany.io:8080/realms/cp/protocol/openid-connect/token"
  routes:
    - name: route-name
      security:
        client:
          authentication:
            type: plain
            jaasConfig:
                secretRef: plain-secrets
          connectionsMaxReauthMs:
          tls:
        cluster:
          payments:
            auth: swap
            secretStore: "oauth-secrets"
            authentication:
              type: oauth
              jaasConfigPassThrough:
                secretRef: oauth-jaas-template
              oauthSettings:
                tokenEndpointUri: "https://idp.mycompany.io:8080/realms/cp/protocol/openid-connect/token"

mTLS to SASL/OAUTHBEARER example:

kind: Gateway
spec:
  podTemplate:
    envVars:
      - name: GATEWAY_OPTS
        value: "-Dorg.apache.kafka.sasl.oauthbearer.allowed.urls=https://idp.mycompany.io:8080/realms/cp/protocol/openid-connect/token"
  routes:
    - name: route-name
      security:
        client:
          authentication:
            type: mtls
            mtls:
              principalMappingRules: ["RULE:^CN=([a-zA-Z0-9._-]+),OU=.*$/$1/", "RULE:^UID=([a-zA-Z0-9._-]+),.*$/$1/","DEFAULT"]
              sslClientAuthentication: "required"
          tls:
            secretRef: tls-secrets
        cluster:
          payments:
            auth: swap
            secretStore: "oauth-secrets"
            authentication:
              type: oauth
              jaasConfigPassThrough:
                secretRef: oauth-jaas-template
              oauthSettings:
                tokenEndpointUri: "https://idp.mycompany.io:8080/realms/cp/protocol/openid-connect/token"

SASL/OAUTHBEARER to SASL/OAUTHBEARER (OAuth-to-OAuth) example:

In this configuration, the client presents an OAuth token to Confluent Gateway. Confluent Gateway validates the token against the client identity provider’s JWKS endpoint, then obtains a separate token from the cluster identity provider to authenticate to the Kafka cluster.

Because both legs use OAuth, set the org.apache.kafka.sasl.oauthbearer.allowed.urls JVM system property in GATEWAY_OPTS to a comma-separated list that includes both the client JWKS endpoint and the cluster token endpoint. Otherwise, Confluent Gateway authentication fails with a ConfigException that reports the URL is not allowed.

kind: Gateway
spec:
  podTemplate:
    envVars:
      - name: GATEWAY_OPTS
        value: "-Dorg.apache.kafka.sasl.oauthbearer.allowed.urls=https://idp.mycompany.io:8080/realms/clients/protocol/openid-connect/certs,https://idp.mycompany.io:8080/realms/cp/protocol/openid-connect/token"
  routes:
    - name: route-name
      security:
        client:
          authentication:
            type: oauth
            jaasConfigPassThrough:
              secretRef: client-oauth-jaas
            oauthSettings:
              jwksEndpointUri: "https://idp.mycompany.io:8080/realms/clients/protocol/openid-connect/certs"
              audience: "kafka-clients"
              expectedIssuer: "https://idp.mycompany.io:8080/realms/clients"
              subClaimName: "sub"
        cluster:
          payments:
            auth: swap
            secretStore: "oauth-secrets"
            authentication:
              type: oauth
              jaasConfigPassThrough:
                secretRef: cluster-oauth-jaas
              oauthSettings:
                tokenEndpointUri: "https://idp.mycompany.io:8080/realms/cp/protocol/openid-connect/token"

TLS/SSL configuration

Confluent Gateway uses TLS/SSL to encrypt connections and verify peer certificates. The same tls block configures encryption in two places:

  • streamingDomains.kafkaCluster.bootstrapServers.tls encrypts traffic from Confluent Gateway to the backing Kafka cluster.

  • routes.security.client.tls encrypts traffic from clients to Confluent Gateway.

The tls block supports the following fields with CFK:

tls:
  ignoreTrustStoreConfig:    --- [1]
  jksPassword:
    secretRef:               --- [2]
  secretRef:                 --- [3]
  directoryPathInContainer:  --- [4]
  • [1] Skip certificate validation (not recommended for production). Setting this to true trusts all certificates.

    Important

    Set ignoreTrustStoreConfig: false in all production configurations. Setting this to true disables TLS certificate validation, introducing critical security risks, such as:

    • Exposure to man-in-the-middle (MITM) attacks

    • Possibility of certificate spoofing

    • Compromise of encrypted traffic

    • Risk to data confidentiality

  • [2] Password that CFK uses for both JKS keystore and truststore. CFK also uses this password as the keystore’s key password.

  • [3] [4] Use either secretRef or directoryPathInContainer to provide the TLS/SSL certificates.

    The following example creates a Kubernetes secret with the JKS type TLS/SSL certificates:

    kubectl create secret generic kafka-tls \
      --from-file=keystore.jks=keystore.jks \
      --from-file=truststore.jks=truststore.jks \
      --from-file=jksPassword.txt=jksPassword.txt
    

    For details on how to create the TLS/SSL certificates, see Provide TLS keys and certificates in PEM format and Provide TLS keys and certificates in Java KeyStore format.

Note

Confluent Gateway doesn’t hot-reload TLS/SSL certificates because CFK doesn’t monitor referenced secrets. As a result, an in-place rotation (for example, by cert-manager) has no effect until the Confluent Gateway custom resource (CR) reconciles. To apply a rotated certificate, trigger a reconciliation to restart the Confluent Gateway pods and load the new certificate. For example, edit the Confluent Gateway spec.

Password configuration

Confluent Gateway supports the file-based and inline password configurations. Provide only one of the two.

password:
  file:                   --- [1]
  value:                  --- [2]
  • [1] The path to the password file.

  • [2] The inline password value.

Secret store configuration

Confluent Gateway uses secret stores, such as AWS Secrets Manager, Azure Key Vault, HashiCorp Vault, or a file, to securely manage authentication credentials and sensitive information. This setup is critical for several key operations:

  • Storing Confluent Gateway to Kafka broker credentials

  • Supporting authentication swapping scenarios

    When Confluent Gateway translates or “swaps” authentication, such as from mTLS clients to SASL/OAUTHBEARER brokers or the reverse, Confluent Gateway needs secret stores to store and fetch the swap credentials. This lets each client connection use its mapped broker credential, which enhances security and enables fine-grained access control.

Confluent Gateway should always interact with these secret stores over TLS for confidentiality and integrity.

As a security best practice, configure Confluent Gateway to assume IAM roles that follow the principle of least privilege. Don’t use static IAM user credentials, which can expose sensitive credentials.

Ensure proper role trust policies are in place and limit permissions to only what Confluent Gateway needs. For example in AWS:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "secretsmanager:GetSecretValue"
            ],
            "Resource": [
                "arn:aws:secretsmanager:us-east-1:123456789012:secret:gateway/*",
                "arn:aws:secretsmanager:us-east-1:123456789012:secret:confluent/*"
            ],
            "Condition": {
                "StringEquals": {
                    "aws:RequestTag/Environment": "production"
                }
            }
        }
    ]
}

When you use SCRAM authentication with automatic credential management (alterScramCredentials: true), Confluent Gateway requires additional permissions to create, update, and delete SCRAM user credentials in the secret store:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "secretsmanager:GetSecretValue",
                "secretsmanager:CreateSecret",
                "secretsmanager:PutSecretValue",
                "secretsmanager:DeleteSecret"
            ],
            "Resource": [
                "arn:aws:secretsmanager:us-east-1:123456789012:secret:gateway/*",
                "arn:aws:secretsmanager:us-east-1:123456789012:secret:confluent/*"
            ]
        }
    ]
}

Configure a secret store

Add the following configurations to the Confluent Gateway CR to configure a secret store:

kind: Gateway
spec:
  secretStores:
    - name:               --- [1]
      provider:
        type:             --- [2]
        configSecretRef:  --- [3]
        certificateRef:   --- [4]
  • [1] A unique name for the secret store.

  • [2] The type of the secret store. Set to AWS (AWS Secrets Managers), Azure (Azure Key Vault), Vault (HashiCorp Vault), or File (file).

  • [3] Required. The name of the Kubernetes secret that contains the secret store configuration.

  • [4] Optional. The name of the Kubernetes secret that contains the certificates to mount as a volume in the Confluent Gateway pod.

The following sections provide examples for creating secret store configurations that you specify in the gateway.spec.secretStores.provider.configSecretRef field.

Create a secret store configuration for HashiCorp Vault

Note

Confluent Gateway does not support connecting to HashiCorp Vault using a certificate.

HashiCorp Vault configuration supports the following fields:

  • address: Required. Sets the address (URL) of the Vault server instance to connect to.

  • authMethod: Required. The authentication method to use. You can set this to Token (the default value) or leave it empty.

  • authToken: The authentication token for the Vault server to connect using the authToken method.

  • path: Required. The path to the secret in Vault.

  • prefixPath: The prefix path to the secret store.

  • separator: The separator for the secret store. The default value is :.

  • role: The role to use to connect to the Vault server.

  • secret: The secret to use to connect to the Vault server.

  • username: The username to use to connect to the Vault server.

  • password: The password to use to connect to the Vault server.

The following example creates a Kubernetes secret for HashiCorp Vault using an authentication token configuration:

kubectl create secret generic vault-config \
  --from-literal=address="https://vault.prod.company.com" \
  --from-literal=authMethod="Token" \
  --from-literal=authToken="<auth-token>" \
  --from-literal=path="/secrets/prod/gateway/swap-creds" \
  --from-literal=prefixPath="" \
  --from-literal=separator=":"

The following example creates a Kubernetes secret for HashiCorp Vault using an AppRole configuration:

kubectl create secret generic vault-config \
  --from-literal=address="https://vault.prod.company.com" \
  --from-literal=authMethod="AppRole" \
  --from-literal=role="<app-role>" \
  --from-literal=secret="<app-role-secret>" \
  --from-literal=path="/secrets/prod/gateway/swap-creds" \
  --from-literal=prefixPath="" \
  --from-literal=separator=":"

The following example creates a Kubernetes secret for HashiCorp Vault using a username and password configuration:

kubectl create secret generic vault-config \
  --from-literal=address="https://vault.prod.company.com" \
  --from-literal=authMethod="UserPass" \
  --from-literal=username="<username>" \
  --from-literal=password="<password>" \
  --from-literal=path="/secrets/prod/gateway/swap-creds" \
  --from-literal=prefixPath="" \
  --from-literal=separator=":"

Additional Vault capabilities for SCRAM credential management

When you use SCRAM authentication with automatic credential management (alterScramCredentials: true), Confluent Gateway requires additional Vault capabilities to create, update, and delete SCRAM user credentials.

HashiCorp Vault uses policies to grant capabilities. Ensure Confluent Gateway has the following capabilities on the secret paths:

path "secret/data/gateway/*" {
  capabilities = ["create", "read", "update", "delete"]
}

For more information on Vault policies, see Policies | Vault | HashiCorp Developer.

Create a secret store configuration for AWS Secrets Manager

If the environment, such as EC2, has an IAM role attached with sufficient permissions, you don’t need to specify accessKey or secretKey. The provider automatically assumes the attached IAM role through the default AWS credential provider chain.

AWS Secrets Manager configuration supports the following fields:

  • region of the AWS Secrets Manager.

  • accessKey of the AWS IAM Access Key ID. Only required when authenticating with IAM user credentials.

  • secretKey of the AWS IAM Secret Key corresponding to the accessKey. Only required when authenticating with IAM user credentials.

  • separator of the AWS Secrets Manager. Defaults to :.

The following example creates a Kubernetes secret for AWS Secrets Manager using an IAM role configuration:

kubectl create secret generic aws-us-west-2-secret-mgr-config \
  --from-literal=region="us-west-2" \
  --from-literal=accessKey="<ACCESS_KEY>" \
  --from-literal=secretKey="<SECRET_KEY>" \
  --from-literal=separator="/"

Create a secret store configuration for Azure Key Vault

Azure Key Vault configuration supports the following fields:

  • vaultUrl of the Azure Key Vault to connect to.

  • credentialType of the Azure Key Vault.

  • tenantId of the Azure Key Vault.

  • clientId of the Azure Key Vault.

  • clientSecret of the Azure Key Vault.

  • prefixPath of the Azure Key Vault. The prefix path to the secret store. Defaults to an empty string.

  • username of the Azure Key Vault.

  • password of the Azure Key Vault.

  • certificateType of the Azure Key Vault. You can connect to Azure Key Vault using the Privacy-Enhanced Mail (PEM) or Personal Information Exchange (PFX) format certificates. Set to PFX for PFX certificates or PEM for PEM certificates.

  • certificatePath of the Azure Key Vault.

  • certificatePfxPassword of the Azure Key Vault.

  • certificateSendChain of the Azure Key Vault.

  • separator: The character or string used to split authentication data within the retrieved secret. Defaults to :.

The following example creates a Kubernetes secret for Azure Key Vault using Client ID and Secret configuration:

kubectl create secret generic azure-eu-vault-config \
  --from-literal=vaultUrl="https://authswap.vault.azure.net/" \
  --from-literal=credentialType="ClientCertificate" \
  --from-literal=tenantId="<TENANT_ID>" \
  --from-literal=clientId="<CLIENT_ID>" \
  --from-literal=certificateType="PFX" \
  --from-literal=certificatePfxPassword="password" \
  --from-literal=separator="/"

The following example creates a Kubernetes secret for Azure Key Vault using Username and Password configuration:

kubectl create secret generic azure-eu-vault-config \
  --from-literal=vaultUrl="https://authswap.vault.azure.net/" \
  --from-literal=credentialType="UsernamePassword" \
  --from-literal=tenantId="<TENANT_ID>" \
  --from-literal=clientId="<CLIENT_ID>" \
  --from-literal=username="<USERNAME>" \
  --from-literal=password="<PASSWORD>" \
  --from-literal=separator="/"

The following example creates a Kubernetes secret for Azure Key Vault using Client Certificate configuration:

kubectl create secret generic azure-keyvault \
  --from-literal=vaultUrl="https://authswap.vault.azure.net/" \
  --from-literal=credentialType="ClientCertificate" \
  --from-literal=tenantId="<TENANT_ID>" \
  --from-literal=clientId="<CLIENT_ID>" \
  --from-literal=certificateType="PEM" \
  --from-literal=certificatePath="/opt/ssl/client-cert.pem" \
  --from-literal=separator="/"

The following example creates a Kubernetes secret for Azure Key Vault using PFX certificate configuration:

kubectl create secret generic azure-keyvault \
  --from-literal=vaultUrl="https://authswap.vault.azure.net/" \
  --from-literal=credentialType="ClientCertificate" \
  --from-literal=tenantId="<TENANT_ID>" \
  --from-literal=clientId="<CLIENT_ID>" \
  --from-literal=certificateType="PFX" \
  --from-literal=certificatePath="/opt/ssl/client-cert.pfx" \
  --from-literal=certificatePfxPassword="<pfx-password>" \
  --from-literal=separator="/"

Note

Azure Key Vault does not support SCRAM authentication.

Create a file-based secret store configuration

In file-based secret store configuration, each file represents the incoming client’s username. For example, if an incoming username is sales-cp-app and you want to swap it to sales-cc-app, the <path_to_credentials>/sales-cp-app file on your workstation should contain sales-cc-app:sales-cc-secret-key.

Confluent Gateway mounts your client credentials secret as a volume in the Confluent Gateway pod, so each key in the secret becomes a file. At runtime, Confluent Gateway matches the incoming client username to the file of the same name and reads its contents as the swapped credential. The provider type takes its name from this file-based lookup.

The separator field sets the delimiter between the swapped username and secret key in each credential file. It defaults to :.

To provision the secret, create a Kubernetes secret containing your credential mappings using one of these methods:

  • From a single credential file:

    kubectl create secret generic file-secret \
      --from-file=sales-cp-app=<path_to_credentials>/sales-cp-app
    
  • From several credential files: Include credential mappings for several incoming usernames within a single Kubernetes secret:

    kubectl create secret generic file-secret \
      --from-file=sales-cp-app=<path_to_credentials>/sales-cp-app \
      --from-file=dev-cp-app=<path_to_credentials>/dev-cp-app \
      --from-file=it-cp-app=<path_to_credentials>/it-cp-app
    
  • From literal values: Define key-value credentials directly without managing local files:

    kubectl create secret generic file-secret \
      --from-literal=sales-cp-app="sales-cc-app:sales-cc-secret-key"
    

Create a Kubernetes secret containing the provider configuration, such as the separator:

kubectl create secret generic file-secret-config \
  --from-literal=separator=":"

To configure the secret store, reference your secrets in the Confluent Gateway CR:

kind: Gateway
spec:
  secretStores:
    - name:                                --- [1]
      provider:
        type: File                         --- [2]
        configSecretRef: file-secret-config --- [3]
        clientCredentialsRef: file-secret   --- [4]