Skip to content

Commit

Permalink
Service Accounts - ensure SetSecurityUserProcessTests work for servic…
Browse files Browse the repository at this point in the history
…e accounts (elastic#71669)

This PR ensures the tests for SetSecurityUserProcessor work for service accounts. 
Note it only makes sure existing tags work. Any new tags, e.g. token name, necessary 
for service accounts will be handled in a separate PR.
  • Loading branch information
ywangd authored Apr 14, 2021
1 parent 7a50ccd commit a642cb3
Showing 1 changed file with 107 additions and 43 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
package org.elasticsearch.xpack.security.ingest;

import org.elasticsearch.Version;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.util.concurrent.ThreadContext;
import org.elasticsearch.ingest.IngestDocument;
Expand All @@ -16,6 +17,7 @@
import org.elasticsearch.xpack.core.security.authc.Authentication;
import org.elasticsearch.xpack.core.security.authc.Authentication.AuthenticationType;
import org.elasticsearch.xpack.core.security.authc.support.AuthenticationContextSerializer;
import org.elasticsearch.xpack.core.security.support.ValidationTests;
import org.elasticsearch.xpack.core.security.user.User;
import org.elasticsearch.xpack.security.authc.ApiKeyService;
import org.elasticsearch.xpack.security.ingest.SetSecurityUserProcessor.Property;
Expand All @@ -29,6 +31,8 @@
import java.util.Map;

import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasKey;
import static org.hamcrest.Matchers.not;
import static org.mockito.Mockito.when;

public class SetSecurityUserProcessorTests extends ESTestCase {
Expand All @@ -46,27 +50,36 @@ public void setupObjects() {
}

public void testProcessorWithData() throws Exception {
User user = new User("_username", new String[] { "role1", "role2" }, "firstname lastname", "_email",
Map.of("key", "value"), true);
Authentication.RealmRef realmRef = new Authentication.RealmRef("_name", "_type", "_node_name");
new Authentication(user, realmRef, null, Version.CURRENT).writeToContext(threadContext);
final Authentication authentication = randomAuthentication();
authentication.writeToContext(threadContext);

IngestDocument ingestDocument = new IngestDocument(new HashMap<>(), new HashMap<>());
SetSecurityUserProcessor processor = new SetSecurityUserProcessor(
"_tag", null, securityContext, licenseState, "_field", EnumSet.allOf(Property.class));
processor.execute(ingestDocument);

Map<String, Object> result = ingestDocument.getFieldValue("_field", Map.class);
assertThat(result.size(), equalTo(7));
assertThat(result.get("username"), equalTo("_username"));
assertThat(result.get("roles"), equalTo(Arrays.asList("role1", "role2")));
assertThat(result.get("full_name"), equalTo("firstname lastname"));
assertThat(result.get("email"), equalTo("_email"));
assertThat(((Map) result.get("metadata")).size(), equalTo(1));
assertThat(((Map) result.get("metadata")).get("key"), equalTo("value"));
assertThat(((Map) result.get("realm")).get("name"), equalTo("_name"));
assertThat(((Map) result.get("realm")).get("type"), equalTo("_type"));
assertThat(result.get("authentication_type"), equalTo("REALM"));
if (authentication.getUser().fullName().startsWith("Service account - ")) {
assertThat(result, not(hasKey("roles")));
assertThat(result, not(hasKey("email")));
} else {
assertThat(result.get("email"), equalTo(authentication.getUser().email()));
if (authentication.getUser().roles().length == 0) {
assertThat(result, not(hasKey("roles")));
} else {
assertThat(result.get("roles"), equalTo(Arrays.asList(authentication.getUser().roles())));
}
}
if (authentication.getUser().metadata().isEmpty()) {
assertThat(result, not(hasKey("metadata")));
} else {
assertThat(result.get("metadata"), equalTo(authentication.getUser().metadata()));
}
assertThat(result.get("username"), equalTo(authentication.getUser().principal()));
assertThat(result.get("full_name"), equalTo(authentication.getUser().fullName()));
assertThat(((Map) result.get("realm")).get("name"), equalTo(authentication.getSourceRealm().getName()));
assertThat(((Map) result.get("realm")).get("type"), equalTo(authentication.getSourceRealm().getType()));
assertThat(result.get("authentication_type"), equalTo(authentication.getAuthenticationType().toString()));
}

public void testProcessorWithEmptyUserData() throws Exception {
Expand Down Expand Up @@ -113,9 +126,8 @@ public void testSecurityDisabled() throws Exception {
}

public void testUsernameProperties() throws Exception {
User user = new User("_username", null, null);
Authentication.RealmRef realmRef = new Authentication.RealmRef("_name", "_type", "_node_name");
new Authentication(user, realmRef, null).writeToContext(threadContext);
final Authentication authentication = randomAuthentication();
authentication.writeToContext(threadContext);

IngestDocument ingestDocument = new IngestDocument(new HashMap<>(), new HashMap<>());
SetSecurityUserProcessor processor = new SetSecurityUserProcessor(
Expand All @@ -125,13 +137,12 @@ public void testUsernameProperties() throws Exception {
@SuppressWarnings("unchecked")
Map<String, Object> result = ingestDocument.getFieldValue("_field", Map.class);
assertThat(result.size(), equalTo(1));
assertThat(result.get("username"), equalTo("_username"));
assertThat(result.get("username"), equalTo(authentication.getUser().principal()));
}

public void testRolesProperties() throws Exception {
User user = new User(randomAlphaOfLengthBetween(4, 12), "role1", "role2");
Authentication.RealmRef realmRef = new Authentication.RealmRef("_name", "_type", "_node_name");
new Authentication(user, realmRef, null).writeToContext(threadContext);
final Authentication authentication = randomAuthentication();
authentication.writeToContext(threadContext);

IngestDocument ingestDocument = new IngestDocument(new HashMap<>(), new HashMap<>());
SetSecurityUserProcessor processor = new SetSecurityUserProcessor(
Expand All @@ -140,14 +151,17 @@ public void testRolesProperties() throws Exception {

@SuppressWarnings("unchecked")
Map<String, Object> result = ingestDocument.getFieldValue("_field", Map.class);
assertThat(result.size(), equalTo(1));
assertThat(result.get("roles"), equalTo(Arrays.asList("role1", "role2")));
if (authentication.getUser().roles().length == 0) {
assertThat(result, not(hasKey("roles")));
} else {
assertThat(result.size(), equalTo(1));
assertThat(result.get("roles"), equalTo(Arrays.asList(authentication.getUser().roles())));
}
}

public void testFullNameProperties() throws Exception {
User user = new User(randomAlphaOfLengthBetween(4, 12), null, "_full_name", null, Map.of(), true);
Authentication.RealmRef realmRef = new Authentication.RealmRef("_name", "_type", "_node_name");
new Authentication(user, realmRef, null).writeToContext(threadContext);
final Authentication authentication = randomAuthentication();
authentication.writeToContext(threadContext);

IngestDocument ingestDocument = new IngestDocument(new HashMap<>(), new HashMap<>());
SetSecurityUserProcessor processor
Expand All @@ -157,13 +171,12 @@ public void testFullNameProperties() throws Exception {
@SuppressWarnings("unchecked")
Map<String, Object> result = ingestDocument.getFieldValue("_field", Map.class);
assertThat(result.size(), equalTo(1));
assertThat(result.get("full_name"), equalTo("_full_name"));
assertThat(result.get("full_name"), equalTo(authentication.getUser().fullName()));
}

public void testEmailProperties() throws Exception {
User user = new User(randomAlphaOfLengthBetween(4, 12), null, null, "_email", Map.of(), true);
Authentication.RealmRef realmRef = new Authentication.RealmRef("_name", "_type", "_node_name");
new Authentication(user, realmRef, null).writeToContext(threadContext);
final Authentication authentication = randomAuthentication();
authentication.writeToContext(threadContext);

IngestDocument ingestDocument = new IngestDocument(new HashMap<>(), new HashMap<>());
SetSecurityUserProcessor processor = new SetSecurityUserProcessor(
Expand All @@ -172,14 +185,17 @@ public void testEmailProperties() throws Exception {

@SuppressWarnings("unchecked")
Map<String, Object> result = ingestDocument.getFieldValue("_field", Map.class);
assertThat(result.size(), equalTo(1));
assertThat(result.get("email"), equalTo("_email"));
if (authentication.getUser().email() != null) {
assertThat(result.size(), equalTo(1));
assertThat(result.get("email"), equalTo(authentication.getUser().email()));
} else {
assertThat(result, not(hasKey("email")));
}
}

public void testMetadataProperties() throws Exception {
User user = new User(randomAlphaOfLengthBetween(4, 12), null, null, null, Map.of("key", "value"), true);
Authentication.RealmRef realmRef = new Authentication.RealmRef("_name", "_type", "_node_name");
new Authentication(user, realmRef, null).writeToContext(threadContext);
final Authentication authentication = randomAuthentication();
authentication.writeToContext(threadContext);

IngestDocument ingestDocument = new IngestDocument(new HashMap<>(), new HashMap<>());
SetSecurityUserProcessor processor = new SetSecurityUserProcessor(
Expand All @@ -188,15 +204,17 @@ public void testMetadataProperties() throws Exception {

@SuppressWarnings("unchecked")
Map<String, Object> result = ingestDocument.getFieldValue("_field", Map.class);
assertThat(result.size(), equalTo(1));
assertThat(((Map) result.get("metadata")).size(), equalTo(1));
assertThat(((Map) result.get("metadata")).get("key"), equalTo("value"));
if (authentication.getUser().metadata().isEmpty()) {
assertThat(result, not(hasKey("metadata")));
} else {
assertThat(result.size(), equalTo(1));
assertThat(result.get("metadata"), equalTo(authentication.getUser().metadata()));
}
}

public void testOverwriteExistingField() throws Exception {
User user = new User("_username", null, null);
Authentication.RealmRef realmRef = new Authentication.RealmRef("_name", "_type", "_node_name");
new Authentication(user, realmRef, null).writeToContext(threadContext);
final Authentication authentication = randomAuthentication();
authentication.writeToContext(threadContext);

SetSecurityUserProcessor processor = new SetSecurityUserProcessor(
"_tag", null, securityContext, licenseState, "_field", EnumSet.of(Property.USERNAME));
Expand All @@ -208,7 +226,7 @@ public void testOverwriteExistingField() throws Exception {
@SuppressWarnings("unchecked")
Map<String, Object> result = ingestDocument.getFieldValue("_field", Map.class);
assertThat(result.size(), equalTo(1));
assertThat(result.get("username"), equalTo("_username"));
assertThat(result.get("username"), equalTo(authentication.getUser().principal()));

ingestDocument = new IngestDocument(new HashMap<>(), new HashMap<>());
ingestDocument.setFieldValue("_field.other", "test");
Expand All @@ -218,7 +236,7 @@ public void testOverwriteExistingField() throws Exception {
@SuppressWarnings("unchecked")
Map<String, Object> result2 = ingestDocument.getFieldValue("_field", Map.class);
assertThat(result2.size(), equalTo(2));
assertThat(result2.get("username"), equalTo("_username"));
assertThat(result2.get("username"), equalTo(authentication.getUser().principal()));
assertThat(result2.get("other"), equalTo("test"));
}

Expand Down Expand Up @@ -302,4 +320,50 @@ public void testWillSetRunAsRealmForNonApiAuth() throws Exception {
assertThat(((Map) result.get("realm")).get("type"), equalTo(lookedUpRealmRef.getType()));
}

private User randomUser() {
final User user = doRandomUser();
if (false == user.fullName().startsWith("Service account - ") && randomBoolean()) {
return new User(user, doRandomUser());
} else {
return user;
}
}

private User doRandomUser() {
if (randomIntBetween(0, 2) < 2) {
return new User(randomAlphaOfLengthBetween(3, 8),
randomArray(1, 3, String[]::new, () -> randomAlphaOfLengthBetween(3, 8)),
randomAlphaOfLengthBetween(5, 20), randomAlphaOfLengthBetween(8, 20),
randomFrom(Map.of(), Map.of("key", "value")), true);
} else {
final String principal = randomAlphaOfLengthBetween(3, 8) + "/" + randomAlphaOfLengthBetween(3, 8);
return new User(principal, Strings.EMPTY_ARRAY, "Service account - " + principal, null,
randomFrom(Map.of(), Map.of("_elastic_service_account", true)), true);
}
}

private Authentication randomAuthentication() {
final User user = randomUser();
if (user.fullName().startsWith("Service account - ")) {
assert false == user.isRunAs() : "cannot run-as service account";
final Authentication.RealmRef authBy =
new Authentication.RealmRef("service_account", "service_account", randomAlphaOfLengthBetween(3, 8));
return new Authentication(user, authBy, null, Version.CURRENT, AuthenticationType.TOKEN,
Map.of("_token_name", ValidationTests.randomTokenName()));
} else {
final Authentication.RealmRef lookupBy;
final String nodeName = randomAlphaOfLengthBetween(3, 8);
if (user.isRunAs()) {
lookupBy = new Authentication.RealmRef(randomAlphaOfLengthBetween(3, 8), randomAlphaOfLengthBetween(3, 8), nodeName);
} else {
lookupBy = null;
}
final Authentication.RealmRef authBy =
new Authentication.RealmRef(randomAlphaOfLengthBetween(3, 8), randomAlphaOfLengthBetween(3, 8), nodeName);
final AuthenticationType authenticationType = user.isRunAs() ? AuthenticationType.REALM
: randomFrom(AuthenticationType.REALM, AuthenticationType.INTERNAL, AuthenticationType.TOKEN, AuthenticationType.ANONYMOUS);
final Map<String, Object> metadata = user.isRunAs() ? Map.of() : randomFrom(Map.of(), Map.of("foo", "bar"));
return new Authentication(user, authBy, lookupBy, Version.CURRENT, authenticationType, metadata);
}
}
}

0 comments on commit a642cb3

Please sign in to comment.