Avoid NPE in set_security_user without security (#53543)

If security was disabled (explicitly), then the SecurityContext would
be null, but the set_security_user processor was still registered.

Attempting to define a pipeline that used that processor would fail
with an (intentional) NPE. This behaviour, introduced in #52032, is a
regression from previous releases where the pipeline was allowed, but
was no usable.

This change restores the previous behaviour (with a new warning).

Backport of: #52691
This commit is contained in:
Tim Vernum 2020-03-17 13:30:07 +11:00 committed by GitHub
parent e7f38674ed
commit 74dbdb991c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 261 additions and 42 deletions

View File

@ -0,0 +1,29 @@
/*
* This QA project tests the security plugin when security is explicitlt disabled.
* It is intended to cover security functionality which is supposed to
* function in a specific way even if security is disabled on the cluster
* For example: If a cluster has a pipeline with the set_security_user processor
* defined, it should be not fail
*/
apply plugin: 'elasticsearch.testclusters'
apply plugin: 'elasticsearch.standalone-rest-test'
apply plugin: 'elasticsearch.rest-test'
dependencies {
testCompile project(path: xpackModule('core'), configuration: 'default')
testCompile project(path: xpackModule('security'), configuration: 'testArtifacts')
testCompile project(path: xpackModule('core'), configuration: 'testArtifacts')
}
testClusters.integTest {
testDistribution = 'DEFAULT'
numberOfNodes = 2
setting 'xpack.ilm.enabled', 'false'
setting 'xpack.ml.enabled', 'false'
// We run with a trial license, but explicitly disable security.
// This means the security plugin is loaded and all feature are permitted, but they are not enabled
setting 'xpack.license.self_generated.type', 'trial'
setting 'xpack.security.enabled', 'false'
}

View File

@ -0,0 +1,48 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
package org.elasticsearch.xpack.security;
import org.apache.http.util.EntityUtils;
import org.elasticsearch.client.Request;
import org.elasticsearch.client.Response;
import org.elasticsearch.client.ResponseException;
import org.elasticsearch.test.rest.ESRestTestCase;
import static org.hamcrest.Matchers.containsString;
/**
* Tests that it is possible to <em>define</em> a pipeline with the
* {@link org.elasticsearch.xpack.security.ingest.SetSecurityUserProcessor} on a cluster with security disabled, but it is not possible
* to use that pipeline for ingestion.
*/
public class SetSecurityUserProcessorWithSecurityDisabledIT extends ESRestTestCase {
public void testDefineAndUseProcessor() throws Exception {
final String pipeline = "pipeline-" + getTestName();
final String index = "index-" + getTestName();
{
final Request putPipeline = new Request("PUT", "/_ingest/pipeline/" + pipeline);
putPipeline.setJsonEntity("{" +
" \"description\": \"Test pipeline (" + getTestName() + ")\"," +
" \"processors\":[{" +
" \"set_security_user\":{ \"field\": \"user\" }" +
" }]" +
"}");
final Response response = client().performRequest(putPipeline);
assertOK(response);
}
{
final Request ingest = new Request("PUT", "/" + index + "/_doc/1?pipeline=" + pipeline);
ingest.setJsonEntity("{\"field\":\"value\"}");
final ResponseException ex = expectThrows(ResponseException.class, () -> client().performRequest(ingest));
final Response response = ex.getResponse();
assertThat(EntityUtils.toString(response.getEntity()),
containsString("Security (authentication) is not enabled on this cluster"));
}
}
}

View File

@ -0,0 +1,28 @@
/*
* This QA project tests the security plugin when security is not enabled.
* It is intended to cover security functionality which is supposed to
* function in a specific way even if security is not enabled on the cluster
* For example: If a cluster has a pipeline with the set_security_user processor
* defined, it should be not fail
*/
apply plugin: 'elasticsearch.testclusters'
apply plugin: 'elasticsearch.standalone-rest-test'
apply plugin: 'elasticsearch.rest-test'
dependencies {
testCompile project(path: xpackModule('core'), configuration: 'default')
testCompile project(path: xpackModule('security'), configuration: 'testArtifacts')
testCompile project(path: xpackModule('core'), configuration: 'testArtifacts')
}
testClusters.integTest {
testDistribution = 'DEFAULT'
numberOfNodes = 2
setting 'xpack.ilm.enabled', 'false'
setting 'xpack.ml.enabled', 'false'
// We run with a trial license, but do not enable security.
// This means the security plugin is loaded and all feature are permitted, but they are not enabled
setting 'xpack.license.self_generated.type', 'trial'
}

View File

@ -0,0 +1,48 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
package org.elasticsearch.xpack.security;
import org.apache.http.util.EntityUtils;
import org.elasticsearch.client.Request;
import org.elasticsearch.client.Response;
import org.elasticsearch.client.ResponseException;
import org.elasticsearch.test.rest.ESRestTestCase;
import static org.hamcrest.Matchers.containsString;
/**
* Tests that it is possible to <em>define</em> a pipeline with the
* {@link org.elasticsearch.xpack.security.ingest.SetSecurityUserProcessor} on a cluster where security is not enabled,
* but it is not possible to use that pipeline for ingestion.
*/
public class SetSecurityUserProcessorWithSecurityNotEnabledIT extends ESRestTestCase {
public void testDefineAndUseProcessor() throws Exception {
final String pipeline = "pipeline-" + getTestName();
final String index = "index-" + getTestName();
{
final Request putPipeline = new Request("PUT", "/_ingest/pipeline/" + pipeline);
putPipeline.setJsonEntity("{" +
" \"description\": \"Test pipeline (" + getTestName() + ")\"," +
" \"processors\":[{" +
" \"set_security_user\":{ \"field\": \"user\" }" +
" }]" +
"}");
final Response response = client().performRequest(putPipeline);
assertOK(response);
}
{
final Request ingest = new Request("PUT", "/" + index + "/_doc/1?pipeline=" + pipeline);
ingest.setJsonEntity("{\"field\":\"value\"}");
final ResponseException ex = expectThrows(ResponseException.class, () -> client().performRequest(ingest));
final Response response = ex.getResponse();
assertThat(EntityUtils.toString(response.getEntity()),
containsString("Security (authentication) is not enabled on this cluster"));
}
}
}

View File

@ -864,7 +864,8 @@ public class Security extends Plugin implements SystemIndexPlugin, IngestPlugin,
@Override @Override
public Map<String, Processor.Factory> getProcessors(Processor.Parameters parameters) { public Map<String, Processor.Factory> getProcessors(Processor.Parameters parameters) {
return Collections.singletonMap(SetSecurityUserProcessor.TYPE, new SetSecurityUserProcessor.Factory(securityContext::get)); return Collections.singletonMap(SetSecurityUserProcessor.TYPE,
new SetSecurityUserProcessor.Factory(securityContext::get, this::getLicenseState));
} }
/** /**

View File

@ -5,9 +5,12 @@
*/ */
package org.elasticsearch.xpack.security.ingest; package org.elasticsearch.xpack.security.ingest;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.elasticsearch.ingest.AbstractProcessor; import org.elasticsearch.ingest.AbstractProcessor;
import org.elasticsearch.ingest.IngestDocument; import org.elasticsearch.ingest.IngestDocument;
import org.elasticsearch.ingest.Processor; import org.elasticsearch.ingest.Processor;
import org.elasticsearch.license.XPackLicenseState;
import org.elasticsearch.xpack.core.security.SecurityContext; import org.elasticsearch.xpack.core.security.SecurityContext;
import org.elasticsearch.xpack.core.security.authc.Authentication; import org.elasticsearch.xpack.core.security.authc.Authentication;
import org.elasticsearch.xpack.core.security.user.User; import org.elasticsearch.xpack.core.security.user.User;
@ -34,27 +37,51 @@ public final class SetSecurityUserProcessor extends AbstractProcessor {
public static final String TYPE = "set_security_user"; public static final String TYPE = "set_security_user";
private final Logger logger = LogManager.getLogger();
private final SecurityContext securityContext; private final SecurityContext securityContext;
private final XPackLicenseState licenseState;
private final String field; private final String field;
private final Set<Property> properties; private final Set<Property> properties;
public public SetSecurityUserProcessor(String tag, SecurityContext securityContext, XPackLicenseState licenseState, String field,
SetSecurityUserProcessor(String tag, SecurityContext securityContext, String field, Set<Property> properties) { Set<Property> properties) {
super(tag); super(tag);
this.securityContext = Objects.requireNonNull(securityContext, "security context must be provided"); this.securityContext = securityContext;
this.licenseState = Objects.requireNonNull(licenseState, "license state cannot be null");
if (licenseState.isAuthAllowed() == false) {
logger.warn("Creating processor [{}] (tag [{}]) on field [{}] but authentication is not currently enabled on this cluster " +
" - this processor is likely to fail at runtime if it is used", TYPE, tag, field);
} else if (this.securityContext == null) {
throw new IllegalArgumentException("Authentication is allowed on this cluster state, but there is no security context");
}
this.field = field; this.field = field;
this.properties = properties; this.properties = properties;
} }
@Override @Override
public IngestDocument execute(IngestDocument ingestDocument) throws Exception { public IngestDocument execute(IngestDocument ingestDocument) throws Exception {
Authentication authentication = securityContext.getAuthentication(); Authentication authentication = null;
if (authentication == null) { User user = null;
throw new IllegalStateException("No user authenticated, only use this processor via authenticated user"); if (this.securityContext != null) {
authentication = securityContext.getAuthentication();
if (authentication != null) {
user = authentication.getUser();
} }
User user = authentication.getUser(); }
if (user == null) { if (user == null) {
throw new IllegalStateException("No user for authentication"); logger.debug(
"Failed to find active user. SecurityContext=[{}] Authentication=[{}] User=[{}]", securityContext, authentication, user);
if (licenseState.isAuthAllowed()) {
// This shouldn't happen. If authentication is allowed (and active), then there _should_ always be an authenticated user.
// If we ever see this error message, then one of our assumptions are wrong.
throw new IllegalStateException("There is no authenticated user - the [" + TYPE
+ "] processor requires an authenticated user");
} else {
throw new IllegalStateException("Security (authentication) is not enabled on this cluster, so there is no active user - " +
"the [" + TYPE + "] processor cannot be used without security");
}
} }
Object fieldValue = ingestDocument.getFieldValue(field, Object.class, true); Object fieldValue = ingestDocument.getFieldValue(field, Object.class, true);
@ -155,9 +182,11 @@ public final class SetSecurityUserProcessor extends AbstractProcessor {
public static final class Factory implements Processor.Factory { public static final class Factory implements Processor.Factory {
private final Supplier<SecurityContext> securityContext; private final Supplier<SecurityContext> securityContext;
private final Supplier<XPackLicenseState> licenseState;
public Factory(Supplier<SecurityContext> securityContext) { public Factory(Supplier<SecurityContext> securityContext, Supplier<XPackLicenseState> licenseState) {
this.securityContext = securityContext; this.securityContext = securityContext;
this.licenseState = licenseState;
} }
@Override @Override
@ -174,7 +203,7 @@ public final class SetSecurityUserProcessor extends AbstractProcessor {
} else { } else {
properties = EnumSet.allOf(Property.class); properties = EnumSet.allOf(Property.class);
} }
return new SetSecurityUserProcessor(tag, securityContext.get(), field, properties); return new SetSecurityUserProcessor(tag, securityContext.get(), licenseState.get(), field, properties);
} }
} }

View File

@ -60,6 +60,7 @@ public final class RestGetApiKeyAction extends ApiKeyBaseRestHandler {
} }
return new BytesRestResponse(RestStatus.OK, builder); return new BytesRestResponse(RestStatus.OK, builder);
} }
}); });
} }

