Skip to content

Commit 35810bd

Browse files
authored
Enforce realm name uniqueness (#46580)
We depend on file realms being unique in a number of places. Pre 7.0 this was enforced by the fact that the multiple realm types with different name would mean identical configuration keys and cause configuration parsing errors. Since we intoduced affix settings for realms this is not the case any more as the realm type is part of the configuration key. This change adds a check when building realms which will explicitly fail if multiple realms are defined with the same name. Backport of #46253
1 parent f8d5145 commit 35810bd

File tree

3 files changed

+32
-2
lines changed

3 files changed

+32
-2
lines changed

x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/Realms.java

+13-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import org.apache.logging.log4j.LogManager;
99
import org.apache.logging.log4j.Logger;
1010
import org.elasticsearch.action.ActionListener;
11+
import org.elasticsearch.common.Strings;
1112
import org.elasticsearch.common.collect.MapBuilder;
1213
import org.elasticsearch.common.settings.Settings;
1314
import org.elasticsearch.common.util.concurrent.CountDown;
@@ -184,6 +185,7 @@ protected List<Realm> initRealms() throws Exception {
184185
Set<String> internalTypes = new HashSet<>();
185186
List<Realm> realms = new ArrayList<>();
186187
List<String> kerberosRealmNames = new ArrayList<>();
188+
Map<String, Set<String>> nameToRealmIdentifier = new HashMap<>();
187189
for (RealmConfig.RealmIdentifier identifier: realmsSettings.keySet()) {
188190
Realm.Factory factory = factories.get(identifier.getType());
189191
if (factory == null) {
@@ -213,7 +215,10 @@ protected List<Realm> initRealms() throws Exception {
213215
"configured");
214216
}
215217
}
216-
realms.add(factory.create(config));
218+
Realm realm = factory.create(config);
219+
nameToRealmIdentifier.computeIfAbsent(realm.name(), k ->
220+
new HashSet<>()).add(RealmSettings.realmSettingPrefix(realm.type()) + realm.name());
221+
realms.add(realm);
217222
}
218223

219224
if (!realms.isEmpty()) {
@@ -224,6 +229,13 @@ protected List<Realm> initRealms() throws Exception {
224229
}
225230
// always add built in first!
226231
realms.add(0, reservedRealm);
232+
String duplicateRealms = nameToRealmIdentifier.entrySet().stream()
233+
.filter(entry -> entry.getValue().size() > 1)
234+
.map(entry -> entry.getKey() + ": " + entry.getValue())
235+
.collect(Collectors.joining("; "));
236+
if (Strings.hasText(duplicateRealms)) {
237+
throw new IllegalArgumentException("Found multiple realms configured with the same name: " + duplicateRealms + "");
238+
}
227239
return realms;
228240
}
229241

x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/AuthenticationServiceTests.java

+4-1
Original file line numberDiff line numberDiff line change
@@ -183,8 +183,11 @@ public void init() throws Exception {
183183
when(licenseState.isAuthAllowed()).thenReturn(true);
184184
when(licenseState.isApiKeyServiceAllowed()).thenReturn(true);
185185
when(licenseState.isTokenServiceAllowed()).thenReturn(true);
186+
ReservedRealm reservedRealm = mock(ReservedRealm.class);
187+
when(reservedRealm.type()).thenReturn("reserved");
188+
when(reservedRealm.name()).thenReturn("reserved_realm");
186189
realms = spy(new TestRealms(Settings.EMPTY, TestEnvironment.newEnvironment(settings), Collections.<String, Realm.Factory>emptyMap(),
187-
licenseState, threadContext, mock(ReservedRealm.class), Arrays.asList(firstRealm, secondRealm),
190+
licenseState, threadContext, reservedRealm, Arrays.asList(firstRealm, secondRealm),
188191
Collections.singletonList(firstRealm)));
189192

190193
auditTrail = mock(AuditTrailService.class);

x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/RealmsTests.java

+15
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ public void init() throws Exception {
7676
when(licenseState.isAuthAllowed()).thenReturn(true);
7777
when(licenseState.allowedRealmType()).thenReturn(AllowedRealmType.ALL);
7878
when(reservedRealm.type()).thenReturn(ReservedRealm.TYPE);
79+
when(reservedRealm.name()).thenReturn("reserved");
7980
}
8081

8182
public void testWithSettings() throws Exception {
@@ -170,6 +171,20 @@ public void testWithSettingsWithMultipleInternalRealmsOfSameType() throws Except
170171
}
171172
}
172173

174+
public void testWithSettingsWithMultipleRealmsWithSameName() throws Exception {
175+
Settings settings = Settings.builder()
176+
.put("xpack.security.authc.realms.file.realm_1.order", 0)
177+
.put("xpack.security.authc.realms.native.realm_1.order", 1)
178+
.put("xpack.security.authc.realms.kerberos.realm_1.order", 2)
179+
.put("path.home", createTempDir())
180+
.build();
181+
Environment env = TestEnvironment.newEnvironment(settings);
182+
IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () ->{
183+
new Realms(settings, env, factories, licenseState, threadContext, reservedRealm);
184+
});
185+
assertThat(e.getMessage(), containsString("Found multiple realms configured with the same name"));
186+
}
187+
173188
public void testWithEmptySettings() throws Exception {
174189
Realms realms = new Realms(Settings.EMPTY, TestEnvironment.newEnvironment(Settings.builder().put("path.home",
175190
createTempDir()).build()), factories, licenseState, threadContext, reservedRealm);

0 commit comments

Comments
 (0)