Merge pull request #191 from dBucik/minio_dev

feat: Added new claims sources
pull/1580/head
Dominik František Bučík 2022-05-30 06:57:39 +02:00 committed by GitHub
commit 5c7481d22c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 199 additions and 25 deletions

View File

@ -625,7 +625,11 @@ public class PerunAdapterLdap extends PerunAdapterWithMappingServices implements
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) {
@ -658,11 +662,14 @@ public class PerunAdapterLdap extends PerunAdapterWithMappingServices implements
Set<AttributeMapping> mappings = this.getMappingsForAttrNames(entity, attrsToFetch);
String[] attributes = this.getAttributesFromMappings(mappings);
Map<String, PerunAttributeValue> res = new HashMap<>();
Map<String, PerunAttributeValue> res = null;
if (attributes.length != 0) {
EntryMapper<Map<String, PerunAttributeValue>> mapper = attrValueMapper(mappings);
res = this.connectorLdap.lookup(dnPrefix, attributes, mapper);
}
if (res == null) {
res = new HashMap<>();
}
return res;
}

View File

@ -1,10 +1,19 @@
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.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.Set;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;
@Slf4j
public class ClaimUtils {
public static final String NO_VALUE = null;
@ -67,4 +76,24 @@ public class ClaimUtils {
}
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;
}
}

View File

@ -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.claims.ClaimSourceInitContext;
import cz.muni.ics.oidc.server.claims.ClaimSourceProduceContext;
import cz.muni.ics.oidc.server.claims.ClaimUtils;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
@ -37,13 +38,13 @@ public class EntitlementExtendedClaimSource extends EntitlementSource {
Long userId = pctx.getPerunUserId();
Set<String> entitlements = produceEntitlementsExtended(pctx.getFacility(),
userId, pctx.getPerunAdapter());
JsonNode result = convertResultStringsToJsonArray(entitlements);
JsonNode result = ClaimUtils.convertResultStringsToJsonArray(entitlements);
log.debug("{} - produced value for user({}): '{}'", getClaimName(), userId, result);
return result;
}
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);
Set<String> entitlements = new TreeSet<>();
this.fillUuidEntitlements(userGroups, entitlements);

View File

@ -84,10 +84,10 @@ public class EntitlementSource extends GroupNamesSource {
PerunAdapter perunAdapter = pctx.getPerunAdapter();
Long userId = pctx.getPerunUserId();
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);
JsonNode result = convertResultStringsToJsonArray(entitlements);
JsonNode result = ClaimUtils.convertResultStringsToJsonArray(entitlements);
log.debug("{} - produced value for user({}): '{}'", getClaimName(), userId, result);
return result;
}

View File

@ -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.ClaimSourceInitContext;
import cz.muni.ics.oidc.server.claims.ClaimSourceProduceContext;
import cz.muni.ics.oidc.server.claims.ClaimUtils;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
@ -42,7 +43,7 @@ public class GroupNamesSource extends ClaimSource {
@Override
public JsonNode produceValue(ClaimSourceProduceContext 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);
return result;
}
@ -50,7 +51,8 @@ public class GroupNamesSource extends ClaimSource {
protected Map<Long, String> produceGroupNames(ClaimSourceProduceContext pctx) {
log.trace("{} - produce group names with trimming 'members' part of the group names", getClaimName());
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);
}
@ -70,21 +72,4 @@ public class GroupNamesSource extends ClaimSource {
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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}