Federico Mariani created CAMEL-23995:
----------------------------------------

             Summary: camel-kafka: saslAuthType overrides explicit 
securityProtocol and generates non-working KERBEROS/OAUTH/AWS_MSK_IAM 
configurations
                 Key: CAMEL-23995
                 URL: https://issues.apache.org/jira/browse/CAMEL-23995
             Project: Camel
          Issue Type: Bug
          Components: camel-kafka
            Reporter: Federico Mariani


Follow-up to CAMEL-22864 ({{saslAuthType}} option). Code review found that the 
auth-type convenience layer overrides explicitly configured security settings 
and generates non-working configurations for three of its auth types. Findings 
1 was verified empirically by building properties from {{target/classes}}, not 
just by reading code. All line numbers refer to current {{main}} 
(4.22.0-SNAPSHOT).

h3. 1. saslAuthType forcibly overrides an explicitly configured securityProtocol

{{KafkaConfiguration#applyAuthTypeConfiguration}} (lines 452-465):

{code:java}
// For SASL types, default to SSL unless explicitly using SASL_PLAINTEXT
if (saslAuthType.isSasl()) {
    boolean useSsl = !securityProtocol.equals("SASL_PLAINTEXT") && 
!securityProtocol.equals("PLAINTEXT");
    configurer.withSsl(useSsl || hasSslConfig || saslAuthType != 
KafkaAuthType.NONE);
}
{code}

{{saslAuthType != KafkaAuthType.NONE}} is a tautology inside the {{isSasl()}} 
branch ({{NONE.isSasl()}} is false), so the carefully computed {{useSsl}} and 
{{hasSslConfig}} are dead and SSL is *always* forced on.

Verified: {{saslAuthType=PLAIN&securityProtocol=SASL_PLAINTEXT}} → 
{{createConsumerProperties()}} yields {{security.protocol=SASL_SSL}}. The 
client attempts a TLS handshake against a plaintext listener and can never 
connect. The component's own ITs ({{KafkaConsumerSaslAuthTypeIT}}, 
{{KafkaProducerSaslAuthTypeIT}}) use exactly this combination — they are gated 
on {{kafka.instance.type}} and skipped in default builds, which is why this 
went unnoticed.

Also verified the converse: {{saslAuthType=NONE}} + explicit 
{{securityProtocol=SSL}} + {{sslTruststoreLocation}} set → downgraded to 
{{security.protocol=PLAINTEXT}} (the SASL block is skipped and {{hasSslConfig}} 
is never used for NONE) — a silent encryption downgrade.

Fix: {{configurer.withSsl(useSsl || hasSslConfig)}} and handle the NONE/SSL 
case so an explicit protocol is never overridden.

h3. 2. saslAuthType=KERBEROS always throws at startup

For KERBEROS, {{applyAuthTypeConfiguration}} deliberately configures nothing 
("we still use the existing kerberos properties"), but 
{{KafkaSecurityConfigurer.configure()}} → {{buildJaasConfig()}} → 
{{validateKerberos()}} requires {{kerberosPrincipal}}/{{kerberosKeytab}} — 
which have *no corresponding @UriParam* on {{KafkaConfiguration}} and no code 
path that sets them ({{withKerberos}} is never called from Camel).

Verified: {{saslAuthType=KERBEROS}} → {{IllegalArgumentException: Kerberos 
principal is required for KERBEROS authentication}} — always. The feature is 
unusable.

Fix options: add {{kerberosPrincipal}}/{{kerberosKeytab}} URI options, or make 
KERBEROS skip JAAS generation (rely on external JAAS/krb5) and only set 
protocol+mechanism, as the code comment claims it does.

h3. 3. saslAuthType=OAUTH and saslAuthType=AWS_MSK_IAM generate configurations 
that cannot authenticate

{{KafkaSecurityConfigurer}} (lines 335-347):

* OAUTH: generates JAAS {{OAuthBearerLoginModule required clientId="..." 
clientSecret="..." oauth.token.endpoint.uri="...";}} — a hybrid matching 
neither convention. Kafka's built-in KIP-768 support needs top-level 
{{sasl.oauthbearer.token.endpoint.url}} *and* 
{{sasl.login.callback.handler.class=org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginCallbackHandler}}
 (neither is set; without it Kafka falls back to the *unsecured* login callback 
handler which ignores clientId/clientSecret). The Strimzi library (which the 
component docs document) uses {{oauth.client.id}}/{{oauth.client.secret}} JAAS 
keys and needs the Strimzi callback handler — also not set, and the generated 
key names don't match.
* AWS_MSK_IAM: generated props contain only 
{{sasl.jaas.config=software.amazon.msk.auth.iam.IAMLoginModule required;}} — 
the mandatory 
{{sasl.client.callback.handler.class=software.amazon.msk.auth.iam.IAMClientCallbackHandler}}
 is missing, so authentication fails at connect.

There are no ITs covering OAUTH/AWS_MSK_IAM (only string-level assertions in 
{{KafkaSecurityConfigurerTest}}).

Fix: inject the needed callback-handler / endpoint configs and pick one OAuth 
convention (KIP-768 is dependency-free).

h3. Related hardening (same rework)

* {{createProducerProperties()}}/{{createConsumerProperties()}} mutate the 
endpoint's {{KafkaConfiguration}} ({{applyAuthTypeConfiguration}} writes 
{{securityProtocol}}/{{saslMechanism}}/{{saslJaasConfig}} back) — a factory 
method with config side effects; consider computing into the {{Properties}} 
only.
* {{oauthTokenEndpointUri}} is not escaped in the generated JAAS string, unlike 
clientId/clientSecret ({{escapeJaasValue}}).
* Integration-test coverage for the auth types should run somewhere in CI, 
otherwise this class of bug returns.
----
_This issue was researched and written by Claude Code on behalf of Federico 
Mariani (GitHub: Croway). Findings were verified against the source and git 
history before filing._



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to