diff --git a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/adapters/impl/PerunAdapterLdap.java b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/adapters/impl/PerunAdapterLdap.java index e96a6f3cd..0c40c0974 100644 --- a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/adapters/impl/PerunAdapterLdap.java +++ b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/adapters/impl/PerunAdapterLdap.java @@ -625,7 +625,11 @@ public class PerunAdapterLdap extends PerunAdapterWithMappingServices implements return ids; }; - return connectorLdap.lookup(dnPrefix, attributes, mapper); + Set 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 mappings = this.getMappingsForAttrNames(entity, attrsToFetch); String[] attributes = this.getAttributesFromMappings(mappings); - Map res = new HashMap<>(); + Map res = null; if (attributes.length != 0) { EntryMapper> mapper = attrValueMapper(mappings); res = this.connectorLdap.lookup(dnPrefix, attributes, mapper); } + if (res == null) { + res = new HashMap<>(); + } return res; } diff --git a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/claims/ClaimUtils.java b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/claims/ClaimUtils.java index 0797bf69c..9c4b41d97 100644 --- a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/claims/ClaimUtils.java +++ b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/claims/ClaimUtils.java @@ -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 getUserGroupsOnFacility(Facility facility, Long userId, + PerunAdapter perunAdapter, String claimName) + { + Set 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 collection) { + ArrayNode arr = JsonNodeFactory.instance.arrayNode(); + collection.forEach(arr::add); + return arr; + } + } diff --git a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/claims/sources/EntitlementExtendedClaimSource.java b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/claims/sources/EntitlementExtendedClaimSource.java index cdf3e7b95..26e5d1b73 100644 --- a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/claims/sources/EntitlementExtendedClaimSource.java +++ b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/claims/sources/EntitlementExtendedClaimSource.java @@ -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 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 produceEntitlementsExtended(Facility facility, Long userId, PerunAdapter perunAdapter) { - Set userGroups = getUserGroupsOnFacility(facility, userId, perunAdapter); + Set userGroups = ClaimUtils.getUserGroupsOnFacility(facility, userId, perunAdapter, getClaimName()); Map groupIdToNameMap = super.getGroupIdToNameMap(userGroups, false); Set entitlements = new TreeSet<>(); this.fillUuidEntitlements(userGroups, entitlements); diff --git a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/claims/sources/EntitlementSource.java b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/claims/sources/EntitlementSource.java index b40b1e8bd..29643045f 100644 --- a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/claims/sources/EntitlementSource.java +++ b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/claims/sources/EntitlementSource.java @@ -84,10 +84,10 @@ public class EntitlementSource extends GroupNamesSource { PerunAdapter perunAdapter = pctx.getPerunAdapter(); Long userId = pctx.getPerunUserId(); Facility facility = pctx.getFacility(); - Set userGroups = getUserGroupsOnFacility(facility, userId, perunAdapter); + Set userGroups = ClaimUtils.getUserGroupsOnFacility(facility, userId, perunAdapter, getClaimName()); Set 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; } diff --git a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/claims/sources/GroupNamesSource.java b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/claims/sources/GroupNamesSource.java index 4b853cee4..715c08a3b 100644 --- a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/claims/sources/GroupNamesSource.java +++ b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/claims/sources/GroupNamesSource.java @@ -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 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 produceGroupNames(ClaimSourceProduceContext pctx) { log.trace("{} - produce group names with trimming 'members' part of the group names", getClaimName()); Facility facility = pctx.getFacility(); - Set userGroups = getUserGroupsOnFacility(facility, pctx.getPerunUserId(), pctx.getPerunAdapter()); + Set 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 getUserGroupsOnFacility(Facility facility, Long userId, PerunAdapter perunAdapter) { - Set 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 collection) { - ArrayNode arr = JsonNodeFactory.instance.arrayNode(); - collection.forEach(arr::add); - return arr; - } - } diff --git a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/claims/sources/MinIOPoliciesClaimSource.java b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/claims/sources/MinIOPoliciesClaimSource.java new file mode 100644 index 000000000..13ee4fb7f --- /dev/null +++ b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/claims/sources/MinIOPoliciesClaimSource.java @@ -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): + *
    + *
  • custom.claim.[claimName].source.groupAttribute - group attribute name containing values for claim
  • + *
  • custom.claim.[claimName].source.usernamePolicyAttribute - attribute mapping for username to add it as another policy
  • + *
+ * @author Dominik Frantisek Bucik + */ +@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 getAttrIdentifiers() { + Set set = new HashSet<>(super.getAttrIdentifiers()); + set.add(usernamePolicyAttribute); + return set; + } + + @Override + public JsonNode produceValue(ClaimSourceProduceContext pctx) { + Long userId = pctx.getPerunUserId(); + Set policies = producePolicies(pctx); + JsonNode result = ClaimUtils.convertResultStringsToJsonArray(policies); + log.debug("{} - produced value for user({}): '{}'", getClaimName(), userId, result); + return result; + } + + protected Set producePolicies(ClaimSourceProduceContext pctx) + { + Set 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; + } + +} diff --git a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/claims/sources/ResourceAssignedActiveMemberGroupsClaimSource.java b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/claims/sources/ResourceAssignedActiveMemberGroupsClaimSource.java new file mode 100644 index 000000000..622975e35 --- /dev/null +++ b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/claims/sources/ResourceAssignedActiveMemberGroupsClaimSource.java @@ -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): + *
    + *
  • custom.claim.[claimName].source.groupAttribute - group attribute name containing values for claim
  • + *
+ * @author Dominik Frantisek Bucik + */ +@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 getAttrIdentifiers() { + return Set.of(groupAttribute); + } + + @Override + public JsonNode produceValue(ClaimSourceProduceContext pctx) { + Long userId = pctx.getPerunUserId(); + + Set value = produceSetValue(pctx); + + JsonNode result = ClaimUtils.convertResultStringsToJsonArray(value); + log.debug("{} - produced value for user({}): '{}'", getClaimName(), userId, result); + return result; + } + + protected Set produceSetValue(ClaimSourceProduceContext pctx) { + Long userId = pctx.getPerunUserId(); + Facility facility = pctx.getFacility(); + PerunAdapter perunAdapter = pctx.getPerunAdapter(); + Set userGroups = ClaimUtils.getUserGroupsOnFacility(facility, userId, perunAdapter, getClaimName()); + return getValuesFromAttribute(userGroups, perunAdapter); + } + + protected Set getValuesFromAttribute(Set userGroups, PerunAdapter perunAdapter) { + Set 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; + } + +} +