Skip to content

Commit 3c94f80

Browse files
authored
Don't allow null User.principal (#51988)
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.
1 parent 6247b07 commit 3c94f80

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import java.io.IOException;
1717
import java.util.Arrays;
1818
import java.util.Map;
19+
import java.util.Objects;
1920

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

5051
private User(String username, String[] roles, String fullName, String email, Map<String, Object> metadata, boolean enabled,
5152
User authenticatedUser) {
52-
this.username = username;
53+
this.username = Objects.requireNonNull(username);
5354
this.roles = roles == null ? Strings.EMPTY_ARRAY : roles;
5455
this.metadata = metadata == null ? Map.of() : metadata;
5556
this.fullName = fullName;

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

Lines changed: 2 additions & 4 deletions
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

Lines changed: 18 additions & 11 deletions
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.Arrays;
1819
import java.util.EnumSet;
@@ -42,15 +43,21 @@ public void testProcessor() throws Exception {
4243
assertThat(result.get("email"), equalTo("_email"));
4344
assertThat(((Map) result.get("metadata")).size(), equalTo(1));
4445
assertThat(((Map) result.get("metadata")).get("key"), equalTo("value"));
46+
}
4547

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

@@ -80,7 +87,7 @@ public void testUsernameProperties() throws Exception {
8087

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

@@ -96,7 +103,7 @@ public void testRolesProperties() throws Exception {
96103

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

@@ -112,7 +119,7 @@ public void testFullNameProperties() throws Exception {
112119

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

@@ -128,7 +135,7 @@ public void testEmailProperties() throws Exception {
128135

129136
public void testMetadataProperties() throws Exception {
130137
ThreadContext threadContext = new ThreadContext(Settings.EMPTY);
131-
User user = new User(null, null, null, null, Map.of("key", "value"), true);
138+
User user = new User(randomAlphaOfLengthBetween(4, 12), null, null, null, Map.of("key", "value"), true);
132139
Authentication.RealmRef realmRef = new Authentication.RealmRef("_name", "_type", "_node_name");
133140
threadContext.putTransient(AuthenticationField.AUTHENTICATION_KEY, new Authentication(user, realmRef, null));
134141

0 commit comments

Comments
 (0)