Skip to content

ams-core

ams-core is the core module used to perform authorization checks in Java applications based on AMS policies.

Installation

The module is available as a Maven dependency:

xml

<dependency>
    <groupId>com.sap.cloud.security.ams</groupId>
    <artifactId>ams-core</artifactId>
</dependency>

Public API

The following packages and classes are part of the stable public API and can be freely used by consumer applications.

Packages

  • com.sap.cloud.security.ams.api
  • com.sap.cloud.security.ams.api.expression*
  • com.sap.cloud.security.ams.config
  • com.sap.cloud.security.ams.events
  • com.sap.cloud.security.ams.error

* To traverse conditions of Decision with the ExpressionVisitor interface and the visit method.

Additional Public Classes

  • com.sap.cloud.security.ams.core.HybridAuthorizationsProvider
  • com.sap.cloud.security.ams.core.SciAuthorizationsProvider
  • com.sap.cloud.security.ams.dcn.visitor.SqlExtractor

Semantic Versioning Notice

Classes and packages not listed above are internal implementation details. They may change, be renamed, or be removed in minor or patch releases without notice. Do not depend on internal classes in production code.

Usage

For detailed usage instructions including initialization, authorization checks, and error handling, see:

Events/Logging

Consumer applications can listen to authorization check events of the AuthorizationManagementService instance to manually log authorization check results and/or create audit log events.

Authorization Check Events

Register an AuthorizationCheckListener to receive notifications about authorization checks:

java
import com.sap.cloud.security.ams.api.AuthorizationCheckListener;
import com.sap.cloud.security.ams.api.DecisionResult;
import com.sap.cloud.security.ams.events.*;

// Option 1: Implement the AuthorizationCheckListener interface
ams.addAuthorizationCheckListener(new AuthorizationCheckListener() {
    @Override
    public void onPrivilegeCheck (PrivilegeCheckEvent event){
        if (event.getResult() == DecisionResult.GRANTED) {
            logger.info("Privilege '{}' on '{}' was granted",
                    event.getAction(), event.getResource());
        }
    }

    @Override
    public void onGetPotentialActions (GetPotentialActionsEvent event){
        logger.debug("Potential actions for '{}': {}",
                event.getResource(), event.getPotentialActions());
    }

    @Override
    public void onGetPotentialResources (GetPotentialResourcesEvent event){
        logger.debug("Potential resources: {}", event.getPotentialResources());
    }

    @Override
    public void onGetPotentialPrivileges (GetPotentialPrivilegesEvent event){
        logger.debug("Potential privileges: {}", event.getPotentialPrivileges());
    }
});

// Option 2: Use the convenience method for simple logging scenarios
ams.addAuthorizationCheckListener(
        AuthorizationCheckListener.fromConsumer(event -> {
            logger.info("Authorization check: {}", event.getDescription());
        })
);

Event Types

The following event types are emitted during authorization operations:

Event TypeDescriptionKey Properties
PrivilegeCheckEventEmitted during a privilege checkaction, resource, result, input, defaultInput, dcn
GetPotentialActionsEventEmitted when collecting potential actions for a resourceresource, potentialActions
GetPotentialResourcesEventEmitted when collecting potential resourcespotentialResources
GetPotentialPrivilegesEventEmitted when collecting potential privilegespotentialPrivileges

All events inherit from AuthorizationCheckEvent and include:

  • policies: The fully-qualified policy names used for the check
  • limitingPolicies: Policy names whose privileges were used as upper limit (if any)
  • description: A human-readable description of the authorization check

PrivilegeCheckEvent Details

The PrivilegeCheckEvent provides comprehensive information about privilege checks:

java
ams.addAuthorizationCheckListener(new AuthorizationCheckListener() {
    @Override
    public void onPrivilegeCheck (PrivilegeCheckEvent event){
        String action = event.getAction();           // e.g., "read"
        String resource = event.getResource();       // e.g., "orders"
        DecisionResult result = event.getResult();   // GRANTED, DENIED, or CONDITIONAL
        String dcn = event.getDcn();                 // DCN condition in human-readable format

        // Input attributes used for the check
        Map<AttributeName, Object> input = event.getInput();
        Map<AttributeName, Object> defaultInput = event.getDefaultInput();

        // Policies involved
        Set<PolicyName> policies = event.getPolicies();
        Set<PolicyName> limitingPolicies = event.getLimitingPolicies();
    }

    // ... other methods
});

Bundle Loading Error Handling

AMS uses a bundle loader internally to manage the policies and assignments bundle in the background, independently of incoming requests. The AuthorizationManagementService emits error events when bundle loading requests fail.

Error Event Types

There are two distinct error event types:

  • BundleInitializationErrorEvent: Emitted when the initial bundle download fails and the instance is not yet ready for use.
  • BundleRefreshErrorEvent: Emitted when a bundle refresh request fails. Since the library continuously polls, this doesn't necessarily mean the data is outdated, just that the polling attempt failed. The instance remains ready but if there have been recent policy or assignment changes, it cannot take them into account.

Handling Bundle Errors

Register an error listener to handle bundle loading errors:

java
import com.sap.cloud.security.ams.error.AmsBackgroundException;
import com.sap.cloud.security.ams.error.BundleInitializationErrorEvent;
import com.sap.cloud.security.ams.error.BundleRefreshErrorEvent;

ams.addErrorListener(event -> {
    if (event instanceof BundleInitializationErrorEvent) {
        logger.error("AMS bundle initialization failed - service not ready: {}",
                event.getException().getMessage());
        // Eventually the cloud platform will restart the application after a 
        // certain number of failed attempts to the health endpoint, so
        // typically no action besides logging is required here
    } else if (event instanceof BundleRefreshErrorEvent refreshError) {
        logger.warn("AMS bundle refresh failed (current bundle age: {} seconds): {}",
                refreshError.getSecondsSinceLastRefresh(),
                refreshError.getException().getMessage());
        // Consider taking action such as logging an error instead of a warning
        // when the bundle is stale for extended periods of time
    }
});

Automatic Error Logging

If your application does not register any error listeners, bundle loading errors will be automatically logged:

  • BundleInitializationErrorEvent: Logged at ERROR level
  • BundleRefreshErrorEvent: Logged at WARN level with the seconds since last refresh

Handling Initial Bundle Load Errors

Refer to the Authorization Bundle documentation for guidance on how to react when AMS fails to initialize the bundle. The error events emitted for this case are only intended to provide information about the failed requests.