
org.swisspush.gateleen.security.authorization.RoleMapper Maven / Gradle / Ivy
package org.swisspush.gateleen.security.authorization;
import io.vertx.core.buffer.Buffer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.swisspush.gateleen.core.http.UriBuilder;
import org.swisspush.gateleen.core.storage.ResourceStorage;
import org.swisspush.gateleen.validation.ValidationException;
import java.util.*;
import java.util.regex.Matcher;
/**
* Holds and maintains the RoleMapper configuration and performs the mapping.
*/
public class RoleMapper implements ConfigurationResource {
private ResourceStorage storage;
private String roleMapper;
private RoleMapperFactory roleMapperFactory;
private List roleMappers = null;
public static final Logger log = LoggerFactory.getLogger(RoleMapper.class);
public static final String ROLEMAPPER = "rolemapper";
/**
* Holds the list of all configured RoleMappings and executes the mapping
*
* @param storage Reference to the storage to retrieve the RoleMappings from
* @param securityRoot Base url to retrieve the rolemapper config resource from (no trailing slash expected nor necessary)
* @param properties The system properties given to the application, used to exctract the Environement where we are running in
*/
public RoleMapper(ResourceStorage storage, String securityRoot, Map properties) {
this.storage = storage;
this.roleMapper = UriBuilder.concatUriSegments(securityRoot, ROLEMAPPER);
this.roleMapperFactory = new RoleMapperFactory(properties);
configUpdate();
}
@Override
public void checkConfigResource(Buffer buffer) throws ValidationException {
roleMapperFactory.parseRoleMapper(buffer);
}
/**
* Retrieve the configured RoleMapper from Storage and populate the corresponding List of mappers.
*/
@Override
public void configUpdate() {
storage.get(roleMapper, buffer -> {
if (buffer != null) {
try {
roleMappers = roleMapperFactory.parseRoleMapper(buffer);
} catch (ValidationException validationException) {
log.error("Could not parse acl for role mapper: {}", validationException.toString());
}
} else {
log.info("No RoleMappers found in storage");
roleMappers = null;
}
});
}
public class MappedRole {
public final String role;
public final boolean forward;
public MappedRole(String role, boolean forward) {
this.role = role;
this.forward = forward;
}
}
/**
* Maps the received roles from http header according the rolemapper rules and return the set of
* mapped roles including the initial list of roles according to the given mapping rule sets.
*
* @param roles The roles to be mapped and enriched according to the rolemapper object
* @return The resulting list of initial plus mapped roles
*/
public Map mapRoles(Set roles) {
Map mappedRoles = new HashMap<>();
if (roles != null) {
String originalRole; // holds the last known original role to be applied in mapping rule chains
Matcher matcher;
for (String role : roles) {
originalRole = role;
if (roleMappers != null && !roleMappers.isEmpty()) {
for (RoleMapperHolder mapper : roleMappers) {
matcher = mapper.getPattern().matcher(role);
if (matcher.matches()) {
// we found a matching mapping rule to map and therefore,
// we must replace matching regex capture groups if there are any
String matchedRole = matcher.replaceAll(mapper.getRole());
// put the original role in the list of mapped roles
mappedRoles.put(originalRole, new MappedRole(originalRole, mapper.getKeepOriginalRole()));
// now we check if we have to continue matching in the chain of RoleMapper definitions
if (mapper.getContinueMapping()) {
// go on with next mapping rule, but the new original rule from now on is the one
// which matched here and not the previous original one
originalRole = matchedRole;
} else {
originalRole = null;
// put the last resulting mapped role to the list of mapped roles
mappedRoles.put(matchedRole, new MappedRole(matchedRole, mapper.getKeepResultingRole()));
// we don't have to loop further as it is finally mapped now for this given role
// according to the mapping definition
break;
}
}
}
// Finally add what is the last known OriginalRole up to here if there is any
if (originalRole != null) {
mappedRoles.put(originalRole, new MappedRole(originalRole, true));
}
} else {
// there is no mapping defined, just add the given role as is
mappedRoles.put(originalRole, new MappedRole(originalRole, true));
}
}
}
return mappedRoles;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy