Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,26 @@
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;

import java.util.HashSet;
import java.util.Set;

import org.springframework.stereotype.Service;

import it.infn.mw.iam.api.account.group_manager.AccountGroupManagerService;
import it.infn.mw.iam.api.scim.exception.ScimException;
import it.infn.mw.iam.api.scim.model.ScimAarcName;
import it.infn.mw.iam.api.scim.model.ScimAddress;
import it.infn.mw.iam.api.scim.model.ScimAffiliation;
import it.infn.mw.iam.api.scim.model.ScimAssurance;
import it.infn.mw.iam.api.scim.model.ScimAttribute;
import it.infn.mw.iam.api.scim.model.ScimEntitlement;
import it.infn.mw.iam.api.scim.model.ScimGroupRef;
import it.infn.mw.iam.api.scim.model.ScimLabel;
import it.infn.mw.iam.api.scim.model.ScimMeta;
import it.infn.mw.iam.api.scim.model.ScimName;
import it.infn.mw.iam.api.scim.model.ScimPhoto;
import it.infn.mw.iam.api.scim.model.ScimUser;
import it.infn.mw.iam.config.IamProperties;
import it.infn.mw.iam.config.scim.ScimProperties;
import it.infn.mw.iam.config.scim.ScimProperties.AttributeDescriptor;
import it.infn.mw.iam.config.scim.ScimProperties.LabelDescriptor;
Expand All @@ -46,6 +54,12 @@
@Service
public class UserConverter implements Converter<ScimUser, IamAccount> {

public static final String REFEDS_ASSURANCE_URI = "https://refeds.org/assurance";
public static final String REFEDS_ASSURANCE_IAP_LOW_URI = "https://refeds.org/assurance/IAP/low";

public static final Set<String> DEFAULT_LOA =
Set.of(REFEDS_ASSURANCE_URI, REFEDS_ASSURANCE_IAP_LOW_URI);

private final ScimResourceLocationProvider resourceLocationProvider;

private final AddressConverter addressConverter;
Expand All @@ -57,20 +71,23 @@ public class UserConverter implements Converter<ScimUser, IamAccount> {

private final AccountGroupManagerService groupManagerService;

private final ScimProperties properties;
private final ScimProperties scimProperties;
private final IamProperties iamProperties;

public UserConverter(ScimProperties properties, ScimResourceLocationProvider rlp,
public UserConverter(ScimProperties scimProperties, ScimResourceLocationProvider rlp,
AddressConverter ac, OidcIdConverter oidc, SshKeyConverter sshc, SamlIdConverter samlc,
X509CertificateConverter x509Iamcc, AccountGroupManagerService groupManagerService) {
X509CertificateConverter x509Iamcc, AccountGroupManagerService groupManagerService,
IamProperties iamProperties) {

this.resourceLocationProvider = rlp;
this.properties = properties;
this.scimProperties = scimProperties;
this.addressConverter = ac;
this.oidcIdConverter = oidc;
this.sshKeyConverter = sshc;
this.samlIdConverter = samlc;
this.x509CertificateIamConverter = x509Iamcc;
this.groupManagerService = groupManagerService;
this.iamProperties = iamProperties;
}

@Override
Expand Down Expand Up @@ -239,7 +256,7 @@ public ScimUser dtoFromEntity(IamAccount entity) {
builder.affiliation(entity.getAffiliation());
}

for (LabelDescriptor ld : properties.getIncludeLabels()) {
for (LabelDescriptor ld : scimProperties.getIncludeLabels()) {
entity.getLabelByPrefixAndName(ld.getPrefix(), ld.getName())
.ifPresent(el -> builder.addLabel(ScimLabel.builder()
.withPrefix(el.getPrefix())
Expand All @@ -248,15 +265,15 @@ public ScimUser dtoFromEntity(IamAccount entity) {
.build()));
}

for (AttributeDescriptor ad : properties.getIncludeAttributes()) {
for (AttributeDescriptor ad : scimProperties.getIncludeAttributes()) {
entity.getAttributeByName(ad.getName())
.ifPresent(attribute -> builder.addAttribute(ScimAttribute.builder()
.withName(attribute.getName())
.withVaule(attribute.getValue())
.build()));
}

if (properties.isIncludeManagedGroups()) {
if (scimProperties.isIncludeManagedGroups()) {
groupManagerService.getManagedGroupInfoForAccount(entity)
.getManagedGroups()
.forEach(mg -> builder.addManagedGroup(ScimGroupRef.builder()
Expand All @@ -266,10 +283,33 @@ public ScimUser dtoFromEntity(IamAccount entity) {
.build()));
}

if (properties.isIncludeAuthorities()) {
if (scimProperties.isIncludeAuthorities()) {
entity.getAuthorities().forEach(a -> builder.addAuthority(a.getAuthority()));
}

builder.enableAarc(scimProperties.isEnableAarc());

if (scimProperties.isEnableAarc()) {
builder.voPersonId(entity.getUuid() + "@" + iamProperties.getOrganisation().getName());
builder.organizationName(iamProperties.getOrganisation().getName());
builder.aarcDisplayName(entity.getUserInfo().getName());
builder.aarcName(new ScimAarcName(getScimName(entity)));
builder.addAarcEmail(entity.getUserInfo().getEmail());

if (entity.hasAffiliation()) {
builder.addVoPersonExternalAffiliation(new ScimAffiliation(
entity.getAffiliation() + "@" + iamProperties.getOrganisation().getName()));
} else {
builder.addVoPersonExternalAffiliation(
new ScimAffiliation("member" + "@" + iamProperties.getOrganisation().getName()));
}

DEFAULT_LOA.forEach(a -> builder.addAssurance(new ScimAssurance(a)));

resolveGroups(entity.getUserInfo())
.forEach(e -> builder.addEntitlements(new ScimEntitlement(e)));
}

return builder.build();
}

Expand Down Expand Up @@ -319,4 +359,29 @@ private ScimPhoto getScimPhoto(IamAccount entity) {

return ScimPhoto.builder().value(entity.getUserInfo().getPicture()).build();
}

public Set<String> resolveGroups(IamUserInfo userInfo) {

Set<String> encodedGroups = new HashSet<>();
userInfo.getGroups().forEach(g -> encodedGroups.add(encodeGroup(g)));
return encodedGroups;
}

private String encodeGroup(IamGroup group) {

var aarcConfig = iamProperties.getAarcProfile();

String urnNid = aarcConfig.getUrnNid();
String urnDelegatedNamespace = aarcConfig.getUrnDelegatedNamespace();
String encodedGroupName = group.getName().replace("/", ":");

String encodedSubnamespace = "";
String urnSubnamespaces = aarcConfig.getUrnSubnamespaces();
if (urnSubnamespaces != null && !urnSubnamespaces.isBlank()) {
encodedSubnamespace = ":" + String.join(":", urnSubnamespaces.trim().split("\\s+"));
}

return String.format("urn:%s:%s%s:group:%s", urnNid, urnDelegatedNamespace, encodedSubnamespace,
encodedGroupName);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/**
* Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2016-2021
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package it.infn.mw.iam.api.scim.model;

public class ScimAarcName {
private final String givenName;
private final String familyName;

public ScimAarcName(ScimName name) {
this.givenName = name.getGivenName();
this.familyName = name.getFamilyName();
}

public String getGivenName() {
return givenName;
}

public String getFamilyName() {
return familyName;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
/**
* Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2016-2021
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package it.infn.mw.iam.api.scim.model;

import java.util.LinkedList;
import java.util.List;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;

@JsonInclude(JsonInclude.Include.NON_EMPTY)
@JsonIgnoreProperties(value = {"voPersonId", "displayName", "name", "email", "organizationName",
"schacHomeOrganization", "voPersonExternalAffiliation", "assurance"}, allowGetters = true)
public class ScimAarcUser {

private final String voPersonId;
private final String displayName;
private final ScimAarcName name;
private final String email;
private final String organizationName;
private final String schacHomeOrganization;
private final List<ScimAffiliation> voPersonExternalAffiliations;
private final List<ScimAssurance> assurance;
private final List<ScimEntitlement> entitlements;

@JsonCreator
private ScimAarcUser(@JsonProperty("voPersonId") String voPersonId,
@JsonProperty("displayName") String displayName, @JsonProperty("name") ScimAarcName name,
@JsonProperty("email") String email,
@JsonProperty("organizationName") String organizationName,
@JsonProperty("schacHomeOrganization") String schacHomeOrganization,
@JsonProperty("voPersonExternalAffiliations") List<ScimAffiliation> voPersonExternalAffiliations,
@JsonProperty("assurance") List<ScimAssurance> assurance,
@JsonProperty("entitlements") List<ScimEntitlement> entitlements) {

this.voPersonId = voPersonId;
this.displayName = displayName;
this.name = name;
this.email = email;
this.organizationName = organizationName;
this.schacHomeOrganization = schacHomeOrganization;
this.voPersonExternalAffiliations = voPersonExternalAffiliations;
this.assurance = assurance != null ? assurance : new LinkedList<>();
this.entitlements = entitlements != null ? entitlements : new LinkedList<>();
}

private ScimAarcUser(Builder b) {
this.voPersonId = b.voPersonId;
this.displayName = b.displayName;
this.name = b.name;
this.email = b.email;
this.organizationName = b.organizationName;
this.schacHomeOrganization = b.schacHomeOrganization;
this.voPersonExternalAffiliations = b.voPersonExternalAffiliations;
this.assurance = b.assurance;
this.entitlements = b.entitlements;
}

public String getVoPersonId() {
return voPersonId;
}

public String getDisplayName() {
return displayName;
}

public String getOrganizationName() {
return organizationName;
}

public ScimAarcName getName() {
return name;
}

public String getEmail() {
return email;
}

public String getSchacHomeOrganization() {
return schacHomeOrganization;
}

public List<ScimAffiliation> getVoPersonExternalAffiliations() {
return voPersonExternalAffiliations;
}

public List<ScimAssurance> getAssurance() {
return assurance;
}

public List<ScimEntitlement> getEntitlements() {
return entitlements;
}

public static Builder builder() {
return new Builder();
}

public static class Builder {

private String voPersonId;
private String displayName;
private ScimAarcName name;
private String email;
private String organizationName;
private String schacHomeOrganization;
private List<ScimAffiliation> voPersonExternalAffiliations = new LinkedList<>();
private List<ScimAssurance> assurance = new LinkedList<>();
private List<ScimEntitlement> entitlements = new LinkedList<>();

public Builder voPersonId(String voPersonId) {
this.voPersonId = voPersonId;
return this;
}

public Builder displayName(String displayName) {
this.displayName = displayName;
return this;
}

public Builder name(ScimAarcName name) {
this.name = name;
return this;
}

public Builder email(String email) {
this.email = email;
return this;
}

public Builder organizationName(String organizationName) {
this.organizationName = organizationName;
return this;
}

public Builder schacHomeOrganization(String schacHomeOrganization) {
this.schacHomeOrganization = schacHomeOrganization;
return this;
}

public Builder addVoPersonExternalAffiliation(ScimAffiliation affiliation) {
this.voPersonExternalAffiliations.add(affiliation);
return this;
}

public Builder addAssurance(ScimAssurance assurance) {
this.assurance.add(assurance);
return this;
}

public Builder addEntitlement(ScimEntitlement entitlement) {
this.entitlements.add(entitlement);
return this;
}

public ScimAarcUser build() {
return new ScimAarcUser(this);
}
}
}
Loading
Loading