in src/main/java/com/amazon/dlic/auth/ldap/backend/LDAPAuthorizationBackend.java [659:950]
public void fillRoles(final User user, final AuthCredentials optionalAuthCreds)
throws OpenSearchSecurityException {
if (user == null) {
return;
}
String authenticatedUser;
String originalUserName;
LdapEntry entry = null;
String dn = null;
final boolean isDebugEnabled = log.isDebugEnabled();
if (isDebugEnabled){
log.debug("DBGTRACE (2): username: {} -> {}", user.getName(), Arrays.toString(user.getName().getBytes(StandardCharsets.UTF_8)));
}
if (user instanceof LdapUser) {
entry = ((LdapUser) user).getUserEntry();
authenticatedUser = entry.getDn();
originalUserName = ((LdapUser) user).getOriginalUsername();
} else {
authenticatedUser = user.getName();
originalUserName = user.getName();
}
if (isDebugEnabled){
log.debug("DBGTRACE (3): authenticatedUser: {} -> {}", authenticatedUser, Arrays.toString(authenticatedUser.getBytes(StandardCharsets.UTF_8)));
}
final boolean rolesearchEnabled = settings.getAsBoolean(ConfigConstants.LDAP_AUTHZ_ROLESEARCH_ENABLED, true);
if (isDebugEnabled) {
log.debug("Try to get roles for {}", authenticatedUser);
}
final boolean isTraceEnabled = log.isTraceEnabled();
if (isTraceEnabled) {
log.trace("user class: {}", user.getClass());
log.trace("authenticatedUser: {}", authenticatedUser);
log.trace("originalUserName: {}", originalUserName);
log.trace("entry: {}", String.valueOf(entry));
log.trace("dn: {}", dn);
}
if (skipUsersMatcher.test(originalUserName) || skipUsersMatcher.test(authenticatedUser)) {
if (isDebugEnabled) {
log.debug("Skipped search roles of user {}/{}", authenticatedUser, originalUserName);
}
return;
}
Connection connection = null;
try {
if (entry == null || dn == null) {
connection = getConnection(settings, configPath);
if (isValidDn(authenticatedUser)) {
// assume dn
if (isTraceEnabled) {
log.trace("{} is a valid DN", authenticatedUser);
}
if (isDebugEnabled){
log.debug("DBGTRACE (4): authenticatedUser="+authenticatedUser+" -> "+Arrays.toString(authenticatedUser.getBytes(StandardCharsets.UTF_8)));
}
entry = LdapHelper.lookup(connection, authenticatedUser);
if (entry == null) {
throw new OpenSearchSecurityException("No user '" + authenticatedUser + "' found");
}
} else {
if (isDebugEnabled)
log.debug("DBGTRACE (5): authenticatedUser="+user.getName()+" -> "+Arrays.toString(user.getName().getBytes(StandardCharsets.UTF_8)));
entry = LDAPAuthenticationBackend.exists(user.getName(), connection, settings, userBaseSettings);
if (isTraceEnabled) {
log.trace("{} is not a valid DN and was resolved to {}", authenticatedUser, entry);
}
if (entry == null || entry.getDn() == null) {
throw new OpenSearchSecurityException("No user " + authenticatedUser + " found");
}
}
dn = entry.getDn();
if (isTraceEnabled) {
log.trace("User found with DN {}", dn);
}
if (isDebugEnabled){
log.debug("DBGTRACE (6): dn"+dn+" -> "+Arrays.toString(dn.getBytes(StandardCharsets.UTF_8)));
}
}
final Set<LdapName> ldapRoles = new HashSet<>(150);
final Set<String> nonLdapRoles = new HashSet<>(150);
final HashMultimap<LdapName, Map.Entry<String, Settings>> resultRoleSearchBaseKeys = HashMultimap.create();
// Roles as an attribute of the user entry
// default is userrolename: memberOf
final String userRoleNames = settings.get(ConfigConstants.LDAP_AUTHZ_USERROLENAME, DEFAULT_USERROLENAME);
if (isTraceEnabled) {
log.trace("raw userRoleName(s): {}", userRoleNames);
}
// we support more than one rolenames, must be separated by a comma
for (String userRoleName : userRoleNames.split(",")) {
final String roleName = userRoleName.trim();
if (entry.getAttribute(roleName) != null) {
final Collection<String> userRoles = entry.getAttribute(roleName).getStringValues();
for (final String possibleRoleDN : userRoles) {
if (isDebugEnabled){
log.debug("DBGTRACE (7): possibleRoleDN"+possibleRoleDN);
}
if (isValidDn(possibleRoleDN)) {
LdapName ldapName = new LdapName(possibleRoleDN);
ldapRoles.add(ldapName);
resultRoleSearchBaseKeys.putAll(ldapName, this.roleBaseSettings);
} else {
nonLdapRoles.add(possibleRoleDN);
}
}
}
}
if (isTraceEnabled) {
log.trace("User attr. ldap roles count: {}", ldapRoles.size());
log.trace("User attr. ldap roles {}", ldapRoles);
log.trace("User attr. non-ldap roles count: {}", nonLdapRoles.size());
log.trace("User attr. non-ldap roles {}", nonLdapRoles);
}
// The attribute in a role entry containing the name of that role, Default is
// "name".
// Can also be "dn" to use the full DN as rolename.
// rolename: name
final String roleName = settings.get(ConfigConstants.LDAP_AUTHZ_ROLENAME, DEFAULT_ROLENAME);
if (isTraceEnabled) {
log.trace("roleName: {}", roleName);
}
// Specify the name of the attribute which value should be substituted with {2}
// Substituted with an attribute value from user's directory entry, of the
// authenticated user
// userroleattribute: null
final String userRoleAttributeName = settings.get(ConfigConstants.LDAP_AUTHZ_USERROLEATTRIBUTE, null);
if (isTraceEnabled) {
log.trace("userRoleAttribute: {}", userRoleAttributeName);
log.trace("rolesearch: {}", settings.get(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, DEFAULT_ROLESEARCH));
}
String userRoleAttributeValue = null;
final LdapAttribute userRoleAttribute = entry.getAttribute(userRoleAttributeName);
if (userRoleAttribute != null) {
userRoleAttributeValue = Utils.getSingleStringValue(userRoleAttribute);
}
if (rolesearchEnabled) {
String escapedDn = dn;
if (isDebugEnabled){
log.debug("DBGTRACE (8): escapedDn"+escapedDn);
}
for (Map.Entry<String, Settings> roleSearchSettingsEntry : roleBaseSettings) {
Settings roleSearchSettings = roleSearchSettingsEntry.getValue();
SearchFilter f = new SearchFilter();
f.setFilter(roleSearchSettings.get(ConfigConstants.LDAP_AUTHCZ_SEARCH, DEFAULT_ROLESEARCH));
f.setParameter(LDAPAuthenticationBackend.ZERO_PLACEHOLDER, escapedDn);
f.setParameter(ONE_PLACEHOLDER, originalUserName);
f.setParameter(TWO_PLACEHOLDER,
userRoleAttributeValue == null ? TWO_PLACEHOLDER : userRoleAttributeValue);
List<LdapEntry> rolesResult = LdapHelper.search(connection,
roleSearchSettings.get(ConfigConstants.LDAP_AUTHCZ_BASE, DEFAULT_ROLEBASE),
f,
SearchScope.SUBTREE);
if (isTraceEnabled) {
log.trace("Results for LDAP group search for {} in base {}:\n{}", escapedDn, roleSearchSettingsEntry.getKey(), rolesResult);
}
if (rolesResult != null && !rolesResult.isEmpty()) {
for (final Iterator<LdapEntry> iterator = rolesResult.iterator(); iterator.hasNext();) {
LdapEntry searchResultEntry = iterator.next();
LdapName ldapName = new LdapName(searchResultEntry.getDn());
ldapRoles.add(ldapName);
resultRoleSearchBaseKeys.put(ldapName, roleSearchSettingsEntry);
}
}
}
}
if (isTraceEnabled) {
log.trace("roles count total {}", ldapRoles.size());
}
// nested roles, makes only sense for DN style role names
if (nestedRoleMatcher != null) {
if (isTraceEnabled) {
log.trace("Evaluate nested roles");
}
final Set<LdapName> nestedReturn = new HashSet<>(ldapRoles);
for (final LdapName roleLdapName : ldapRoles) {
Set<Map.Entry<String, Settings>> nameRoleSearchBaseKeys = resultRoleSearchBaseKeys
.get(roleLdapName);
if (nameRoleSearchBaseKeys == null) {
log.error("Could not find roleSearchBaseKeys for " + roleLdapName + "; existing: "
+ resultRoleSearchBaseKeys);
continue;
}
final Set<LdapName> nestedRoles = resolveNestedRoles(roleLdapName, connection, userRoleNames, 0,
rolesearchEnabled, nameRoleSearchBaseKeys);
if (isTraceEnabled) {
log.trace("{} nested roles for {}", nestedRoles.size(), roleLdapName);
}
nestedReturn.addAll(nestedRoles);
}
for (final LdapName roleLdapName : nestedReturn) {
final String role = getRoleFromEntry(connection, roleLdapName, roleName);
if (!Strings.isNullOrEmpty(role)) {
user.addRole(role);
} else {
log.warn("No or empty attribute '{}' for entry {}", roleName, roleLdapName);
}
}
} else {
// DN roles, extract rolename according to config
for (final LdapName roleLdapName : ldapRoles) {
final String role = getRoleFromEntry(connection, roleLdapName, roleName);
if (!Strings.isNullOrEmpty(role)) {
user.addRole(role);
} else {
log.warn("No or empty attribute '{}' for entry {}", roleName, roleLdapName);
}
}
}
// add all non-LDAP roles from user attributes to the final set of backend roles
for (String nonLdapRoleName : nonLdapRoles) {
user.addRole(nonLdapRoleName);
}
if (isDebugEnabled) {
log.debug("Roles for {} -> {}", user.getName(), user.getRoles());
}
if (isTraceEnabled) {
log.trace("returned user: {}", user);
}
} catch (final Exception e) {
if (isDebugEnabled) {
log.debug("Unable to fill user roles due to ", e);
}
throw new OpenSearchSecurityException(e.toString(), e);
} finally {
Utils.unbindAndCloseSilently(connection);
}
}