feat: Added new claims sources
- Added Claim source for producing values based on attribute value set on the groups, where user is active member and the groups are assigned to the resource in Perun - Added Claim source for producing MinIO policiespull/1580/head
parent
fa67431a52
commit
15cf3a95eb
|
@ -625,7 +625,11 @@ public class PerunAdapterLdap extends PerunAdapterWithMappingServices implements
|
||||||
return ids;
|
return ids;
|
||||||
};
|
};
|
||||||
|
|
||||||
return connectorLdap.lookup(dnPrefix, attributes, mapper);
|
Set<Long> res = connectorLdap.lookup(dnPrefix, attributes, mapper);
|
||||||
|
if (res == null) {
|
||||||
|
res = new HashSet<>();
|
||||||
|
}
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getDnPrefixForUserId(Long userId) {
|
private String getDnPrefixForUserId(Long userId) {
|
||||||
|
@ -658,11 +662,14 @@ public class PerunAdapterLdap extends PerunAdapterWithMappingServices implements
|
||||||
Set<AttributeMapping> mappings = this.getMappingsForAttrNames(entity, attrsToFetch);
|
Set<AttributeMapping> mappings = this.getMappingsForAttrNames(entity, attrsToFetch);
|
||||||
String[] attributes = this.getAttributesFromMappings(mappings);
|
String[] attributes = this.getAttributesFromMappings(mappings);
|
||||||
|
|
||||||
Map<String, PerunAttributeValue> res = new HashMap<>();
|
Map<String, PerunAttributeValue> res = null;
|
||||||
if (attributes.length != 0) {
|
if (attributes.length != 0) {
|
||||||
EntryMapper<Map<String, PerunAttributeValue>> mapper = attrValueMapper(mappings);
|
EntryMapper<Map<String, PerunAttributeValue>> mapper = attrValueMapper(mappings);
|
||||||
res = this.connectorLdap.lookup(dnPrefix, attributes, mapper);
|
res = this.connectorLdap.lookup(dnPrefix, attributes, mapper);
|
||||||
}
|
}
|
||||||
|
if (res == null) {
|
||||||
|
res = new HashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,19 @@
|
||||||
package cz.muni.ics.oidc.server.claims;
|
package cz.muni.ics.oidc.server.claims;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
import com.fasterxml.jackson.databind.node.ArrayNode;
|
import com.fasterxml.jackson.databind.node.ArrayNode;
|
||||||
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
|
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
|
||||||
|
import cz.muni.ics.oidc.models.Facility;
|
||||||
|
import cz.muni.ics.oidc.models.Group;
|
||||||
|
import cz.muni.ics.oidc.server.adapters.PerunAdapter;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class ClaimUtils {
|
public class ClaimUtils {
|
||||||
|
|
||||||
public static final String NO_VALUE = null;
|
public static final String NO_VALUE = null;
|
||||||
|
@ -67,4 +76,24 @@ public class ClaimUtils {
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Set<Group> getUserGroupsOnFacility(Facility facility, Long userId,
|
||||||
|
PerunAdapter perunAdapter, String claimName)
|
||||||
|
{
|
||||||
|
Set<Group> userGroups = new HashSet<>();
|
||||||
|
if (facility == null) {
|
||||||
|
log.warn("{} - no facility provided when searching for user groups, will return empty set", claimName);
|
||||||
|
} else {
|
||||||
|
userGroups = perunAdapter.getGroupsWhereUserIsActiveWithUniqueNames(facility.getId(), userId);
|
||||||
|
}
|
||||||
|
log.trace("{} - found user groups: '{}'", claimName, userGroups);
|
||||||
|
return userGroups;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static JsonNode convertResultStringsToJsonArray(Collection<String> collection) {
|
||||||
|
ArrayNode arr = JsonNodeFactory.instance.arrayNode();
|
||||||
|
collection.forEach(arr::add);
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import cz.muni.ics.oidc.models.Group;
|
||||||
import cz.muni.ics.oidc.server.adapters.PerunAdapter;
|
import cz.muni.ics.oidc.server.adapters.PerunAdapter;
|
||||||
import cz.muni.ics.oidc.server.claims.ClaimSourceInitContext;
|
import cz.muni.ics.oidc.server.claims.ClaimSourceInitContext;
|
||||||
import cz.muni.ics.oidc.server.claims.ClaimSourceProduceContext;
|
import cz.muni.ics.oidc.server.claims.ClaimSourceProduceContext;
|
||||||
|
import cz.muni.ics.oidc.server.claims.ClaimUtils;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
|
@ -37,13 +38,13 @@ public class EntitlementExtendedClaimSource extends EntitlementSource {
|
||||||
Long userId = pctx.getPerunUserId();
|
Long userId = pctx.getPerunUserId();
|
||||||
Set<String> entitlements = produceEntitlementsExtended(pctx.getFacility(),
|
Set<String> entitlements = produceEntitlementsExtended(pctx.getFacility(),
|
||||||
userId, pctx.getPerunAdapter());
|
userId, pctx.getPerunAdapter());
|
||||||
JsonNode result = convertResultStringsToJsonArray(entitlements);
|
JsonNode result = ClaimUtils.convertResultStringsToJsonArray(entitlements);
|
||||||
log.debug("{} - produced value for user({}): '{}'", getClaimName(), userId, result);
|
log.debug("{} - produced value for user({}): '{}'", getClaimName(), userId, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Set<String> produceEntitlementsExtended(Facility facility, Long userId, PerunAdapter perunAdapter) {
|
private Set<String> produceEntitlementsExtended(Facility facility, Long userId, PerunAdapter perunAdapter) {
|
||||||
Set<Group> userGroups = getUserGroupsOnFacility(facility, userId, perunAdapter);
|
Set<Group> userGroups = ClaimUtils.getUserGroupsOnFacility(facility, userId, perunAdapter, getClaimName());
|
||||||
Map<Long, String> groupIdToNameMap = super.getGroupIdToNameMap(userGroups, false);
|
Map<Long, String> groupIdToNameMap = super.getGroupIdToNameMap(userGroups, false);
|
||||||
Set<String> entitlements = new TreeSet<>();
|
Set<String> entitlements = new TreeSet<>();
|
||||||
this.fillUuidEntitlements(userGroups, entitlements);
|
this.fillUuidEntitlements(userGroups, entitlements);
|
||||||
|
|
|
@ -84,10 +84,10 @@ public class EntitlementSource extends GroupNamesSource {
|
||||||
PerunAdapter perunAdapter = pctx.getPerunAdapter();
|
PerunAdapter perunAdapter = pctx.getPerunAdapter();
|
||||||
Long userId = pctx.getPerunUserId();
|
Long userId = pctx.getPerunUserId();
|
||||||
Facility facility = pctx.getFacility();
|
Facility facility = pctx.getFacility();
|
||||||
Set<Group> userGroups = getUserGroupsOnFacility(facility, userId, perunAdapter);
|
Set<Group> userGroups = ClaimUtils.getUserGroupsOnFacility(facility, userId, perunAdapter, getClaimName());
|
||||||
Set<String> entitlements = produceEntitlements(facility, userGroups, userId, perunAdapter);
|
Set<String> entitlements = produceEntitlements(facility, userGroups, userId, perunAdapter);
|
||||||
|
|
||||||
JsonNode result = convertResultStringsToJsonArray(entitlements);
|
JsonNode result = ClaimUtils.convertResultStringsToJsonArray(entitlements);
|
||||||
log.debug("{} - produced value for user({}): '{}'", getClaimName(), userId, result);
|
log.debug("{} - produced value for user({}): '{}'", getClaimName(), userId, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ import cz.muni.ics.oidc.server.adapters.PerunAdapter;
|
||||||
import cz.muni.ics.oidc.server.claims.ClaimSource;
|
import cz.muni.ics.oidc.server.claims.ClaimSource;
|
||||||
import cz.muni.ics.oidc.server.claims.ClaimSourceInitContext;
|
import cz.muni.ics.oidc.server.claims.ClaimSourceInitContext;
|
||||||
import cz.muni.ics.oidc.server.claims.ClaimSourceProduceContext;
|
import cz.muni.ics.oidc.server.claims.ClaimSourceProduceContext;
|
||||||
|
import cz.muni.ics.oidc.server.claims.ClaimUtils;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
@ -42,7 +43,7 @@ public class GroupNamesSource extends ClaimSource {
|
||||||
@Override
|
@Override
|
||||||
public JsonNode produceValue(ClaimSourceProduceContext pctx) {
|
public JsonNode produceValue(ClaimSourceProduceContext pctx) {
|
||||||
Map<Long, String> idToNameMap = this.produceGroupNames(pctx);
|
Map<Long, String> idToNameMap = this.produceGroupNames(pctx);
|
||||||
JsonNode result = convertResultStringsToJsonArray(new HashSet<>(idToNameMap.values()));
|
JsonNode result = ClaimUtils.convertResultStringsToJsonArray(new HashSet<>(idToNameMap.values()));
|
||||||
log.debug("{} - produced value for user({}): '{}'", getClaimName(), pctx.getPerunUserId(), result);
|
log.debug("{} - produced value for user({}): '{}'", getClaimName(), pctx.getPerunUserId(), result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -50,7 +51,8 @@ public class GroupNamesSource extends ClaimSource {
|
||||||
protected Map<Long, String> produceGroupNames(ClaimSourceProduceContext pctx) {
|
protected Map<Long, String> produceGroupNames(ClaimSourceProduceContext pctx) {
|
||||||
log.trace("{} - produce group names with trimming 'members' part of the group names", getClaimName());
|
log.trace("{} - produce group names with trimming 'members' part of the group names", getClaimName());
|
||||||
Facility facility = pctx.getFacility();
|
Facility facility = pctx.getFacility();
|
||||||
Set<Group> userGroups = getUserGroupsOnFacility(facility, pctx.getPerunUserId(), pctx.getPerunAdapter());
|
Set<Group> userGroups = ClaimUtils.getUserGroupsOnFacility(facility, pctx.getPerunUserId(),
|
||||||
|
pctx.getPerunAdapter(), getClaimName());
|
||||||
return getGroupIdToNameMap(userGroups, true);
|
return getGroupIdToNameMap(userGroups, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,21 +72,4 @@ public class GroupNamesSource extends ClaimSource {
|
||||||
return idToNameMap;
|
return idToNameMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Set<Group> getUserGroupsOnFacility(Facility facility, Long userId, PerunAdapter perunAdapter) {
|
|
||||||
Set<Group> userGroups = new HashSet<>();
|
|
||||||
if (facility == null) {
|
|
||||||
log.warn("{} - no facility provided when searching for user groups, will return empty set", getClaimName());
|
|
||||||
} else {
|
|
||||||
userGroups = perunAdapter.getGroupsWhereUserIsActiveWithUniqueNames(facility.getId(), userId);
|
|
||||||
}
|
|
||||||
log.trace("{} - found user groups: '{}'", getClaimName(), userGroups);
|
|
||||||
return userGroups;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected JsonNode convertResultStringsToJsonArray(Collection<String> collection) {
|
|
||||||
ArrayNode arr = JsonNodeFactory.instance.arrayNode();
|
|
||||||
collection.forEach(arr::add);
|
|
||||||
return arr;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
package cz.muni.ics.oidc.server.claims.sources;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import cz.muni.ics.oidc.models.PerunAttributeValue;
|
||||||
|
import cz.muni.ics.oidc.server.adapters.PerunAdapter;
|
||||||
|
import cz.muni.ics.oidc.server.claims.ClaimSourceInitContext;
|
||||||
|
import cz.muni.ics.oidc.server.claims.ClaimSourceProduceContext;
|
||||||
|
import cz.muni.ics.oidc.server.claims.ClaimUtils;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Source produces MINIO policies based on groups assigned to the facility resource and username.
|
||||||
|
*
|
||||||
|
* Configuration (replace [claimName] with the name of the claim):
|
||||||
|
* <ul>
|
||||||
|
* <li><b>custom.claim.[claimName].source.groupAttribute</b> - group attribute name containing values for claim</li>
|
||||||
|
* <li><b>custom.claim.[claimName].source.usernamePolicyAttribute</b> - attribute mapping for username to add it as another policy</li>
|
||||||
|
* </ul>
|
||||||
|
* @author Dominik Frantisek Bucik <bucik@ics.muni.cz>
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class MinIOPoliciesClaimSource extends ResourceAssignedActiveMemberGroupsClaimSource {
|
||||||
|
|
||||||
|
protected static final String USERNAME_POLICY_ATTRIBUTE = "usernamePolicyAttribute";
|
||||||
|
private final String usernamePolicyAttribute;
|
||||||
|
|
||||||
|
public MinIOPoliciesClaimSource(ClaimSourceInitContext ctx) {
|
||||||
|
super(ctx);
|
||||||
|
this.usernamePolicyAttribute = ClaimUtils.fillStringMandatoryProperty(
|
||||||
|
USERNAME_POLICY_ATTRIBUTE, ctx, ctx.getClaimName());
|
||||||
|
log.debug("{} - groupPoliciesAttribute: '{}', usernamePolicyAttribute: '{}'",
|
||||||
|
getClaimName(), super.getGroupAttribute(), usernamePolicyAttribute);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> getAttrIdentifiers() {
|
||||||
|
Set<String> set = new HashSet<>(super.getAttrIdentifiers());
|
||||||
|
set.add(usernamePolicyAttribute);
|
||||||
|
return set;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JsonNode produceValue(ClaimSourceProduceContext pctx) {
|
||||||
|
Long userId = pctx.getPerunUserId();
|
||||||
|
Set<String> policies = producePolicies(pctx);
|
||||||
|
JsonNode result = ClaimUtils.convertResultStringsToJsonArray(policies);
|
||||||
|
log.debug("{} - produced value for user({}): '{}'", getClaimName(), userId, result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Set<String> producePolicies(ClaimSourceProduceContext pctx)
|
||||||
|
{
|
||||||
|
Set<String> policies = super.produceSetValue(pctx);
|
||||||
|
String userNamePolicy = getUsername(pctx.getPerunUserId(), pctx.getPerunAdapter());
|
||||||
|
if (userNamePolicy != null) {
|
||||||
|
policies.add(userNamePolicy);
|
||||||
|
}
|
||||||
|
|
||||||
|
return policies;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getUsername(Long userId, PerunAdapter perunAdapter) {
|
||||||
|
PerunAttributeValue usernameAttrValue = perunAdapter.getAdapterFallback().getUserAttributeValue(userId, usernamePolicyAttribute);
|
||||||
|
if (usernameAttrValue != null && !usernameAttrValue.isNullValue() && StringUtils.hasText(usernameAttrValue.valueAsString())) {
|
||||||
|
return usernameAttrValue.valueAsString();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,79 @@
|
||||||
|
package cz.muni.ics.oidc.server.claims.sources;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import cz.muni.ics.oidc.models.Facility;
|
||||||
|
import cz.muni.ics.oidc.models.Group;
|
||||||
|
import cz.muni.ics.oidc.models.PerunAttributeValue;
|
||||||
|
import cz.muni.ics.oidc.server.adapters.PerunAdapter;
|
||||||
|
import cz.muni.ics.oidc.server.claims.ClaimSource;
|
||||||
|
import cz.muni.ics.oidc.server.claims.ClaimSourceInitContext;
|
||||||
|
import cz.muni.ics.oidc.server.claims.ClaimSourceProduceContext;
|
||||||
|
import cz.muni.ics.oidc.server.claims.ClaimUtils;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.RecursiveTask;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Source produces values on attribute value of groups assigned to the facility resource.
|
||||||
|
*
|
||||||
|
* Configuration (replace [claimName] with the name of the claim):
|
||||||
|
* <ul>
|
||||||
|
* <li><b>custom.claim.[claimName].source.groupAttribute</b> - group attribute name containing values for claim</li>
|
||||||
|
* </ul>
|
||||||
|
* @author Dominik Frantisek Bucik <bucik@ics.muni.cz>
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Getter
|
||||||
|
public class ResourceAssignedActiveMemberGroupsClaimSource extends ClaimSource {
|
||||||
|
|
||||||
|
protected static final String GROUP_ATTRIBUTE = "groupAttribute";
|
||||||
|
|
||||||
|
private final String groupAttribute;
|
||||||
|
|
||||||
|
public ResourceAssignedActiveMemberGroupsClaimSource(ClaimSourceInitContext ctx) {
|
||||||
|
super(ctx);
|
||||||
|
this.groupAttribute = ClaimUtils.fillStringMandatoryProperty(GROUP_ATTRIBUTE, ctx, ctx.getClaimName());
|
||||||
|
log.debug("{} - groupAttribute: '{}'", getClaimName(), groupAttribute);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> getAttrIdentifiers() {
|
||||||
|
return Set.of(groupAttribute);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JsonNode produceValue(ClaimSourceProduceContext pctx) {
|
||||||
|
Long userId = pctx.getPerunUserId();
|
||||||
|
|
||||||
|
Set<String> value = produceSetValue(pctx);
|
||||||
|
|
||||||
|
JsonNode result = ClaimUtils.convertResultStringsToJsonArray(value);
|
||||||
|
log.debug("{} - produced value for user({}): '{}'", getClaimName(), userId, result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Set<String> produceSetValue(ClaimSourceProduceContext pctx) {
|
||||||
|
Long userId = pctx.getPerunUserId();
|
||||||
|
Facility facility = pctx.getFacility();
|
||||||
|
PerunAdapter perunAdapter = pctx.getPerunAdapter();
|
||||||
|
Set<Group> userGroups = ClaimUtils.getUserGroupsOnFacility(facility, userId, perunAdapter, getClaimName());
|
||||||
|
return getValuesFromAttribute(userGroups, perunAdapter);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Set<String> getValuesFromAttribute(Set<Group> userGroups, PerunAdapter perunAdapter) {
|
||||||
|
Set<String> policies = new HashSet<>();
|
||||||
|
for (Group g: userGroups) {
|
||||||
|
PerunAttributeValue policiesAttrValue = perunAdapter.getAdapterFallback()
|
||||||
|
.getGroupAttributeValue(g, groupAttribute);
|
||||||
|
if (policiesAttrValue != null && !policiesAttrValue.isNullValue() && policiesAttrValue.valueAsList() != null) {
|
||||||
|
policies.addAll(policiesAttrValue.valueAsList());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return policies;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue