Skip to content

Commit d5c0150

Browse files
authored
Don't allow null User.principal (#52049)
Some parts of the User class (e.g. equals/hashCode) assumed that principal could never be null, but the constructor didn't enforce that. This adds a null check into the constructor and fixes a few tests that relied on being able to pass in null usernames. Backport of: #51988
1 parent 2b99291 commit d5c0150

File tree

3 files changed

+22
-16
lines changed

3 files changed

+22
-16
lines changed

x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/user/User.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import java.util.Arrays;
1818
import java.util.Collections;
1919
import java.util.Map;
20+
import java.util.Objects;
2021

2122
/**
2223
* An authenticated user
@@ -50,7 +51,7 @@ public User(String username, String[] roles, String fullName, String email, Map<
5051

5152
private User(String username, String[] roles, String fullName, String email, Map<String, Object> metadata, boolean enabled,
5253
User authenticatedUser) {
53-
this.username = username;
54+
this.username = Objects.requireNonNull(username);
5455
this.roles = roles == null ? Strings.EMPTY_ARRAY : roles;
5556
this.metadata = metadata != null ? Collections.unmodifiableMap(metadata) : Collections.emptyMap();
5657
this.fullName = fullName;

x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/audit/logfile/LoggingAuditTrailFilterTests.java

+2-4
Original file line numberDiff line numberDiff line change
@@ -113,11 +113,9 @@ public void testPolicyDoesNotMatchNullValuesInEvent() throws Exception {
113113
// user field matches
114114
assertTrue("Matches the user filter predicate.", auditTrail.eventFilterPolicyRegistry.ignorePredicate().test(
115115
new AuditEventMetaInfo(Optional.of(randomFrom(filteredUsers)), Optional.empty(), Optional.empty(), Optional.empty())));
116-
final User unfilteredUser;
116+
final User unfilteredUser = mock(User.class);
117117
if (randomBoolean()) {
118-
unfilteredUser = new User(null);
119-
} else {
120-
unfilteredUser = new User(new User(null), new User(randomFrom(filteredUsers).principal()));
118+
when(unfilteredUser.authenticatedUser()).thenReturn(new User(randomFrom(filteredUsernames)));
121119
}
122120
// null user field does NOT match
123121
assertFalse("Does not match the user filter predicate because of null username.",

x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/ingest/SetSecurityUserProcessorTests.java

+18-11
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import org.elasticsearch.xpack.core.security.authc.AuthenticationField;
1414
import org.elasticsearch.xpack.core.security.user.User;
1515
import org.elasticsearch.xpack.security.ingest.SetSecurityUserProcessor.Property;
16+
import org.mockito.Mockito;
1617

1718
import java.util.Collections;
1819
import java.util.Arrays;
@@ -43,15 +44,21 @@ public void testProcessor() throws Exception {
4344
assertThat(result.get("email"), equalTo("_email"));
4445
assertThat(((Map) result.get("metadata")).size(), equalTo(1));
4546
assertThat(((Map) result.get("metadata")).get("key"), equalTo("value"));
47+
}
4648

47-
// test when user holds no data:
48-
threadContext = new ThreadContext(Settings.EMPTY);
49-
user = new User(null, null, null);
50-
threadContext.putTransient(AuthenticationField.AUTHENTICATION_KEY, new Authentication(user, realmRef, null));
51-
ingestDocument = new IngestDocument(new HashMap<>(), new HashMap<>());
52-
processor = new SetSecurityUserProcessor("_tag", threadContext, "_field", EnumSet.allOf(Property.class));
49+
public void testProcessorWithEmptyUserData() throws Exception {
50+
// test when user returns null for all values (need a mock, because a real user cannot have a null username)
51+
User user = Mockito.mock(User.class);
52+
Authentication authentication = Mockito.mock(Authentication.class);
53+
Mockito.when(authentication.getUser()).thenReturn(user);
54+
55+
ThreadContext threadContext = new ThreadContext(Settings.EMPTY);
56+
threadContext.putTransient(AuthenticationField.AUTHENTICATION_KEY, authentication);
57+
58+
IngestDocument ingestDocument = new IngestDocument(new HashMap<>(), new HashMap<>());
59+
SetSecurityUserProcessor processor = new SetSecurityUserProcessor("_tag", threadContext, "_field", EnumSet.allOf(Property.class));
5360
processor.execute(ingestDocument);
54-
result = ingestDocument.getFieldValue("_field", Map.class);
61+
Map result = ingestDocument.getFieldValue("_field", Map.class);
5562
assertThat(result.size(), equalTo(0));
5663
}
5764

@@ -81,7 +88,7 @@ public void testUsernameProperties() throws Exception {
8188

8289
public void testRolesProperties() throws Exception {
8390
ThreadContext threadContext = new ThreadContext(Settings.EMPTY);
84-
User user = new User(null, "role1", "role2");
91+
User user = new User(randomAlphaOfLengthBetween(4, 12), "role1", "role2");
8592
Authentication.RealmRef realmRef = new Authentication.RealmRef("_name", "_type", "_node_name");
8693
threadContext.putTransient(AuthenticationField.AUTHENTICATION_KEY, new Authentication(user, realmRef, null));
8794

@@ -97,7 +104,7 @@ public void testRolesProperties() throws Exception {
97104

98105
public void testFullNameProperties() throws Exception {
99106
ThreadContext threadContext = new ThreadContext(Settings.EMPTY);
100-
User user = new User(null, null, "_full_name", null, null, true);
107+
User user = new User(randomAlphaOfLengthBetween(4, 12), null, "_full_name", null, null, true);
101108
Authentication.RealmRef realmRef = new Authentication.RealmRef("_name", "_type", "_node_name");
102109
threadContext.putTransient(AuthenticationField.AUTHENTICATION_KEY, new Authentication(user, realmRef, null));
103110

@@ -113,7 +120,7 @@ public void testFullNameProperties() throws Exception {
113120

114121
public void testEmailProperties() throws Exception {
115122
ThreadContext threadContext = new ThreadContext(Settings.EMPTY);
116-
User user = new User(null, null, null, "_email", null, true);
123+
User user = new User(randomAlphaOfLengthBetween(4, 12), null, null, "_email", null, true);
117124
Authentication.RealmRef realmRef = new Authentication.RealmRef("_name", "_type", "_node_name");
118125
threadContext.putTransient(AuthenticationField.AUTHENTICATION_KEY, new Authentication(user, realmRef, null));
119126

@@ -129,7 +136,7 @@ public void testEmailProperties() throws Exception {
129136

130137
public void testMetadataProperties() throws Exception {
131138
ThreadContext threadContext = new ThreadContext(Settings.EMPTY);
132-
User user = new User(null, null, null, null, Collections.singletonMap("key", "value"), true);
139+
User user = new User(randomAlphaOfLengthBetween(4, 12), null, null, null, Collections.singletonMap("key", "value"), true);
133140
Authentication.RealmRef realmRef = new Authentication.RealmRef("_name", "_type", "_node_name");
134141
threadContext.putTransient(AuthenticationField.AUTHENTICATION_KEY, new Authentication(user, realmRef, null));
135142

0 commit comments

Comments
 (0)