protected Any<?> update(final Any<?> any, final Boolean enabled) {
    boolean changepwd;
    Collection<String> resourceNames;
    if (any instanceof User) {
      changepwd = true;
      resourceNames = userDAO.findAllResourceNames((User) any);
    } else if (any instanceof AnyObject) {
      changepwd = false;
      resourceNames = anyObjectDAO.findAllResourceNames((AnyObject) any);
    } else {
      changepwd = false;
      resourceNames = ((Group) any).getResourceNames();
    }

    List<String> noPropResources = new ArrayList<>(resourceNames);
    noPropResources.remove(profile.getTask().getResource().getKey());

    PropagationByResource propByRes = new PropagationByResource();
    propByRes.add(ResourceOperation.CREATE, profile.getTask().getResource().getKey());

    taskExecutor.execute(
        propagationManager.getUpdateTasks(
            any.getType().getKind(),
            any.getKey(),
            changepwd,
            null,
            propByRes,
            null,
            noPropResources));

    return getAny(any.getKey());
  }
  protected void deprovision(final Any<?> any) {
    AnyTO before = getAnyTO(any.getKey());

    List<String> noPropResources = new ArrayList<>(before.getResources());
    noPropResources.remove(profile.getTask().getResource().getKey());

    taskExecutor.execute(
        propagationManager.getDeleteTasks(
            any.getType().getKind(), any.getKey(), null, noPropResources));
  }
  protected void provision(final Any<?> any, final Boolean enabled) {
    AnyTO before = getAnyTO(any.getKey());

    List<String> noPropResources = new ArrayList<>(before.getResources());
    noPropResources.remove(profile.getTask().getResource().getKey());

    PropagationByResource propByRes = new PropagationByResource();
    propByRes.add(ResourceOperation.CREATE, profile.getTask().getResource().getKey());

    taskExecutor.execute(
        propagationManager.getCreateTasks(
            any.getType().getKind(),
            any.getKey(),
            propByRes,
            before.getVirAttrs(),
            noPropResources));
  }
  @SuppressWarnings("unchecked")
  protected void link(final Any<?> any, final Boolean unlink) {
    AnyPatch patch = newPatch(any.getKey());
    patch
        .getResources()
        .add(
            new StringPatchItem.Builder()
                .operation(unlink ? PatchOperation.DELETE : PatchOperation.ADD_REPLACE)
                .value(profile.getTask().getResource().getKey())
                .build());

    update(patch);
  }
  @Transactional(propagation = Propagation.REQUIRES_NEW)
  @Override
  public boolean handle(final long anyKey) {
    Any<?> any = null;
    try {
      any = getAny(anyKey);
      doHandle(any);
      return true;
    } catch (IgnoreProvisionException e) {
      ProvisioningReport result = new ProvisioningReport();
      result.setOperation(ResourceOperation.NONE);
      result.setAnyType(any == null ? null : any.getType().getKey());
      result.setStatus(ProvisioningReport.Status.IGNORE);
      result.setKey(anyKey);
      profile.getResults().add(result);

      LOG.warn("Ignoring during push", e);
      return true;
    } catch (JobExecutionException e) {
      LOG.error("Push failed", e);
      return false;
    }
  }
  protected void assign(final Any<?> any, final Boolean enabled) {
    AnyPatch patch = newPatch(any.getKey());
    patch
        .getResources()
        .add(
            new StringPatchItem.Builder()
                .operation(PatchOperation.ADD_REPLACE)
                .value(profile.getTask().getResource().getKey())
                .build());

    update(patch);

    provision(any, enabled);
  }
  @SuppressWarnings("unchecked")
  protected void unassign(final Any<?> any) {
    AnyPatch patch = newPatch(any.getKey());
    patch
        .getResources()
        .add(
            new StringPatchItem.Builder()
                .operation(PatchOperation.DELETE)
                .value(profile.getTask().getResource().getKey())
                .build());

    update(patch);

    deprovision(any);
  }
  protected final void doHandle(final Any<?> any) throws JobExecutionException {
    AnyUtils anyUtils = anyUtilsFactory.getInstance(any);

    ProvisioningReport result = new ProvisioningReport();
    profile.getResults().add(result);

    result.setKey(any.getKey());
    result.setAnyType(any.getType().getKey());
    result.setName(getName(any));

    Boolean enabled =
        any instanceof User && profile.getTask().isSyncStatus()
            ? ((User) any).isSuspended() ? Boolean.FALSE : Boolean.TRUE
            : null;

    LOG.debug(
        "Propagating {} with key {} towards {}",
        anyUtils.getAnyTypeKind(),
        any.getKey(),
        profile.getTask().getResource());

    Object output = null;
    Result resultStatus = null;
    String operation = null;

    // Try to read remote object BEFORE any actual operation
    Provision provision = profile.getTask().getResource().getProvision(any.getType());
    String connObjecKey = mappingUtils.getConnObjectKeyValue(any, provision);

    ConnectorObject beforeObj = getRemoteObject(connObjecKey, provision.getObjectClass());

    Boolean status = profile.getTask().isSyncStatus() ? enabled : null;

    if (profile.isDryRun()) {
      if (beforeObj == null) {
        result.setOperation(getResourceOperation(profile.getTask().getUnmatchingRule()));
      } else {
        result.setOperation(getResourceOperation(profile.getTask().getMatchingRule()));
      }
      result.setStatus(ProvisioningReport.Status.SUCCESS);
    } else {
      try {
        if (beforeObj == null) {
          operation = UnmatchingRule.toEventName(profile.getTask().getUnmatchingRule());
          result.setOperation(getResourceOperation(profile.getTask().getUnmatchingRule()));

          switch (profile.getTask().getUnmatchingRule()) {
            case ASSIGN:
              for (PushActions action : profile.getActions()) {
                action.beforeAssign(this.getProfile(), any);
              }

              if (!profile.getTask().isPerformCreate()) {
                LOG.debug("PushTask not configured for create");
              } else {
                assign(any, status);
              }

              break;

            case PROVISION:
              for (PushActions action : profile.getActions()) {
                action.beforeProvision(this.getProfile(), any);
              }

              if (!profile.getTask().isPerformCreate()) {
                LOG.debug("PushTask not configured for create");
              } else {
                provision(any, status);
              }

              break;

            case UNLINK:
              for (PushActions action : profile.getActions()) {
                action.beforeUnlink(this.getProfile(), any);
              }

              if (!profile.getTask().isPerformUpdate()) {
                LOG.debug("PushTask not configured for update");
              } else {
                link(any, true);
              }

              break;

            case IGNORE:
              LOG.debug("Ignored any: {}", any);
              break;
            default:
              // do nothing
          }
        } else {
          operation = MatchingRule.toEventName(profile.getTask().getMatchingRule());
          result.setOperation(getResourceOperation(profile.getTask().getMatchingRule()));

          switch (profile.getTask().getMatchingRule()) {
            case UPDATE:
              for (PushActions action : profile.getActions()) {
                action.beforeUpdate(this.getProfile(), any);
              }
              if (!profile.getTask().isPerformUpdate()) {
                LOG.debug("PushTask not configured for update");
              } else {
                update(any, status);
              }

              break;

            case DEPROVISION:
              for (PushActions action : profile.getActions()) {
                action.beforeDeprovision(this.getProfile(), any);
              }

              if (!profile.getTask().isPerformDelete()) {
                LOG.debug("PushTask not configured for delete");
              } else {
                deprovision(any);
              }

              break;

            case UNASSIGN:
              for (PushActions action : profile.getActions()) {
                action.beforeUnassign(this.getProfile(), any);
              }

              if (!profile.getTask().isPerformDelete()) {
                LOG.debug("PushTask not configured for delete");
              } else {
                unassign(any);
              }

              break;

            case LINK:
              for (PushActions action : profile.getActions()) {
                action.beforeLink(this.getProfile(), any);
              }

              if (!profile.getTask().isPerformUpdate()) {
                LOG.debug("PushTask not configured for update");
              } else {
                link(any, false);
              }

              break;

            case UNLINK:
              for (PushActions action : profile.getActions()) {
                action.beforeUnlink(this.getProfile(), any);
              }

              if (!profile.getTask().isPerformUpdate()) {
                LOG.debug("PushTask not configured for update");
              } else {
                link(any, true);
              }

              break;

            case IGNORE:
              LOG.debug("Ignored any: {}", any);
              break;
            default:
              // do nothing
          }
        }

        for (PushActions action : profile.getActions()) {
          action.after(this.getProfile(), any, result);
        }

        result.setStatus(ProvisioningReport.Status.SUCCESS);
        resultStatus = AuditElements.Result.SUCCESS;
        output = getRemoteObject(connObjecKey, provision.getObjectClass());
      } catch (IgnoreProvisionException e) {
        throw e;
      } catch (Exception e) {
        result.setStatus(ProvisioningReport.Status.FAILURE);
        result.setMessage(ExceptionUtils.getRootCauseMessage(e));
        resultStatus = AuditElements.Result.FAILURE;
        output = e;

        LOG.warn("Error pushing {} towards {}", any, profile.getTask().getResource(), e);

        for (PushActions action : profile.getActions()) {
          action.onError(this.getProfile(), any, result, e);
        }

        throw new JobExecutionException(e);
      } finally {
        notificationManager.createTasks(
            AuditElements.EventCategoryType.PUSH,
            any.getType().getKind().name().toLowerCase(),
            profile.getTask().getResource().getKey(),
            operation,
            resultStatus,
            beforeObj,
            output,
            any);
        auditManager.audit(
            AuditElements.EventCategoryType.PUSH,
            any.getType().getKind().name().toLowerCase(),
            profile.getTask().getResource().getKey(),
            operation,
            resultStatus,
            connObjectUtils.getConnObjectTO(beforeObj),
            output instanceof ConnectorObject
                ? connObjectUtils.getConnObjectTO((ConnectorObject) output)
                : output,
            any);
      }
    }
  }