View File

@ -8,31 +8,36 @@ package org.elasticsearch.xpack.security.ingest;
import org.elasticsearch.ElasticsearchParseException; import org.elasticsearch.ElasticsearchParseException;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.util.concurrent.ThreadContext; import org.elasticsearch.common.util.concurrent.ThreadContext;
import org.elasticsearch.license.XPackLicenseState;
import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.xpack.core.security.SecurityContext; import org.elasticsearch.xpack.core.security.SecurityContext;
import org.elasticsearch.xpack.security.ingest.SetSecurityUserProcessor.Property; import org.elasticsearch.xpack.security.ingest.SetSecurityUserProcessor.Property;
import org.junit.Before; import org.junit.Before;
import org.mockito.Mockito;
import java.util.Arrays; import java.util.Arrays;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import static org.elasticsearch.test.TestMatchers.throwableWithMessage;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.notNullValue;
import static org.mockito.Mockito.when;
public class SetSecurityUserProcessorFactoryTests extends ESTestCase { public class SetSecurityUserProcessorFactoryTests extends ESTestCase {
private SecurityContext securityContext; private SecurityContext securityContext;
private XPackLicenseState licenseState;
@Before @Before
public void setupContext() { public void setupContext() {
securityContext = new SecurityContext(Settings.EMPTY, new ThreadContext(Settings.EMPTY)); securityContext = new SecurityContext(Settings.EMPTY, new ThreadContext(Settings.EMPTY));
licenseState = Mockito.mock(XPackLicenseState.class);
when(licenseState.isAuthAllowed()).thenReturn(true);
} }
public void testProcessor() throws Exception { public void testProcessor() throws Exception {
SetSecurityUserProcessor.Factory factory = new SetSecurityUserProcessor.Factory(() -> securityContext); SetSecurityUserProcessor.Factory factory = new SetSecurityUserProcessor.Factory(() -> securityContext, () -> licenseState);
Map<String, Object> config = new HashMap<>(); Map<String, Object> config = new HashMap<>();
config.put("field", "_field"); config.put("field", "_field");
SetSecurityUserProcessor processor = factory.create(null, "_tag", config); SetSecurityUserProcessor processor = factory.create(null, "_tag", config);
@ -41,7 +46,7 @@ public class SetSecurityUserProcessorFactoryTests extends ESTestCase {
} }
public void testProcessor_noField() throws Exception { public void testProcessor_noField() throws Exception {
SetSecurityUserProcessor.Factory factory = new SetSecurityUserProcessor.Factory(() -> securityContext); SetSecurityUserProcessor.Factory factory = new SetSecurityUserProcessor.Factory(() -> securityContext, () -> licenseState);
Map<String, Object> config = new HashMap<>(); Map<String, Object> config = new HashMap<>();
ElasticsearchParseException e = expectThrows(ElasticsearchParseException.class, () -> factory.create(null, "_tag", config)); ElasticsearchParseException e = expectThrows(ElasticsearchParseException.class, () -> factory.create(null, "_tag", config));
assertThat(e.getMetadata("es.property_name").get(0), equalTo("field")); assertThat(e.getMetadata("es.property_name").get(0), equalTo("field"));
@ -50,7 +55,7 @@ public class SetSecurityUserProcessorFactoryTests extends ESTestCase {
} }
public void testProcessor_validProperties() throws Exception { public void testProcessor_validProperties() throws Exception {
SetSecurityUserProcessor.Factory factory = new SetSecurityUserProcessor.Factory(() -> securityContext); SetSecurityUserProcessor.Factory factory = new SetSecurityUserProcessor.Factory(() -> securityContext, () -> licenseState);
Map<String, Object> config = new HashMap<>(); Map<String, Object> config = new HashMap<>();
config.put("field", "_field"); config.put("field", "_field");
config.put("properties", Arrays.asList(Property.USERNAME.name(), Property.ROLES.name())); config.put("properties", Arrays.asList(Property.USERNAME.name(), Property.ROLES.name()));
@ -60,7 +65,7 @@ public class SetSecurityUserProcessorFactoryTests extends ESTestCase {
} }
public void testProcessor_invalidProperties() throws Exception { public void testProcessor_invalidProperties() throws Exception {
SetSecurityUserProcessor.Factory factory = new SetSecurityUserProcessor.Factory(() -> securityContext); SetSecurityUserProcessor.Factory factory = new SetSecurityUserProcessor.Factory(() -> securityContext, () -> licenseState);
Map<String, Object> config = new HashMap<>(); Map<String, Object> config = new HashMap<>();
config.put("field", "_field"); config.put("field", "_field");
config.put("properties", Arrays.asList("invalid")); config.put("properties", Arrays.asList("invalid"));
@ -70,12 +75,13 @@ public class SetSecurityUserProcessorFactoryTests extends ESTestCase {
assertThat(e.getMetadata("es.processor_tag").get(0), equalTo("_tag")); assertThat(e.getMetadata("es.processor_tag").get(0), equalTo("_tag"));
} }
public void testNullSecurityContextThrowsException() throws Exception { public void testCanConstructorProcessorWithoutSecurityEnabled() throws Exception {
SetSecurityUserProcessor.Factory factory = new SetSecurityUserProcessor.Factory(() -> null); when(licenseState.isAuthAllowed()).thenReturn(false);
SetSecurityUserProcessor.Factory factory = new SetSecurityUserProcessor.Factory(() -> null, () -> licenseState);
Map<String, Object> config = new HashMap<>(); Map<String, Object> config = new HashMap<>();
config.put("field", "_field"); config.put("field", "_field");
NullPointerException e = expectThrows(NullPointerException.class, () -> factory.create(null, "_tag", config)); final SetSecurityUserProcessor processor = factory.create(null, "_tag", config);
assertThat(e, throwableWithMessage(containsString("security context"))); assertThat(processor, notNullValue());
} }
} }

View File

@ -10,6 +10,7 @@ import org.elasticsearch.common.collect.MapBuilder;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.util.concurrent.ThreadContext; import org.elasticsearch.common.util.concurrent.ThreadContext;
import org.elasticsearch.ingest.IngestDocument; import org.elasticsearch.ingest.IngestDocument;
import org.elasticsearch.license.XPackLicenseState;
import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.xpack.core.security.SecurityContext; import org.elasticsearch.xpack.core.security.SecurityContext;
import org.elasticsearch.xpack.core.security.authc.Authentication; import org.elasticsearch.xpack.core.security.authc.Authentication;
@ -28,16 +29,20 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.equalTo;
import static org.mockito.Mockito.when;
public class SetSecurityUserProcessorTests extends ESTestCase { public class SetSecurityUserProcessorTests extends ESTestCase {
private ThreadContext threadContext; private ThreadContext threadContext;
private SecurityContext securityContext; private SecurityContext securityContext;
private XPackLicenseState licenseState;
@Before @Before
public void setupObjects() { public void setupObjects() {
threadContext = new ThreadContext(Settings.EMPTY); threadContext = new ThreadContext(Settings.EMPTY);
securityContext = new SecurityContext(Settings.EMPTY, threadContext); securityContext = new SecurityContext(Settings.EMPTY, threadContext);
licenseState = Mockito.mock(XPackLicenseState.class);
when(licenseState.isAuthAllowed()).thenReturn(true);
} }
public void testProcessorWithData() throws Exception { public void testProcessorWithData() throws Exception {
@ -47,7 +52,8 @@ public class SetSecurityUserProcessorTests extends ESTestCase {
new Authentication(user, realmRef, null).writeToContext(threadContext); new Authentication(user, realmRef, null).writeToContext(threadContext);
IngestDocument ingestDocument = new IngestDocument(new HashMap<>(), new HashMap<>()); IngestDocument ingestDocument = new IngestDocument(new HashMap<>(), new HashMap<>());
SetSecurityUserProcessor processor = new SetSecurityUserProcessor("_tag", securityContext, "_field", EnumSet.allOf(Property.class)); SetSecurityUserProcessor processor = new SetSecurityUserProcessor(
"_tag", securityContext, licenseState, "_field", EnumSet.allOf(Property.class));
processor.execute(ingestDocument); processor.execute(ingestDocument);
Map<String, Object> result = ingestDocument.getFieldValue("_field", Map.class); Map<String, Object> result = ingestDocument.getFieldValue("_field", Map.class);
@ -67,16 +73,17 @@ public class SetSecurityUserProcessorTests extends ESTestCase {
// test when user returns null for all values (need a mock, because a real user cannot have a null username) // test when user returns null for all values (need a mock, because a real user cannot have a null username)
User user = Mockito.mock(User.class); User user = Mockito.mock(User.class);
Authentication authentication = Mockito.mock(Authentication.class); Authentication authentication = Mockito.mock(Authentication.class);
Mockito.when(authentication.getUser()).thenReturn(user); when(authentication.getUser()).thenReturn(user);
final Authentication.RealmRef authByRealm = new Authentication.RealmRef("_name", "_type", "_node_name"); final Authentication.RealmRef authByRealm = new Authentication.RealmRef("_name", "_type", "_node_name");
Mockito.when(authentication.getSourceRealm()).thenReturn(authByRealm); when(authentication.getSourceRealm()).thenReturn(authByRealm);
Mockito.when(authentication.getAuthenticatedBy()).thenReturn(authByRealm); when(authentication.getAuthenticatedBy()).thenReturn(authByRealm);
Mockito.when(authentication.getAuthenticationType()).thenReturn(AuthenticationType.REALM); when(authentication.getAuthenticationType()).thenReturn(AuthenticationType.REALM);
Mockito.when(authentication.encode()).thenReturn(randomAlphaOfLength(24)); // don't care as long as it's not null when(authentication.encode()).thenReturn(randomAlphaOfLength(24)); // don't care as long as it's not null
new AuthenticationContextSerializer().writeToContext(authentication, threadContext); new AuthenticationContextSerializer().writeToContext(authentication, threadContext);
IngestDocument ingestDocument = new IngestDocument(new HashMap<>(), new HashMap<>()); IngestDocument ingestDocument = new IngestDocument(new HashMap<>(), new HashMap<>());
SetSecurityUserProcessor processor = new SetSecurityUserProcessor("_tag", securityContext, "_field", EnumSet.allOf(Property.class)); SetSecurityUserProcessor processor = new SetSecurityUserProcessor(
"_tag", securityContext, licenseState, "_field", EnumSet.allOf(Property.class));
processor.execute(ingestDocument); processor.execute(ingestDocument);
Map<String, Object> result = ingestDocument.getFieldValue("_field", Map.class); Map<String, Object> result = ingestDocument.getFieldValue("_field", Map.class);
// Still holds data for realm and authentication type // Still holds data for realm and authentication type
@ -88,9 +95,21 @@ public class SetSecurityUserProcessorTests extends ESTestCase {
public void testNoCurrentUser() throws Exception { public void testNoCurrentUser() throws Exception {
IngestDocument ingestDocument = new IngestDocument(new HashMap<>(), new HashMap<>()); IngestDocument ingestDocument = new IngestDocument(new HashMap<>(), new HashMap<>());
SetSecurityUserProcessor processor = new SetSecurityUserProcessor("_tag", securityContext, "_field", EnumSet.allOf(Property.class)); SetSecurityUserProcessor processor = new SetSecurityUserProcessor(
"_tag", securityContext, licenseState, "_field", EnumSet.allOf(Property.class));
IllegalStateException e = expectThrows(IllegalStateException.class, () -> processor.execute(ingestDocument)); IllegalStateException e = expectThrows(IllegalStateException.class, () -> processor.execute(ingestDocument));
assertThat(e.getMessage(), equalTo("No user authenticated, only use this processor via authenticated user")); assertThat(e.getMessage(),
equalTo("There is no authenticated user - the [set_security_user] processor requires an authenticated user"));
}
public void testSecurityDisabled() throws Exception {
when(licenseState.isAuthAllowed()).thenReturn(false);
IngestDocument ingestDocument = new IngestDocument(new HashMap<>(), new HashMap<>());
SetSecurityUserProcessor processor = new SetSecurityUserProcessor(
"_tag", securityContext, licenseState, "_field", EnumSet.allOf(Property.class));
IllegalStateException e = expectThrows(IllegalStateException.class, () -> processor.execute(ingestDocument));
assertThat(e.getMessage(), equalTo("Security (authentication) is not enabled on this cluster, so there is no active user" +
" - the [set_security_user] processor cannot be used without security"));
} }
public void testUsernameProperties() throws Exception { public void testUsernameProperties() throws Exception {
@ -99,7 +118,8 @@ public class SetSecurityUserProcessorTests extends ESTestCase {
new Authentication(user, realmRef, null).writeToContext(threadContext); new Authentication(user, realmRef, null).writeToContext(threadContext);
IngestDocument ingestDocument = new IngestDocument(new HashMap<>(), new HashMap<>()); IngestDocument ingestDocument = new IngestDocument(new HashMap<>(), new HashMap<>());
SetSecurityUserProcessor processor = new SetSecurityUserProcessor("_tag", securityContext, "_field", EnumSet.of(Property.USERNAME)); SetSecurityUserProcessor processor = new SetSecurityUserProcessor(
"_tag", securityContext, licenseState, "_field", EnumSet.of(Property.USERNAME));
processor.execute(ingestDocument); processor.execute(ingestDocument);
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@ -114,7 +134,8 @@ public class SetSecurityUserProcessorTests extends ESTestCase {
new Authentication(user, realmRef, null).writeToContext(threadContext); new Authentication(user, realmRef, null).writeToContext(threadContext);
IngestDocument ingestDocument = new IngestDocument(new HashMap<>(), new HashMap<>()); IngestDocument ingestDocument = new IngestDocument(new HashMap<>(), new HashMap<>());
SetSecurityUserProcessor processor = new SetSecurityUserProcessor("_tag", securityContext, "_field", EnumSet.of(Property.ROLES)); SetSecurityUserProcessor processor = new SetSecurityUserProcessor(
"_tag", securityContext, licenseState, "_field", EnumSet.of(Property.ROLES));
processor.execute(ingestDocument); processor.execute(ingestDocument);
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@ -130,7 +151,7 @@ public class SetSecurityUserProcessorTests extends ESTestCase {
IngestDocument ingestDocument = new IngestDocument(new HashMap<>(), new HashMap<>()); IngestDocument ingestDocument = new IngestDocument(new HashMap<>(), new HashMap<>());
SetSecurityUserProcessor processor SetSecurityUserProcessor processor
= new SetSecurityUserProcessor("_tag", securityContext, "_field", EnumSet.of(Property.FULL_NAME)); = new SetSecurityUserProcessor("_tag", securityContext, licenseState, "_field", EnumSet.of(Property.FULL_NAME));
processor.execute(ingestDocument); processor.execute(ingestDocument);
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@ -145,7 +166,8 @@ public class SetSecurityUserProcessorTests extends ESTestCase {
new Authentication(user, realmRef, null).writeToContext(threadContext); new Authentication(user, realmRef, null).writeToContext(threadContext);
IngestDocument ingestDocument = new IngestDocument(new HashMap<>(), new HashMap<>()); IngestDocument ingestDocument = new IngestDocument(new HashMap<>(), new HashMap<>());
SetSecurityUserProcessor processor = new SetSecurityUserProcessor("_tag", securityContext, "_field", EnumSet.of(Property.EMAIL)); SetSecurityUserProcessor processor = new SetSecurityUserProcessor(
"_tag", securityContext, licenseState, "_field", EnumSet.of(Property.EMAIL));
processor.execute(ingestDocument); processor.execute(ingestDocument);
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@ -160,7 +182,8 @@ public class SetSecurityUserProcessorTests extends ESTestCase {
new Authentication(user, realmRef, null).writeToContext(threadContext); new Authentication(user, realmRef, null).writeToContext(threadContext);
IngestDocument ingestDocument = new IngestDocument(new HashMap<>(), new HashMap<>()); IngestDocument ingestDocument = new IngestDocument(new HashMap<>(), new HashMap<>());
SetSecurityUserProcessor processor = new SetSecurityUserProcessor("_tag", securityContext, "_field", EnumSet.of(Property.METADATA)); SetSecurityUserProcessor processor = new SetSecurityUserProcessor(
"_tag", securityContext, licenseState, "_field", EnumSet.of(Property.METADATA));
processor.execute(ingestDocument); processor.execute(ingestDocument);
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@ -175,7 +198,8 @@ public class SetSecurityUserProcessorTests extends ESTestCase {
Authentication.RealmRef realmRef = new Authentication.RealmRef("_name", "_type", "_node_name"); Authentication.RealmRef realmRef = new Authentication.RealmRef("_name", "_type", "_node_name");
new Authentication(user, realmRef, null).writeToContext(threadContext); new Authentication(user, realmRef, null).writeToContext(threadContext);
SetSecurityUserProcessor processor = new SetSecurityUserProcessor("_tag", securityContext, "_field", EnumSet.of(Property.USERNAME)); SetSecurityUserProcessor processor = new SetSecurityUserProcessor(
"_tag", securityContext, licenseState, "_field", EnumSet.of(Property.USERNAME));
IngestDocument ingestDocument = new IngestDocument(new HashMap<>(), new HashMap<>()); IngestDocument ingestDocument = new IngestDocument(new HashMap<>(), new HashMap<>());
ingestDocument.setFieldValue("_field", "test"); ingestDocument.setFieldValue("_field", "test");
@ -209,11 +233,13 @@ public class SetSecurityUserProcessorTests extends ESTestCase {
.put(ApiKeyService.API_KEY_CREATOR_REALM_NAME, "creator_realm_name") .put(ApiKeyService.API_KEY_CREATOR_REALM_NAME, "creator_realm_name")
.put(ApiKeyService.API_KEY_CREATOR_REALM_TYPE, "creator_realm_type") .put(ApiKeyService.API_KEY_CREATOR_REALM_TYPE, "creator_realm_type")
.immutableMap(); .immutableMap();
new Authentication(user, realmRef, null, Version.CURRENT, AuthenticationType.API_KEY,metadata) Authentication auth = new Authentication(user, realmRef, null, Version.CURRENT,
.writeToContext(threadContext); AuthenticationType.API_KEY, metadata);
auth.writeToContext(threadContext);
IngestDocument ingestDocument = new IngestDocument(new HashMap<>(), new HashMap<>()); IngestDocument ingestDocument = new IngestDocument(new HashMap<>(), new HashMap<>());
SetSecurityUserProcessor processor = new SetSecurityUserProcessor("_tag", securityContext, "_field", EnumSet.allOf(Property.class)); SetSecurityUserProcessor processor = new SetSecurityUserProcessor(
"_tag", securityContext, licenseState, "_field", EnumSet.allOf(Property.class));
processor.execute(ingestDocument); processor.execute(ingestDocument);
Map<String, Object> result = ingestDocument.getFieldValue("_field", Map.class); Map<String, Object> result = ingestDocument.getFieldValue("_field", Map.class);
@ -245,7 +271,9 @@ public class SetSecurityUserProcessorTests extends ESTestCase {
.put("api_key", new MapBuilder<>().put("version", 42).immutableMap()) .put("api_key", new MapBuilder<>().put("version", 42).immutableMap())
.put("realm", new MapBuilder<>().put("id", 7).immutableMap()).immutableMap() .put("realm", new MapBuilder<>().put("id", 7).immutableMap()).immutableMap()
).immutableMap()), new HashMap<>()); ).immutableMap()), new HashMap<>());
SetSecurityUserProcessor processor = new SetSecurityUserProcessor("_tag", securityContext, "_field", EnumSet.allOf(Property.class));
SetSecurityUserProcessor processor = new SetSecurityUserProcessor(
"_tag", securityContext, licenseState, "_field", EnumSet.allOf(Property.class));
processor.execute(ingestDocument); processor.execute(ingestDocument);
Map<String, Object> result = ingestDocument.getFieldValue("_field", Map.class); Map<String, Object> result = ingestDocument.getFieldValue("_field", Map.class);
@ -266,7 +294,8 @@ public class SetSecurityUserProcessorTests extends ESTestCase {
Collections.emptyMap()).writeToContext(threadContext); Collections.emptyMap()).writeToContext(threadContext);
IngestDocument ingestDocument = new IngestDocument(new HashMap<>(), new HashMap<>()); IngestDocument ingestDocument = new IngestDocument(new HashMap<>(), new HashMap<>());
SetSecurityUserProcessor processor = new SetSecurityUserProcessor("_tag", securityContext, "_field", EnumSet.allOf(Property.class)); SetSecurityUserProcessor processor = new SetSecurityUserProcessor(
"_tag", securityContext, licenseState, "_field", EnumSet.allOf(Property.class));
processor.execute(ingestDocument); processor.execute(ingestDocument);
Map<String, Object> result = ingestDocument.getFieldValue("_field", Map.class); Map<String, Object> result = ingestDocument.getFieldValue("_field", Map.class);