Skip to content

Commit 63dbd1d

Browse files
authored
Allow User/Password realms to disable authc (#34033)
The "lookupUser" method on a realm facilitates the "run-as" and "authorization_realms" features. This commit allows a realm to be used for "lookup only", in which case the "authenticate" method (and associated token methods) are disabled. It does this through the introduction of a new "authentication.enabled" setting, which defaults to true.
1 parent 6608992 commit 63dbd1d

File tree

7 files changed

+83
-7
lines changed

7 files changed

+83
-7
lines changed

docs/reference/settings/security-settings.asciidoc

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,11 @@ cache at any given time. Defaults to 100,000.
204204
in-memory cached user credentials. For possible values, see <<cache-hash-algo>>.
205205
Defaults to `ssha256`.
206206

207+
`authentication.enabled`:: If set to `false`, disables authentication support in
208+
this realm, so that it only supports user lookups.
209+
(See the {xpack-ref}/run-as-privilege.html[run as] and
210+
{stack-ov}/realm-chains.html#authorization_realms[authorization realms] features).
211+
Defaults to `true`.
207212

208213
[[ref-users-settings]]
209214

@@ -228,6 +233,12 @@ Defaults to 100,000.
228233
(Expert Setting) The hashing algorithm that is used for the in-memory cached
229234
user credentials. See <<cache-hash-algo>>. Defaults to `ssha256`.
230235

236+
`authentication.enabled`:: If set to `false`, disables authentication support in
237+
this realm, so that it only supports user lookups.
238+
(See the {xpack-ref}/run-as-privilege.html[run as] and
239+
{stack-ov}/realm-chains.html#authorization_realms[authorization realms] features).
240+
Defaults to `true`.
241+
231242
[[ref-ldap-settings]]
232243
[float]
233244
===== LDAP realm settings
@@ -490,6 +501,12 @@ Defaults to `100000`.
490501
(Expert Setting) Specifies the hashing algorithm that is used for the
491502
in-memory cached user credentials. See <<cache-hash-algo>>. Defaults to `ssha256`.
492503

504+
`authentication.enabled`:: If set to `false`, disables authentication support in
505+
this realm, so that it only supports user lookups.
506+
(See the {xpack-ref}/run-as-privilege.html[run as] and
507+
{stack-ov}/realm-chains.html#authorization_realms[authorization realms] features).
508+
Defaults to `true`.
509+
493510
[[ref-ad-settings]]
494511
[float]
495512
===== Active Directory realm settings
@@ -731,6 +748,12 @@ Defaults to `100000`.
731748
(Expert Setting) Specifies the hashing algorithm that is used for
732749
the in-memory cached user credentials. See <<cache-hash-algo>>. Defaults to `ssha256`.
733750

751+
`authentication.enabled`:: If set to `false`, disables authentication support in
752+
this realm, so that it only supports user lookups.
753+
(See the {xpack-ref}/run-as-privilege.html[run as] and
754+
{stack-ov}/realm-chains.html#authorization_realms[authorization realms] features).
755+
Defaults to `true`.
756+
734757
`follow_referrals`::
735758
If set to `true` {security} follows referrals returned by the LDAP server.
736759
Referrals are URLs returned by the server that are to be used to continue the

x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authc/esnative/NativeRealmSettings.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,6 @@ private NativeRealmSettings() {}
1919
* @return The {@link Setting setting configuration} for this realm type
2020
*/
2121
public static Set<Setting<?>> getSettings() {
22-
return CachingUsernamePasswordRealmSettings.getCachingSettings();
22+
return CachingUsernamePasswordRealmSettings.getSettings();
2323
}
2424
}

x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authc/file/FileRealmSettings.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,6 @@ private FileRealmSettings() {}
1919
* @return The {@link Setting setting configuration} for this realm type
2020
*/
2121
public static Set<Setting<?>> getSettings() {
22-
return CachingUsernamePasswordRealmSettings.getCachingSettings();
22+
return CachingUsernamePasswordRealmSettings.getSettings();
2323
}
2424
}

x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authc/ldap/LdapRealmSettings.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ private LdapRealmSettings() {}
2929
*/
3030
public static Set<Setting<?>> getSettings(String type) {
3131
Set<Setting<?>> settings = new HashSet<>();
32-
settings.addAll(CachingUsernamePasswordRealmSettings.getCachingSettings());
32+
settings.addAll(CachingUsernamePasswordRealmSettings.getSettings());
3333
settings.addAll(CompositeRoleMapperSettings.getSettings());
3434
settings.add(LdapRealmSettings.EXECUTION_TIMEOUT);
3535
if (AD_TYPE.equals(type)) {

x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authc/support/CachingUsernamePasswordRealmSettings.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,15 @@ public final class CachingUsernamePasswordRealmSettings {
2121
public static final Setting<Integer> CACHE_MAX_USERS_SETTING = Setting.intSetting("cache.max_users", DEFAULT_MAX_USERS,
2222
Setting.Property.NodeScope);
2323

24+
public static final Setting<Boolean> AUTHC_ENABLED_SETTING = Setting.boolSetting("authentication.enabled", true,
25+
Setting.Property.NodeScope);
26+
2427
private CachingUsernamePasswordRealmSettings() {}
2528

2629
/**
2730
* Returns the {@link Setting setting configuration} that is common for all caching realms
2831
*/
29-
public static Set<Setting<?>> getCachingSettings() {
30-
return new HashSet<>(Arrays.asList(CACHE_HASH_ALGO_SETTING, CACHE_TTL_SETTING, CACHE_MAX_USERS_SETTING));
32+
public static Set<Setting<?>> getSettings() {
33+
return new HashSet<>(Arrays.asList(CACHE_HASH_ALGO_SETTING, CACHE_TTL_SETTING, CACHE_MAX_USERS_SETTING, AUTHC_ENABLED_SETTING));
3134
}
3235
}

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

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import org.elasticsearch.common.settings.SecureString;
1212
import org.elasticsearch.common.unit.TimeValue;
1313
import org.elasticsearch.common.util.concurrent.ListenableFuture;
14+
import org.elasticsearch.common.util.concurrent.ThreadContext;
1415
import org.elasticsearch.threadpool.ThreadPool;
1516
import org.elasticsearch.xpack.core.security.authc.AuthenticationResult;
1617
import org.elasticsearch.xpack.core.security.authc.AuthenticationToken;
@@ -30,6 +31,7 @@ public abstract class CachingUsernamePasswordRealm extends UsernamePasswordRealm
3031

3132
private final Cache<String, ListenableFuture<UserWithHash>> cache;
3233
private final ThreadPool threadPool;
34+
private final boolean authenticationEnabled;
3335
final Hasher cacheHasher;
3436

3537
protected CachingUsernamePasswordRealm(String type, RealmConfig config, ThreadPool threadPool) {
@@ -45,6 +47,7 @@ protected CachingUsernamePasswordRealm(String type, RealmConfig config, ThreadPo
4547
} else {
4648
cache = null;
4749
}
50+
this.authenticationEnabled = CachingUsernamePasswordRealmSettings.AUTHC_ENABLED_SETTING.get(config.settings());
4851
}
4952

5053
@Override
@@ -63,15 +66,34 @@ public final void expireAll() {
6366
}
6467
}
6568

69+
@Override
70+
public UsernamePasswordToken token(ThreadContext threadContext) {
71+
if (authenticationEnabled == false) {
72+
return null;
73+
}
74+
return super.token(threadContext);
75+
}
76+
77+
@Override
78+
public boolean supports(AuthenticationToken token) {
79+
return authenticationEnabled && super.supports(token);
80+
}
81+
6682
/**
6783
* If the user exists in the cache (keyed by the principle name), then the password is validated
6884
* against a hash also stored in the cache. Otherwise the subclass authenticates the user via
69-
* doAuthenticate
85+
* doAuthenticate.
86+
* This method will respond with {@link AuthenticationResult#notHandled()} if
87+
* {@link CachingUsernamePasswordRealmSettings#AUTHC_ENABLED_SETTING authentication is not enabled}.
7088
* @param authToken The authentication token
7189
* @param listener to be called at completion
7290
*/
7391
@Override
7492
public final void authenticate(AuthenticationToken authToken, ActionListener<AuthenticationResult> listener) {
93+
if (authenticationEnabled == false) {
94+
listener.onResponse(AuthenticationResult.notHandled());
95+
return;
96+
}
7597
final UsernamePasswordToken token = (UsernamePasswordToken) authToken;
7698
try {
7799
if (cache == null) {

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

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import org.elasticsearch.common.settings.Settings;
1212
import org.elasticsearch.common.unit.TimeValue;
1313
import org.elasticsearch.common.util.concurrent.ThreadContext;
14+
import org.elasticsearch.env.Environment;
1415
import org.elasticsearch.env.TestEnvironment;
1516
import org.elasticsearch.test.ESTestCase;
1617
import org.elasticsearch.test.SecuritySettingsSourceField;
@@ -62,7 +63,7 @@ public void stop() throws InterruptedException {
6263
}
6364
}
6465

65-
public void testSettings() throws Exception {
66+
public void testCacheSettings() throws Exception {
6667
String cachingHashAlgo = Hasher.values()[randomIntBetween(0, Hasher.values().length - 1)].name().toLowerCase(Locale.ROOT);
6768
int maxUsers = randomIntBetween(10, 100);
6869
TimeValue ttl = TimeValue.timeValueMinutes(randomIntBetween(10, 20));
@@ -560,6 +561,33 @@ protected void doLookupUser(String username, ActionListener<User> listener) {
560561
assertEquals(1, lookupCounter.get());
561562
}
562563

564+
public void testAuthenticateDisabled() throws Exception {
565+
final Settings settings = Settings.builder()
566+
.put(CachingUsernamePasswordRealmSettings.AUTHC_ENABLED_SETTING.getKey(), false)
567+
.build();
568+
final Environment env = TestEnvironment.newEnvironment(globalSettings);
569+
final ThreadContext threadContext = new ThreadContext(Settings.EMPTY);
570+
final RealmConfig config = new RealmConfig("test_authentication_disabled", settings, globalSettings, env, threadContext);
571+
final AlwaysAuthenticateCachingRealm realm = new AlwaysAuthenticateCachingRealm(config, threadPool);
572+
573+
final UsernamePasswordToken token = new UsernamePasswordToken("phil", new SecureString("tahiti"));
574+
UsernamePasswordToken.putTokenHeader(threadContext, token);
575+
assertThat(realm.token(threadContext), nullValue());
576+
assertThat(realm.supports(token), equalTo(false));
577+
578+
PlainActionFuture<AuthenticationResult> authFuture = new PlainActionFuture<>();
579+
realm.authenticate(token, authFuture);
580+
final AuthenticationResult authResult = authFuture.get();
581+
assertThat(authResult.isAuthenticated(), equalTo(false));
582+
assertThat(authResult.getStatus(), equalTo(AuthenticationResult.Status.CONTINUE));
583+
584+
PlainActionFuture<User> lookupFuture = new PlainActionFuture<>();
585+
realm.lookupUser(token.principal(), lookupFuture);
586+
final User user = lookupFuture.get();
587+
assertThat(user, notNullValue());
588+
assertThat(user.principal(), equalTo(token.principal()));
589+
}
590+
563591
static class FailingAuthenticationRealm extends CachingUsernamePasswordRealm {
564592

565593
FailingAuthenticationRealm(Settings settings, Settings global, ThreadPool threadPool) {

0 commit comments

Comments
 (0)