All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sap.cloud.security.ams.logging.PolicyEvaluationV2AuditLogger Maven / Gradle / Ivy

/************************************************************************
* © 2019-2023 SAP SE or an SAP affiliate company. All rights reserved. *
************************************************************************/
package com.sap.cloud.security.ams.logging;

import com.sap.cloud.security.ams.api.Principal;
import com.sap.cloud.security.ams.dcl.client.pdp.PolicyEvaluationResult;
import com.sap.cloud.security.ams.dcl.client.pdp.PolicyEvaluationResultSerializer;
import com.sap.xs.audit.api.exception.AuditLogNotAvailableException;
import com.sap.xs.audit.api.exception.AuditLogWriteException;
import com.sap.xs.audit.api.v2.AuditLogMessageFactory;
import com.sap.xs.audit.api.v2.AuditedDataSubject;
import com.sap.xs.audit.api.v2.AuditedObject;
import com.sap.xs.audit.api.v2.DataAccessAuditMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;

import java.util.function.BiConsumer;
import java.util.function.Consumer;

import static com.sap.cloud.security.ams.dcl.client.pdp.PolicyEvaluationKind.TECHNICAL;
import static com.sap.cloud.security.ams.dcl.client.pdp.PolicyEvaluationResultSerializer.*;

/**
 * In case the business application does not have the option to write the
 * decision logs to AMS server, it requires some other reliable logs to analyze
 * WHETHER and WHY a user was able to access / manipulate
 * (sensitive/configuration) data. This policy evaluation log should be written
 * in a separate transaction to make sure that the log is written, even in case
 * the operation wasn't successful and rolled back.
 * 

* Furthermore, the audit log shall be written independent whether the policy * evaluation was triggered via request or via event. */ public class PolicyEvaluationV2AuditLogger implements Consumer { protected static final Logger LOGGER = LoggerFactory.getLogger(PolicyEvaluationV2AuditLogger.class); private final AuditedDataSubject auditedDataSubject; protected AuditLogMessageFactory auditLogFactory; protected static final String TYPE_VALUE = "AmsPolicyEvaluation"; public static final String MDC_SAP_PASSPORT = "sap-passport"; protected static final String CHANNEL_VALUE = "web"; protected static final String CONDITIONAL_ACCESS = "conditionalAccess"; /** * Constructs an object. * * @param logFactory * the {@link AuditLogMessageFactory} implementation * @param dataSubject * the audited data subject, which is the owner of the modified * personal data, audit logged with this event. A data subject (id * and type) is mandatory for writing an audit log entry. In this * case this might be the application's ams service instance guid. * Example:
* {@code "data_subject": {"type": "ams-service","id": {"guid": * "28c17dfe-dc96-47fe-83ad-54f52d4bbd57"}}} */ public PolicyEvaluationV2AuditLogger(AuditLogMessageFactory logFactory, AuditedDataSubject dataSubject) { if (logFactory == null || dataSubject == null) { throw new IllegalArgumentException("requires logFactory and dataSubject"); } this.auditLogFactory = logFactory; this.auditedDataSubject = dataSubject; } /** * Is always called when the * {@link com.sap.cloud.security.ams.dcl.client.pdp.PolicyDecisionPoint} returns * with a result. * * @param result * the result of the policy evaluation containing the input */ @Override public void accept(PolicyEvaluationResult result) { if (result.getKind().equals(TECHNICAL)) { // result and kind can never be null return; } Principal principal = Principal.create(); DataAccessAuditMessage message = auditLogFactory.createDataAccessAuditMessage(); message.setChannel(getDataAccessChannel()); message.setTenant(principal.getAppTid()); message.setUser(principal.getId()); AuditedObject auditedObject = auditLogFactory.createAuditedObject(); auditedObject.setType(TYPE_VALUE); auditedObject.addIdentifier(MDC_SAP_PASSPORT, MDC.get(MDC_SAP_PASSPORT)); BiConsumer enhanceMessage = auditedObject::addIdentifier; switch (result.getResultType()) { case DENY: case ERROR: message.addAttribute(ACCESS, false); break; case GRANT: message.addAttribute(ACCESS, true); break; case EXPRESSION: message.addAttribute(CONDITIONAL_ACCESS, true); break; default: LOGGER.error("This resultType {} is not yet supported. Audit Log can't be written without attributes.", result.getResultType()); return; } PolicyEvaluationResultSerializer.getInstance().process(result, enhanceMessage); message.setObject(auditedObject); message.setDataSubject(auditedDataSubject); log(message); } /** * Provides the type of the data access channel such as RFC, web service, IDOC, * file based interfaces, user interface, spool, printing etc. * * @return by default "web" */ protected String getDataAccessChannel() { return CHANNEL_VALUE; } /** * Handles the provided message. * * @param message * the message to be logged */ protected void log(DataAccessAuditMessage message) { try { message.log(); } catch (AuditLogNotAvailableException e) { LOGGER.warn("Unable to audit log Policy Evaluation: {}", e.getMessage()); } catch (AuditLogWriteException e) { LOGGER.error("Error during audit logging Policy Evaluation: {}", e.getErrors()); } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy