Skip to content

Commit 6a2f81c

Browse files
edanidzerdagaryrussell
authored andcommitted
GH-2709: Preserve existing JAAS configuration
Resolves #2709 The existing JAAS configuration at the time the KafkaJaasLoginModuleInitializer's afterSingletonsInstantiated() is now saved. The InternalConfiguration class will now search the saved JAAS Configuration first before returning its own stored configurationEntries. This mimics the approach used by Microsoft's SQL Server JDBC driver, which preserves any existing Configuration while still being able to return its own default JAAS Configuration. Added a unit test to KafkaJaasLoginModuleInitializerTests.java to ensure that an existing configuration can be found.
1 parent cbb60c8 commit 6a2f81c

File tree

2 files changed

+59
-4
lines changed

2 files changed

+59
-4
lines changed

spring-kafka/src/main/java/org/springframework/kafka/security/jaas/KafkaJaasLoginModuleInitializer.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
*
3737
* @author Marius Bogoevici
3838
* @author Gary Russell
39+
* @author Edan Idzerda
3940
*
4041
* @since 1.3
4142
*/
@@ -134,7 +135,8 @@ public void afterSingletonsInstantiated() {
134135
this.options);
135136
configurationEntries.put(KAFKA_CLIENT_CONTEXT_NAME,
136137
new AppConfigurationEntry[] { kafkaClientConfigurationEntry });
137-
Configuration.setConfiguration(new InternalConfiguration(configurationEntries));
138+
Configuration.setConfiguration(new InternalConfiguration(configurationEntries,
139+
Configuration.getConfiguration()));
138140
// Workaround for a 0.9 client issue where even if the Configuration is
139141
// set
140142
// a system property check is performed.
@@ -157,15 +159,19 @@ private static class InternalConfiguration extends Configuration {
157159

158160
private final Map<String, AppConfigurationEntry[]> configurationEntries;
159161

160-
InternalConfiguration(Map<String, AppConfigurationEntry[]> configurationEntries) {
162+
private final Configuration delegate;
163+
164+
InternalConfiguration(Map<String, AppConfigurationEntry[]> configurationEntries, Configuration delegate) {
161165
Assert.notNull(configurationEntries, " cannot be null");
162166
Assert.notEmpty(configurationEntries, " cannot be empty");
163167
this.configurationEntries = configurationEntries;
168+
this.delegate = delegate;
164169
}
165170

166171
@Override
167172
public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
168-
return this.configurationEntries.get(name);
173+
AppConfigurationEntry[] conf = this.delegate == null ? null : this.delegate.getAppConfigurationEntry(name);
174+
return conf != null ? conf : this.configurationEntries.get(name);
169175
}
170176

171177
}

spring-kafka/src/test/java/org/springframework/kafka/security/jaas/KafkaJaasLoginModuleInitializerTests.java

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2017-2019 the original author or authors.
2+
* Copyright 2017-2023 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -27,8 +27,11 @@
2727
import javax.security.auth.login.AppConfigurationEntry;
2828

2929
import org.apache.kafka.common.security.JaasContext;
30+
import org.jetbrains.annotations.NotNull;
3031
import org.junit.jupiter.api.Test;
3132

33+
import org.springframework.beans.BeansException;
34+
import org.springframework.beans.factory.config.BeanPostProcessor;
3235
import org.springframework.context.annotation.Bean;
3336
import org.springframework.context.annotation.Configuration;
3437
import org.springframework.core.io.ClassPathResource;
@@ -40,6 +43,7 @@
4043
/**
4144
* @author Marius Bogoevici
4245
* @author Gary Russell
46+
* @author Edan Idzerda
4347
*
4448
* @since 1.3
4549
*/
@@ -68,6 +72,16 @@ public void testConfigurationParsedCorrectlyWithKafkaClient() throws Exception {
6872
assertThat(appConfigurationEntries.get(0).getOptions()).isEqualTo(kafkaConfigurationArray[0].getOptions());
6973
}
7074

75+
@Test
76+
public void testOtherConfigurationFound() {
77+
javax.security.auth.login.Configuration configuration = javax.security.auth.login.Configuration
78+
.getConfiguration();
79+
80+
final AppConfigurationEntry[] otherConfiguration = configuration
81+
.getAppConfigurationEntry(PreConfiguredJaasConfig.OtherJaasConfigurationName);
82+
assertThat(otherConfiguration).hasSize(1);
83+
}
84+
7185
@Configuration
7286
public static class Config {
7387

@@ -86,4 +100,39 @@ public KafkaJaasLoginModuleInitializer jaasConfig() throws IOException {
86100

87101
}
88102

103+
@Configuration
104+
public static class PreConfiguredJaasConfig implements BeanPostProcessor {
105+
106+
private boolean initialized = false;
107+
108+
public static String OtherJaasConfigurationName = "other-jaas-configuration-name";
109+
110+
@Override
111+
public Object postProcessBeforeInitialization(@NotNull Object bean, @NotNull String beanName)
112+
throws BeansException {
113+
114+
// Install our "other" configuration before the KAFKA_CLIENT_CONTEXT_NAME is installed
115+
if (!initialized) {
116+
javax.security.auth.login.Configuration.setConfiguration(new OtherJaasConfiguration());
117+
initialized = true;
118+
}
119+
return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
120+
}
121+
122+
public static class OtherJaasConfiguration extends javax.security.auth.login.Configuration {
123+
@Override
124+
public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
125+
if (name.equals(OtherJaasConfigurationName)) {
126+
AppConfigurationEntry dummyAppConfigurationEntry = new AppConfigurationEntry("loginModuleName",
127+
AppConfigurationEntry.LoginModuleControlFlag.OPTIONAL, new HashMap<>());
128+
return new AppConfigurationEntry[] { dummyAppConfigurationEntry };
129+
}
130+
else {
131+
return null;
132+
}
133+
}
134+
}
135+
136+
}
137+
89138
}

0 commit comments

Comments
 (0)