Search in sources :

Example 46 with AuditEventRecord

use of com.evolveum.midpoint.audit.api.AuditEventRecord in project midpoint by Evolveum.

the class AuditController method getChangeTrail.

private List<AuditEventRecord> getChangeTrail(String targetOid, String finalEventIdentifier) throws ObjectNotFoundException {
    AuditEventRecord finalEvent = findEvent(finalEventIdentifier);
    if (finalEvent == null) {
        throw new ObjectNotFoundException("Audit event ID " + finalEventIdentifier + " was not found");
    }
    if (LOGGER.isTraceEnabled()) {
        LOGGER.trace("Final event:\n{}", finalEvent.debugDump(1));
    }
    List<AuditEventRecord> changeTrail = getChangeTrail(targetOid, XmlTypeConverter.createXMLGregorianCalendar(finalEvent.getTimestamp()));
    // The search may have returned more events that we want to, e.g. if two
    // events happened in the same millisecond.
    Iterator<AuditEventRecord> iterator = changeTrail.iterator();
    boolean foundFinalEvent = false;
    while (iterator.hasNext()) {
        AuditEventRecord event = iterator.next();
        if (foundFinalEvent) {
            iterator.remove();
        } else if (finalEventIdentifier.equals(event.getEventIdentifier())) {
            foundFinalEvent = true;
        }
    }
    return changeTrail;
}
Also used : ObjectNotFoundException(com.evolveum.midpoint.util.exception.ObjectNotFoundException) AuditEventRecord(com.evolveum.midpoint.audit.api.AuditEventRecord)

Example 47 with AuditEventRecord

use of com.evolveum.midpoint.audit.api.AuditEventRecord in project midpoint by Evolveum.

the class AuditController method getObjectFromLastEvent.

private <O extends ObjectType> PrismObject<O> getObjectFromLastEvent(PrismObject<O> object, List<AuditEventRecord> changeTrail, String eventIdentifier) {
    if (changeTrail.isEmpty()) {
        return object;
    }
    AuditEventRecord lastEvent = changeTrail.remove(changeTrail.size() - 1);
    if (!eventIdentifier.equals(lastEvent.getEventIdentifier())) {
        throw new IllegalStateException("Wrong last event identifier, expected " + eventIdentifier + " but was " + lastEvent.getEventIdentifier());
    }
    Collection<ObjectDeltaOperation<? extends ObjectType>> lastEventDeltasOperations = lastEvent.getDeltas();
    for (ObjectDeltaOperation<? extends ObjectType> lastEventDeltasOperation : lastEventDeltasOperations) {
        ObjectDelta<O> objectDelta = (ObjectDelta<O>) lastEventDeltasOperation.getObjectDelta();
        if (!isApplicable(lastEventDeltasOperation, object, lastEvent)) {
            continue;
        }
        if (objectDelta.isAdd()) {
            // We are lucky. This is object add, so we have complete object there. No need to roll back
            // the operations.
            PrismObject<O> objectToAdd = objectDelta.getObjectToAdd();
            if (LOGGER.isTraceEnabled()) {
                LOGGER.trace("Taking object from add delta in last event {}:\n{}", lastEvent.getEventIdentifier(), objectToAdd.debugDump(1));
            }
            return objectToAdd;
        }
    }
    return null;
}
Also used : ObjectType(com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType) ObjectDeltaOperation(com.evolveum.midpoint.schema.ObjectDeltaOperation) ObjectDelta(com.evolveum.midpoint.prism.delta.ObjectDelta) AuditEventRecord(com.evolveum.midpoint.audit.api.AuditEventRecord)

Example 48 with AuditEventRecord

use of com.evolveum.midpoint.audit.api.AuditEventRecord in project midpoint by Evolveum.

the class ModelController method executeChanges.

/* (non-Javadoc)
	 * @see com.evolveum.midpoint.model.api.ModelService#executeChanges(java.util.Collection, com.evolveum.midpoint.task.api.Task, com.evolveum.midpoint.schema.result.OperationResult)
	 */
