Skip to content

Commit d2c434c

Browse files
committed
First shot at an immutable user object
1 parent 24a4593 commit d2c434c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+837
-689
lines changed

src/integrationTest/java/org/opensearch/security/privileges/ActionPrivilegesTest.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1040,8 +1040,7 @@ static SecurityDynamicConfiguration<RoleV7> createRoles(int numberOfRoles, int n
10401040
}
10411041

10421042
static PrivilegesEvaluationContext ctx(String... roles) {
1043-
User user = new User("test_user");
1044-
user.addAttributes(ImmutableMap.of("attrs.dept_no", "a11"));
1043+
User user = new User("test_user").withAttributes(ImmutableMap.of("attrs.dept_no", "a11"));
10451044
return new PrivilegesEvaluationContext(
10461045
user,
10471046
ImmutableSet.copyOf(roles),
@@ -1055,8 +1054,7 @@ static PrivilegesEvaluationContext ctx(String... roles) {
10551054
}
10561055

10571056
static PrivilegesEvaluationContext ctxByUsername(String username) {
1058-
User user = new User(username);
1059-
user.addAttributes(ImmutableMap.of("attrs.dept_no", "a11"));
1057+
User user = new User(username).withAttributes(ImmutableMap.of("attrs.dept_no", "a11"));
10601058
return new PrivilegesEvaluationContext(
10611059
user,
10621060
ImmutableSet.of(),

src/integrationTest/java/org/opensearch/security/privileges/IndexPatternTest.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -234,10 +234,7 @@ public void equals() {
234234
private static PrivilegesEvaluationContext ctx() {
235235
IndexNameExpressionResolver indexNameExpressionResolver = new IndexNameExpressionResolver(new ThreadContext(Settings.EMPTY));
236236
IndexResolverReplacer indexResolverReplacer = new IndexResolverReplacer(indexNameExpressionResolver, () -> CLUSTER_STATE, null);
237-
User user = new User("test_user");
238-
user.addAttributes(ImmutableMap.of("attrs.a11", "a11"));
239-
user.addAttributes(ImmutableMap.of("attrs.year", "year"));
240-
237+
User user = new User("test_user").withAttributes(ImmutableMap.of("attrs.a11", "a11", "attrs.year", "year"));
241238
return new PrivilegesEvaluationContext(
242239
user,
243240
ImmutableSet.of(),

src/integrationTest/java/org/opensearch/security/privileges/dlsfls/DocumentPrivilegesTest.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1191,9 +1191,7 @@ UserSpec attribute(String name, String value) {
11911191
}
11921192

11931193
User buildUser() {
1194-
User user = new User("test_user_" + description);
1195-
user.addAttributes(this.attributes);
1196-
return user;
1194+
return new User("test_user_" + description).withAttributes(this.attributes);
11971195
}
11981196

11991197
@Override
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
*
4+
* The OpenSearch Contributors require contributions made to
5+
* this file be licensed under the Apache-2.0 license or a
6+
* compatible open source license.
7+
*
8+
* Modifications Copyright OpenSearch Contributors. See
9+
* GitHub history for details.
10+
*/
11+
package org.opensearch.security.user;
12+
13+
import java.util.Arrays;
14+
15+
import com.google.common.collect.ImmutableMap;
16+
import org.junit.Test;
17+
18+
import org.opensearch.security.support.Base64JDKHelper;
19+
20+
import static org.junit.Assert.*;
21+
22+
public class UserTest {
23+
@Test
24+
public void serialization() {
25+
User user = new User("serialization_test_user").withRoles(Arrays.asList("br1", "br2", "br3"))
26+
.withSecurityRoles(Arrays.asList("sr1", "sr2"))
27+
.withAttributes(ImmutableMap.of("a", "v_a", "b", "v_b"));
28+
29+
System.out.println(Base64JDKHelper.serializeObject(user));
30+
}
31+
32+
@Test
33+
public void deserializationFrom2_19() {
34+
// The following base64 string was produced by the following code on OpenSearch 2.19
35+
// User user = new User("serialization_test_user");
36+
// user.addRoles(Arrays.asList("br1", "br2", "br3"));
37+
// user.addSecurityRoles(Arrays.asList("sr1", "sr2"));
38+
// user.addAttributes(ImmutableMap.of("a", "v_a", "b", "v_b"));
39+
// System.out.println(Base64JDKHelper.serializeObject(user));
40+
String serialized =
41+
"rO0ABXNyACFvcmcub3BlbnNlYXJjaC5zZWN1cml0eS51c2VyLlVzZXKzqL2T65dH3AIABloACmlzSW5qZWN0ZWRMAAphdHRyaWJ1dGVzdAAPTGphdmEvdXRpbC9NYXA7TAAEbmFtZXQAEkxqYXZhL2xhbmcvU3RyaW5nO0wAD3JlcXVlc3RlZFRlbmFudHEAfgACTAAFcm9sZXN0AA9MamF2YS91dGlsL1NldDtMAA1zZWN1cml0eVJvbGVzcQB+AAN4cABzcgAlamF2YS51dGlsLkNvbGxlY3Rpb25zJFN5bmNocm9uaXplZE1hcBtz+QlLSzl7AwACTAABbXEAfgABTAAFbXV0ZXh0ABJMamF2YS9sYW5nL09iamVjdDt4cHNyABFqYXZhLnV0aWwuSGFzaE1hcAUH2sHDFmDRAwACRgAKbG9hZEZhY3RvckkACXRocmVzaG9sZHhwP0AAAAAAAAN3CAAAAAQAAAACdAABYXQAA3ZfYXQAAWJ0AAN2X2J4cQB+AAd4dAAXc2VyaWFsaXphdGlvbl90ZXN0X3VzZXJwc3IAJWphdmEudXRpbC5Db2xsZWN0aW9ucyRTeW5jaHJvbml6ZWRTZXQGw8J5Au7fPAIAAHhyACxqYXZhLnV0aWwuQ29sbGVjdGlvbnMkU3luY2hyb25pemVkQ29sbGVjdGlvbiph+E0JnJm1AwACTAABY3QAFkxqYXZhL3V0aWwvQ29sbGVjdGlvbjtMAAVtdXRleHEAfgAGeHBzcgARamF2YS51dGlsLkhhc2hTZXS6RIWVlri3NAMAAHhwdwwAAAAQP0AAAAAAAAN0AANicjF0AANicjN0AANicjJ4cQB+ABJ4c3EAfgAPc3EAfgATdwwAAAAQP0AAAAAAAAJ0AANzcjJ0AANzcjF4cQB+ABh4";
42+
43+
User user = User.fromSerializedBase64(serialized);
44+
assertEquals(
45+
new User("serialization_test_user").withRoles(Arrays.asList("br1", "br2", "br3"))
46+
.withSecurityRoles(Arrays.asList("sr1", "sr2"))
47+
.withAttributes(ImmutableMap.of("a", "v_a", "b", "v_b")),
48+
user
49+
);
50+
}
51+
}

src/main/java/com/amazon/dlic/auth/ldap/LdapUser.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ public LdapUser(
4444
this.originalUsername = originalUsername;
4545
this.userEntry = userEntry;
4646
Map<String, String> attributes = getCustomAttributesMap();
47+
// TODO
4748
attributes.putAll(extractLdapAttributes(originalUsername, userEntry, customAttrMaxValueLen, allowlistedCustomLdapAttrMatcher));
4849
}
4950

src/main/java/com/amazon/dlic/auth/ldap/backend/LDAPAuthenticationBackend.java

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import java.util.HashSet;
2020
import java.util.List;
2121
import java.util.Map;
22+
import java.util.Optional;
2223
import java.util.Set;
2324
import java.util.UUID;
2425

@@ -29,6 +30,7 @@
2930
import org.opensearch.OpenSearchSecurityException;
3031
import org.opensearch.common.settings.Settings;
3132
import org.opensearch.security.auth.AuthenticationBackend;
33+
import org.opensearch.security.auth.ImpersonationBackend;
3234
import org.opensearch.security.support.WildcardMatcher;
3335
import org.opensearch.security.user.AuthCredentials;
3436
import org.opensearch.security.user.User;
@@ -46,7 +48,7 @@
4648

4749
import static org.opensearch.security.setting.DeprecatedSettings.checkForDeprecatedSetting;
4850

49-
public class LDAPAuthenticationBackend implements AuthenticationBackend {
51+
public class LDAPAuthenticationBackend implements AuthenticationBackend, ImpersonationBackend {
5052

5153
static final int ZERO_PLACEHOLDER = 0;
5254
static final String DEFAULT_USERBASE = "";
@@ -160,7 +162,7 @@ public String getType() {
160162
}
161163

162164
@Override
163-
public boolean exists(final User user) {
165+
public Optional<User> impersonate(User user) {
164166
Connection ldapConnection = null;
165167
String userName = user.getName();
166168

@@ -178,19 +180,19 @@ public boolean exists(final User user) {
178180
this.returnAttributes,
179181
this.shouldFollowReferrals
180182
);
181-
boolean exists = userEntry != null;
182183

183-
if (exists) {
184-
user.addAttributes(
185-
LdapUser.extractLdapAttributes(userName, userEntry, customAttrMaxValueLen, allowlistedCustomLdapAttrMatcher)
184+
if (userEntry != null) {
185+
return Optional.of(
186+
user.withAttributes(
187+
LdapUser.extractLdapAttributes(userName, userEntry, customAttrMaxValueLen, allowlistedCustomLdapAttrMatcher)
188+
)
186189
);
190+
} else {
191+
return Optional.empty();
187192
}
188-
189-
return exists;
190-
191193
} catch (final Exception e) {
192-
log.warn("User {} does not exist due to ", userName, e);
193-
return false;
194+
log.warn("User {} does not exist due to exception", userName, e);
195+
return Optional.empty();
194196
} finally {
195197
Utils.unbindAndCloseSilently(ldapConnection);
196198
}

src/main/java/com/amazon/dlic/auth/ldap/backend/LDAPAuthorizationBackend.java

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -686,10 +686,10 @@ private static void configureSSL(final ConnectionConfig config, final Settings s
686686
}
687687

688688
@Override
689-
public void fillRoles(final User user, final AuthCredentials optionalAuthCreds) throws OpenSearchSecurityException {
689+
public User addRoles(User user, AuthCredentials credentials) throws OpenSearchSecurityException {
690690

691691
if (user == null) {
692-
return;
692+
return user;
693693
}
694694

695695
String authenticatedUser;
@@ -738,12 +738,13 @@ public void fillRoles(final User user, final AuthCredentials optionalAuthCreds)
738738
if (isDebugEnabled) {
739739
log.debug("Skipped search roles of user {}/{}", authenticatedUser, originalUserName);
740740
}
741-
return;
741+
return user;
742742
}
743743

744744
Connection connection = null;
745745

746746
try {
747+
Set<String> additionalRoles = new HashSet<>();
747748

748749
if (entry == null || dn == null) {
749750

@@ -969,7 +970,7 @@ public void fillRoles(final User user, final AuthCredentials optionalAuthCreds)
969970
log.debug("Role was excluded or empty, attribute: '{}' for entry: {}", roleName, roleLdapName);
970971
}
971972
} else {
972-
user.addRole(role);
973+
additionalRoles.add(role);
973974
}
974975
}
975976

@@ -983,16 +984,14 @@ public void fillRoles(final User user, final AuthCredentials optionalAuthCreds)
983984
log.debug("Role was excluded or empty, attribute: '{}' for entry: {}", roleName, roleLdapName);
984985
}
985986
} else {
986-
user.addRole(role);
987+
additionalRoles.add(role);
987988
}
988989
}
989990

990991
}
991992

992993
// add all non-LDAP roles from user attributes to the final set of backend roles
993-
for (String nonLdapRoleName : nonLdapRoles) {
994-
user.addRole(nonLdapRoleName);
995-
}
994+
additionalRoles.addAll(nonLdapRoles);
996995

997996
if (isDebugEnabled) {
998997
log.debug("Roles for {} -> {}", user.getName(), user.getRoles());
@@ -1002,6 +1001,8 @@ public void fillRoles(final User user, final AuthCredentials optionalAuthCreds)
10021001
log.trace("returned user: {}", user);
10031002
}
10041003

1004+
return user.withRoles(additionalRoles);
1005+
10051006
} catch (final Exception e) {
10061007
if (isDebugEnabled) {
10071008
log.debug("Unable to fill user roles due to ", e);

src/main/java/com/amazon/dlic/auth/ldap2/LDAPAuthenticationBackend2.java

Lines changed: 30 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import java.security.PrivilegedExceptionAction;
2020
import java.util.Arrays;
2121
import java.util.Collections;
22+
import java.util.Optional;
2223
import java.util.UUID;
2324

2425
import org.apache.logging.log4j.LogManager;
@@ -29,6 +30,7 @@
2930
import org.opensearch.common.settings.Settings;
3031
import org.opensearch.security.auth.AuthenticationBackend;
3132
import org.opensearch.security.auth.Destroyable;
33+
import org.opensearch.security.auth.ImpersonationBackend;
3234
import org.opensearch.security.support.WildcardMatcher;
3335
import org.opensearch.security.user.AuthCredentials;
3436
import org.opensearch.security.user.User;
@@ -47,7 +49,7 @@
4749
import org.ldaptive.ReturnAttributes;
4850
import org.ldaptive.pool.ConnectionPool;
4951

50-
public class LDAPAuthenticationBackend2 implements AuthenticationBackend, Destroyable {
52+
public class LDAPAuthenticationBackend2 implements AuthenticationBackend, ImpersonationBackend, Destroyable {
5153

5254
protected static final Logger log = LogManager.getLogger(LDAPAuthenticationBackend2.class);
5355

@@ -189,50 +191,42 @@ public String getType() {
189191

190192
@SuppressWarnings("removal")
191193
@Override
192-
public boolean exists(final User user) {
194+
public Optional<User> impersonate(User user) {
193195
final SecurityManager sm = System.getSecurityManager();
194196

195197
if (sm != null) {
196198
sm.checkPermission(new SpecialPermission());
197199
}
198200

199-
return AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
200-
@Override
201-
public Boolean run() {
202-
return exists0(user);
203-
}
204-
});
205-
206-
}
207-
208-
private boolean exists0(final User user) {
209-
Connection ldapConnection = null;
210-
String userName = user.getName();
211-
212-
if (user instanceof LdapUser) {
213-
userName = ((LdapUser) user).getUserEntry().getDn();
214-
}
215-
216-
try {
217-
ldapConnection = this.connectionFactory.getConnection();
218-
ldapConnection.open();
219-
LdapEntry userEntry = this.userSearcher.exists(ldapConnection, userName, this.returnAttributes, this.shouldFollowReferrals);
220-
221-
boolean exists = userEntry != null;
201+
return AccessController.doPrivileged((PrivilegedAction<Optional<User>>) () -> {
202+
Connection ldapConnection = null;
203+
String userName = user.getName();
222204

223-
if (exists) {
224-
user.addAttributes(
225-
LdapUser.extractLdapAttributes(userName, userEntry, customAttrMaxValueLen, whitelistedCustomLdapAttrMatcher)
226-
);
205+
if (user instanceof LdapUser) {
206+
userName = ((LdapUser) user).getUserEntry().getDn();
227207
}
228208

229-
return exists;
230-
} catch (final Exception e) {
231-
log.warn("User {} does not exist due to exception", userName, e);
232-
return false;
233-
} finally {
234-
Utils.unbindAndCloseSilently(ldapConnection);
235-
}
209+
try {
210+
ldapConnection = this.connectionFactory.getConnection();
211+
ldapConnection.open();
212+
LdapEntry userEntry = this.userSearcher.exists(ldapConnection, userName, this.returnAttributes, this.shouldFollowReferrals);
213+
214+
if (userEntry != null) {
215+
return Optional.of(
216+
user.withAttributes(
217+
LdapUser.extractLdapAttributes(userName, userEntry, customAttrMaxValueLen, whitelistedCustomLdapAttrMatcher)
218+
)
219+
);
220+
} else {
221+
return Optional.empty();
222+
}
223+
} catch (final Exception e) {
224+
log.warn("User {} does not exist due to exception", userName, e);
225+
return Optional.empty();
226+
} finally {
227+
Utils.unbindAndCloseSilently(ldapConnection);
228+
}
229+
});
236230
}
237231

238232
@SuppressWarnings("removal")

0 commit comments

Comments
 (0)