You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by md...@apache.org on 2019/05/31 15:33:59 UTC
[syncope] branch master updated: [SYNCOPE-1473] conservative
membership policy management
This is an automated email from the ASF dual-hosted git repository.
mdisabatino pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/syncope.git
The following commit(s) were added to refs/heads/master by this push:
new 3d6e0b6 [SYNCOPE-1473] conservative membership policy management
3d6e0b6 is described below
commit 3d6e0b6ba70bdfe0b0083215578b3def1fd0a396
Author: Marco Di Sabatino Di Diodoro <ma...@tirasa.net>
AuthorDate: Fri May 31 15:25:22 2019 +0200
[SYNCOPE-1473] conservative membership policy management
---
.../LDAPMembershipPropagationActions.java | 56 +++++++++--
.../syncope/fit/core/PropagationTaskITCase.java | 107 +++++++++++++++++++++
2 files changed, 153 insertions(+), 10 deletions(-)
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/LDAPMembershipPropagationActions.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/LDAPMembershipPropagationActions.java
index 58fc0d3..d1817ae 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/LDAPMembershipPropagationActions.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/LDAPMembershipPropagationActions.java
@@ -23,6 +23,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
+import java.util.TreeSet;
import org.apache.commons.jexl3.JexlContext;
import org.apache.commons.jexl3.MapContext;
import org.apache.commons.lang3.StringUtils;
@@ -34,6 +35,7 @@ import org.apache.syncope.core.persistence.api.entity.user.User;
import org.apache.syncope.core.provisioning.java.jexl.JexlUtils;
import org.apache.syncope.core.persistence.api.dao.AnyTypeDAO;
import org.apache.syncope.core.persistence.api.dao.GroupDAO;
+import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
import org.apache.syncope.core.persistence.api.entity.resource.Provision;
import org.apache.syncope.core.provisioning.api.propagation.PropagationActions;
import org.identityconnectors.framework.common.objects.Attribute;
@@ -87,16 +89,14 @@ public class LDAPMembershipPropagationActions implements PropagationActions {
userDAO.findAllGroupKeys(user).forEach(groupKey -> {
Group group = groupDAO.find(groupKey);
if (group != null && groupDAO.findAllResourceKeys(groupKey).contains(task.getResource().getKey())) {
- LOG.debug("Evaluating connObjectLink for {}", group);
- JexlContext jexlContext = new MapContext();
- JexlUtils.addFieldsToContext(group, jexlContext);
- JexlUtils.addPlainAttrsToContext(group.getPlainAttrs(), jexlContext);
- JexlUtils.addDerAttrsToContext(group, jexlContext);
- String groupConnObjectLinkLink =
- JexlUtils.evaluate(provision.get().getMapping().getConnObjectLink(), jexlContext);
- LOG.debug("ConnObjectLink for {} is '{}'", group, groupConnObjectLinkLink);
- if (StringUtils.isNotBlank(groupConnObjectLinkLink)) {
- groupConnObjectLinks.add(groupConnObjectLinkLink);
+
+ String groupConnObjectLink = evaluateGroupConnObjectLink(
+ provision.get().getMapping().getConnObjectLink(), group);
+
+ LOG.debug("ConnObjectLink for {} is '{}'", group, groupConnObjectLink);
+ if (StringUtils.isNotBlank(groupConnObjectLink)) {
+ groupConnObjectLinks.add(groupConnObjectLink);
+
}
}
});
@@ -111,7 +111,24 @@ public class LDAPMembershipPropagationActions implements PropagationActions {
groups.add(obj.toString());
});
attributes.remove(ldapGroups);
+
+ if (beforeObj != null && beforeObj.getAttributeByName(getGroupMembershipAttrName()) != null) {
+ Set<String> connObjectLinks = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
+ buildManagedGroupConnObjectLinks(
+ provision.get().getResource(),
+ provision.get().getMapping().getConnObjectLink(),
+ connObjectLinks);
+
+ Attribute beforeLdapGroups = beforeObj.getAttributeByName(getGroupMembershipAttrName());
+ LOG.debug("Memberships not managed by Syncope: {}", beforeLdapGroups);
+ for (Object value : beforeLdapGroups.getValue()) {
+ if (!connObjectLinks.contains(String.valueOf(value))) {
+ groups.add(String.valueOf(value));
+ }
+ }
+ }
}
+ LOG.debug("Add ldapGroups to attributes: {}" + groups);
attributes.add(AttributeBuilder.build(getGroupMembershipAttrName(), groups));
task.setAttributes(attributes);
@@ -120,4 +137,23 @@ public class LDAPMembershipPropagationActions implements PropagationActions {
LOG.debug("Not about user, or group mapping missing for resource: not doing anything");
}
}
+
+ private String evaluateGroupConnObjectLink(final String connObjectLinkTemplate, final Group group) {
+ LOG.debug("Evaluating connObjectLink for {}", group);
+
+ JexlContext jexlContext = new MapContext();
+ JexlUtils.addFieldsToContext(group, jexlContext);
+ JexlUtils.addPlainAttrsToContext(group.getPlainAttrs(), jexlContext);
+ JexlUtils.addDerAttrsToContext(group, jexlContext);
+
+ return JexlUtils.evaluate(connObjectLinkTemplate, jexlContext);
+ }
+
+ private void buildManagedGroupConnObjectLinks(final ExternalResource externalResource,
+ final String connObjectLinkTemplate, final Set<String> connObjectLinks) {
+ List<Group> managedGroups = groupDAO.findByResource(externalResource);
+ managedGroups.forEach(group -> {
+ connObjectLinks.add(evaluateGroupConnObjectLink(connObjectLinkTemplate, group));
+ });
+ }
}
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PropagationTaskITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PropagationTaskITCase.java
index 458e09f..63ec15e 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PropagationTaskITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PropagationTaskITCase.java
@@ -46,12 +46,18 @@ import org.apache.syncope.common.lib.SyncopeClientException;
import org.apache.syncope.common.lib.to.TaskTO;
import org.apache.syncope.common.lib.to.AnyObjectTO;
import org.apache.syncope.common.lib.Attr;
+import org.apache.syncope.common.lib.request.GroupCR;
+import org.apache.syncope.common.lib.request.MembershipUR;
+import org.apache.syncope.common.lib.request.ResourceDR;
import org.apache.syncope.common.lib.to.ConnObjectTO;
import org.apache.syncope.common.lib.to.PagedResult;
import org.apache.syncope.common.lib.to.PropagationTaskTO;
import org.apache.syncope.common.lib.to.ExecTO;
import org.apache.syncope.common.lib.to.ImplementationTO;
+import org.apache.syncope.common.lib.to.GroupTO;
import org.apache.syncope.common.lib.to.ItemTO;
+import org.apache.syncope.common.lib.to.MembershipTO;
+import org.apache.syncope.common.lib.to.PlainSchemaTO;
import org.apache.syncope.common.lib.to.ProvisionTO;
import org.apache.syncope.common.lib.to.ProvisioningResult;
import org.apache.syncope.common.lib.to.ResourceTO;
@@ -59,8 +65,11 @@ import org.apache.syncope.common.lib.to.UserTO;
import org.apache.syncope.common.lib.types.AnyTypeKind;
import org.apache.syncope.common.lib.types.IdMImplementationType;
import org.apache.syncope.common.lib.types.ImplementationEngine;
+import org.apache.syncope.common.lib.types.AttrSchemaType;
import org.apache.syncope.common.lib.types.MappingPurpose;
import org.apache.syncope.common.lib.types.PatchOperation;
+import org.apache.syncope.common.lib.types.ResourceDeassociationAction;
+import org.apache.syncope.common.lib.types.SchemaType;
import org.apache.syncope.common.lib.types.TaskType;
import org.apache.syncope.common.rest.api.RESTHeaders;
import org.apache.syncope.common.rest.api.beans.ExecuteQuery;
@@ -462,4 +471,102 @@ public class PropagationTaskITCase extends AbstractTaskITCase {
}
}
}
+
+ @Test
+ public void issueSYNCOPE1473() throws ParseException {
+ // create a new group schema
+ PlainSchemaTO schemaTO = new PlainSchemaTO();
+ schemaTO.setKey("ldapGroups" + getUUIDString());
+ schemaTO.setType(AttrSchemaType.String);
+ schemaTO.setMultivalue(true);
+ schemaTO.setReadonly(true);
+ schemaTO.setAnyTypeClass("minimal user");
+
+ schemaTO = createSchema(SchemaType.PLAIN, schemaTO);
+ assertNotNull(schemaTO);
+
+ ResourceTO ldap = resourceService.read(RESOURCE_NAME_LDAP);
+ try {
+ // 1. clone the LDAP resource and add some sensible mappings
+ ProvisionTO provisionGroup =
+ SerializationUtils.clone(ldap.getProvision(AnyTypeKind.GROUP.name()).orElse(null));
+ assertNotNull(provisionGroup);
+ provisionGroup.getVirSchemas().clear();
+
+ ProvisionTO provisionUser =
+ SerializationUtils.clone(ldap.getProvision(AnyTypeKind.USER.name()).orElse(null));
+ assertNotNull(provisionUser);
+ provisionUser.getMapping().getItems().removeIf(item -> "mail".equals(item.getExtAttrName()));
+ provisionUser.getVirSchemas().clear();
+
+ ItemTO ldapGroups = new ItemTO();
+ ldapGroups.setPurpose(MappingPurpose.PROPAGATION);
+ ldapGroups.setIntAttrName(schemaTO.getKey());
+ ldapGroups.setExtAttrName("ldapGroups");
+ provisionUser.getMapping().add(ldapGroups);
+
+ ldap.getProvisions().clear();
+ ldap.getProvisions().add(provisionUser);
+ ldap.getProvisions().add(provisionGroup);
+ ldap.setKey(RESOURCE_NAME_LDAP + "1473" + getUUIDString());
+ resourceService.create(ldap);
+
+ // 1. create group with the new resource assigned
+ GroupCR groupCR = new GroupCR();
+ groupCR.setName("SYNCOPEGROUP1473-" + getUUIDString());
+ groupCR.setRealm("/");
+ groupCR.getResources().add(ldap.getKey());
+
+ GroupTO groupTO = createGroup(groupCR).getEntity();
+ assertNotNull(groupCR);
+
+ // 2. create user with the new resource assigned
+ UserCR userCR = UserITCase.getUniqueSample("syncope1473@syncope.apache.org");
+ userCR.getResources().clear();
+ userCR.getResources().add(ldap.getKey());
+ userCR.getMemberships().add(new MembershipTO.Builder(groupTO.getKey()).build());
+
+ UserTO userTO = createUser(userCR).getEntity();
+ assertNotNull(userTO);
+
+ // 3. check attributes prepared for propagation
+ PagedResult<PropagationTaskTO> tasks = taskService.search(new TaskQuery.Builder(TaskType.PROPAGATION).
+ resource(userTO.getResources().iterator().next()).
+ anyTypeKind(AnyTypeKind.USER).entityKey(userTO.getKey()).build());
+ assertEquals(1, tasks.getSize());
+
+ ResourceDR resourceDR = new ResourceDR.Builder().key(groupTO.getKey()).
+ action(ResourceDeassociationAction.UNLINK).resource(ldap.getKey()).build();
+
+ groupService.deassociate(resourceDR);
+ groupService.delete(groupTO.getKey());
+
+ GroupCR newGroupCR = new GroupCR();
+ newGroupCR.setName("NEWSYNCOPEGROUP1473-" + getUUIDString());
+ newGroupCR.setRealm("/");
+ newGroupCR.getResources().add(ldap.getKey());
+
+ GroupTO newGroupTO = createGroup(newGroupCR).getEntity();
+ assertNotNull(newGroupTO);
+
+ UserUR userUR = new UserUR();
+ userUR.setKey(userTO.getKey());
+ userUR.getMemberships().add(
+ new MembershipUR.Builder(newGroupTO.getKey()).operation(PatchOperation.ADD_REPLACE).build());
+ userService.update(userUR);
+
+ ConnObjectTO connObject =
+ resourceService.readConnObject(ldap.getKey(), AnyTypeKind.USER.name(), userTO.getKey());
+ assertNotNull(connObject);
+ assertNotNull(connObject.getAttr("ldapGroups"));
+ assertTrue(connObject.getAttr("ldapGroups").get().getValues().size() == 2);
+
+ } finally {
+ try {
+ resourceService.delete(ldap.getKey());
+ } catch (Exception ignore) {
+ // ignore
+ }
+ }
+ }
}