@Override
public Collection<ObjectDeltaOperation<? extends ObjectType>> executeChanges(final Collection<ObjectDelta<? extends ObjectType>> deltas, ModelExecuteOptions options, Task task, Collection<ProgressListener> statusListeners, OperationResult parentResult) throws ObjectAlreadyExistsException, ObjectNotFoundException, SchemaException, ExpressionEvaluationException, CommunicationException, ConfigurationException, PolicyViolationException, SecurityViolationException {
    Collection<ObjectDeltaOperation<? extends ObjectType>> executedDeltas = new ArrayList<>();
    OperationResult result = parentResult.createSubresult(EXECUTE_CHANGES);
    result.addParam(OperationResult.PARAM_OPTIONS, options);
    // 3) for MODIFY operation: filters contained in deltas -> these have to be treated here, because if OID is missing from such a delta, the change would be rejected by the repository
    if (ModelExecuteOptions.isReevaluateSearchFilters(options)) {
        for (ObjectDelta<? extends ObjectType> delta : deltas) {
            Utils.resolveReferences(delta, cacheRepositoryService, false, true, EvaluationTimeType.IMPORT, true, prismContext, result);
        }
    } else if (ModelExecuteOptions.isIsImport(options)) {
        // if plain import is requested, we simply evaluate filters in ADD operation (and we do not force reevaluation if OID is already set)
        for (ObjectDelta<? extends ObjectType> delta : deltas) {
            if (delta.isAdd()) {
                Utils.resolveReferences(delta.getObjectToAdd(), cacheRepositoryService, false, false, EvaluationTimeType.IMPORT, true, prismContext, result);
            }
        }
    }
    // Make sure everything is encrypted as needed before logging anything.
    // But before that we need to make sure that we have proper definition, otherwise we
    // might miss some encryptable data in dynamic schemas
    applyDefinitions(deltas, options, task, result);
    Utils.encrypt(deltas, protector, options, result);
    if (LOGGER.isTraceEnabled()) {
        LOGGER.trace("MODEL.executeChanges(\n  deltas:\n{}\n  options:{}", DebugUtil.debugDump(deltas, 2), options);
    }
    if (InternalsConfig.consistencyChecks) {
        OperationResultRunner.run(result, () -> {
            for (ObjectDelta<? extends ObjectType> delta : deltas) {
                delta.checkConsistence();
            }
        });
    }
    RepositoryCache.enter();
    try {
        if (ModelExecuteOptions.isRaw(options)) {
            // Go directly to repository
            AuditEventRecord auditRecord = new AuditEventRecord(AuditEventType.EXECUTE_CHANGES_RAW, AuditEventStage.REQUEST);
            auditRecord.addDeltas(ObjectDeltaOperation.cloneDeltaCollection(deltas));
            auditRecord.setTarget(Utils.determineAuditTarget(deltas));
            // we don't know auxiliary information (resource, objectName) at this moment -- so we do nothing
            auditService.audit(auditRecord, task);
            try {
                for (ObjectDelta<? extends ObjectType> delta : deltas) {
                    OperationResult result1 = result.createSubresult(EXECUTE_CHANGE);
                    // MID-2486
                    if (delta.getObjectTypeClass() == ShadowType.class || delta.getObjectTypeClass() == ResourceType.class) {
                        try {
                            provisioning.applyDefinition(delta, task, result1);
                        } catch (SchemaException | ObjectNotFoundException | CommunicationException | ConfigurationException | RuntimeException e) {
                            // we can tolerate this - if there's a real problem with definition, repo call below will fail
                            LoggingUtils.logExceptionAsWarning(LOGGER, "Couldn't apply definition on shadow/resource raw-mode delta {} -- continuing the operation.", e, delta);
                            result1.muteLastSubresultError();
                        }
                    }
                    final boolean preAuthorized = ModelExecuteOptions.isPreAuthorized(options);
                    PrismObject objectToDetermineDetailsForAudit = null;
                    try {
                        if (delta.isAdd()) {
                            RepoAddOptions repoOptions = new RepoAddOptions();
                            if (ModelExecuteOptions.isNoCrypt(options)) {
                                repoOptions.setAllowUnencryptedValues(true);
                            }
                            if (ModelExecuteOptions.isOverwrite(options)) {
                                repoOptions.setOverwrite(true);
                            }
                            PrismObject<? extends ObjectType> objectToAdd = delta.getObjectToAdd();
                            if (!preAuthorized) {
                                securityEnforcer.authorize(ModelAuthorizationAction.ADD.getUrl(), null, objectToAdd, null, null, null, result1);
                            }
                            String oid;
                            try {
                                oid = cacheRepositoryService.addObject(objectToAdd, repoOptions, result1);
                                task.recordObjectActionExecuted(objectToAdd, null, oid, ChangeType.ADD, task.getChannel(), null);
                            } catch (Throwable t) {
                                task.recordObjectActionExecuted(objectToAdd, null, null, ChangeType.ADD, task.getChannel(), t);
                                throw t;
                            }
                            delta.setOid(oid);
                            objectToDetermineDetailsForAudit = objectToAdd;
                        } else if (delta.isDelete()) {
                            // MID-2218
                            QNameUtil.setTemporarilyTolerateUndeclaredPrefixes(true);
                            try {
                                PrismObject<? extends ObjectType> existingObject = null;
                                try {
                                    existingObject = cacheRepositoryService.getObject(delta.getObjectTypeClass(), delta.getOid(), null, result1);
                                    objectToDetermineDetailsForAudit = existingObject;
                                } catch (Throwable t) {
                                    if (!securityEnforcer.isAuthorized(AuthorizationConstants.AUTZ_ALL_URL, null, null, null, null, null)) {
                                        throw t;
                                    } else {
                                    // in case of administrator's request we continue - in order to allow deleting malformed (unreadable) objects
                                    }
                                }
                                if (!preAuthorized) {
                                    securityEnforcer.authorize(ModelAuthorizationAction.DELETE.getUrl(), null, existingObject, null, null, null, result1);
                                }
                                try {
                                    if (ObjectTypes.isClassManagedByProvisioning(delta.getObjectTypeClass())) {
                                        Utils.clearRequestee(task);
                                        provisioning.deleteObject(delta.getObjectTypeClass(), delta.getOid(), ProvisioningOperationOptions.createRaw(), null, task, result1);
                                    } else {
                                        cacheRepositoryService.deleteObject(delta.getObjectTypeClass(), delta.getOid(), result1);
                                    }
                                    task.recordObjectActionExecuted(objectToDetermineDetailsForAudit, delta.getObjectTypeClass(), delta.getOid(), ChangeType.DELETE, task.getChannel(), null);
                                } catch (Throwable t) {
                                    task.recordObjectActionExecuted(objectToDetermineDetailsForAudit, delta.getObjectTypeClass(), delta.getOid(), ChangeType.DELETE, task.getChannel(), t);
                                    throw t;
                                }
                            } finally {
                                QNameUtil.setTemporarilyTolerateUndeclaredPrefixes(false);
                            }
                        } else if (delta.isModify()) {
                            // MID-2218
                            QNameUtil.setTemporarilyTolerateUndeclaredPrefixes(true);
                            try {
                                PrismObject existingObject = cacheRepositoryService.getObject(delta.getObjectTypeClass(), delta.getOid(), null, result1);
                                objectToDetermineDetailsForAudit = existingObject;
                                if (!preAuthorized) {
                                    securityEnforcer.authorize(ModelAuthorizationAction.MODIFY.getUrl(), null, existingObject, delta, null, null, result1);
                                }
                                try {
                                    cacheRepositoryService.modifyObject(delta.getObjectTypeClass(), delta.getOid(), delta.getModifications(), result1);
                                    task.recordObjectActionExecuted(existingObject, ChangeType.MODIFY, null);
                                } catch (Throwable t) {
                                    task.recordObjectActionExecuted(existingObject, ChangeType.MODIFY, t);
                                    throw t;
                                }
                            } finally {
                                QNameUtil.setTemporarilyTolerateUndeclaredPrefixes(false);
                            }
                            if (ModelExecuteOptions.isReevaluateSearchFilters(options)) {
                                // treat filters that already exist in the object (case #2 above)
                                reevaluateSearchFilters(delta.getObjectTypeClass(), delta.getOid(), task, result1);
                            }
                        } else {
                            throw new IllegalArgumentException("Wrong delta type " + delta.getChangeType() + " in " + delta);
                        }
                    } catch (ObjectAlreadyExistsException | SchemaException | ObjectNotFoundException | ConfigurationException | CommunicationException | SecurityViolationException | RuntimeException e) {
                        ModelUtils.recordFatalError(result1, e);
                        throw e;
                    } finally {
                        // to have a record with the failed delta as well
                        result1.computeStatus();
                        ObjectDeltaOperation<? extends ObjectType> odoToAudit = new ObjectDeltaOperation<>(delta, result1);
                        if (objectToDetermineDetailsForAudit != null) {
                            odoToAudit.setObjectName(objectToDetermineDetailsForAudit.getName());
                            if (objectToDetermineDetailsForAudit.asObjectable() instanceof ShadowType) {
                                ShadowType shadow = (ShadowType) objectToDetermineDetailsForAudit.asObjectable();
                                odoToAudit.setResourceOid(ShadowUtil.getResourceOid(shadow));
                                odoToAudit.setResourceName(ShadowUtil.getResourceName(shadow));
                            }
                        }
                        executedDeltas.add(odoToAudit);
                    }
                }
            } finally {
                cleanupOperationResult(result);
                auditRecord.setTimestamp(System.currentTimeMillis());
                auditRecord.setOutcome(result.getStatus());
                auditRecord.setEventStage(AuditEventStage.EXECUTION);
                auditRecord.getDeltas().clear();
                auditRecord.getDeltas().addAll(executedDeltas);
                auditService.audit(auditRecord, task);
                task.markObjectActionExecutedBoundary();
            }
        } else {
            try {
                LensContext<? extends ObjectType> context = contextFactory.createContext(deltas, options, task, result);
                if (ModelExecuteOptions.isReevaluateSearchFilters(options)) {
                    String m = "ReevaluateSearchFilters option is not fully supported for non-raw operations yet. Filters already present in the object will not be touched.";
                    LOGGER.warn("{} Context = {}", m, context.debugDump());
                    result.createSubresult(CLASS_NAME_WITH_DOT + "reevaluateSearchFilters").recordWarning(m);
                }
                context.setProgressListeners(statusListeners);
                // Note: Request authorization happens inside clockwork
                clockwork.run(context, task, result);
                // prepare return value
                if (context.getFocusContext() != null) {
                    executedDeltas.addAll(context.getFocusContext().getExecutedDeltas());
                }
                for (LensProjectionContext projectionContext : context.getProjectionContexts()) {
                    executedDeltas.addAll(projectionContext.getExecutedDeltas());
                }
                if (context.hasExplosiveProjection()) {
                    PrismObject<? extends ObjectType> focus = context.getFocusContext().getObjectAny();
                    LOGGER.debug("Recomputing {} because there was explosive projection", focus);
                    LensContext<? extends ObjectType> recomputeContext = contextFactory.createRecomputeContext(focus, options, task, result);
                    recomputeContext.setDoReconciliationForAllProjections(true);
                    if (LOGGER.isTraceEnabled()) {
                        LOGGER.trace("Recomputing {}, context:\n{}", focus, recomputeContext.debugDump());
                    }
                    clockwork.run(recomputeContext, task, result);
                }
                cleanupOperationResult(result);
            } catch (ObjectAlreadyExistsException | ObjectNotFoundException | SchemaException | ExpressionEvaluationException | CommunicationException | ConfigurationException | PolicyViolationException | SecurityViolationException | RuntimeException e) {
                ModelUtils.recordFatalError(result, e);
                throw e;
            } finally {
                task.markObjectActionExecutedBoundary();
            }
        }
        invalidateCaches(executedDeltas);
    } catch (RuntimeException e) {
        // just for sure (TODO split this method into two: raw and non-raw case)
        ModelUtils.recordFatalError(result, e);
        throw e;
    } finally {
        RepositoryCache.exit();
    }
    return executedDeltas;
}
Also used : OperationResult(com.evolveum.midpoint.schema.result.OperationResult) PolyString(com.evolveum.midpoint.prism.polystring.PolyString) ObjectDelta(com.evolveum.midpoint.prism.delta.ObjectDelta) RepoAddOptions(com.evolveum.midpoint.repo.api.RepoAddOptions) AuditEventRecord(com.evolveum.midpoint.audit.api.AuditEventRecord)

