diff --git a/ams-cap-bookshop/README.md b/ams-cap-bookshop/README.md new file mode 100644 index 0000000..60f5b07 --- /dev/null +++ b/ams-cap-bookshop/README.md @@ -0,0 +1,75 @@ +# AMS CAP Bookshop Sample + +## Overview + +This is a sample for the CAP Spring Boot integration of the AMS Java library. It is a typical SAP Cloud Application Programming Model (CAP) bookshop that combines CDS declarative authorization (`@requires`, `@restrict`) with AMS policies to show standard role-based access checks. Additionally, it demonstrates how `@ams.attributes` annotations and conditional role assignments can be combined to restrict access based on attribute filters for instance-based authorization. + +## Domain Entities + +Defined in [`db/schema.cds`](db/schema.cds) (namespace `sap.capire.bookshop`): + +| Entity | Description | Source | +|--------|--------------------------------------------------------------------------------------------------------------------|--------| +| **Books** | `title`, `descr`, `author`, `stock`, `price`, `currency`, `genre`; `@ams.attributes` maps **Genre** to `genre.name` | [`db/schema.cds`](db/schema.cds), seed data in [`db/data/`](db/data/) | +| **Authors** | `name`, dates and places of birth/death; association to books | [`db/schema.cds`](db/schema.cds), seed data in [`db/data/`](db/data/) | +| **Genres** | Hierarchical code list | [`db/schema.cds`](db/schema.cds), seed data in [`db/data/`](db/data/) | + +Persistence uses H2 at runtime (see [`srv/src/main/resources/application.yaml`](srv/src/main/resources/application.yaml)). + +## Services + +| Component | Responsibility | +|-----------|----------------| +| **CatalogService** | [`srv/cat-service.cds`](srv/cat-service.cds) — read-only book views, `submitOrder` action, `OrderedBook` event | +| **AdminService** | [`srv/admin-service.cds`](srv/admin-service.cds) — CRUD projections on Books and Authors with `@restrict` | +| [`CatalogServiceHandler`](srv/src/main/java/customer/ams_cap_bookshop/handlers/CatalogServiceHandler.java) | Stock update for `submitOrder`, discount display logic on read | + +Application entry point: [`Application`](srv/src/main/java/customer/ams_cap_bookshop/Application.java). + +## API + +OData v4 endpoints (also used by Fiori apps under [`app/`](app/)): + +| Method | Path | Auth | +|--------|------|------| +| OData | `/odata/v4/CatalogService/` | Catalog reads and `submitOrder` (not gated by AdminService roles) | +| OData | `/odata/v4/AdminService/` | Requires CAP roles `ManageAuthors` or `ManageBooks`; entity operations per `@restrict` | + +Notable Catalog operations: read `Books`, `ListOfBooks`; action `submitOrder(book, quantity)`. + +## Authorization model + +While anyone can use the catalog service to browse through the shop, there are two roles (`ManageBooks`, `ManageAuthors`) defined in the CAP model (see [`srv/admin-service.cds`](srv/admin-service.cds)) for management purposes. The policy intended for the business role `StockManager` grants only the former (optionally restricted to a specific book genre), while the policy for the business role `ContentManager` grants both roles. + +| CAP role | AMS policy | Typical effect | Enforcement | +|----------|------------|----------------|-------------| +| `ManageBooks` | `cap.StockManager`, `cap.ContentManager` | Manage book stock/content; genre may be restricted by policy | [`srv/admin-service.cds`](srv/admin-service.cds) `@restrict` on `Books` | +| `ManageAuthors` | `cap.ContentManager` | Manage authors | [`srv/admin-service.cds`](srv/admin-service.cds) `@restrict` on `Authors` | +| `ManageBooks` (restricted) | `local.StockManagerFiction` | `ManageBooks` limited to Mystery and Fantasy genres | [`srv/src/main/resources/ams/local/testPolicies.dcl`](srv/src/main/resources/ams/local/testPolicies.dcl) | + +## Policy definitions (DCL) + +| Package | File | Purpose | +|---------|------|--------------------------------------------------------------------------------------------------| +| `cap` | [`srv/src/main/resources/ams/cap/basePolicies.dcl`](srv/src/main/resources/ams/cap/basePolicies.dcl) | `StockManager`, `ContentManager` — assign management roles | +| `local` | [`srv/src/main/resources/ams/local/testPolicies.dcl`](srv/src/main/resources/ams/local/testPolicies.dcl) | Mocked derived policies for testing, e.g. `StockManagerFiction` (genre-restricted `ManageBooks`) | +| Schema | [`srv/src/main/resources/ams/schema.dcl`](srv/src/main/resources/ams/schema.dcl) | Attributes for instance-based authorization (`Genre`) | + +## Running tests + +From this directory: + +```bash +mvn test +``` + +This builds and tests the [`srv`](srv/) module. + +| Test class | Focus | +|------------|--------| +| [`AdminServiceHandlerTest`](srv/src/test/java/customer/ams_cap_bookshop/handlers/AdminServiceHandlerTest.java) | AdminService CRUD with `@WithMockUser` (`stock-manager`, `content-manager`, `stock-manager-fiction`) | +| [`CatalogServiceHandlerTest`](srv/src/test/java/customer/ams_cap_bookshop/handlers/CatalogServiceHandlerTest.java) | Unit tests for discount logic in `CatalogServiceHandler` | + +## License + +Licensed under the Apache License 2.0 — see the [LICENSE](../LICENSE) file in the repository root. diff --git a/ams-javalin-shopping/README.md b/ams-javalin-shopping/README.md index ec332da..e2c2478 100644 --- a/ams-javalin-shopping/README.md +++ b/ams-javalin-shopping/README.md @@ -1,170 +1,83 @@ # AMS Javalin Shopping Sample -A Java shopping application sample using Javalin framework and SAP Authorization Management Service (AMS). This project demonstrates how to build a RESTful API with authentication and authorization using Javalin as an alternative to Spring Boot. - ## Overview -This sample is a Java equivalent of the Node.js Express shopping sample, showcasing: - -- **Javalin Framework**: Lightweight Java web framework for REST APIs -- **SAP AMS Integration**: Authorization Management Service for role-based access control -- **In-memory Database**: Simple CSV-based data initialization -- **Authentication & Authorization**: Configurable auth handlers for production and testing -- **Clean Architecture**: Modular design with separation of concerns +This is a sample for the plain Java (i.e. non-Spring) API of the AMS Java library. It is a simplified shopping REST API built with the lightweight [Javalin](https://javalin.io/) framework which was chosen due to its simplicity and brevity in order to put the focus on the AMS specific parts of the implementation. The sample integrates both SAP Authorization Management Service (AMS) and the SAP Identity Authentication Service (IAS). Route-level authorization pre-checks are implemented in [`AuthHandler`](src/main/java/com/sap/cloud/security/ams/samples/auth/AuthHandler.java) while fine-grained contextual checks are implemented in the service handlers. -## Project Structure - -``` -ams-javalin-shopping/ -├── src/main/java/com/sap/ams/cloud/security/samples/ -│ ├── JavalinShoppingApplication.java # Main application entry point -│ ├── AppFactory.java # Configurable app builder -│ ├── auth/ -│ │ └── AuthHandler.java # Production auth handler (AMS integration) -│ ├── service/ -│ │ ├── ProductsService.java # Products REST service -│ │ ├── OrdersService.java # Orders REST service -│ │ └── PrivilegesService.java # User privileges service -│ ├── db/ -│ │ ├── SimpleDatabase.java # In-memory database -│ │ └── DataLoader.java # CSV data loader -│ └── model/ -│ ├── Product.java # Product entity -│ ├── Order.java # Order entity -│ └── HealthStatus.java # Health check model -├── src/main/resources/ -│ └── csv/ -│ ├── products.csv # Initial product data -│ └── orders.csv # Initial order data -└── src/test/java/com/sap/ams/cloud/security/samples/ - ├── JavalinShoppingApplicationTest.java # Integration tests - └── auth/ - └── MockAuthHandler.java # Mock auth for testing -``` +## Domain Entities -## Features +| Entity | Description | Source | +|--------|-------------|--------| +| **Product** | `id`, `name`, `price`, `category` | [`Product.java`](src/main/java/com/sap/cloud/security/ams/samples/model/Product.java), seeded from [`src/main/resources/csv/products.csv`](src/main/resources/csv/products.csv) | +| **Order** | `id`, `productId`, `quantity`, `totalAmount`, `createdBy` (SCIM id) | [`Order.java`](src/main/java/com/sap/cloud/security/ams/samples/model/Order.java), seeded from [`src/main/resources/csv/orders.csv`](src/main/resources/csv/orders.csv) | +| **HealthStatus** | Health response payload | [`HealthStatus.java`](src/main/java/com/sap/cloud/security/ams/samples/model/HealthStatus.java) | -### API Endpoints +Persistence is in-memory via [`SimpleDatabase`](src/main/java/com/sap/cloud/security/ams/samples/db/SimpleDatabase.java) and [`DataLoader`](src/main/java/com/sap/cloud/security/ams/samples/db/DataLoader.java). -- `GET /health` - Health check endpoint (accessible to ANYONE) -- `GET /products` - Get all products (requires authentication) -- `GET /orders` - Get user orders with contextual filtering -- `POST /orders` - Create new order with business validation -- `DELETE /orders/{id}` - Delete specific order -- `GET /privileges` - Get user's potential privileges for UI +## Services -### Key Components +| Component | Responsibility | +|-----------|------------------------------------------------------------------------------------------------------------------------------------------------------------| +| [`ProductsService`](src/main/java/com/sap/cloud/security/ams/samples/service/ProductsService.java) | `GET /products` | +| [`OrdersService`](src/main/java/com/sap/cloud/security/ams/samples/service/OrdersService.java) | `GET` / `POST` / `DELETE` on `/orders`; contextual AMS checks for list, create, and optional in-handler delete check | +| [`PrivilegesService`](src/main/java/com/sap/cloud/security/ams/samples/service/PrivilegesService.java) | `GET /privileges` — returns potential privileges for the current user | +| [`AuthHandler`](src/main/java/com/sap/cloud/security/ams/samples/auth/AuthHandler.java) | IAS JWT authentication and route-level authorization via [`ShoppingAuthorizations`](src/main/java/com/sap/cloud/security/ams/samples/auth/ShoppingAuthorizations.java) | +| [`AppFactory`](src/main/java/com/sap/cloud/security/ams/samples/AppFactory.java) | Wires together the different application components on start-up | -1. **Configurable Authentication**: Factory pattern allows different auth handlers for production vs testing -2. **Role-based Authorization**: Health endpoint accessible to "ANYONE", others require proper authentication -3. **CSV-based Initialization**: Data loaded from CSV files similar to the Node.js version -4. **Error Handling**: Comprehensive error handling with proper HTTP status codes -5. **Logging**: Structured logging throughout the application +Production entry point: [`JavalinShoppingApplication`](src/main/java/com/sap/cloud/security/ams/samples/JavalinShoppingApplication.java). -## Getting Started +## API -### Prerequisites +| Method | Path | Auth | +|--------|------|---------------------------------------------------| +| `GET` | `/health` | Public (503 until AMS library is ready, then 200) | +| `GET` | `/privileges` | Authenticated | +| `GET` | `/products` | `read:products` | +| `GET` | `/orders` | `read:orders` (with optional row filtering) | +| `POST` | `/orders` | `create:orders` (with per-order attribute checks) | +| `DELETE` | `/orders/{id}` | `delete:orders` | -- Java 17 or higher -- Maven 3.6 or higher +Request body for `POST /orders`: JSON `{ "productId": number, "quantity": number }`. -### Building the Application +## Authorization model -```bash -cd ams-javalin-shopping -mvn clean compile -``` +Privileges are defined in [`Role`](src/main/java/com/sap/cloud/security/ams/samples/auth/Role.java) and granted by AMS policies. Enforcement is split between the route layer (`AuthHandler` + Javalin route roles in [`AppFactory`](src/main/java/com/sap/cloud/security/ams/samples/AppFactory.java)) and the service layer where instance-based authorization is implemented. -### Running the Application +| Operation | AMS privilege | Typical policy | Route-level check | Contextual / service check | +|-----------|-----------------|----------------|-------------------|----------------------------| +| `GET /health` | — | — | No AMS role on route | [`AppFactory`](src/main/java/com/sap/cloud/security/ams/samples/AppFactory.java) waits for AMS before reporting UP | +| `GET /privileges` | — | — | [`Role.AUTHENTICATED`](src/main/java/com/sap/cloud/security/ams/samples/auth/Role.java) in [`AuthHandler.authorize`](src/main/java/com/sap/cloud/security/ams/samples/auth/AuthHandler.java) | [`PrivilegesService`](src/main/java/com/sap/cloud/security/ams/samples/service/PrivilegesService.java) | +| `GET /products` | `read:products` | `ReadProducts` | `Role.READ_PRODUCTS` in [`AppFactory`](src/main/java/com/sap/cloud/security/ams/samples/AppFactory.java) | Route only | +| `GET /orders` | `read:orders` | `ReadOrders`, `ReadOwnOrders` | `Role.READ_ORDERS` in [`AppFactory`](src/main/java/com/sap/cloud/security/ams/samples/AppFactory.java) | [`OrdersService.getOrders`](src/main/java/com/sap/cloud/security/ams/samples/service/OrdersService.java) — deny, full list, or filter via [`ShoppingAuthorizations.checkRole`](src/main/java/com/sap/cloud/security/ams/samples/auth/ShoppingAuthorizations.java) | +| `POST /orders` | `create:orders` | `CreateOrders` | `Role.CREATE_ORDERS` in [`AppFactory`](src/main/java/com/sap/cloud/security/ams/samples/AppFactory.java) | [`OrdersService.createOrder`](src/main/java/com/sap/cloud/security/ams/samples/service/OrdersService.java) — [`checkCreateOrder`](src/main/java/com/sap/cloud/security/ams/samples/auth/ShoppingAuthorizations.java) with product category and order total | +| `DELETE /orders/{id}` | `delete:orders` | `DeleteOrders` | `Role.DELETE_ORDERS` in [`AppFactory`](src/main/java/com/sap/cloud/security/ams/samples/AppFactory.java) | Route only (see commented equivalent check in [`OrdersService.deleteOrder`](src/main/java/com/sap/cloud/security/ams/samples/service/OrdersService.java)) | -```bash -mvn exec:java -``` +**App2App communication**: External principal propagation and technical user requests from other applications may act only with controlled privileges as defined by the policy mappers in [`AuthHandler.createAuthProvider`](src/main/java/com/sap/cloud/security/ams/samples/auth/AuthHandler.java), see [`PolicyTest`](src/test/java/com/sap/cloud/security/ams/samples/auth/PolicyTest.java). -Or with custom port: +## Policy definitions (DCL) -```bash -mvn exec:java -Dserver.port=8080 -``` +| Package | File | Purpose | +|---------|------|--------------------------------------------------------------------------------------------| +| `shopping` | [`src/main/resources/ams/dcl/shopping/basePolicies.dcl`](src/main/resources/ams/dcl/shopping/basePolicies.dcl) | `ReadProducts`, `ReadOrders`, `ReadOwnOrders`, `CreateOrders`, `DeleteOrders` | +| `local` | [`src/main/resources/ams/dcl/local/adminPolicies.dcl`](src/main/resources/ams/dcl/local/adminPolicies.dcl) | Mocked derived policies for testing, e.g. `OrderAccessory` (restricted create) | +| `internal` | [`src/main/resources/ams/dcl/internal/internalPolicies.dcl`](src/main/resources/ams/dcl/internal/internalPolicies.dcl) | Internal App2App policies (inaccessible by administrators) | +| Schema | [`src/main/resources/ams/dcl/schema.dcl`](src/main/resources/ams/dcl/schema.dcl) | Attributes for instance-based authorization `order.*`, `product.category`, `$user.scim_id` | -The application will start on port 7000 by default and be available at: -- Health check: http://localhost:7000/health -- API endpoints: http://localhost:7000/products, etc. +## Running tests -### Running Tests +From this directory: ```bash mvn test ``` -## Configuration - -### Environment Variables - -- `PORT` - Server port (default: 7000) - -### System Properties - -- `server.port` - Alternative way to set server port - -## Authentication & Authorization - -### Production Mode - -The `AuthHandler` class provides production authentication using SAP AMS. Currently implemented as stubs that can be extended with actual AMS integration: - -```java -// TODO: Implement actual AMS authentication and authorization -// This would include: -// 1. Extract JWT token from Authorization header -// 2. Validate token with Identity Service -// 3. Create security context -// 4. Perform authorization checks with AMS -``` - -### Testing Mode - -The `MockAuthHandler` allows testing with simple Basic Authentication: - -```bash -curl -H "Authorization: Basic $(echo -n 'testuser:password' | base64)" \ - http://localhost:7000/products -``` - -## Sample Data - -### Products -- MacBook Pro M3 (pc category) -- Dell Monitor (monitor category) -- Apple Mouse (accessory category) -- Cherry Keyboard (accessory category) -- Yubikey (securityAccessory category) - -### Orders -- Pre-loaded orders for users: carol, alice, bob - -## Dependencies - -### Main Dependencies -- **Javalin 5.6.3** - Web framework -- **Jackson** - JSON processing -- **OpenCSV** - CSV file processing -- **SAP Jakarta AMS 3.9.0-SNAPSHOT** - Authorization Management Service -- **SLF4J** - Logging - -### Test Dependencies -- **JUnit 5** - Testing framework -- **Javalin Test Tools** - Integration testing support - -## Future Enhancements +| Test class | Focus | +|------------|--------| +| [`JavalinShoppingApplicationTest`](src/test/java/com/sap/cloud/security/ams/samples/JavalinShoppingApplicationTest.java) | HTTP integration tests with [`TestAuthHandler`](src/test/java/com/sap/cloud/security/ams/samples/auth/TestAuthHandler.java) and JWT fixtures under `src/test/resources/jwt/` | +| [`PolicyTest`](src/test/java/com/sap/cloud/security/ams/samples/auth/PolicyTest.java) | DCL policy evaluation via local DCN (`AmsTestExtension`) | -1. **Complete AMS Integration**: Implement actual authentication and authorization with SAP AMS -2. **Database Integration**: Replace in-memory database with persistent storage -3. **Advanced Authorization**: Implement contextual authorization checks -4. **API Documentation**: Add OpenAPI/Swagger documentation -5. **Monitoring**: Add metrics and health indicators -6. **Security**: Implement HTTPS, CORS configuration, and security headers +Tests use a local AMS DCN compiled to `target/generated-test-resources/ams/dcn` and policy assignments in [`src/test/resources/mockPolicyAssignments.json`](src/test/resources/mockPolicyAssignments.json). Run tests with Maven so the DCN is generated before execution. ## License -This project is licensed under the Apache License 2.0 - see the LICENSE file for details. +Licensed under the Apache License 2.0 — see the [LICENSE](../LICENSE) file in the repository root. diff --git a/ams-spring-boot-shopping/README.md b/ams-spring-boot-shopping/README.md new file mode 100644 index 0000000..a25f93b --- /dev/null +++ b/ams-spring-boot-shopping/README.md @@ -0,0 +1,83 @@ +# AMS Spring Boot Shopping Sample + +## Overview + +This is a sample for the plain Spring Boot (i.e., non-CAP) integration of the AMS Java library. It shows a simplified shopping REST API, secured with Spring Security. The sample integrates both SAP Authorization Management Service (AMS) and the SAP Identity Authentication Service (IAS). Route-level authorization pre-checks are implemented via [`AmsRouteSecurity`](src/main/java/com/sap/cloud/security/ams/samples/config/SecurityConfiguration.java) in [`SecurityConfiguration`](src/main/java/com/sap/cloud/security/ams/samples/config/SecurityConfiguration.java), while fine-grained instance-based checks are demonstrated both via custom AMS Spring annotations and manually in service logic. + +## Domain Entities + +| Entity | Description | Source | +|--------|-------------|--------| +| **Product** | `id`, `name`, `price`, `category` | [`Product.java`](src/main/java/com/sap/cloud/security/ams/samples/model/Product.java), seeded from [`src/main/resources/csv/products.csv`](src/main/resources/csv/products.csv) | +| **Order** | `id`, `productId`, `quantity`, `totalAmount`, `createdBy` (SCIM id) | [`Order.java`](src/main/java/com/sap/cloud/security/ams/samples/model/Order.java), seeded from [`src/main/resources/csv/orders.csv`](src/main/resources/csv/orders.csv) | +| **HealthStatus** | Health response payload | [`HealthStatus.java`](src/main/java/com/sap/cloud/security/ams/samples/model/HealthStatus.java) | + +Persistence is in-memory via [`SimpleDatabase`](src/main/java/com/sap/cloud/security/ams/samples/db/SimpleDatabase.java) and [`DataLoader`](src/main/java/com/sap/cloud/security/ams/samples/db/DataLoader.java). + +## Services + +| Component | Responsibility | +|-----------|------------------------------------------------------------------------------------------------------------| +| [`ProductsService`](src/main/java/com/sap/cloud/security/ams/samples/service/ProductsService.java) | `GET /products` | +| [`OrdersService`](src/main/java/com/sap/cloud/security/ams/samples/service/OrdersService.java) | `GET` / `POST` / `DELETE` on `/orders`; instance-based AMS checks for list, create, and delete | +| [`PrivilegesService`](src/main/java/com/sap/cloud/security/ams/samples/service/PrivilegesService.java) | `GET /privileges` — returns privileges for the current user (without the instance-based filter conditions) | +| [`ProductsController`](src/main/java/com/sap/cloud/security/ams/samples/controller/ProductsController.java), [`OrdersController`](src/main/java/com/sap/cloud/security/ams/samples/controller/OrdersController.java), [`PrivilegesController`](src/main/java/com/sap/cloud/security/ams/samples/controller/PrivilegesController.java), [`HealthController`](src/main/java/com/sap/cloud/security/ams/samples/controller/HealthController.java) | REST endpoints | + +Application entry point: [`Application`](src/main/java/com/sap/cloud/security/ams/samples/Application.java). Privilege constants: [`Privileges`](src/main/java/com/sap/cloud/security/ams/samples/config/Privileges.java). Context attributes: [`AmsAttributes`](src/main/java/com/sap/cloud/security/ams/samples/config/AmsAttributes.java). + +## API + +| Method | Path | Auth | +|--------|------|------| +| `GET` | `/actuator/health` | Public | +| `GET` | `/health` | Public | +| `GET` | `/privileges` | Authenticated | +| `GET` | `/products` | `read:products` | +| `GET` | `/orders` | `read:orders` (with optional row filtering) | +| `POST` | `/orders` | `create:orders` (with per-order attribute checks) | +| `DELETE` | `/orders/{id}` | `delete:orders` | + +Request body for `POST /orders`: JSON `{ "productId": number, "quantity": number }`. + +## Authorization model + +Privileges are defined in [`Privileges`](src/main/java/com/sap/cloud/security/ams/samples/config/Privileges.java) and granted by AMS policies. Enforcement is split between the route layer ([`SecurityConfiguration`](src/main/java/com/sap/cloud/security/ams/samples/config/SecurityConfiguration.java) and `AmsRouteSecurity`) and the service or controller layer where instance-based authorization is implemented. + +| Operation | AMS privilege | Typical policy | Route-level check | Contextual / service check | +|-----------|-----------------|----------------|-------------------|----------------------------| +| `GET /actuator/health` | — | — | `permitAll` in [`SecurityConfiguration`](src/main/java/com/sap/cloud/security/ams/samples/config/SecurityConfiguration.java) | — | +| `GET /health` | — | — | Public (no AMS check on route) | [`HealthController`](src/main/java/com/sap/cloud/security/ams/samples/controller/HealthController.java) | +| `GET /privileges` | — | — | `authenticated()` in [`SecurityConfiguration`](src/main/java/com/sap/cloud/security/ams/samples/config/SecurityConfiguration.java) | [`PrivilegesService`](src/main/java/com/sap/cloud/security/ams/samples/service/PrivilegesService.java) | +| `GET /products` | `read:products` | `ReadProducts` | `via.checkPrivilege(READ_PRODUCTS)` in [`SecurityConfiguration`](src/main/java/com/sap/cloud/security/ams/samples/config/SecurityConfiguration.java) | [`ProductsService.getProducts`](src/main/java/com/sap/cloud/security/ams/samples/service/ProductsService.java) `@CheckPrivilege` | +| `GET /orders` | `read:orders` | `ReadOrders`, `ReadOwnOrders` | `via.precheckPrivilege(READ_ORDERS)` in [`SecurityConfiguration`](src/main/java/com/sap/cloud/security/ams/samples/config/SecurityConfiguration.java) | [`OrdersService.getOrders`](src/main/java/com/sap/cloud/security/ams/samples/service/OrdersService.java) — deny, full list, or instance-based filter | +| `POST /orders` | `create:orders` | `CreateOrders` | `via.precheckPrivilege(CREATE_ORDERS)` in [`SecurityConfiguration`](src/main/java/com/sap/cloud/security/ams/samples/config/SecurityConfiguration.java) | [`OrdersController.createOrder`](src/main/java/com/sap/cloud/security/ams/samples/controller/OrdersController.java) `@PrecheckPrivilege`; instance-based check in [`OrdersService.createOrder`](src/main/java/com/sap/cloud/security/ams/samples/service/OrdersService.java) | +| `DELETE /orders/{id}` | `delete:orders` | `DeleteOrders` | `via.checkPrivilege(DELETE_ORDERS)` in [`SecurityConfiguration`](src/main/java/com/sap/cloud/security/ams/samples/config/SecurityConfiguration.java) | [`OrdersService.deleteOrder`](src/main/java/com/sap/cloud/security/ams/samples/service/OrdersService.java) `@CheckPrivilege` | + +**App2App communication**: External principal propagation and technical user requests from other applications may act only with controlled privileges as defined by the policy mappers in [`App2AppAuthorizationConfiguration`](src/main/java/com/sap/cloud/security/ams/samples/config/App2AppAuthorizationConfiguration.java); internal policies are listed under Policy definitions (DCL) below. + +## Policy definitions (DCL) + +| Package | File | Purpose | +|---------|------|---------| +| `shopping` | [`src/main/resources/ams/dcl/shopping/basePolicies.dcl`](src/main/resources/ams/dcl/shopping/basePolicies.dcl) | `ReadProducts`, `ReadOrders`, `ReadOwnOrders`, `CreateOrders`, `DeleteOrders` | +| `local` | [`src/main/resources/ams/dcl/local/adminPolicies.dcl`](src/main/resources/ams/dcl/local/adminPolicies.dcl) | Mocked derived policies for testing, e.g. `OrderAccessory` (restricted create) | +| `internal` | [`src/main/resources/ams/dcl/internal/internalPolicies.dcl`](src/main/resources/ams/dcl/internal/internalPolicies.dcl) | Internal App2App policies (inaccessible by administrators) | +| Schema | [`src/main/resources/ams/dcl/schema.dcl`](src/main/resources/ams/dcl/schema.dcl) | Attributes for instance-based authorization `order.*`, `product.category`, `$user.scim_id` | + +## Running tests + +From this directory: + +```bash +mvn test +``` + +| Test class | Focus | +|------------|--------| +| [`ApplicationTest`](src/test/java/com/sap/cloud/security/ams/samples/ApplicationTest.java) | HTTP integration tests with `@ActiveProfiles("test")`, [`TestSecurityConfiguration`](src/test/java/com/sap/cloud/security/ams/samples/config/TestSecurityConfiguration.java), and JWT fixtures under `src/test/resources/jwt/` | + +Tests use a local AMS DCN compiled to `target/generated-test-resources/ams/dcn` and policy assignments in [`src/test/resources/mockPolicyAssignments.json`](src/test/resources/mockPolicyAssignments.json). Run tests with Maven so the DCN is generated before execution. + +## License + +Licensed under the Apache License 2.0 — see the [LICENSE](../LICENSE) file in the repository root.