Beispiel #9
0
  @SuppressWarnings("unchecked")
  public <T extends PolicySpec> T evaluate(final Policy policy, final Any<?, ?, ?> any) {
    if (policy == null) {
      return null;
    }

    T result = null;
    switch (policy.getType()) {
      case PASSWORD:
        PasswordPolicySpec ppSpec = policy.getSpecification(PasswordPolicySpec.class);
        PasswordPolicySpec evaluatedPPSpec = new PasswordPolicySpec();

        BeanUtils.copyProperties(ppSpec, evaluatedPPSpec, new String[] {"schemasNotPermitted"});

        for (String schema : ppSpec.getSchemasNotPermitted()) {
          PlainAttr attr = any.getPlainAttr(schema);
          if (attr != null) {
            List<String> values = attr.getValuesAsStrings();
            if (values != null && !values.isEmpty()) {
              evaluatedPPSpec.getWordsNotPermitted().add(values.get(0));
            }
          }
        }

        // Password history verification and update
        if (!(any instanceof User)) {
          LOG.error(
              "Cannot check previous passwords. instance is not user object: {}",
              any.getClass().getName());
          result = (T) evaluatedPPSpec;
          break;
        }
        User user = (User) any;
        if (user.verifyPasswordHistory(user.getClearPassword(), ppSpec.getHistoryLength())) {
          evaluatedPPSpec.getWordsNotPermitted().add(user.getClearPassword());
        }
        result = (T) evaluatedPPSpec;
        break;

      case ACCOUNT:
        final AccountPolicySpec spec = policy.getSpecification(AccountPolicySpec.class);
        final AccountPolicySpec accountPolicy = new AccountPolicySpec();

        BeanUtils.copyProperties(spec, accountPolicy, new String[] {"schemasNotPermitted"});

        for (String schema : spec.getSchemasNotPermitted()) {
          PlainAttr attr = any.getPlainAttr(schema);
          if (attr != null) {
            List<String> values = attr.getValuesAsStrings();
            if (values != null && !values.isEmpty()) {
              accountPolicy.getWordsNotPermitted().add(values.get(0));
            }
          }
        }

        result = (T) accountPolicy;
        break;

      case SYNC:
      default:
        result = null;
    }

    return result;
  }
  private Map<VirSchema, List<String>> getValues(final Any<?> any, final Set<VirSchema> schemas) {
    Collection<? extends ExternalResource> ownedResources =
        anyUtilsFactory.getInstance(any).getAllResources(any);

    Map<VirSchema, List<String>> result = new HashMap<>();

    Map<Provision, Set<VirSchema>> toRead = new HashMap<>();

    for (VirSchema schema : schemas) {
      if (ownedResources.contains(schema.getProvision().getResource())) {
        VirAttrCacheValue virAttrCacheValue =
            virAttrCache.get(any.getType().getKey(), any.getKey(), schema.getKey());

        if (virAttrCache.isValidEntry(virAttrCacheValue)) {
          LOG.debug("Values for {} found in cache: {}", schema, virAttrCacheValue);
          result.put(schema, virAttrCacheValue.getValues());
        } else {
          Set<VirSchema> schemasToRead = toRead.get(schema.getProvision());
          if (schemasToRead == null) {
            schemasToRead = new HashSet<>();
            toRead.put(schema.getProvision(), schemasToRead);
          }
          schemasToRead.add(schema);
        }
      } else {
        LOG.debug(
            "Not considering {} since {} is not assigned to {}",
            schema,
            any,
            schema.getProvision().getResource());
      }
    }

    for (Map.Entry<Provision, Set<VirSchema>> entry : toRead.entrySet()) {
      LOG.debug("About to read from {}: {}", entry.getKey(), entry.getValue());

      String connObjectKey =
          MappingUtils.getConnObjectKeyItem(entry.getKey()) == null
              ? null
              : mappingManager.getConnObjectKeyValue(any, entry.getKey());
      if (StringUtils.isBlank(connObjectKey)) {
        LOG.error("No ConnObjectKey found for {}, ignoring...", entry.getKey());
      } else {
        Set<MappingItem> linkingMappingItems = new HashSet<>();
        for (VirSchema schema : entry.getValue()) {
          linkingMappingItems.add(schema.asLinkingMappingItem());
        }

        Connector connector = connFactory.getConnector(entry.getKey().getResource());
        try {
          ConnectorObject connectorObject =
              connector.getObject(
                  entry.getKey().getObjectClass(),
                  new Uid(connObjectKey),
                  MappingUtils.buildOperationOptions(linkingMappingItems.iterator()));

          if (connectorObject == null) {
            LOG.debug("No read from {} about {}", entry.getKey(), connObjectKey);
          } else {
            for (VirSchema schema : entry.getValue()) {
              Attribute attr = connectorObject.getAttributeByName(schema.getExtAttrName());
              if (attr != null) {
                VirAttrCacheValue virAttrCacheValue = new VirAttrCacheValue();
                virAttrCacheValue.setValues(attr.getValue());
                virAttrCache.put(
                    any.getType().getKey(), any.getKey(), schema.getKey(), virAttrCacheValue);
                LOG.debug("Values for {} set in cache: {}", schema, virAttrCacheValue);

                result.put(schema, virAttrCacheValue.getValues());
              }
            }
          }
        } catch (Exception e) {
          LOG.error("Error reading from {}", entry.getKey(), e);
        }
      }
    }

    return result;
  }