Example 49 with AuditEventRecord

use of com.evolveum.midpoint.audit.api.AuditEventRecord in project midpoint by Evolveum.

the class MidPointQueryExecutor method createDatasource.

@Override
public JRDataSource createDatasource() throws JRException {
    try {
        if (query == null && script == null) {
            throw new JRException("Neither query, nor script defined in the report.");
        }
        if (query != null) {
            Collection<PrismObject<? extends ObjectType>> results;
            results = searchObjects(query, SelectorOptions.createCollection(GetOperationOptions.createRaw()));
            return createDataSourceFromObjects(results);
        } else {
            if (script.contains("AuditEventRecord")) {
                Collection<AuditEventRecord> audtiEventRecords = searchAuditRecords(script, getPromptingParameters());
                Collection<AuditEventRecordType> auditEventRecordsType = new ArrayList<>();
                for (AuditEventRecord aer : audtiEventRecords) {
                    AuditEventRecordType aerType = aer.createAuditEventRecordType(true);
                    auditEventRecordsType.add(aerType);
                }
                return new JRBeanCollectionDataSource(auditEventRecordsType);
            } else {
                Collection<PrismContainerValue<? extends Containerable>> results;
                results = evaluateScript(script, getParameters());
                return createDataSourceFromContainerValues(results);
            }
        }
    } catch (SchemaException | ObjectNotFoundException | SecurityViolationException | CommunicationException | ConfigurationException | ExpressionEvaluationException e) {
        // TODO Auto-generated catch block
        throw new JRException(e);
    }
}
Also used : SchemaException(com.evolveum.midpoint.util.exception.SchemaException) PrismContainerValue(com.evolveum.midpoint.prism.PrismContainerValue) ExpressionEvaluationException(com.evolveum.midpoint.util.exception.ExpressionEvaluationException) JRException(net.sf.jasperreports.engine.JRException) SecurityViolationException(com.evolveum.midpoint.util.exception.SecurityViolationException) CommunicationException(com.evolveum.midpoint.util.exception.CommunicationException) ArrayList(java.util.ArrayList) JRBeanCollectionDataSource(net.sf.jasperreports.engine.data.JRBeanCollectionDataSource) PrismObject(com.evolveum.midpoint.prism.PrismObject) ObjectType(com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType) ConfigurationException(com.evolveum.midpoint.util.exception.ConfigurationException) AuditEventRecordType(com.evolveum.midpoint.xml.ns._public.common.audit_3.AuditEventRecordType) ObjectNotFoundException(com.evolveum.midpoint.util.exception.ObjectNotFoundException) Containerable(com.evolveum.midpoint.prism.Containerable) AuditEventRecord(com.evolveum.midpoint.audit.api.AuditEventRecord)

Example 50 with AuditEventRecord

use of com.evolveum.midpoint.audit.api.AuditEventRecord in project midpoint by Evolveum.

the class AbstractModelWebService method auditLogout.

protected void auditLogout(Task task) {
    AuditEventRecord record = new AuditEventRecord(AuditEventType.TERMINATE_SESSION, AuditEventStage.REQUEST);
    record.setInitiatorAndLoginParameter(task.getOwner());
    record.setChannel(SchemaConstants.CHANNEL_WEB_SERVICE_URI);
    record.setTimestamp(System.currentTimeMillis());
    record.setOutcome(OperationResultStatus.SUCCESS);
    auditService.audit(record, task);
}
Also used : AuditEventRecord(com.evolveum.midpoint.audit.api.AuditEventRecord)

Aggregations

AuditEventRecord (com.evolveum.midpoint.audit.api.AuditEventRecord)56 OperationResult (com.evolveum.midpoint.schema.result.OperationResult)12 Task (com.evolveum.midpoint.task.api.Task)11 Test (org.testng.annotations.Test)11 ObjectDeltaOperation (com.evolveum.midpoint.schema.ObjectDeltaOperation)10 ObjectDelta (com.evolveum.midpoint.prism.delta.ObjectDelta)6 SchemaException (com.evolveum.midpoint.util.exception.SchemaException)6 ObjectType (com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType)6 PrismObject (com.evolveum.midpoint.prism.PrismObject)5 PolyString (com.evolveum.midpoint.prism.polystring.PolyString)5 RAuditEventRecord (com.evolveum.midpoint.repo.sql.data.audit.RAuditEventRecord)4 ObjectNotFoundException (com.evolveum.midpoint.util.exception.ObjectNotFoundException)4 ArrayList (java.util.ArrayList)4 Message (com.evolveum.midpoint.notifications.api.transports.Message)3 DtoTranslationException (com.evolveum.midpoint.repo.sql.util.DtoTranslationException)3 SimpleTaskAdapter (com.evolveum.midpoint.repo.sql.util.SimpleTaskAdapter)3 AuditResultHandler (com.evolveum.midpoint.audit.api.AuditResultHandler)2 ItemPath (com.evolveum.midpoint.prism.path.ItemPath)2 MidPointPrincipal (com.evolveum.midpoint.security.api.MidPointPrincipal)2 ExpressionEvaluationException (com.evolveum.midpoint.util.exception.ExpressionEvaluationException)2