diff --git a/example/basyx/aas-env.properties b/example/basyx/aas-env.properties deleted file mode 100644 index 70ef7e28..00000000 --- a/example/basyx/aas-env.properties +++ /dev/null @@ -1,16 +0,0 @@ -server.port=8081 -basyx.environment=file:aas -basyx.cors.allowed-origins=* -basyx.cors.allowed-methods=GET,POST,PATCH,DELETE,PUT,OPTIONS,HEAD -basyx.aasrepository.feature.registryintegration=http://aas-template-registry:8080 -basyx.submodelrepository.feature.registryintegration=http://sm-template-registry:8080 -spring.servlet.multipart.max-file-size=128MB -spring.servlet.multipart.max-request-size=128MB -basyx.backend=MongoDB -spring.data.mongodb.host=mongo -spring.data.mongodb.port=27017 -spring.data.mongodb.database=aasenvironment -spring.data.mongodb.authentication-database=admin -spring.data.mongodb.username=mongoAdmin -spring.data.mongodb.password=mongoPassword - diff --git a/example/README.md b/examples/minimalExample/README.md similarity index 68% rename from example/README.md rename to examples/minimalExample/README.md index a237d966..3a56c717 100644 --- a/example/README.md +++ b/examples/minimalExample/README.md @@ -10,11 +10,11 @@ The setup includes a complete tech stack with services for AAS registry, reposit This example includes 5 standardized submodel templates from the **Digital Product Passport for Industry 4.0**: -- **Nameplate** -- **MaintenanceInstructions** -- **TechnicalData** -- **CarbonFootprint** -- **HandoverDocumentation** +- **Nameplate** +- **MaintenanceInstructions** +- **TechnicalData** +- **CarbonFootprint** +- **HandoverDocumentation** ## Quick Start @@ -26,7 +26,7 @@ Before running the demonstrator, ensure you have installed: - **Docker Compose** (v1.29+) — Usually included with Docker Desktop - **Available Ports** — The following ports must be available on your machine: - `8080` — Main API Gateway (nginx) - - `8081` - PGAdmin + - `8081` — PGAdmin ### Running the Setup @@ -34,26 +34,22 @@ Before running the demonstrator, ensure you have installed: ```bash git clone https://github.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine.git ``` -2. **Go Inside example Folder** - -```bash -cd AAS.TwinEngine.DataEngine\example -``` - -2. **Start all services:** +2. **Navigate to the minimal example folder:** ```bash - docker-compose up -d + cd AAS.TwinEngine.DataEngine/examples/minimalExample ``` - -3. **Access the Web UI:** +3. **Start all services:** + ```bash + docker compose up -d + ``` +4. **Access the Web UI:** Open your browser and navigate to: ``` http://localhost:8080/aas-ui/ ``` - -4. **Stop all services:** +5. **Stop all services:** ```bash - docker-compose down + docker compose down ``` ## Architecture & Services @@ -65,20 +61,24 @@ The docker-compose setup includes the following services, all running on a share | Service | Port | Image | Purpose | |---------|------|-------|----------| | **nginx** | 8080 | `nginx:trixie-perl` | API Gateway & Web UI proxy | -| **twinengine-dataengine** | - | `ghcr.io/aas-twinengine/dataengine:1.0.0` | Main TwinEngine DataEngine service | -| **template-repository** | - | `eclipsebasyx/aas-environment:2.0.0-SNAPSHOT` | AAS Environment & Submodel repository | -| **aas-template-registry** | - | `eclipsebasyx/aas-registry-log-mongodb:2.0.0-SNAPSHOT` | AAS Shell Descriptor Registry | -| **sm-template-registry** | - | `eclipsebasyx/submodel-registry-log-mongodb:2.0.0-SNAPSHOT` | Submodel Descriptor Registry | -| **dpp-plugin** | - | `ghcr.io/aas-twinengine/plugindpp:1.0.0` | Digital Product Passport Plugin | +| **twinengine-dataengine** | - | `ghcr.io/aas-twinengine/dataengine:develop` | Main TwinEngine DataEngine service | +| **template-repository-registry** | 8082 | `eclipsebasyx/aasenvironment-go:SNAPSHOT` | AAS Environment & Submodel repository (BaSyx Go) | +| **dpp-plugin** | - | `ghcr.io/aas-twinengine/plugindpp:develop` | Digital Product Passport Plugin | | **aas-web-ui** | — | `eclipsebasyx/aas-gui:SNAPSHOT` | Web User Interface (served via nginx) | ### Infrastructure Services | Service | Port | Image | Purpose | |---------|------|-------|----------| -| **postgres** | - | `postgres:16-alpine` | Relational database for plugin data | +| **basyx_configuration** | - | `eclipsebasyx/basyxconfigurationservice-go:SNAPSHOT` | Initializes BaSyx Go database schema | +| **postgres** | - | `postgres:16-alpine` | Relational database for plugin and BaSyx Go data | | **pgadmin** | 8081 | `dpage/pgadmin4:snapshot` | Web UI for managing PostgreSQL database | -| **mongo** | - | `mongo:6.0` | NoSQL database for registry metadata | + +Notes: + +- `postgres` hosts both databases: `twinengine` (plugin data) and `basyxTestDB` (BaSyx Go data). +- DB initialization scripts are in [../shared/postgres](../shared/postgres). +- The setup uses the BaSyx Go stack — no Java or MongoDB services. ## Creating/Changing Your AAS-Data @@ -110,9 +110,9 @@ PGAdmin provides a web-based interface to manage the PostgreSQL database without **How changes affect the Plugin:** - Updates to application data (e.g., shell records, submodels, submodel element values) are reflected in what the Plugin serves. -- Submodel and shell templates are managed by BaSyx services and are not modified via PostgreSQL. +- Submodel and shell templates are managed by BaSyx Go services and are not modified via PostgreSQL. --- +--- ## Additional Notes @@ -120,51 +120,50 @@ PGAdmin provides a web-based interface to manage the PostgreSQL database without If desired, you can edit credentials in `docker-compose.yml`: ```yaml -POSTGRES_PASSWORD: admin +POSTGRES_PASSWORD: admin ``` -Update plugin connection string to match. Edit `example/postgres/init.sql` for custom schema/data. +Update the plugin connection string to match. Edit `../shared/postgres/` scripts for custom schema/data. -**Using an External Database:** +**Using an External Database:** To use your own database instead: 1. Change `RelationalDatabaseConfiguration__ConnectionString` in the plugin service environment variables 2. Remove the postgres container from `docker-compose.yml` -**Database Initialization:** -The initial database script is located in `postgres/init.sql`. Modify this file as needed for your requirements. - -**Security and Production Notice** - -Change all default passwords before any use beyond local development. Default credentials (postgres: admin) are for **development** only. - -In production, hosting and managing the PostgreSQL database is the customer's responsibility, not the DataEngine's. Use a managed or self-hosted, production-grade PostgreSQL instance and configure the plugin connection string accordingly. - +**Database Initialization:** +The initial database scripts are in `../shared/postgres/`. Modify these files as needed for your requirements. ### Port Changes Modify port mappings in `docker-compose.yml`. Update corresponding environment variables in affected services. -### Security Note +### Security and Production Notice + +Change all default passwords before any use beyond local development. Default credentials (postgres: admin) are for **development** only. -**Change default passwords before any use beyond local development.** Default credentials (postgres: admin) are for development only. +In production, hosting and managing the PostgreSQL database is the customer's responsibility, not the DataEngine's. Use a managed or self-hosted, production-grade PostgreSQL instance and configure the plugin connection string accordingly. -In production: use a secure API gateway (Azure API Management, AWS API Gateway, Kong), and manage database security (encryption, access control, backups) is a customer responsibility. *Do not use this Docker Compose configuration in production.* + --- ## Troubleshooting -**UI not loading:** `docker-compose logs nginx` - Verify ports 8080-8086 are available. +**UI not loading:** `docker compose logs nginx` — Verify ports 8080 and 8081 are available. **Port conflicts:** `netstat -ano | findstr :8080` (Windows) to find conflicts. Change ports in `docker-compose.yml`. -**Startup issues:** Run `docker-compose pull` followed by `docker-compose up -d --force-recreate` +**Startup issues:** Run `docker compose pull` -**Database errors:** Check `docker-compose ps` for health status. Verify connection strings match credentials. - -**PGAdmin not accessible:** Verify the postgres service is healthy with `docker-compose ps`. Check port mappings are correctly configured. +**Database errors:** Check `docker compose ps` for health status. Verify connection strings match credentials. +**PGAdmin not accessible:** Verify the postgres service is healthy with `docker compose ps`. Check port mappings are correctly configured. +**Schema/init changed — recreate volumes:** +```bash +docker compose down -v +docker compose up -d +``` ## Additional Resources diff --git a/example/apiCollection/Aas Registry/Get All ShellDescriptors.bru b/examples/minimalExample/apiCollection/Aas Registry/Get All ShellDescriptors.bru similarity index 100% rename from example/apiCollection/Aas Registry/Get All ShellDescriptors.bru rename to examples/minimalExample/apiCollection/Aas Registry/Get All ShellDescriptors.bru diff --git a/example/apiCollection/Aas Registry/Get Shell Descriptor By Id - Product1.bru b/examples/minimalExample/apiCollection/Aas Registry/Get Shell Descriptor By Id - Product1.bru similarity index 100% rename from example/apiCollection/Aas Registry/Get Shell Descriptor By Id - Product1.bru rename to examples/minimalExample/apiCollection/Aas Registry/Get Shell Descriptor By Id - Product1.bru diff --git a/example/apiCollection/Aas Registry/Get Shell Descriptor By Id - Product2.bru b/examples/minimalExample/apiCollection/Aas Registry/Get Shell Descriptor By Id - Product2.bru similarity index 100% rename from example/apiCollection/Aas Registry/Get Shell Descriptor By Id - Product2.bru rename to examples/minimalExample/apiCollection/Aas Registry/Get Shell Descriptor By Id - Product2.bru diff --git a/example/apiCollection/Aas Registry/Get Shell Descriptor By Id - Product3.bru b/examples/minimalExample/apiCollection/Aas Registry/Get Shell Descriptor By Id - Product3.bru similarity index 100% rename from example/apiCollection/Aas Registry/Get Shell Descriptor By Id - Product3.bru rename to examples/minimalExample/apiCollection/Aas Registry/Get Shell Descriptor By Id - Product3.bru diff --git a/example/apiCollection/Aas Registry/folder.bru b/examples/minimalExample/apiCollection/Aas Registry/folder.bru similarity index 100% rename from example/apiCollection/Aas Registry/folder.bru rename to examples/minimalExample/apiCollection/Aas Registry/folder.bru diff --git a/example/apiCollection/Aas Repository/Get All Shells.bru b/examples/minimalExample/apiCollection/Aas Repository/Get All Shells.bru similarity index 100% rename from example/apiCollection/Aas Repository/Get All Shells.bru rename to examples/minimalExample/apiCollection/Aas Repository/Get All Shells.bru diff --git a/example/apiCollection/Aas Repository/Get Shells By Asset Id - Product1.bru b/examples/minimalExample/apiCollection/Aas Repository/Get Shells By Asset Id - Product1.bru similarity index 100% rename from example/apiCollection/Aas Repository/Get Shells By Asset Id - Product1.bru rename to examples/minimalExample/apiCollection/Aas Repository/Get Shells By Asset Id - Product1.bru diff --git a/example/apiCollection/Aas Repository/Get Shells By Asset Id - Product2.bru b/examples/minimalExample/apiCollection/Aas Repository/Get Shells By Asset Id - Product2.bru similarity index 100% rename from example/apiCollection/Aas Repository/Get Shells By Asset Id - Product2.bru rename to examples/minimalExample/apiCollection/Aas Repository/Get Shells By Asset Id - Product2.bru diff --git a/example/apiCollection/Aas Repository/Product1/Get Asset Information By Id.bru b/examples/minimalExample/apiCollection/Aas Repository/Product1/Get Asset Information By Id.bru similarity index 100% rename from example/apiCollection/Aas Repository/Product1/Get Asset Information By Id.bru rename to examples/minimalExample/apiCollection/Aas Repository/Product1/Get Asset Information By Id.bru diff --git a/example/apiCollection/Aas Repository/Product1/Get Shell By Id.bru b/examples/minimalExample/apiCollection/Aas Repository/Product1/Get Shell By Id.bru similarity index 100% rename from example/apiCollection/Aas Repository/Product1/Get Shell By Id.bru rename to examples/minimalExample/apiCollection/Aas Repository/Product1/Get Shell By Id.bru diff --git a/example/apiCollection/Aas Repository/Product1/Get Submodel Ref By Id.bru b/examples/minimalExample/apiCollection/Aas Repository/Product1/Get Submodel Ref By Id.bru similarity index 100% rename from example/apiCollection/Aas Repository/Product1/Get Submodel Ref By Id.bru rename to examples/minimalExample/apiCollection/Aas Repository/Product1/Get Submodel Ref By Id.bru diff --git a/example/apiCollection/Aas Repository/Product1/folder.bru b/examples/minimalExample/apiCollection/Aas Repository/Product1/folder.bru similarity index 100% rename from example/apiCollection/Aas Repository/Product1/folder.bru rename to examples/minimalExample/apiCollection/Aas Repository/Product1/folder.bru diff --git a/example/apiCollection/Aas Repository/Product2/Get Asset Information By Id.bru b/examples/minimalExample/apiCollection/Aas Repository/Product2/Get Asset Information By Id.bru similarity index 100% rename from example/apiCollection/Aas Repository/Product2/Get Asset Information By Id.bru rename to examples/minimalExample/apiCollection/Aas Repository/Product2/Get Asset Information By Id.bru diff --git a/example/apiCollection/Aas Repository/Product2/Get Shell By Id.bru b/examples/minimalExample/apiCollection/Aas Repository/Product2/Get Shell By Id.bru similarity index 100% rename from example/apiCollection/Aas Repository/Product2/Get Shell By Id.bru rename to examples/minimalExample/apiCollection/Aas Repository/Product2/Get Shell By Id.bru diff --git a/example/apiCollection/Aas Repository/Product2/Get Submodel Ref By Id.bru b/examples/minimalExample/apiCollection/Aas Repository/Product2/Get Submodel Ref By Id.bru similarity index 100% rename from example/apiCollection/Aas Repository/Product2/Get Submodel Ref By Id.bru rename to examples/minimalExample/apiCollection/Aas Repository/Product2/Get Submodel Ref By Id.bru diff --git a/example/apiCollection/Aas Repository/Product2/folder.bru b/examples/minimalExample/apiCollection/Aas Repository/Product2/folder.bru similarity index 100% rename from example/apiCollection/Aas Repository/Product2/folder.bru rename to examples/minimalExample/apiCollection/Aas Repository/Product2/folder.bru diff --git a/example/apiCollection/Aas Repository/Product3/Get Asset Information By Id.bru b/examples/minimalExample/apiCollection/Aas Repository/Product3/Get Asset Information By Id.bru similarity index 100% rename from example/apiCollection/Aas Repository/Product3/Get Asset Information By Id.bru rename to examples/minimalExample/apiCollection/Aas Repository/Product3/Get Asset Information By Id.bru diff --git a/example/apiCollection/Aas Repository/Product3/Get Shell By Id.bru b/examples/minimalExample/apiCollection/Aas Repository/Product3/Get Shell By Id.bru similarity index 100% rename from example/apiCollection/Aas Repository/Product3/Get Shell By Id.bru rename to examples/minimalExample/apiCollection/Aas Repository/Product3/Get Shell By Id.bru diff --git a/example/apiCollection/Aas Repository/Product3/Get Submodel Ref By Id.bru b/examples/minimalExample/apiCollection/Aas Repository/Product3/Get Submodel Ref By Id.bru similarity index 100% rename from example/apiCollection/Aas Repository/Product3/Get Submodel Ref By Id.bru rename to examples/minimalExample/apiCollection/Aas Repository/Product3/Get Submodel Ref By Id.bru diff --git a/example/apiCollection/Aas Repository/Product3/folder.bru b/examples/minimalExample/apiCollection/Aas Repository/Product3/folder.bru similarity index 100% rename from example/apiCollection/Aas Repository/Product3/folder.bru rename to examples/minimalExample/apiCollection/Aas Repository/Product3/folder.bru diff --git a/example/apiCollection/Aas Repository/folder.bru b/examples/minimalExample/apiCollection/Aas Repository/folder.bru similarity index 100% rename from example/apiCollection/Aas Repository/folder.bru rename to examples/minimalExample/apiCollection/Aas Repository/folder.bru diff --git a/example/apiCollection/Discovery/Search Shells By Asset Link - Multiple Filters.bru b/examples/minimalExample/apiCollection/Discovery/Search Shells By Asset Link - Multiple Filters.bru similarity index 100% rename from example/apiCollection/Discovery/Search Shells By Asset Link - Multiple Filters.bru rename to examples/minimalExample/apiCollection/Discovery/Search Shells By Asset Link - Multiple Filters.bru diff --git a/example/apiCollection/Discovery/Search Shells By Asset Link.bru b/examples/minimalExample/apiCollection/Discovery/Search Shells By Asset Link.bru similarity index 100% rename from example/apiCollection/Discovery/Search Shells By Asset Link.bru rename to examples/minimalExample/apiCollection/Discovery/Search Shells By Asset Link.bru diff --git a/example/apiCollection/Discovery/folder.bru b/examples/minimalExample/apiCollection/Discovery/folder.bru similarity index 100% rename from example/apiCollection/Discovery/folder.bru rename to examples/minimalExample/apiCollection/Discovery/folder.bru diff --git a/example/apiCollection/README.md b/examples/minimalExample/apiCollection/README.md similarity index 100% rename from example/apiCollection/README.md rename to examples/minimalExample/apiCollection/README.md diff --git a/example/apiCollection/Submodel Registry/Get Submodel Descriptor By Id - CarbonFootprint.bru b/examples/minimalExample/apiCollection/Submodel Registry/Get Submodel Descriptor By Id - CarbonFootprint.bru similarity index 100% rename from example/apiCollection/Submodel Registry/Get Submodel Descriptor By Id - CarbonFootprint.bru rename to examples/minimalExample/apiCollection/Submodel Registry/Get Submodel Descriptor By Id - CarbonFootprint.bru diff --git a/example/apiCollection/Submodel Registry/Get Submodel Descriptor By Id - HandoverDocumentation.bru b/examples/minimalExample/apiCollection/Submodel Registry/Get Submodel Descriptor By Id - HandoverDocumentation.bru similarity index 100% rename from example/apiCollection/Submodel Registry/Get Submodel Descriptor By Id - HandoverDocumentation.bru rename to examples/minimalExample/apiCollection/Submodel Registry/Get Submodel Descriptor By Id - HandoverDocumentation.bru diff --git a/example/apiCollection/Submodel Registry/Get Submodel Descriptor By Id - MaintenanceInstructions.bru b/examples/minimalExample/apiCollection/Submodel Registry/Get Submodel Descriptor By Id - MaintenanceInstructions.bru similarity index 100% rename from example/apiCollection/Submodel Registry/Get Submodel Descriptor By Id - MaintenanceInstructions.bru rename to examples/minimalExample/apiCollection/Submodel Registry/Get Submodel Descriptor By Id - MaintenanceInstructions.bru diff --git a/example/apiCollection/Submodel Registry/Get Submodel Descriptor By Id - Nameplate.bru b/examples/minimalExample/apiCollection/Submodel Registry/Get Submodel Descriptor By Id - Nameplate.bru similarity index 100% rename from example/apiCollection/Submodel Registry/Get Submodel Descriptor By Id - Nameplate.bru rename to examples/minimalExample/apiCollection/Submodel Registry/Get Submodel Descriptor By Id - Nameplate.bru diff --git a/example/apiCollection/Submodel Registry/Get Submodel Descriptor By Id - TechnicalData.bru b/examples/minimalExample/apiCollection/Submodel Registry/Get Submodel Descriptor By Id - TechnicalData.bru similarity index 100% rename from example/apiCollection/Submodel Registry/Get Submodel Descriptor By Id - TechnicalData.bru rename to examples/minimalExample/apiCollection/Submodel Registry/Get Submodel Descriptor By Id - TechnicalData.bru diff --git a/example/apiCollection/Submodel Registry/folder.bru b/examples/minimalExample/apiCollection/Submodel Registry/folder.bru similarity index 100% rename from example/apiCollection/Submodel Registry/folder.bru rename to examples/minimalExample/apiCollection/Submodel Registry/folder.bru diff --git a/example/apiCollection/Submodel Repository/Serialization/Get appropriate serialization - Product1.bru b/examples/minimalExample/apiCollection/Submodel Repository/Serialization/Get appropriate serialization - Product1.bru similarity index 100% rename from example/apiCollection/Submodel Repository/Serialization/Get appropriate serialization - Product1.bru rename to examples/minimalExample/apiCollection/Submodel Repository/Serialization/Get appropriate serialization - Product1.bru diff --git a/example/apiCollection/Submodel Repository/Serialization/folder.bru b/examples/minimalExample/apiCollection/Submodel Repository/Serialization/folder.bru similarity index 100% rename from example/apiCollection/Submodel Repository/Serialization/folder.bru rename to examples/minimalExample/apiCollection/Submodel Repository/Serialization/folder.bru diff --git a/example/apiCollection/Submodel Repository/Submodel Element/Get Submodel Element - CarbonFootprint.bru b/examples/minimalExample/apiCollection/Submodel Repository/Submodel Element/Get Submodel Element - CarbonFootprint.bru similarity index 100% rename from example/apiCollection/Submodel Repository/Submodel Element/Get Submodel Element - CarbonFootprint.bru rename to examples/minimalExample/apiCollection/Submodel Repository/Submodel Element/Get Submodel Element - CarbonFootprint.bru diff --git a/example/apiCollection/Submodel Repository/Submodel Element/Get Submodel Element - ContactInfo.bru b/examples/minimalExample/apiCollection/Submodel Repository/Submodel Element/Get Submodel Element - ContactInfo.bru similarity index 100% rename from example/apiCollection/Submodel Repository/Submodel Element/Get Submodel Element - ContactInfo.bru rename to examples/minimalExample/apiCollection/Submodel Repository/Submodel Element/Get Submodel Element - ContactInfo.bru diff --git a/example/apiCollection/Submodel Repository/Submodel Element/Get Submodel Element - HandoverDocumentation.bru b/examples/minimalExample/apiCollection/Submodel Repository/Submodel Element/Get Submodel Element - HandoverDocumentation.bru similarity index 100% rename from example/apiCollection/Submodel Repository/Submodel Element/Get Submodel Element - HandoverDocumentation.bru rename to examples/minimalExample/apiCollection/Submodel Repository/Submodel Element/Get Submodel Element - HandoverDocumentation.bru diff --git a/example/apiCollection/Submodel Repository/Submodel Element/Get Submodel Element - Nameplate.bru b/examples/minimalExample/apiCollection/Submodel Repository/Submodel Element/Get Submodel Element - Nameplate.bru similarity index 100% rename from example/apiCollection/Submodel Repository/Submodel Element/Get Submodel Element - Nameplate.bru rename to examples/minimalExample/apiCollection/Submodel Repository/Submodel Element/Get Submodel Element - Nameplate.bru diff --git a/example/apiCollection/Submodel Repository/Submodel Element/Get Submodel Element - TechnicalData.bru b/examples/minimalExample/apiCollection/Submodel Repository/Submodel Element/Get Submodel Element - TechnicalData.bru similarity index 100% rename from example/apiCollection/Submodel Repository/Submodel Element/Get Submodel Element - TechnicalData.bru rename to examples/minimalExample/apiCollection/Submodel Repository/Submodel Element/Get Submodel Element - TechnicalData.bru diff --git a/example/apiCollection/Submodel Repository/Submodel Element/folder.bru b/examples/minimalExample/apiCollection/Submodel Repository/Submodel Element/folder.bru similarity index 100% rename from example/apiCollection/Submodel Repository/Submodel Element/folder.bru rename to examples/minimalExample/apiCollection/Submodel Repository/Submodel Element/folder.bru diff --git a/example/apiCollection/Submodel Repository/Submodel/Get Submodel - HandoverDocumentation.bru b/examples/minimalExample/apiCollection/Submodel Repository/Submodel/Get Submodel - HandoverDocumentation.bru similarity index 100% rename from example/apiCollection/Submodel Repository/Submodel/Get Submodel - HandoverDocumentation.bru rename to examples/minimalExample/apiCollection/Submodel Repository/Submodel/Get Submodel - HandoverDocumentation.bru diff --git a/example/apiCollection/Submodel Repository/Submodel/Get Submodel - MaintenanceInstructions.bru b/examples/minimalExample/apiCollection/Submodel Repository/Submodel/Get Submodel - MaintenanceInstructions.bru similarity index 100% rename from example/apiCollection/Submodel Repository/Submodel/Get Submodel - MaintenanceInstructions.bru rename to examples/minimalExample/apiCollection/Submodel Repository/Submodel/Get Submodel - MaintenanceInstructions.bru diff --git a/example/apiCollection/Submodel Repository/Submodel/Get Submodel - Nameplate.bru b/examples/minimalExample/apiCollection/Submodel Repository/Submodel/Get Submodel - Nameplate.bru similarity index 100% rename from example/apiCollection/Submodel Repository/Submodel/Get Submodel - Nameplate.bru rename to examples/minimalExample/apiCollection/Submodel Repository/Submodel/Get Submodel - Nameplate.bru diff --git a/example/apiCollection/Submodel Repository/Submodel/Get Submodel - TechnicalData.bru b/examples/minimalExample/apiCollection/Submodel Repository/Submodel/Get Submodel - TechnicalData.bru similarity index 100% rename from example/apiCollection/Submodel Repository/Submodel/Get Submodel - TechnicalData.bru rename to examples/minimalExample/apiCollection/Submodel Repository/Submodel/Get Submodel - TechnicalData.bru diff --git a/example/apiCollection/Submodel Repository/Submodel/Get Submodel -CarbonFootprint.bru b/examples/minimalExample/apiCollection/Submodel Repository/Submodel/Get Submodel -CarbonFootprint.bru similarity index 100% rename from example/apiCollection/Submodel Repository/Submodel/Get Submodel -CarbonFootprint.bru rename to examples/minimalExample/apiCollection/Submodel Repository/Submodel/Get Submodel -CarbonFootprint.bru diff --git a/example/apiCollection/Submodel Repository/Submodel/folder.bru b/examples/minimalExample/apiCollection/Submodel Repository/Submodel/folder.bru similarity index 100% rename from example/apiCollection/Submodel Repository/Submodel/folder.bru rename to examples/minimalExample/apiCollection/Submodel Repository/Submodel/folder.bru diff --git a/example/apiCollection/Submodel Repository/folder.bru b/examples/minimalExample/apiCollection/Submodel Repository/folder.bru similarity index 100% rename from example/apiCollection/Submodel Repository/folder.bru rename to examples/minimalExample/apiCollection/Submodel Repository/folder.bru diff --git a/example/apiCollection/bruno.json b/examples/minimalExample/apiCollection/bruno.json similarity index 100% rename from example/apiCollection/bruno.json rename to examples/minimalExample/apiCollection/bruno.json diff --git a/example/apiCollection/collection.bru b/examples/minimalExample/apiCollection/collection.bru similarity index 100% rename from example/apiCollection/collection.bru rename to examples/minimalExample/apiCollection/collection.bru diff --git a/example/apiCollection/environments/local.bru b/examples/minimalExample/apiCollection/environments/local.bru similarity index 100% rename from example/apiCollection/environments/local.bru rename to examples/minimalExample/apiCollection/environments/local.bru diff --git a/example/docker-compose.yml b/examples/minimalExample/docker-compose.yml similarity index 71% rename from example/docker-compose.yml rename to examples/minimalExample/docker-compose.yml index b902ae58..aa852ab6 100644 --- a/example/docker-compose.yml +++ b/examples/minimalExample/docker-compose.yml @@ -12,16 +12,12 @@ services: ports: - "8080:80" volumes: - - ./nginx/html:/usr/share/nginx/html - - ./nginx/default.conf.template:/etc/nginx/templates/default.conf.template + - ../shared/nginx/html:/usr/share/nginx/html + - ../shared/nginx/default.conf.template:/etc/nginx/templates/default.conf.template restart: always depends_on: - aas-template-registry: - condition: service_healthy - sm-template-registry: - condition: service_healthy - template-repository: - condition: service_healthy + template-repository-registry: + condition: service_started networks: - twinengine-network @@ -62,35 +58,20 @@ services: - TemplateManagement__TemplateMappingRules__AasIdExtractionRules__0__Pattern=/ - TemplateManagement__TemplateMappingRules__AasIdExtractionRules__0__Index=5 - TemplateManagement__AasTemplateRepository__Name=AasTemplateRepository - - TemplateManagement__AasTemplateRepository__baseUrl=http://template-repository:8081 - - TemplateManagement__AasTemplateRepository__headerMappings__0__source=Authorization - - TemplateManagement__AasTemplateRepository__headerMappings__0__target=Authorization - - TemplateManagement__AasTemplateRepository__headerMappings__0__required=false - - TemplateManagement__AasTemplateRepository__healthEndpoint=/actuator/health + - TemplateManagement__AasTemplateRepository__baseUrl=http://template-repository-registry:8082 + - TemplateManagement__AasTemplateRepository__healthEndpoint=/health - TemplateManagement__SubmodelTemplateRepository__Name=SubmodelTemplateRepository - - TemplateManagement__SubmodelTemplateRepository__baseUrl=http://template-repository:8081 - - TemplateManagement__SubmodelTemplateRepository__headerMappings__0__source=Authorization - - TemplateManagement__SubmodelTemplateRepository__headerMappings__0__target=Authorization - - TemplateManagement__SubmodelTemplateRepository__headerMappings__0__required=false - - TemplateManagement__SubmodelTemplateRepository__healthEndpoint=/actuator/health + - TemplateManagement__SubmodelTemplateRepository__baseUrl=http://template-repository-registry:8082 + - TemplateManagement__SubmodelTemplateRepository__healthEndpoint=/health - TemplateManagement__ConceptDescriptionTemplateRepository__Name=ConceptDescriptionTemplateRepository - - TemplateManagement__ConceptDescriptionTemplateRepository__baseUrl=http://template-repository:8081 - - TemplateManagement__ConceptDescriptionTemplateRepository__headerMappings__0__source=Authorization - - TemplateManagement__ConceptDescriptionTemplateRepository__headerMappings__0__target=Authorization - - TemplateManagement__ConceptDescriptionTemplateRepository__headerMappings__0__required=false - - TemplateManagement__ConceptDescriptionTemplateRepository__healthEndpoint=/actuator/health + - TemplateManagement__ConceptDescriptionTemplateRepository__baseUrl=http://template-repository-registry:8082 + - TemplateManagement__ConceptDescriptionTemplateRepository__healthEndpoint=/health - TemplateManagement__AasTemplateRegistry__Name=AasTemplateRegistry - - TemplateManagement__AasTemplateRegistry__baseUrl=http://aas-template-registry:8080 - - TemplateManagement__AasTemplateRegistry__headerMappings__0__source=Authorization - - TemplateManagement__AasTemplateRegistry__headerMappings__0__target=Authorization - - TemplateManagement__AasTemplateRegistry__headerMappings__0__required=false - - TemplateManagement__AasTemplateRegistry__healthEndpoint=/actuator/health + - TemplateManagement__AasTemplateRegistry__baseUrl=http://template-repository-registry:8082 + - TemplateManagement__AasTemplateRegistry__healthEndpoint=/health - TemplateManagement__SubmodelTemplateRegistry__Name=SubmodelTemplateRegistry - - TemplateManagement__SubmodelTemplateRegistry__baseUrl=http://sm-template-registry:8080 - - TemplateManagement__SubmodelTemplateRegistry__headerMappings__0__source=Authorization - - TemplateManagement__SubmodelTemplateRegistry__headerMappings__0__target=Authorization - - TemplateManagement__SubmodelTemplateRegistry__headerMappings__0__required=false - - TemplateManagement__SubmodelTemplateRegistry__healthEndpoint=/actuator/health + - TemplateManagement__SubmodelTemplateRegistry__baseUrl=http://template-repository-registry:8082 + - TemplateManagement__SubmodelTemplateRegistry__healthEndpoint=/health networks: - twinengine-network @@ -129,41 +110,56 @@ services: networks: - twinengine-network - template-repository: - image: eclipsebasyx/aas-environment:2.0.0-SNAPSHOT - container_name: template-repository + template-repository-registry: + image: eclipsebasyx/aasenvironment-go:SNAPSHOT + container_name: template-repository-registry + pull_policy: always + command: ["/app/aasenvironmentservice"] volumes: - - ./aas:/application/aas - - ./basyx/aas-env.properties:/application/application.properties + - ../shared/aas:/app/preconfiguration:ro environment: - BASYX_EXTERNALURL : http://localhost:8080 + - SERVER_PORT=8082 + - CORS_ALLOWEDORIGINS=* + - CORS_ALLOWEDHEADERS=* + - CORS_ALLOWEDCREDENTIALS=true + - CORS_ALLOWEDMETHODS=GET,OPTIONS + - POSTGRES_HOST=postgres + - POSTGRES_PORT=5432 + - POSTGRES_USER=postgres + - POSTGRES_PASSWORD=admin + - POSTGRES_DBNAME=basyxTestDB + - POSTGRES_MAXOPENCONNECTIONS=500 + - POSTGRES_MAXIDLECONNECTIONS=500 + - POSTGRES_CONNMAXLIFETIMEMINUTES=5 + - ABAC_ENABLED=false + - GENERAL_AASREGISTRYINTEGRATION=true + - GENERAL_SUBMODELREGISTRYINTEGRATION=true + - GENERAL_DISCOVERYINTEGRATION=true + - GENERAL_EXTERNALURL=http://localhost:8080 + - GENERAL_AAS_PRECONFIG_PATHS=/app/preconfiguration restart: always depends_on: - aas-template-registry: - condition: service_healthy - sm-template-registry: - condition: service_healthy + basyx_configuration: + condition: service_completed_successfully networks: - twinengine-network - aas-template-registry: - image: eclipsebasyx/aas-registry-log-mongodb:2.0.0-SNAPSHOT - container_name: aas-template-registry - restart: always - depends_on: - - mongo + basyx_configuration: + container_name: basyx_configuration + image: eclipsebasyx/basyxconfigurationservice-go:SNAPSHOT + pull_policy: always environment: - - SPRING_DATA_MONGODB_URI=mongodb://mongoAdmin:mongoPassword@mongo:27017 - networks: - - twinengine-network - - sm-template-registry: - image: eclipsebasyx/submodel-registry-log-mongodb:2.0.0-SNAPSHOT - container_name: sm-template-registry + - POSTGRES_HOST=postgres + - POSTGRES_PORT=5432 + - POSTGRES_USER=postgres + - POSTGRES_PASSWORD=admin + - POSTGRES_DBNAME=basyxTestDB + - POSTGRES_MAXOPENCONNECTIONS=500 + - POSTGRES_MAXIDLECONNECTIONS=500 + - POSTGRES_CONNMAXLIFETIMEMINUTES=5 depends_on: - - mongo - environment: - - SPRING_DATA_MONGODB_URI=mongodb://mongoAdmin:mongoPassword@mongo:27017 + postgres: + condition: service_healthy networks: - twinengine-network @@ -171,7 +167,7 @@ services: image: eclipsebasyx/aas-gui:SNAPSHOT container_name: aas-ui volumes: - - ./logo:/usr/src/app/dist/Logo + - ../shared/logo:/usr/src/app/dist/Logo environment: AAS_REGISTRY_PATH: http://localhost:8080/shell-descriptors SUBMODEL_REGISTRY_PATH: http://localhost:8080/submodel-descriptors @@ -184,17 +180,8 @@ services: PRIMARY_LIGHT_COLOR: "#041b2b" restart: always depends_on: - template-repository: - condition: service_healthy - networks: - - twinengine-network - - mongo: - image: mongo:6.0 - container_name: mongo - environment: - MONGO_INITDB_ROOT_USERNAME: mongoAdmin - MONGO_INITDB_ROOT_PASSWORD: mongoPassword + template-repository-registry: + condition: service_started networks: - twinengine-network @@ -206,7 +193,7 @@ services: POSTGRES_USER: postgres POSTGRES_PASSWORD: admin volumes: - - ./postgres:/docker-entrypoint-initdb.d + - ../shared/postgres:/docker-entrypoint-initdb.d - postgres-data:/var/lib/postgresql/data restart: always healthcheck: diff --git a/examples/securedExample/README.md b/examples/securedExample/README.md new file mode 100644 index 00000000..55065826 --- /dev/null +++ b/examples/securedExample/README.md @@ -0,0 +1,206 @@ +# TwinEngine Secured Setup (Keycloak + BaSyx Go ABAC) + +## Overview + +This folder provides a secured, containerized setup to demonstrate how **TwinEngine.DataEngine** can be integrated and run locally with authentication and authorization enabled. It creates a fully functional environment for managing Asset Administration Shells (AAS), submodels, and related digital asset components using Docker Compose. + +The setup adds Keycloak-based OIDC authentication and BaSyx Go ABAC authorization on top of the minimal example—all orchestrated through Docker containers on a shared network. + +## Included Submodel Templates + +This example includes 5 standardized submodel templates from the **Digital Product Passport for Industry 4.0**: + +- **Nameplate** +- **MaintenanceInstructions** +- **TechnicalData** +- **CarbonFootprint** +- **HandoverDocumentation** + +## Quick Start + +### Prerequisites + +Before running the demonstrator, ensure you have installed: + +- **Docker** (v20.10+) — [Install Docker](https://docs.docker.com/get-docker/) +- **Docker Compose** (v1.29+) — Usually included with Docker Desktop +- **Available Ports** — The following ports must be available on your machine: + - `8080` — Main API Gateway (nginx) + - `8081` — PGAdmin + - `9090` — Keycloak + +### Running the Setup + +1. **Clone or extract this repository:** + ```bash + git clone https://github.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine.git + ``` +2. **Navigate to the secured example folder:** + ```bash + cd AAS.TwinEngine.DataEngine/examples/securedExample + ``` +3. **Start all services:** + ```bash + docker compose up -d + ``` +4. **Access the Web UI:** + Open your browser and navigate to: + ``` + http://localhost:8080/aas-ui/ + ``` +5. **Stop all services:** + ```bash + docker compose down + ``` + +## Architecture & Services + +The docker-compose setup includes the following services, all running on a shared `twinengine-network`: + +### Core Services + +| Service | Port | Image | Purpose | +|---------|------|-------|----------| +| **nginx** | 8080 | `nginx:trixie-perl` | API Gateway & Web UI proxy | +| **twinengine-dataengine** | - | `ghcr.io/aas-twinengine/dataengine:develop` | Main TwinEngine DataEngine service | +| **template-repository-registry** | 8082 | `eclipsebasyx/aasenvironment-go:SNAPSHOT` | AAS Environment & Submodel repository (ABAC enabled) | +| **dpp-plugin** | - | `ghcr.io/aas-twinengine/plugindpp:develop` | Digital Product Passport Plugin | +| **aas-web-ui** | — | `eclipsebasyx/aas-gui:SNAPSHOT` | Web User Interface (served via nginx) | +| **keycloak** | 9090 | `keycloak/keycloak:26.0.6` | OIDC Identity Provider | + +### Infrastructure Services + +| Service | Port | Image | Purpose | +|---------|------|-------|----------| +| **basyx_configuration** | - | `eclipsebasyx/basyxconfigurationservice-go:SNAPSHOT` | Initializes BaSyx Go database schema | +| **postgres** | - | `postgres:16-alpine` | Relational database for plugin, BaSyx Go, and Keycloak data | +| **pgadmin** | 8081 | `dpage/pgadmin4:snapshot` | Web UI for managing PostgreSQL database | + +Notes: + +- `postgres` hosts all databases: `twinengine` (plugin data), `basyxTestDB` (BaSyx Go and Keycloak data). +- DB initialization scripts are in [../shared/postgres](../shared/postgres). +- The Keycloak realm is imported from [keycloak/realm/basyx-realm.json](keycloak/realm/basyx-realm.json) on first startup. + +## Login Information + +### AAS UI Login + +The UI is configured for Keycloak client `basyx-ui`. + +Open [http://localhost:8080/aas-ui/](http://localhost:8080/aas-ui/) and log in through Keycloak. + +Test users from imported realm [keycloak/realm/basyx-realm.json](keycloak/realm/basyx-realm.json): + +| Username | Password | Role | +|----------|----------|------| +| `admin` | `pwd` | admin — full access | +| `usera` | `pwd` | viewer — read access | +| `userx` | `pwd` | editor | + +### Keycloak Admin Login + +Open [http://localhost:9090](http://localhost:9090) and use: + +- **Username:** `admin` +- **Password:** `admin` + +## Creating/Changing Your AAS-Data + +### Using PGAdmin + +PGAdmin provides a web-based interface to manage the PostgreSQL database without writing SQL queries. + +**Access PGAdmin:** +1. Navigate to `http://localhost:8081` +2. Login with: + - **Email:** admin@example.com + - **Password:** admin + +**Connect to PostgreSQL Server:** +1. In PGAdmin, click **"Add New Server"** +2. Fill in the connection details: + - **Name:** twinengine + - **Host name:** postgres + - **Port:** 5432 + - **Username:** postgres + - **Password:** admin + - **Database:** twinengine +3. Click **"Save"** + +**Browse and Modify Data:** +- In the left sidebar, navigate to: **Servers → twinengine → Databases → twinengine → Schemas → public → Tables** +- Right-click any table and select **"View/Edit Data"** to manage records +- Create new records or modify existing ones directly through the UI + +**How changes affect the Plugin:** +- Updates to application data (e.g., shell records, submodels, submodel element values) are reflected in what the Plugin serves. +- Submodel and shell templates are managed by BaSyx Go services and are not modified via PostgreSQL. + +--- + +## Additional Notes + +### Authorization Model + +ABAC is enabled on `template-repository-registry` via: +- `ABAC_ENABLED=true` +- `ABAC_MODELPATH=/security_env/access-rules.json` +- `OIDC_TRUSTLISTPATH=/security_env/trustlist.json` + +Rules in [security_env/access-rules.json](security_env/access-rules.json) are role-based by claim `role`: + +- `admin`: full access to all configured routes +- `viewer`: read access to allowed descriptors/identifiables +- anonymous: limited read access for selected public items + +### Header Forwarding Flow + +DataEngine forwards incoming auth headers: + +- `Authorization` → `Authorization` (to BaSyx template endpoints) + +### PostgreSQL Database (Plugin) + +If desired, you can edit credentials in `docker-compose.yml`: +```yaml +POSTGRES_PASSWORD: admin +``` + +Update the plugin connection string to match. Edit `../shared/postgres/` scripts for custom schema/data. + +### Port Changes + +Modify port mappings in `docker-compose.yml`. Update corresponding environment variables in affected services. + +### Security and Production Notice + +Change all default passwords before any use beyond local development. Default credentials (postgres: admin, keycloak: admin) are for **development** only. + +In production, use TLS, a managed Keycloak instance, and a production-grade PostgreSQL database. Managing database security, encryption, and backups is the customer's responsibility. + +*Do not use this Docker Compose configuration in production.* + +--- + +## Troubleshooting + +**UI not loading:** `docker compose logs nginx` — Verify ports 8080, 8081, and 9090 are available. + +**Port conflicts:** `netstat -ano | findstr :8080` (Windows) to find conflicts. Change ports in `docker-compose.yml`. + +**Keycloak not ready:** `docker compose logs keycloak` — Wait for realm import to complete before other services start. + +**Startup issues:** Run `docker compose pull` followed by `docker compose up -d --force-recreate` + +**Database errors:** Check `docker compose ps` for health status. Verify connection strings match credentials. + +**Schema/init changed — recreate volumes:** +```bash +docker compose down -v +docker compose up -d +``` + +## Additional Resources + +- [TwinEngine Documentation](https://github.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/wiki) diff --git a/examples/securedExample/apiCollection/Aas Registry/Get All ShellDescriptors.bru b/examples/securedExample/apiCollection/Aas Registry/Get All ShellDescriptors.bru new file mode 100644 index 00000000..1fc57910 --- /dev/null +++ b/examples/securedExample/apiCollection/Aas Registry/Get All ShellDescriptors.bru @@ -0,0 +1,21 @@ +meta { + name: Get All ShellDescriptors + type: http + seq: 1 +} + +get { + url: {{DataEngineBaseUrl}}/shell-descriptors?limit&cursor + body: none + auth: inherit +} + +params:query { + limit: + cursor: +} + +settings { + encodeUrl: true + timeout: 0 +} diff --git a/examples/securedExample/apiCollection/Aas Registry/Get Shell Descriptor By Id - Product1.bru b/examples/securedExample/apiCollection/Aas Registry/Get Shell Descriptor By Id - Product1.bru new file mode 100644 index 00000000..549bcf82 --- /dev/null +++ b/examples/securedExample/apiCollection/Aas Registry/Get Shell Descriptor By Id - Product1.bru @@ -0,0 +1,25 @@ +meta { + name: Get Shell Descriptor By Id - Product1 + type: http + seq: 2 +} + +get { + url: {{DataEngineBaseUrl}}/shell-descriptors/:aasIdentifier + body: none + auth: inherit +} + +params:path { + aasIdentifier: {{aasIdentifier-1}} +} + +script:pre-request { + + +} + +settings { + encodeUrl: true + timeout: 0 +} diff --git a/examples/securedExample/apiCollection/Aas Registry/Get Shell Descriptor By Id - Product2.bru b/examples/securedExample/apiCollection/Aas Registry/Get Shell Descriptor By Id - Product2.bru new file mode 100644 index 00000000..f4ece148 --- /dev/null +++ b/examples/securedExample/apiCollection/Aas Registry/Get Shell Descriptor By Id - Product2.bru @@ -0,0 +1,25 @@ +meta { + name: Get Shell Descriptor By Id - Product2 + type: http + seq: 3 +} + +get { + url: {{DataEngineBaseUrl}}/shell-descriptors/:aasIdentifier + body: none + auth: inherit +} + +params:path { + aasIdentifier: {{aasIdentifier-2}} +} + +script:pre-request { + + +} + +settings { + encodeUrl: true + timeout: 0 +} diff --git a/examples/securedExample/apiCollection/Aas Registry/Get Shell Descriptor By Id - Product3.bru b/examples/securedExample/apiCollection/Aas Registry/Get Shell Descriptor By Id - Product3.bru new file mode 100644 index 00000000..69a7745c --- /dev/null +++ b/examples/securedExample/apiCollection/Aas Registry/Get Shell Descriptor By Id - Product3.bru @@ -0,0 +1,25 @@ +meta { + name: Get Shell Descriptor By Id - Product3 + type: http + seq: 4 +} + +get { + url: {{DataEngineBaseUrl}}/shell-descriptors/:aasIdentifier + body: none + auth: inherit +} + +params:path { + aasIdentifier: {{aasIdentifier-3}} +} + +script:pre-request { + + +} + +settings { + encodeUrl: true + timeout: 0 +} diff --git a/examples/securedExample/apiCollection/Aas Registry/folder.bru b/examples/securedExample/apiCollection/Aas Registry/folder.bru new file mode 100644 index 00000000..4d45dcd2 --- /dev/null +++ b/examples/securedExample/apiCollection/Aas Registry/folder.bru @@ -0,0 +1,8 @@ +meta { + name: Aas Registry + seq: 2 +} + +auth { + mode: inherit +} diff --git a/examples/securedExample/apiCollection/Aas Repository/Get All Shells.bru b/examples/securedExample/apiCollection/Aas Repository/Get All Shells.bru new file mode 100644 index 00000000..41f5adc0 --- /dev/null +++ b/examples/securedExample/apiCollection/Aas Repository/Get All Shells.bru @@ -0,0 +1,21 @@ +meta { + name: Get All Shells + type: http + seq: 1 +} + +get { + url: {{DataEngineBaseUrl}}/shells?limit&cursor + body: none + auth: inherit +} + +params:query { + limit: + cursor: +} + +settings { + encodeUrl: true + timeout: 0 +} diff --git a/examples/securedExample/apiCollection/Aas Repository/Get Shells By Asset Id - Product1.bru b/examples/securedExample/apiCollection/Aas Repository/Get Shells By Asset Id - Product1.bru new file mode 100644 index 00000000..2111cbaf --- /dev/null +++ b/examples/securedExample/apiCollection/Aas Repository/Get Shells By Asset Id - Product1.bru @@ -0,0 +1,31 @@ +meta { + name: Get Shells By Asset Id - Product1 + type: http + seq: 2 +} + +get { + url: {{DataEngineBaseUrl}}/shells?assetIds={{assetId-product1}}&limit&cursor + body: none + auth: inherit +} + +params:query { + assetIds: {{assetId-product1}} + limit: + cursor: +} + +settings { + encodeUrl: true + timeout: 0 +} + +docs { + Retrieves shells filtered by specific asset ID for Product1. + + The `assetIds` parameter must be a base64url-encoded JSON object: + {"name":"SerialNumber","value":"SN-FMABC1234-9804820"} + + Encoded value: eyJuYW1lIjoicHJvZHVjdDEuMCIsInZhbHVlIjoiTSZNIC0gMDAxIn0= +} diff --git a/examples/securedExample/apiCollection/Aas Repository/Get Shells By Asset Id - Product2.bru b/examples/securedExample/apiCollection/Aas Repository/Get Shells By Asset Id - Product2.bru new file mode 100644 index 00000000..51e7b7a8 --- /dev/null +++ b/examples/securedExample/apiCollection/Aas Repository/Get Shells By Asset Id - Product2.bru @@ -0,0 +1,31 @@ +meta { + name: Get Shells By Asset Id - Product2 + type: http + seq: 3 +} + +get { + url: {{DataEngineBaseUrl}}/shells?assetIds={{assetId-product2}}&limit&cursor + body: none + auth: inherit +} + +params:query { + assetIds: {{assetId-product2}} + limit: + cursor: +} + +settings { + encodeUrl: true + timeout: 0 +} + +docs { + Retrieves shells filtered by specific asset ID for Product2. + + The `assetIds` parameter must be a base64url-encoded JSON object: + {"name":"product2","value":"M&M - 003"} + + Encoded value: eyJuYW1lIjoicHJvZHVjdDIiLCJ2YWx1ZSI6Ik0mTSAtIDAwMyJ9 +} diff --git a/examples/securedExample/apiCollection/Aas Repository/Product1/Get Asset Information By Id.bru b/examples/securedExample/apiCollection/Aas Repository/Product1/Get Asset Information By Id.bru new file mode 100644 index 00000000..eb0df9fc --- /dev/null +++ b/examples/securedExample/apiCollection/Aas Repository/Product1/Get Asset Information By Id.bru @@ -0,0 +1,20 @@ +meta { + name: Get Asset Information By Id + type: http + seq: 1 +} + +get { + url: {{DataEngineBaseUrl}}/shells/:aasIdentifier/asset-information + body: none + auth: inherit +} + +params:path { + aasIdentifier: {{aasIdentifier-1}} +} + +settings { + encodeUrl: true + timeout: 0 +} diff --git a/examples/securedExample/apiCollection/Aas Repository/Product1/Get Shell By Id.bru b/examples/securedExample/apiCollection/Aas Repository/Product1/Get Shell By Id.bru new file mode 100644 index 00000000..2f49754b --- /dev/null +++ b/examples/securedExample/apiCollection/Aas Repository/Product1/Get Shell By Id.bru @@ -0,0 +1,20 @@ +meta { + name: Get Shell By Id + type: http + seq: 1 +} + +get { + url: {{DataEngineBaseUrl}}/shells/:aasIdentifier + body: none + auth: inherit +} + +params:path { + aasIdentifier: {{aasIdentifier-1}} +} + +settings { + encodeUrl: true + timeout: 0 +} diff --git a/examples/securedExample/apiCollection/Aas Repository/Product1/Get Submodel Ref By Id.bru b/examples/securedExample/apiCollection/Aas Repository/Product1/Get Submodel Ref By Id.bru new file mode 100644 index 00000000..fad39781 --- /dev/null +++ b/examples/securedExample/apiCollection/Aas Repository/Product1/Get Submodel Ref By Id.bru @@ -0,0 +1,25 @@ +meta { + name: Get Submodel Ref By Id + type: http + seq: 2 +} + +get { + url: {{DataEngineBaseUrl}}/shells/:aasIdentifier/submodel-refs?limit&cursor + body: none + auth: inherit +} + +params:query { + limit: + cursor: +} + +params:path { + aasIdentifier: {{aasIdentifier-1}} +} + +settings { + encodeUrl: true + timeout: 0 +} diff --git a/examples/securedExample/apiCollection/Aas Repository/Product1/folder.bru b/examples/securedExample/apiCollection/Aas Repository/Product1/folder.bru new file mode 100644 index 00000000..a64c644e --- /dev/null +++ b/examples/securedExample/apiCollection/Aas Repository/Product1/folder.bru @@ -0,0 +1,8 @@ +meta { + name: Product1 + seq: 1 +} + +auth { + mode: inherit +} diff --git a/examples/securedExample/apiCollection/Aas Repository/Product2/Get Asset Information By Id.bru b/examples/securedExample/apiCollection/Aas Repository/Product2/Get Asset Information By Id.bru new file mode 100644 index 00000000..72d5c9be --- /dev/null +++ b/examples/securedExample/apiCollection/Aas Repository/Product2/Get Asset Information By Id.bru @@ -0,0 +1,20 @@ +meta { + name: Get Asset Information By Id + type: http + seq: 1 +} + +get { + url: {{DataEngineBaseUrl}}/shells/:aasIdentifier/asset-information + body: none + auth: inherit +} + +params:path { + aasIdentifier: {{aasIdentifier-2}} +} + +settings { + encodeUrl: true + timeout: 0 +} diff --git a/examples/securedExample/apiCollection/Aas Repository/Product2/Get Shell By Id.bru b/examples/securedExample/apiCollection/Aas Repository/Product2/Get Shell By Id.bru new file mode 100644 index 00000000..e0901d98 --- /dev/null +++ b/examples/securedExample/apiCollection/Aas Repository/Product2/Get Shell By Id.bru @@ -0,0 +1,20 @@ +meta { + name: Get Shell By Id + type: http + seq: 2 +} + +get { + url: {{DataEngineBaseUrl}}/shells/:aasIdentifier + body: none + auth: inherit +} + +params:path { + aasIdentifier: {{aasIdentifier-2}} +} + +settings { + encodeUrl: true + timeout: 0 +} diff --git a/examples/securedExample/apiCollection/Aas Repository/Product2/Get Submodel Ref By Id.bru b/examples/securedExample/apiCollection/Aas Repository/Product2/Get Submodel Ref By Id.bru new file mode 100644 index 00000000..43cd8eae --- /dev/null +++ b/examples/securedExample/apiCollection/Aas Repository/Product2/Get Submodel Ref By Id.bru @@ -0,0 +1,25 @@ +meta { + name: Get Submodel Ref By Id + type: http + seq: 3 +} + +get { + url: {{DataEngineBaseUrl}}/shells/:aasIdentifier/submodel-refs?limit&cursor + body: none + auth: inherit +} + +params:query { + limit: + cursor: +} + +params:path { + aasIdentifier: {{aasIdentifier-2}} +} + +settings { + encodeUrl: true + timeout: 0 +} diff --git a/examples/securedExample/apiCollection/Aas Repository/Product2/folder.bru b/examples/securedExample/apiCollection/Aas Repository/Product2/folder.bru new file mode 100644 index 00000000..eef63239 --- /dev/null +++ b/examples/securedExample/apiCollection/Aas Repository/Product2/folder.bru @@ -0,0 +1,8 @@ +meta { + name: Product2 + seq: 2 +} + +auth { + mode: inherit +} diff --git a/examples/securedExample/apiCollection/Aas Repository/Product3/Get Asset Information By Id.bru b/examples/securedExample/apiCollection/Aas Repository/Product3/Get Asset Information By Id.bru new file mode 100644 index 00000000..62e52a24 --- /dev/null +++ b/examples/securedExample/apiCollection/Aas Repository/Product3/Get Asset Information By Id.bru @@ -0,0 +1,20 @@ +meta { + name: Get Asset Information By Id + type: http + seq: 1 +} + +get { + url: {{DataEngineBaseUrl}}/shells/:aasIdentifier/asset-information + body: none + auth: inherit +} + +params:path { + aasIdentifier: {{aasIdentifier-3}} +} + +settings { + encodeUrl: true + timeout: 0 +} diff --git a/examples/securedExample/apiCollection/Aas Repository/Product3/Get Shell By Id.bru b/examples/securedExample/apiCollection/Aas Repository/Product3/Get Shell By Id.bru new file mode 100644 index 00000000..1fe6f178 --- /dev/null +++ b/examples/securedExample/apiCollection/Aas Repository/Product3/Get Shell By Id.bru @@ -0,0 +1,20 @@ +meta { + name: Get Shell By Id + type: http + seq: 2 +} + +get { + url: {{DataEngineBaseUrl}}/shells/:aasIdentifier + body: none + auth: inherit +} + +params:path { + aasIdentifier: {{aasIdentifier-3}} +} + +settings { + encodeUrl: true + timeout: 0 +} diff --git a/examples/securedExample/apiCollection/Aas Repository/Product3/Get Submodel Ref By Id.bru b/examples/securedExample/apiCollection/Aas Repository/Product3/Get Submodel Ref By Id.bru new file mode 100644 index 00000000..cf736ec6 --- /dev/null +++ b/examples/securedExample/apiCollection/Aas Repository/Product3/Get Submodel Ref By Id.bru @@ -0,0 +1,25 @@ +meta { + name: Get Submodel Ref By Id + type: http + seq: 3 +} + +get { + url: {{DataEngineBaseUrl}}/shells/:aasIdentifier/submodel-refs?limit&cursor + body: none + auth: inherit +} + +params:query { + limit: + cursor: +} + +params:path { + aasIdentifier: {{aasIdentifier-3}} +} + +settings { + encodeUrl: true + timeout: 0 +} diff --git a/examples/securedExample/apiCollection/Aas Repository/Product3/folder.bru b/examples/securedExample/apiCollection/Aas Repository/Product3/folder.bru new file mode 100644 index 00000000..a102df28 --- /dev/null +++ b/examples/securedExample/apiCollection/Aas Repository/Product3/folder.bru @@ -0,0 +1,8 @@ +meta { + name: Product3 + seq: 3 +} + +auth { + mode: inherit +} diff --git a/examples/securedExample/apiCollection/Aas Repository/folder.bru b/examples/securedExample/apiCollection/Aas Repository/folder.bru new file mode 100644 index 00000000..3720e726 --- /dev/null +++ b/examples/securedExample/apiCollection/Aas Repository/folder.bru @@ -0,0 +1,8 @@ +meta { + name: Aas Repository + seq: 3 +} + +auth { + mode: inherit +} diff --git a/examples/securedExample/apiCollection/Discovery/Search Shells By Asset Link - Multiple Filters.bru b/examples/securedExample/apiCollection/Discovery/Search Shells By Asset Link - Multiple Filters.bru new file mode 100644 index 00000000..196ea4a7 --- /dev/null +++ b/examples/securedExample/apiCollection/Discovery/Search Shells By Asset Link - Multiple Filters.bru @@ -0,0 +1,38 @@ +meta { + name: Search Shells By Asset Link - Multiple Filters + type: http + seq: 2 +} + +post { + url: {{DataEngineBaseUrl}}/lookup/shellsByAssetLink?limit&cursor + body: json + auth: inherit +} + +params:query { + limit: + cursor: +} + +body:json { + [ + { + "name": "SerialNumber", + "value": "SN-FMABC1234-9804820" + }, + { + "name": "BatchId", + "value": "BATCH-2022-001" + }, + { + "name": "LotNumber", + "value": "LOT-DE-77881" + } + ] +} + +settings { + encodeUrl: true + timeout: 0 +} diff --git a/examples/securedExample/apiCollection/Discovery/Search Shells By Asset Link.bru b/examples/securedExample/apiCollection/Discovery/Search Shells By Asset Link.bru new file mode 100644 index 00000000..f6612e3a --- /dev/null +++ b/examples/securedExample/apiCollection/Discovery/Search Shells By Asset Link.bru @@ -0,0 +1,30 @@ +meta { + name: Search Shells By Asset Link + type: http + seq: 1 +} + +post { + url: {{DataEngineBaseUrl}}/lookup/shellsByAssetLink?limit&cursor + body: json + auth: inherit +} + +params:query { + limit: + cursor: +} + +body:json { + [ + { + "name": "SerialNumber", + "value": "SN-TMABC1680-980476" + } + ] +} + +settings { + encodeUrl: true + timeout: 0 +} diff --git a/examples/securedExample/apiCollection/Discovery/folder.bru b/examples/securedExample/apiCollection/Discovery/folder.bru new file mode 100644 index 00000000..2eef2bd6 --- /dev/null +++ b/examples/securedExample/apiCollection/Discovery/folder.bru @@ -0,0 +1,8 @@ +meta { + name: Discovery + seq: 5 +} + +auth { + mode: inherit +} diff --git a/examples/securedExample/apiCollection/README.md b/examples/securedExample/apiCollection/README.md new file mode 100644 index 00000000..8157859d --- /dev/null +++ b/examples/securedExample/apiCollection/README.md @@ -0,0 +1,160 @@ +# Bruno API Testing Setup – DataEngine (.NET Backend) + +## Overview + +This directory contains the Bruno collection and instructions to test the **AAS.TwinEngine.DataEngine** .NET API using Bruno. The collection includes pre-configured requests and environments to exercise the DataEngine API and its plugin-based data sources. + +--- + +## Quick Summary + +| Item | Description | +|--------------------------|-----------------------------------------------------| +| **API** | `AAS.TwinEngine.DataEngine` (.NET) | +| **Testing Tool** | [Bruno](https://www.usebruno.com/downloads) | +| **Default API URL** | `http://localhost:8080` | +| **SDK Required** | .NET 8 (recommended) | +| **Run docker compose file** | Run `docker-compose-up` [form AasTwin.DataEngine](../README.md) | + +--- + +## Prerequisites + +1. **Install Bruno** + + * Download: [https://www.usebruno.com/downloads](https://www.usebruno.com/downloads) + * Platforms: Windows, macOS, Linux + +2. **Install .NET SDK** + + * Recommended: **.NET 8** (install from Microsoft docs) + +3. **Install docker** + +--- + +## Running the services + + +### 1. Run docker compose file + +Before starting , run twinengine environmnet with dpp-plugin. +[click here for getting starated with docker-compose](../README.md) + + +## Bruno Collection — Quick Start + +1. Open Bruno +2. `Collection -> Open Collection` and choose the Bruno collection folder (`apiCollection`) from the AasTwin.DataEngine repository +3. From the top-right environment dropdown select an environment: `local` +4. Expand folders to find requests, select a request and click **Send** +5. Inspect the request/response in the right panel + +--- + +## Bruno environment & collection variables + +The collection includes a set of environment/collection variables you can edit to point the requests at your local or dev instance. +**Enter these variables in plain text — the collection’s Pre-request script will automatically change value to Base64-encode.** + +| Variable name | Purpose | Example value | +| ------------------------------------------- | ---------------------------------------------------------- | -------------------------------------------------------------------------------------------------- | +| `DataEngineBaseUrl` | Base URL for DataEngine API | `http://localhost:8080` | +| `productId-1` | Product ID for first asset | `000-001` | +| `productId-2` | Product ID for second asset | `000-002` | +| `productId-3` | Product ID for third asset | `001-001` | +| `aasIdentifier-1` | AAS identifier (auto-encoded to Base64 by script) | `https://mm-software.com/ids/aas/000-001` | +| `aasIdentifier-2` | AAS identifier (auto-encoded to Base64 by script) | `https://mm-software.com/ids/aas/000-002` | +| `aasIdentifier-3` | AAS identifier (auto-encoded to Base64 by script) | `https://mm-software.com/ids/aas/001-001` | +| `submodelIdentifierMaintenanceInstructions-1` | Submodel identifier for MaintenanceInstructions (auto-encoded) | `https://mm-software.com/submodel/000-001/MaintenanceInstructions` | +| `submodelIdentifierNameplate-1` | Submodel identifier for Nameplate (auto-encoded) | `https://mm-software.com/submodel/000-001/Nameplate` | +| `submodelIdentifierTechnicalData-1` | Submodel identifier for TechnicalData (auto-encoded) | `https://mm-software.com/submodel/000-001/TechnicalData` | +| `submodelIdentifierCarbonFootprint-1` | Submodel identifier for CarbonFootprint (auto-encoded) | `https://mm-software.com/submodel/000-001/CarbonFootprint` | +| `submodelIdentifierHandoverDocumentation-1` | Submodel identifier for HandoverDocumentation (auto-encoded) | `https://mm-software.com/submodel/000-001/HandoverDocumentation` | + +**Note:** All identifier variables (aasIdentifier-*, submodelIdentifier-*) are automatically Base64-encoded by the collection's pre-request script. Enter plain URLs as shown above. + +--- + +## Default api-test configuration + +* The default configuration includes four shell descriptors with these IDs: + + * `https://mm-software.com/ids/aas/000-001` + * `https://mm-software.com/ids/aas/000-002` + * `https://mm-software.com/ids/aas/001-001` + +* Default submodel templates (under `../aas`): + + * `MaintenanceInstructions` + * `Nameplate` + * `HandoverDocumentation` + * `CarbonFootprint` + * `TechnicalData` + +* Default shell template used by all 5 shells: + +```json +{ + "id": "https://mm-software.com/aas/aasTemplate", + "assetInformation": { + "assetKind": "Instance" + }, + "submodels": [ + { + "type": "ModelReference", + "keys": [ + { "type": "Submodel", "value": "Nameplate" } + ] + }, + { + "type": "ModelReference", + "keys": [ + { "type": "Submodel", "value": "MaintenanceInstructions" } + ] + }, + { + "type": "ModelReference", + "keys": [ + { "type": "Submodel", "value": "HandoverDocumentation" } + ] + }, + { + "type": "ModelReference", + "keys": [ + { "type": "Submodel", "value": "CarbonFootprint" } + ] + }, + { + "type": "ModelReference", + "keys": [ + { "type": "Submodel", "value": "TechnicalData" } + ] + } + ], + "modelType": "AssetAdministrationShell" +} +``` + +--- + +## Useful requests & folders + +* **Aas Registry** — endpoints to get all ShellDescriptors and ShellDescriptor by id +* **Aas Repository** — endpoints to get Shell by id, SubmodelRef by id, Asset Information by id +* **Submodel Registry** — endpoints to get SubmodelDescriptor by id +* **Submodel Repository** — endpoints to get submodel, submodelElement, and serialization + +(Each Bruno request contains example payloads.) + +--- + +## Troubleshooting + +#### Bruno shows `SSL/TLS handshake failed` + +- Run `dotnet dev-certs https --trust` +- Ensure plugin and API endpoints match port and schema (`https://`) + + +--- diff --git a/examples/securedExample/apiCollection/Submodel Registry/Get Submodel Descriptor By Id - CarbonFootprint.bru b/examples/securedExample/apiCollection/Submodel Registry/Get Submodel Descriptor By Id - CarbonFootprint.bru new file mode 100644 index 00000000..77916baf --- /dev/null +++ b/examples/securedExample/apiCollection/Submodel Registry/Get Submodel Descriptor By Id - CarbonFootprint.bru @@ -0,0 +1,20 @@ +meta { + name: Get Submodel Descriptor By Id - CarbonFootprint + type: http + seq: 3 +} + +get { + url: {{DataEngineBaseUrl}}/submodel-descriptors/:submodelIdentifier + body: none + auth: inherit +} + +params:path { + submodelIdentifier: {{submodelIdentifierCarbonFootprint-1}} +} + +settings { + encodeUrl: true + timeout: 0 +} diff --git a/examples/securedExample/apiCollection/Submodel Registry/Get Submodel Descriptor By Id - HandoverDocumentation.bru b/examples/securedExample/apiCollection/Submodel Registry/Get Submodel Descriptor By Id - HandoverDocumentation.bru new file mode 100644 index 00000000..66fb37ac --- /dev/null +++ b/examples/securedExample/apiCollection/Submodel Registry/Get Submodel Descriptor By Id - HandoverDocumentation.bru @@ -0,0 +1,20 @@ +meta { + name: Get Submodel Descriptor By Id - HandoverDocumentation + type: http + seq: 4 +} + +get { + url: {{DataEngineBaseUrl}}/submodel-descriptors/:submodelIdentifier + body: none + auth: inherit +} + +params:path { + submodelIdentifier: {{submodelIdentifierHandoverDocumentation-1}} +} + +settings { + encodeUrl: true + timeout: 0 +} diff --git a/examples/securedExample/apiCollection/Submodel Registry/Get Submodel Descriptor By Id - MaintenanceInstructions.bru b/examples/securedExample/apiCollection/Submodel Registry/Get Submodel Descriptor By Id - MaintenanceInstructions.bru new file mode 100644 index 00000000..638c19b6 --- /dev/null +++ b/examples/securedExample/apiCollection/Submodel Registry/Get Submodel Descriptor By Id - MaintenanceInstructions.bru @@ -0,0 +1,20 @@ +meta { + name: Get Submodel Descriptor By Id - MaintenanceInstructions + type: http + seq: 1 +} + +get { + url: {{DataEngineBaseUrl}}/submodel-descriptors/:submodelIdentifier + body: none + auth: inherit +} + +params:path { + submodelIdentifier: {{submodelIdentifierMaintenanceInstructions-1}} +} + +settings { + encodeUrl: true + timeout: 0 +} diff --git a/examples/securedExample/apiCollection/Submodel Registry/Get Submodel Descriptor By Id - Nameplate.bru b/examples/securedExample/apiCollection/Submodel Registry/Get Submodel Descriptor By Id - Nameplate.bru new file mode 100644 index 00000000..08b73d4d --- /dev/null +++ b/examples/securedExample/apiCollection/Submodel Registry/Get Submodel Descriptor By Id - Nameplate.bru @@ -0,0 +1,20 @@ +meta { + name: Get Submodel Descriptor By Id - Nameplate + type: http + seq: 2 +} + +get { + url: {{DataEngineBaseUrl}}/submodel-descriptors/:submodelIdentifier + body: none + auth: inherit +} + +params:path { + submodelIdentifier: {{submodelIdentifierNameplate-1}} +} + +settings { + encodeUrl: true + timeout: 0 +} diff --git a/examples/securedExample/apiCollection/Submodel Registry/Get Submodel Descriptor By Id - TechnicalData.bru b/examples/securedExample/apiCollection/Submodel Registry/Get Submodel Descriptor By Id - TechnicalData.bru new file mode 100644 index 00000000..e2b1dfc4 --- /dev/null +++ b/examples/securedExample/apiCollection/Submodel Registry/Get Submodel Descriptor By Id - TechnicalData.bru @@ -0,0 +1,20 @@ +meta { + name: Get Submodel Descriptor By Id - TechnicalData + type: http + seq: 5 +} + +get { + url: {{DataEngineBaseUrl}}/submodel-descriptors/:submodelIdentifier + body: none + auth: inherit +} + +params:path { + submodelIdentifier: {{submodelIdentifierTechnicalData-1}} +} + +settings { + encodeUrl: true + timeout: 0 +} diff --git a/examples/securedExample/apiCollection/Submodel Registry/folder.bru b/examples/securedExample/apiCollection/Submodel Registry/folder.bru new file mode 100644 index 00000000..bd3aeb4c --- /dev/null +++ b/examples/securedExample/apiCollection/Submodel Registry/folder.bru @@ -0,0 +1,8 @@ +meta { + name: Submodel Registry + seq: 4 +} + +auth { + mode: inherit +} diff --git a/examples/securedExample/apiCollection/Submodel Repository/Serialization/Get appropriate serialization - Product1.bru b/examples/securedExample/apiCollection/Submodel Repository/Serialization/Get appropriate serialization - Product1.bru new file mode 100644 index 00000000..141bf883 --- /dev/null +++ b/examples/securedExample/apiCollection/Submodel Repository/Serialization/Get appropriate serialization - Product1.bru @@ -0,0 +1,26 @@ +meta { + name: Get appropriate serialization - Product1 + type: http + seq: 1 +} + +get { + url: {{DataEngineBaseUrl}}/serialization?aasIds={{aasIdentifier-1}}&submodelIds={{submodelIdentifierMaintenanceInstructions-1}}&submodelIds={{submodelIdentifierNameplate-1}}&submodelIds={{submodelIdentifierCarbonFootprint-1}}&submodelIds={{submodelIdentifierHandoverDocumentation-1}}&submodelIds={{submodelIdentifierTechnicalData-1}}&includeConceptDescriptions=false + body: none + auth: inherit +} + +params:query { + aasIds: {{aasIdentifier-1}} + submodelIds: {{submodelIdentifierMaintenanceInstructions-1}} + submodelIds: {{submodelIdentifierNameplate-1}} + submodelIds: {{submodelIdentifierCarbonFootprint-1}} + submodelIds: {{submodelIdentifierHandoverDocumentation-1}} + submodelIds: {{submodelIdentifierTechnicalData-1}} + includeConceptDescriptions: false +} + +settings { + encodeUrl: true + timeout: 0 +} diff --git a/examples/securedExample/apiCollection/Submodel Repository/Serialization/folder.bru b/examples/securedExample/apiCollection/Submodel Repository/Serialization/folder.bru new file mode 100644 index 00000000..d303a468 --- /dev/null +++ b/examples/securedExample/apiCollection/Submodel Repository/Serialization/folder.bru @@ -0,0 +1,8 @@ +meta { + name: Serialization + seq: 3 +} + +auth { + mode: inherit +} diff --git a/examples/securedExample/apiCollection/Submodel Repository/Submodel Element/Get Submodel Element - CarbonFootprint.bru b/examples/securedExample/apiCollection/Submodel Repository/Submodel Element/Get Submodel Element - CarbonFootprint.bru new file mode 100644 index 00000000..9ee3129a --- /dev/null +++ b/examples/securedExample/apiCollection/Submodel Repository/Submodel Element/Get Submodel Element - CarbonFootprint.bru @@ -0,0 +1,21 @@ +meta { + name: Get Submodel Element - CarbonFootprint + type: http + seq: 3 +} + +get { + url: {{DataEngineBaseUrl}}/submodels/:submodelIdentifier/submodel-elements/:idShortPath + body: none + auth: inherit +} + +params:path { + submodelIdentifier: {{submodelIdentifierCarbonFootprint-1}} + idShortPath: ProductCarbonFootprints[0].LifeCyclePhases[0] +} + +settings { + encodeUrl: true + timeout: 0 +} diff --git a/examples/securedExample/apiCollection/Submodel Repository/Submodel Element/Get Submodel Element - ContactInfo.bru b/examples/securedExample/apiCollection/Submodel Repository/Submodel Element/Get Submodel Element - ContactInfo.bru new file mode 100644 index 00000000..1d6c6bd5 --- /dev/null +++ b/examples/securedExample/apiCollection/Submodel Repository/Submodel Element/Get Submodel Element - ContactInfo.bru @@ -0,0 +1,21 @@ +meta { + name: Get Submodel Element - MaintenanceInstructionsInfo + type: http + seq: 1 +} + +get { + url: {{DataEngineBaseUrl}}/submodels/:submodelIdentifier/submodel-elements/:idShortPath + body: none + auth: inherit +} + +params:path { + submodelIdentifier: {{submodelIdentifierMaintenanceInstructions-1}} + idShortPath: MaintenanceToolList%255B0%255D.OrderCodeToolOfManufacturer +} + +settings { + encodeUrl: true + timeout: 0 +} diff --git a/examples/securedExample/apiCollection/Submodel Repository/Submodel Element/Get Submodel Element - HandoverDocumentation.bru b/examples/securedExample/apiCollection/Submodel Repository/Submodel Element/Get Submodel Element - HandoverDocumentation.bru new file mode 100644 index 00000000..be59fe65 --- /dev/null +++ b/examples/securedExample/apiCollection/Submodel Repository/Submodel Element/Get Submodel Element - HandoverDocumentation.bru @@ -0,0 +1,21 @@ +meta { + name: Get Submodel Element - HandoverDocumentation + type: http + seq: 5 +} + +get { + url: {{DataEngineBaseUrl}}/submodels/:submodelIdentifier/submodel-elements/:idShortPath + body: none + auth: inherit +} + +params:path { + submodelIdentifier: {{submodelIdentifierHandoverDocumentation-1}} + idShortPath: Documents[0].DocumentClassifications[1].ClassName +} + +settings { + encodeUrl: true + timeout: 0 +} diff --git a/examples/securedExample/apiCollection/Submodel Repository/Submodel Element/Get Submodel Element - Nameplate.bru b/examples/securedExample/apiCollection/Submodel Repository/Submodel Element/Get Submodel Element - Nameplate.bru new file mode 100644 index 00000000..52030391 --- /dev/null +++ b/examples/securedExample/apiCollection/Submodel Repository/Submodel Element/Get Submodel Element - Nameplate.bru @@ -0,0 +1,21 @@ +meta { + name: Get Submodel Element - Nameplate + type: http + seq: 2 +} + +get { + url: {{DataEngineBaseUrl}}/submodels/:submodelIdentifier/submodel-elements/:idShortPath + body: none + auth: inherit +} + +params:path { + submodelIdentifier: {{submodelIdentifierNameplate-1}} + idShortPath: ManufacturerName +} + +settings { + encodeUrl: true + timeout: 0 +} diff --git a/examples/securedExample/apiCollection/Submodel Repository/Submodel Element/Get Submodel Element - TechnicalData.bru b/examples/securedExample/apiCollection/Submodel Repository/Submodel Element/Get Submodel Element - TechnicalData.bru new file mode 100644 index 00000000..34ec067f --- /dev/null +++ b/examples/securedExample/apiCollection/Submodel Repository/Submodel Element/Get Submodel Element - TechnicalData.bru @@ -0,0 +1,21 @@ +meta { + name: Get Submodel Element - TechnicalData + type: http + seq: 4 +} + +get { + url: {{DataEngineBaseUrl}}/submodels/:submodelIdentifier/submodel-elements/:idShortPath + body: none + auth: inherit +} + +params:path { + submodelIdentifier: {{submodelIdentifierTechnicalData-1}} + idShortPath: GeneralInformation.ProductImage +} + +settings { + encodeUrl: true + timeout: 0 +} diff --git a/examples/securedExample/apiCollection/Submodel Repository/Submodel Element/folder.bru b/examples/securedExample/apiCollection/Submodel Repository/Submodel Element/folder.bru new file mode 100644 index 00000000..04497c42 --- /dev/null +++ b/examples/securedExample/apiCollection/Submodel Repository/Submodel Element/folder.bru @@ -0,0 +1,8 @@ +meta { + name: Submodel Element + seq: 2 +} + +auth { + mode: inherit +} diff --git a/examples/securedExample/apiCollection/Submodel Repository/Submodel/Get Submodel - HandoverDocumentation.bru b/examples/securedExample/apiCollection/Submodel Repository/Submodel/Get Submodel - HandoverDocumentation.bru new file mode 100644 index 00000000..07c7652a --- /dev/null +++ b/examples/securedExample/apiCollection/Submodel Repository/Submodel/Get Submodel - HandoverDocumentation.bru @@ -0,0 +1,20 @@ +meta { + name: Get Submodel - HandoverDocumentation + type: http + seq: 5 +} + +get { + url: {{DataEngineBaseUrl}}/submodels/:submodelIdentifier + body: none + auth: inherit +} + +params:path { + submodelIdentifier: {{submodelIdentifierHandoverDocumentation-1}} +} + +settings { + encodeUrl: true + timeout: 0 +} diff --git a/examples/securedExample/apiCollection/Submodel Repository/Submodel/Get Submodel - MaintenanceInstructions.bru b/examples/securedExample/apiCollection/Submodel Repository/Submodel/Get Submodel - MaintenanceInstructions.bru new file mode 100644 index 00000000..c2f9e0c9 --- /dev/null +++ b/examples/securedExample/apiCollection/Submodel Repository/Submodel/Get Submodel - MaintenanceInstructions.bru @@ -0,0 +1,20 @@ +meta { + name: Get Submodel - MaintenanceInstructions + type: http + seq: 1 +} + +get { + url: {{DataEngineBaseUrl}}/submodels/:submodelIdentifier + body: none + auth: inherit +} + +params:path { + submodelIdentifier: {{submodelIdentifierMaintenanceInstructions-1}} +} + +settings { + encodeUrl: true + timeout: 0 +} diff --git a/examples/securedExample/apiCollection/Submodel Repository/Submodel/Get Submodel - Nameplate.bru b/examples/securedExample/apiCollection/Submodel Repository/Submodel/Get Submodel - Nameplate.bru new file mode 100644 index 00000000..f69644bc --- /dev/null +++ b/examples/securedExample/apiCollection/Submodel Repository/Submodel/Get Submodel - Nameplate.bru @@ -0,0 +1,20 @@ +meta { + name: Get Submodel - Nameplate + type: http + seq: 2 +} + +get { + url: {{DataEngineBaseUrl}}/submodels/:submodelIdentifier/ + body: none + auth: inherit +} + +params:path { + submodelIdentifier: {{submodelIdentifierNameplate-1}} +} + +settings { + encodeUrl: true + timeout: 0 +} diff --git a/examples/securedExample/apiCollection/Submodel Repository/Submodel/Get Submodel - TechnicalData.bru b/examples/securedExample/apiCollection/Submodel Repository/Submodel/Get Submodel - TechnicalData.bru new file mode 100644 index 00000000..2a645ba4 --- /dev/null +++ b/examples/securedExample/apiCollection/Submodel Repository/Submodel/Get Submodel - TechnicalData.bru @@ -0,0 +1,20 @@ +meta { + name: Get Submodel - TechnicalData + type: http + seq: 3 +} + +get { + url: {{DataEngineBaseUrl}}/submodels/:submodelIdentifier + body: none + auth: inherit +} + +params:path { + submodelIdentifier: {{submodelIdentifierTechnicalData-1}} +} + +settings { + encodeUrl: true + timeout: 0 +} diff --git a/examples/securedExample/apiCollection/Submodel Repository/Submodel/Get Submodel -CarbonFootprint.bru b/examples/securedExample/apiCollection/Submodel Repository/Submodel/Get Submodel -CarbonFootprint.bru new file mode 100644 index 00000000..847d0e2e --- /dev/null +++ b/examples/securedExample/apiCollection/Submodel Repository/Submodel/Get Submodel -CarbonFootprint.bru @@ -0,0 +1,15 @@ +meta { + name: Get Submodel - CarbonFootprint + type: http + seq: 4 +} + +get { + url: {{DataEngineBaseUrl}}/submodels/:submodelIdentifier + body: none + auth: inherit +} + +params:path { + submodelIdentifier: {{submodelIdentifierCarbonFootprint-1}} +} diff --git a/examples/securedExample/apiCollection/Submodel Repository/Submodel/folder.bru b/examples/securedExample/apiCollection/Submodel Repository/Submodel/folder.bru new file mode 100644 index 00000000..03deb2ed --- /dev/null +++ b/examples/securedExample/apiCollection/Submodel Repository/Submodel/folder.bru @@ -0,0 +1,8 @@ +meta { + name: Submodel + seq: 1 +} + +auth { + mode: inherit +} diff --git a/examples/securedExample/apiCollection/Submodel Repository/folder.bru b/examples/securedExample/apiCollection/Submodel Repository/folder.bru new file mode 100644 index 00000000..a5f17145 --- /dev/null +++ b/examples/securedExample/apiCollection/Submodel Repository/folder.bru @@ -0,0 +1,8 @@ +meta { + name: Submodel Repository + seq: 5 +} + +auth { + mode: inherit +} diff --git a/examples/securedExample/apiCollection/bruno.json b/examples/securedExample/apiCollection/bruno.json new file mode 100644 index 00000000..b8aef25b --- /dev/null +++ b/examples/securedExample/apiCollection/bruno.json @@ -0,0 +1,9 @@ +{ + "version": "1", + "name": "Secured-DataEngine-DPPPlugin", + "type": "collection", + "ignore": [ + "node_modules", + ".git" + ] +} \ No newline at end of file diff --git a/examples/securedExample/apiCollection/collection.bru b/examples/securedExample/apiCollection/collection.bru new file mode 100644 index 00000000..e57b6bf6 --- /dev/null +++ b/examples/securedExample/apiCollection/collection.bru @@ -0,0 +1,42 @@ +vars:pre-request { + aasIdentifier-1: https://mm-software.com/ids/aas/{{productId-1}} + submodelIdentifierMaintenanceInstructions-1: https://mm-software.com/submodel/{{productId-1}}/MaintenanceInstructions + submodelIdentifierNameplate-1: https://mm-software.com/submodel/{{productId-1}}/Nameplate + aasIdentifier-2: https://mm-software.com/ids/aas/{{productId-2}} + aasIdentifier-3: https://mm-software.com/ids/aas/{{productId-3}} + submodelIdentifierTechnicalData-1: https://mm-software.com/submodel/{{productId-1}}/TechnicalData + submodelIdentifierCarbonFootprint-1: https://mm-software.com/submodel/{{productId-1}}/CarbonFootprint + submodelIdentifierHandoverDocumentation-1: https://mm-software.com/submodel/{{productId-1}}/HandoverDocumentation + productId-1: 000-001 + productId-2: 000-002 + productId-3: 001-001 + assetId-product1: {"name":"SerialNumber","value":"SN-FMABC1234-9804820"} + assetId-product2: {"name":"SerialNumber","value":"SN-FMABC1238-9804821"} +} + +script:pre-request { + function b64EncodeUnicode(str){ + return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, (m,p)=>String.fromCharCode('0x'+p))); + } + + const varsToEncode = [ + 'aasIdentifier-1', + 'aasIdentifier-2', + 'aasIdentifier-3', + 'submodelIdentifierMaintenanceInstructions-1', + 'submodelIdentifierNameplate-1', + 'submodelIdentifierHandoverDocumentation-1', + 'submodelIdentifierTechnicalData-1', + 'submodelIdentifierCarbonFootprint-1', + 'assetId-product1', + 'assetId-product2' + ]; + + varsToEncode.forEach(name => { + const plain = bru.getCollectionVar(name); + const encoded = b64EncodeUnicode(plain); + bru.setVar(name, encoded); + }); + + +} diff --git a/examples/securedExample/apiCollection/environments/local.bru b/examples/securedExample/apiCollection/environments/local.bru new file mode 100644 index 00000000..5987017c --- /dev/null +++ b/examples/securedExample/apiCollection/environments/local.bru @@ -0,0 +1,3 @@ +vars { + DataEngineBaseUrl: http://localhost:8080 +} diff --git a/examples/securedExample/docker-compose.yml b/examples/securedExample/docker-compose.yml new file mode 100644 index 00000000..6e3f12dc --- /dev/null +++ b/examples/securedExample/docker-compose.yml @@ -0,0 +1,296 @@ +networks: + twinengine-network: + name: twinengine-network + +volumes: + postgres-data: + +services: + nginx: + image: nginx:trixie-perl + container_name: nginx + ports: + - "8080:80" + volumes: + - ../shared/nginx/html:/usr/share/nginx/html + - ../shared/nginx/default.conf.template:/etc/nginx/templates/default.conf.template + restart: always + depends_on: + template-repository-registry: + condition: service_started + networks: + - twinengine-network + + twinengine-dataengine: + image: ghcr.io/aas-twinengine/dataengine:1.0.0 + container_name: twinengine-dataengine + depends_on: + dpp-plugin: + condition: service_started + keycloak-healthcheck: + condition: service_completed_successfully + restart: always + environment: + - General__DataEngineRepositoryBaseUrl=http://localhost:8080 + - General__CustomerDomainUrl=https://mm-software.com + - Plugins__Instances__0__Name=RelationalDatabasePlugin + - Plugins__Instances__0__baseUrl=http://dpp-plugin:8080 + - Plugins__Instances__0__healthEndpoint=/healthz + - Plugins__MultiLanguageProperty__DefaultLanguages__0=en + - Plugins__MultiLanguageProperty__DefaultLanguages__1=de + - TemplateManagement__TemplateMappingRules__SubmodelTemplateMappings__0__templateId=https://admin-shell.io/idta/SubmodelTemplate/TechnicalData/2/0 + - TemplateManagement__TemplateMappingRules__SubmodelTemplateMappings__0__pattern__0=TechnicalData + - TemplateManagement__TemplateMappingRules__SubmodelTemplateMappings__1__templateId=https://admin-shell.io/idta/SubmodelTemplate/DigitalNameplate/3/0 + - TemplateManagement__TemplateMappingRules__SubmodelTemplateMappings__1__pattern__0=Nameplate + - TemplateManagement__TemplateMappingRules__SubmodelTemplateMappings__2__templateId=https://admin-shell.io/idta/SubmodelTemplate/MaintenanceInstructions/1/0 + - TemplateManagement__TemplateMappingRules__SubmodelTemplateMappings__2__pattern__0=MaintenanceInstructions + - TemplateManagement__TemplateMappingRules__SubmodelTemplateMappings__3__templateId=https://admin-shell.io/idta/SubmodelTemplate/CarbonFootprint/1/0 + - TemplateManagement__TemplateMappingRules__SubmodelTemplateMappings__3__pattern__0=CarbonFootprint + - TemplateManagement__TemplateMappingRules__SubmodelTemplateMappings__4__templateId=https://admin-shell.io/idta/SubmodelTemplate/HandoverDocumentation/2/0 + - TemplateManagement__TemplateMappingRules__SubmodelTemplateMappings__4__pattern__0=HandoverDocumentation + - TemplateManagement__TemplateMappingRules__ShellTemplateMappings__0__templateId=https://mm-software.com/aas/aasTemplate + - TemplateManagement__TemplateMappingRules__ShellTemplateMappings__0__pattern__0= + - TemplateManagement__TemplateMappingRules__AasIdExtractionRules__0__Strategy=Split + - TemplateManagement__TemplateMappingRules__AasIdExtractionRules__0__Pattern=/ + - TemplateManagement__TemplateMappingRules__AasIdExtractionRules__0__Index=5 + - TemplateManagement__AasTemplateRepository__Name=AasTemplateRepository + - TemplateManagement__AasTemplateRepository__baseUrl=http://template-repository-registry:8082 + - TemplateManagement__AasTemplateRepository__headerMappings__0__source=Authorization + - TemplateManagement__AasTemplateRepository__headerMappings__0__target=Authorization + - TemplateManagement__AasTemplateRepository__headerMappings__0__required=false + - TemplateManagement__AasTemplateRepository__healthEndpoint=/health + - TemplateManagement__SubmodelTemplateRepository__Name=SubmodelTemplateRepository + - TemplateManagement__SubmodelTemplateRepository__baseUrl=http://template-repository-registry:8082 + - TemplateManagement__SubmodelTemplateRepository__headerMappings__0__source=Authorization + - TemplateManagement__SubmodelTemplateRepository__headerMappings__0__target=Authorization + - TemplateManagement__SubmodelTemplateRepository__headerMappings__0__required=false + - TemplateManagement__SubmodelTemplateRepository__healthEndpoint=/health + - TemplateManagement__ConceptDescriptionTemplateRepository__Name=ConceptDescriptionTemplateRepository + - TemplateManagement__ConceptDescriptionTemplateRepository__baseUrl=http://template-repository-registry:8082 + - TemplateManagement__ConceptDescriptionTemplateRepository__headerMappings__0__source=Authorization + - TemplateManagement__ConceptDescriptionTemplateRepository__headerMappings__0__target=Authorization + - TemplateManagement__ConceptDescriptionTemplateRepository__headerMappings__0__required=false + - TemplateManagement__ConceptDescriptionTemplateRepository__healthEndpoint=/health + - TemplateManagement__AasTemplateRegistry__Name=AasTemplateRegistry + - TemplateManagement__AasTemplateRegistry__baseUrl=http://template-repository-registry:8082 + - TemplateManagement__AasTemplateRegistry__headerMappings__0__source=Authorization + - TemplateManagement__AasTemplateRegistry__headerMappings__0__target=Authorization + - TemplateManagement__AasTemplateRegistry__headerMappings__0__required=false + - TemplateManagement__AasTemplateRegistry__healthEndpoint=/health + - TemplateManagement__SubmodelTemplateRegistry__Name=SubmodelTemplateRegistry + - TemplateManagement__SubmodelTemplateRegistry__baseUrl=http://template-repository-registry:8082 + - TemplateManagement__SubmodelTemplateRegistry__headerMappings__0__source=Authorization + - TemplateManagement__SubmodelTemplateRegistry__headerMappings__0__target=Authorization + - TemplateManagement__SubmodelTemplateRegistry__headerMappings__0__required=false + - TemplateManagement__SubmodelTemplateRegistry__healthEndpoint=/health + networks: + - twinengine-network + + dpp-plugin: + image: ghcr.io/aas-twinengine/plugindpp:1.0.0 + container_name: dpp-plugin + depends_on: + postgres: + condition: service_healthy + restart: always + environment: + - Semantics__IndexContextPrefix=_aastwinengineindex_ + - Capabilities__HasShellDescriptor=true + - Capabilities__HasAssetInformation=true + - Capabilities__HasAssetIdSearch=true + - RelationalDatabaseConfiguration__ConnectionString=Host=postgres;Port=5432;Database=twinengine;Username=postgres;Password=admin + - ExtractionRules__SubmodelNameExtractionRules__0__SubmodelName=NamePlate + - ExtractionRules__SubmodelNameExtractionRules__0__pattern__0=Nameplate + - ExtractionRules__SubmodelNameExtractionRules__0__pattern__1=NamePlate + - ExtractionRules__SubmodelNameExtractionRules__1__SubmodelName=MaintenanceInstructions + - ExtractionRules__SubmodelNameExtractionRules__1__pattern__0=MaintenanceInstructions + - ExtractionRules__SubmodelNameExtractionRules__1__pattern__1=MaintenanceInstruction + - ExtractionRules__SubmodelNameExtractionRules__2__SubmodelName=HandoverDocumentation + - ExtractionRules__SubmodelNameExtractionRules__2__pattern__0=HandoverDocumentation + - ExtractionRules__SubmodelNameExtractionRules__2__pattern__1=HandoverDocumentations + - ExtractionRules__SubmodelNameExtractionRules__3__SubmodelName=TechnicalData + - ExtractionRules__SubmodelNameExtractionRules__3__pattern__0=TechnicalData + - ExtractionRules__SubmodelNameExtractionRules__4__SubmodelName=CarbonFootprint + - ExtractionRules__SubmodelNameExtractionRules__4__pattern__0=CarbonFootprint + - ExtractionRules__SubmodelNameExtractionRules__4__pattern__1=Footprint + - ExtractionRules__SubmodelNameExtractionRules__4__pattern__2=Carbon + - ExtractionRules__ProductIdExtractionRules__0__Pattern=/ + - ExtractionRules__ProductIdExtractionRules__0__Index=5 + - ExtractionRules__ProductIdExtractionRules__0__Strategy=Split + - ExtractionRules__ProductIdExtractionRules__0__Description=Default split by '/' segment 5 + networks: + - twinengine-network + + template-repository-registry: + image: eclipsebasyx/aasenvironment-go:SNAPSHOT + container_name: template-repository-registry + command: ["/app/aasenvironmentservice"] + ports: + - "8082:8082" + volumes: + - ../shared/aas:/app/preconfiguration:ro + - ./security_env:/security_env:ro + environment: + - SERVER_PORT=8082 + - CORS_ALLOWEDORIGINS=* + - CORS_ALLOWEDHEADERS=* + - CORS_ALLOWEDCREDENTIALS=true + - CORS_ALLOWEDMETHODS=GET,OPTIONS + - POSTGRES_HOST=postgres + - POSTGRES_PORT=5432 + - POSTGRES_USER=postgres + - POSTGRES_PASSWORD=admin + - POSTGRES_DBNAME=basyxTestDB + - POSTGRES_MAXOPENCONNECTIONS=500 + - POSTGRES_MAXIDLECONNECTIONS=500 + - POSTGRES_CONNMAXLIFETIMEMINUTES=5 + - ABAC_ENABLED=true + - ABAC_MODELPATH=/security_env/access-rules.json + - OIDC_TRUSTLISTPATH=/security_env/trustlist.json + - GENERAL_AASREGISTRYINTEGRATION=true + - GENERAL_SUBMODELREGISTRYINTEGRATION=true + - GENERAL_DISCOVERYINTEGRATION=true + - GENERAL_EXTERNALURL=http://localhost:8080 + - GENERAL_AAS_PRECONFIG_PATHS=/app/preconfiguration + depends_on: + basyx_configuration: + condition: service_completed_successfully + keycloak-healthcheck: + condition: service_completed_successfully + extra_hosts: + - "keycloak.localhost:host-gateway" + restart: always + networks: + - twinengine-network + + basyx_configuration: + container_name: basyx_configuration + image: eclipsebasyx/basyxconfigurationservice-go:SNAPSHOT + pull_policy: always + environment: + - POSTGRES_HOST=postgres + - POSTGRES_PORT=5432 + - POSTGRES_USER=postgres + - POSTGRES_PASSWORD=admin + - POSTGRES_DBNAME=basyxTestDB + - POSTGRES_MAXOPENCONNECTIONS=500 + - POSTGRES_MAXIDLECONNECTIONS=500 + - POSTGRES_CONNMAXLIFETIMEMINUTES=5 + depends_on: + postgres: + condition: service_healthy + networks: + - twinengine-network + + aas-web-ui: + image: eclipsebasyx/aas-gui:SNAPSHOT + container_name: aas-ui + volumes: + - ../shared/logo:/usr/src/app/dist/Logo + environment: + AAS_REGISTRY_PATH: http://localhost:8080/shell-descriptors + SUBMODEL_REGISTRY_PATH: http://localhost:8080/submodel-descriptors + AAS_REPO_PATH: http://localhost:8080/shells + SUBMODEL_REPO_PATH: http://localhost:8080/submodels + CD_REPO_PATH: http://localhost:8080/concept-descriptions + BASE_PATH: "/aas-ui" + LOGO_PATH: "MM_Logo.svg" + PRIMARY_DARK_COLOR: "#00F2E5" + PRIMARY_LIGHT_COLOR: "#041b2b" + ENDPOINT_CONFIG_AVAILABLE: "false" + KEYCLOAK_URL: http://localhost:9090 + KEYCLOAK_REALM: basyx + KEYCLOAK_CLIENT_ID: basyx-ui + ALLOW_EDITING: "false" + SM_VIEWER_EDITOR: "false" + ALLOW_UPLOADING: "false" + depends_on: + template-repository-registry: + condition: service_started + keycloak-healthcheck: + condition: service_completed_successfully + extra_hosts: + - "keycloak.localhost:host-gateway" + restart: always + networks: + - twinengine-network + + keycloak: + image: keycloak/keycloak:26.0.6 + container_name: keycloak + environment: + KC_DB: postgres + KC_DB_URL: jdbc:postgresql://postgres:5432/basyxTestDB + KC_DB_USERNAME: postgres + KC_DB_PASSWORD: admin + KC_HOSTNAME: keycloak.localhost + KEYCLOAK_ADMIN: admin + KEYCLOAK_ADMIN_PASSWORD: admin + KC_HTTP_ENABLED: "true" + KC_HTTPS_ENABLED: "false" + KC_HEALTH_ENABLED: "true" + KC_HOSTNAME_STRICT: "false" + KC_HOSTNAME_STRICT_BACKCHANNEL: "false" + KC_HTTP_PORT: "9090" + KC_HTTP_MANAGEMENT_PORT: "9000" + KC_IMPORT: /opt/keycloak/data/import/ + KC_HTTP_MANAGEMENT_ENABLED: "true" + command: ["start-dev", "--import-realm", "--health-enabled=true", "--http-port=9090"] + ports: + - "9090:9090" + volumes: + - ./keycloak/realm:/opt/keycloak/data/import:ro + depends_on: + postgres: + condition: service_healthy + networks: + - twinengine-network + + keycloak-healthcheck: + image: curlimages/curl:latest + container_name: keycloak-healthcheck + command: > + sh -c " + echo 'Waiting for Keycloak to become ready...'; + until curl -sf http://keycloak:9000/health/ready; do + sleep 5; + done; + echo 'Keycloak is ready!'" + depends_on: + - keycloak + networks: + - twinengine-network + + postgres: + image: postgres:16-alpine + container_name: postgres + environment: + POSTGRES_DB: twinengine + POSTGRES_USER: postgres + POSTGRES_PASSWORD: admin + volumes: + - ../shared/postgres:/docker-entrypoint-initdb.d + - postgres-data:/var/lib/postgresql/data + restart: always + healthcheck: + test: ["CMD-SHELL", "pg_isready -U postgres -d twinengine"] + interval: 10s + timeout: 5s + retries: 5 + networks: + - twinengine-network + + pgadmin: + image: dpage/pgadmin4:snapshot + container_name: pgadmin + ports: + - "8081:80" + environment: + PGADMIN_DEFAULT_EMAIL: admin@example.com + PGADMIN_DEFAULT_PASSWORD: admin + depends_on: + postgres: + condition: service_healthy + restart: always + networks: + - twinengine-network diff --git a/examples/securedExample/keycloak/realm/basyx-realm.json b/examples/securedExample/keycloak/realm/basyx-realm.json new file mode 100644 index 00000000..3100f089 --- /dev/null +++ b/examples/securedExample/keycloak/realm/basyx-realm.json @@ -0,0 +1,3115 @@ +{ + "id": "f97245ab-82c3-45ac-9b5b-dc160b1a1311", + "realm": "basyx", + "displayName": "", + "displayNameHtml": "", + "notBefore": 0, + "defaultSignatureAlgorithm": "RS256", + "revokeRefreshToken": false, + "refreshTokenMaxReuse": 0, + "accessTokenLifespan": 300, + "accessTokenLifespanForImplicitFlow": 900, + "ssoSessionIdleTimeout": 1800, + "ssoSessionMaxLifespan": 36000, + "ssoSessionIdleTimeoutRememberMe": 0, + "ssoSessionMaxLifespanRememberMe": 0, + "offlineSessionIdleTimeout": 2592000, + "offlineSessionMaxLifespanEnabled": false, + "offlineSessionMaxLifespan": 5184000, + "clientSessionIdleTimeout": 0, + "clientSessionMaxLifespan": 0, + "clientOfflineSessionIdleTimeout": 0, + "clientOfflineSessionMaxLifespan": 0, + "accessCodeLifespan": 60, + "accessCodeLifespanUserAction": 300, + "accessCodeLifespanLogin": 1800, + "actionTokenGeneratedByAdminLifespan": 43200, + "actionTokenGeneratedByUserLifespan": 300, + "oauth2DeviceCodeLifespan": 600, + "oauth2DevicePollingInterval": 5, + "enabled": true, + "sslRequired": "external", + "registrationAllowed": false, + "registrationEmailAsUsername": false, + "rememberMe": false, + "verifyEmail": false, + "loginWithEmailAllowed": true, + "duplicateEmailsAllowed": false, + "resetPasswordAllowed": false, + "editUsernameAllowed": false, + "bruteForceProtected": false, + "permanentLockout": false, + "maxTemporaryLockouts": 0, + "bruteForceStrategy": "MULTIPLE", + "maxFailureWaitSeconds": 900, + "minimumQuickLoginWaitSeconds": 60, + "waitIncrementSeconds": 60, + "quickLoginCheckMilliSeconds": 1000, + "maxDeltaTimeSeconds": 43200, + "failureFactor": 30, + "roles": { + "realm": [ + { + "id": "a83a65a8-0a55-4a8b-86b2-cf6e6484d70d", + "name": "admin", + "description": "", + "composite": false, + "clientRole": false, + "containerId": "f97245ab-82c3-45ac-9b5b-dc160b1a1311", + "attributes": {} + }, + { + "id": "ee306a9f-d72f-456b-84dd-04ae55262e23", + "name": "offline_access", + "description": "${role_offline-access}", + "composite": false, + "clientRole": false, + "containerId": "f97245ab-82c3-45ac-9b5b-dc160b1a1311", + "attributes": {} + }, + { + "id": "6981ff7a-5223-40dd-bc78-322ae5a357fa", + "name": "default-roles-basyx", + "description": "${role_default-roles}", + "composite": true, + "composites": { + "realm": [ + "offline_access", + "uma_authorization" + ], + "client": { + "account": [ + "view-profile", + "manage-account" + ] + } + }, + "clientRole": false, + "containerId": "f97245ab-82c3-45ac-9b5b-dc160b1a1311", + "attributes": {} + }, + { + "id": "f58b8d72-388b-4d3e-8431-1bb4a540e2ef", + "name": "uma_authorization", + "description": "${role_uma_authorization}", + "composite": false, + "clientRole": false, + "containerId": "f97245ab-82c3-45ac-9b5b-dc160b1a1311", + "attributes": {} + } + ], + "client": { + "realm-management": [ + { + "id": "7c4855d3-c93e-440c-b511-608bf4148d1a", + "name": "query-realms", + "description": "${role_query-realms}", + "composite": false, + "clientRole": true, + "containerId": "d66f233e-c934-40d3-912e-cccb235a254e", + "attributes": {} + }, + { + "id": "578c8556-266a-4978-b779-e4f6d43c23ea", + "name": "query-users", + "description": "${role_query-users}", + "composite": false, + "clientRole": true, + "containerId": "d66f233e-c934-40d3-912e-cccb235a254e", + "attributes": {} + }, + { + "id": "41cfe82c-e73a-4270-9938-c9e311795d06", + "name": "query-clients", + "description": "${role_query-clients}", + "composite": false, + "clientRole": true, + "containerId": "d66f233e-c934-40d3-912e-cccb235a254e", + "attributes": {} + }, + { + "id": "dfbbee59-23f9-4e3e-81d2-d7f34772c55e", + "name": "view-authorization", + "description": "${role_view-authorization}", + "composite": false, + "clientRole": true, + "containerId": "d66f233e-c934-40d3-912e-cccb235a254e", + "attributes": {} + }, + { + "id": "f86cb5a6-0cfa-4ab8-bdc5-772127027818", + "name": "view-clients", + "description": "${role_view-clients}", + "composite": true, + "composites": { + "client": { + "realm-management": [ + "query-clients" + ] + } + }, + "clientRole": true, + "containerId": "d66f233e-c934-40d3-912e-cccb235a254e", + "attributes": {} + }, + { + "id": "8a65a532-867f-41e2-8357-22ddcc2eaeca", + "name": "manage-users", + "description": "${role_manage-users}", + "composite": false, + "clientRole": true, + "containerId": "d66f233e-c934-40d3-912e-cccb235a254e", + "attributes": {} + }, + { + "id": "017bfacd-59a5-4897-a49a-d5f8651f54f6", + "name": "manage-clients", + "description": "${role_manage-clients}", + "composite": false, + "clientRole": true, + "containerId": "d66f233e-c934-40d3-912e-cccb235a254e", + "attributes": {} + }, + { + "id": "8cbe1350-1398-4293-899e-64ff21bfc9b0", + "name": "impersonation", + "description": "${role_impersonation}", + "composite": false, + "clientRole": true, + "containerId": "d66f233e-c934-40d3-912e-cccb235a254e", + "attributes": {} + }, + { + "id": "3c5eef9f-c1f3-42f0-9ab6-6950da0d0250", + "name": "create-client", + "description": "${role_create-client}", + "composite": false, + "clientRole": true, + "containerId": "d66f233e-c934-40d3-912e-cccb235a254e", + "attributes": {} + }, + { + "id": "66445e2e-d718-4b70-b5b1-a328c6a234d1", + "name": "view-identity-providers", + "description": "${role_view-identity-providers}", + "composite": false, + "clientRole": true, + "containerId": "d66f233e-c934-40d3-912e-cccb235a254e", + "attributes": {} + }, + { + "id": "dead45ca-5b7b-4466-8b88-738dc7217197", + "name": "view-events", + "description": "${role_view-events}", + "composite": false, + "clientRole": true, + "containerId": "d66f233e-c934-40d3-912e-cccb235a254e", + "attributes": {} + }, + { + "id": "a24a4aa7-d557-4a39-8845-92af98b5c538", + "name": "realm-admin", + "description": "${role_realm-admin}", + "composite": true, + "composites": { + "client": { + "realm-management": [ + "query-users", + "query-realms", + "view-authorization", + "query-clients", + "view-clients", + "manage-users", + "manage-clients", + "impersonation", + "create-client", + "view-identity-providers", + "view-events", + "manage-realm", + "manage-events", + "query-groups", + "manage-identity-providers", + "manage-authorization", + "view-realm", + "view-users" + ] + } + }, + "clientRole": true, + "containerId": "d66f233e-c934-40d3-912e-cccb235a254e", + "attributes": {} + }, + { + "id": "a2f95f4a-d337-438f-953a-77b69b11251b", + "name": "manage-realm", + "description": "${role_manage-realm}", + "composite": false, + "clientRole": true, + "containerId": "d66f233e-c934-40d3-912e-cccb235a254e", + "attributes": {} + }, + { + "id": "427c8af1-075a-4141-9c11-cd5efdfac68a", + "name": "manage-events", + "description": "${role_manage-events}", + "composite": false, + "clientRole": true, + "containerId": "d66f233e-c934-40d3-912e-cccb235a254e", + "attributes": {} + }, + { + "id": "bd2628b9-6518-4e77-92ac-010c2a9e5815", + "name": "query-groups", + "description": "${role_query-groups}", + "composite": false, + "clientRole": true, + "containerId": "d66f233e-c934-40d3-912e-cccb235a254e", + "attributes": {} + }, + { + "id": "b020d5aa-a1ed-4bb1-9326-7345a8e85720", + "name": "manage-identity-providers", + "description": "${role_manage-identity-providers}", + "composite": false, + "clientRole": true, + "containerId": "d66f233e-c934-40d3-912e-cccb235a254e", + "attributes": {} + }, + { + "id": "77e9ecaf-5fd4-40df-9031-78d71ad4c4cf", + "name": "manage-authorization", + "description": "${role_manage-authorization}", + "composite": false, + "clientRole": true, + "containerId": "d66f233e-c934-40d3-912e-cccb235a254e", + "attributes": {} + }, + { + "id": "f886dc7a-5644-41bb-83ed-61c49ea25444", + "name": "view-realm", + "description": "${role_view-realm}", + "composite": false, + "clientRole": true, + "containerId": "d66f233e-c934-40d3-912e-cccb235a254e", + "attributes": {} + }, + { + "id": "a458476f-82e7-49e8-9cd9-d30c384e8c08", + "name": "view-users", + "description": "${role_view-users}", + "composite": true, + "composites": { + "client": { + "realm-management": [ + "query-users", + "query-groups" + ] + } + }, + "clientRole": true, + "containerId": "d66f233e-c934-40d3-912e-cccb235a254e", + "attributes": {} + } + ], + "basyx-ui": [], + "security-admin-console": [], + "admin-cli": [], + "account-console": [], + "broker": [ + { + "id": "97476aed-c5f7-491e-8775-27638fc10cf5", + "name": "read-token", + "description": "${role_read-token}", + "composite": false, + "clientRole": true, + "containerId": "20974092-14b8-4258-a260-12cccbb34ce1", + "attributes": {} + } + ], + "aas-env": [ + { + "id": "60882525-791b-48d2-b036-759aa6a81337", + "name": "admin", + "description": "", + "composite": false, + "clientRole": true, + "containerId": "a943241a-12bf-44b4-a0bc-8bed1edf744a", + "attributes": {} + } + ], + "account": [ + { + "id": "02c9a901-d899-4d04-ace8-b2265745c33b", + "name": "view-profile", + "description": "${role_view-profile}", + "composite": false, + "clientRole": true, + "containerId": "5056cdec-06ed-4c3b-b478-90a524521a69", + "attributes": {} + }, + { + "id": "e804a2b0-01dd-44a3-8580-f23255236470", + "name": "manage-consent", + "description": "${role_manage-consent}", + "composite": true, + "composites": { + "client": { + "account": [ + "view-consent" + ] + } + }, + "clientRole": true, + "containerId": "5056cdec-06ed-4c3b-b478-90a524521a69", + "attributes": {} + }, + { + "id": "2e9ed72e-e808-408c-b67a-fbd023ddc12b", + "name": "manage-account-links", + "description": "${role_manage-account-links}", + "composite": false, + "clientRole": true, + "containerId": "5056cdec-06ed-4c3b-b478-90a524521a69", + "attributes": {} + }, + { + "id": "9cd59e5e-1622-419b-ae1c-82887566598f", + "name": "view-applications", + "description": "${role_view-applications}", + "composite": false, + "clientRole": true, + "containerId": "5056cdec-06ed-4c3b-b478-90a524521a69", + "attributes": {} + }, + { + "id": "a4665872-9e8a-407a-be8b-3bac927dbd62", + "name": "view-consent", + "description": "${role_view-consent}", + "composite": false, + "clientRole": true, + "containerId": "5056cdec-06ed-4c3b-b478-90a524521a69", + "attributes": {} + }, + { + "id": "8a1152f2-6d11-4b60-bff9-355a621ba440", + "name": "view-groups", + "description": "${role_view-groups}", + "composite": false, + "clientRole": true, + "containerId": "5056cdec-06ed-4c3b-b478-90a524521a69", + "attributes": {} + }, + { + "id": "3651b578-e3c6-4912-989f-cd3a19e4fa89", + "name": "delete-account", + "description": "${role_delete-account}", + "composite": false, + "clientRole": true, + "containerId": "5056cdec-06ed-4c3b-b478-90a524521a69", + "attributes": {} + }, + { + "id": "0fb29d7e-4a49-47ec-adf6-5528ee19a301", + "name": "manage-account", + "description": "${role_manage-account}", + "composite": true, + "composites": { + "client": { + "account": [ + "manage-account-links" + ] + } + }, + "clientRole": true, + "containerId": "5056cdec-06ed-4c3b-b478-90a524521a69", + "attributes": {} + } + ], + "discovery-service": [ + { + "id": "ca583d4f-0319-423c-aa5a-5a8632409979", + "name": "uma_protection", + "composite": false, + "clientRole": true, + "containerId": "988bf103-59ae-4ea9-9301-34d973e69c4d", + "attributes": {} + } + ] + } + }, + "groups": [], + "defaultRole": { + "id": "6981ff7a-5223-40dd-bc78-322ae5a357fa", + "name": "default-roles-basyx", + "description": "${role_default-roles}", + "composite": true, + "clientRole": false, + "containerId": "f97245ab-82c3-45ac-9b5b-dc160b1a1311" + }, + "requiredCredentials": [ + "password" + ], + "otpPolicyType": "totp", + "otpPolicyAlgorithm": "HmacSHA1", + "otpPolicyInitialCounter": 0, + "otpPolicyDigits": 6, + "otpPolicyLookAheadWindow": 1, + "otpPolicyPeriod": 30, + "otpPolicyCodeReusable": false, + "otpSupportedApplications": [ + "totpAppFreeOTPName", + "totpAppGoogleName", + "totpAppMicrosoftAuthenticatorName" + ], + "localizationTexts": {}, + "webAuthnPolicyRpEntityName": "keycloak", + "webAuthnPolicySignatureAlgorithms": [ + "ES256", + "RS256" + ], + "webAuthnPolicyRpId": "", + "webAuthnPolicyAttestationConveyancePreference": "not specified", + "webAuthnPolicyAuthenticatorAttachment": "not specified", + "webAuthnPolicyRequireResidentKey": "not specified", + "webAuthnPolicyUserVerificationRequirement": "not specified", + "webAuthnPolicyCreateTimeout": 0, + "webAuthnPolicyAvoidSameAuthenticatorRegister": false, + "webAuthnPolicyAcceptableAaguids": [], + "webAuthnPolicyExtraOrigins": [], + "webAuthnPolicyPasswordlessRpEntityName": "keycloak", + "webAuthnPolicyPasswordlessSignatureAlgorithms": [ + "ES256", + "RS256" + ], + "webAuthnPolicyPasswordlessRpId": "", + "webAuthnPolicyPasswordlessAttestationConveyancePreference": "not specified", + "webAuthnPolicyPasswordlessAuthenticatorAttachment": "not specified", + "webAuthnPolicyPasswordlessRequireResidentKey": "not specified", + "webAuthnPolicyPasswordlessUserVerificationRequirement": "not specified", + "webAuthnPolicyPasswordlessCreateTimeout": 0, + "webAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister": false, + "webAuthnPolicyPasswordlessAcceptableAaguids": [], + "webAuthnPolicyPasswordlessExtraOrigins": [], + "users": [ + { + "id": "32103f0d-1d0e-4d94-b720-bcd22e1c7709", + "username": "admin", + "firstName": "Max", + "lastName": "Mustermann", + "email": "admin@mail.com", + "emailVerified": false, + "attributes": { + "clear": [ + "20" + ], + "role": [ + "admin" + ] + }, + "createdTimestamp": 1763553349664, + "enabled": true, + "totp": false, + "credentials": [ + { + "id": "d0e2fd16-b38a-42d3-84e5-7dc631bd83ae", + "type": "password", + "userLabel": "My password", + "createdDate": 1763553379929, + "secretData": "{\"value\":\"Bz6V9b1teEAVbvhx6kFeR8qJX6TdDGL+yDWpJbOuByA=\",\"salt\":\"4BGpZ3Uxlllp8SCXYXYOjQ==\",\"additionalParameters\":{}}", + "credentialData": "{\"hashIterations\":5,\"algorithm\":\"argon2\",\"additionalParameters\":{\"hashLength\":[\"32\"],\"memory\":[\"7168\"],\"type\":[\"id\"],\"version\":[\"1.3\"],\"parallelism\":[\"1\"]}}" + } + ], + "disableableCredentialTypes": [], + "requiredActions": [], + "realmRoles": [ + "default-roles-basyx" + ], + "clientRoles": { + "aas-env": [ + "admin" + ] + }, + "notBefore": 0, + "groups": [] + }, + { + "id": "78b8ff04-d473-4143-9e5e-42716e41f7cb", + "username": "service-account-aas-env", + "firstName": "Martin", + "lastName": "Stemmer", + "email": "martin-stemmer@t-online.de", + "emailVerified": false, + "attributes": { + "clear": [ + "20" + ], + "role": [ + "admin" + ] + }, + "createdTimestamp": 1764768925034, + "enabled": true, + "totp": false, + "serviceAccountClientId": "aas-env", + "credentials": [], + "disableableCredentialTypes": [], + "requiredActions": [], + "realmRoles": [ + "default-roles-basyx" + ], + "clientRoles": { + "aas-env": [ + "admin" + ] + }, + "notBefore": 0, + "groups": [] + }, + { + "id": "6a2d8f76-af47-40e9-b8b2-1ca14918c448", + "username": "service-account-discovery-service", + "emailVerified": false, + "createdTimestamp": 1761290465613, + "enabled": true, + "totp": false, + "serviceAccountClientId": "discovery-service", + "credentials": [], + "disableableCredentialTypes": [], + "requiredActions": [], + "realmRoles": [ + "default-roles-basyx" + ], + "clientRoles": { + "discovery-service": [ + "uma_protection" + ] + }, + "notBefore": 0, + "groups": [] + }, + { + "id": "c4d04982-cd08-4dc7-ba30-75c49c62dc3a", + "username": "usera", + "firstName": "Max", + "lastName": "Mustermann", + "email": "usera@mail.com", + "emailVerified": false, + "attributes": { + "role": [ + "viewer" + ] + }, + "createdTimestamp": 1763553182453, + "enabled": true, + "totp": false, + "credentials": [ + { + "id": "733effaa-4527-4582-917e-9d6453a70e91", + "type": "password", + "userLabel": "My password", + "createdDate": 1763553389508, + "secretData": "{\"value\":\"/DfHWYWN5tIuRUt7vdh5F6fpt/xcDN4bdWkhY+jCnVs=\",\"salt\":\"1V1zPwre8fO/hEFYf+PEtg==\",\"additionalParameters\":{}}", + "credentialData": "{\"hashIterations\":5,\"algorithm\":\"argon2\",\"additionalParameters\":{\"hashLength\":[\"32\"],\"memory\":[\"7168\"],\"type\":[\"id\"],\"version\":[\"1.3\"],\"parallelism\":[\"1\"]}}" + } + ], + "disableableCredentialTypes": [], + "requiredActions": [], + "realmRoles": [ + "default-roles-basyx" + ], + "notBefore": 0, + "groups": [] + }, + { + "id": "803f798c-3e11-440e-ad66-26016efca76c", + "username": "userx", + "firstName": "Max", + "lastName": "Mustermann", + "email": "userx@mail.com", + "emailVerified": false, + "attributes": { + "role": [ + "editor" + ] + }, + "createdTimestamp": 1763553277239, + "enabled": true, + "totp": false, + "credentials": [ + { + "id": "c1bb153c-951e-471e-9ddf-a3dec64f7452", + "type": "password", + "userLabel": "My password", + "createdDate": 1763553410862, + "secretData": "{\"value\":\"rILNeJ1Atdyg3V1eF7KDkw3kZgbXSmHP8z4g4MQVidU=\",\"salt\":\"qFkvnew602rmkafCjUueCg==\",\"additionalParameters\":{}}", + "credentialData": "{\"hashIterations\":5,\"algorithm\":\"argon2\",\"additionalParameters\":{\"hashLength\":[\"32\"],\"memory\":[\"7168\"],\"type\":[\"id\"],\"version\":[\"1.3\"],\"parallelism\":[\"1\"]}}" + } + ], + "disableableCredentialTypes": [], + "requiredActions": [], + "realmRoles": [ + "default-roles-basyx" + ], + "notBefore": 0, + "groups": [] + }, + { + "id": "5d4e91f5-f48d-42e3-8f6f-c2d6e111f9de", + "username": "usery", + "firstName": "Max", + "lastName": "Mustermann", + "email": "usery@mail.com", + "emailVerified": false, + "attributes": { + "clear": [ + "2" + ], + "role": [ + "editor" + ] + }, + "createdTimestamp": 1763553312697, + "enabled": true, + "totp": false, + "credentials": [ + { + "id": "711a05f1-f9bb-414c-ba74-aee52dddea2d", + "type": "password", + "userLabel": "My password", + "createdDate": 1763553423175, + "secretData": "{\"value\":\"xno1fB+MsKoetwJJM9d+monjFXQj1UuVfFLv9pSS42o=\",\"salt\":\"Vw62MhV+JlPIrJdCfdSIug==\",\"additionalParameters\":{}}", + "credentialData": "{\"hashIterations\":5,\"algorithm\":\"argon2\",\"additionalParameters\":{\"hashLength\":[\"32\"],\"memory\":[\"7168\"],\"type\":[\"id\"],\"version\":[\"1.3\"],\"parallelism\":[\"1\"]}}" + } + ], + "disableableCredentialTypes": [], + "requiredActions": [], + "realmRoles": [ + "default-roles-basyx" + ], + "notBefore": 0, + "groups": [] + } + ], + "scopeMappings": [ + { + "clientScope": "offline_access", + "roles": [ + "offline_access" + ] + } + ], + "clientScopeMappings": { + "account": [ + { + "client": "account-console", + "roles": [ + "manage-account", + "view-groups" + ] + } + ] + }, + "clients": [ + { + "id": "a943241a-12bf-44b4-a0bc-8bed1edf744a", + "clientId": "aas-env", + "name": "aas-env", + "description": "", + "rootUrl": "", + "adminUrl": "", + "baseUrl": "", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "gqj6bXy7uBx0F97mXzy4vOsnD1frqYcB", + "redirectUris": [ + "/*" + ], + "webOrigins": [ + "/*" + ], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": true, + "directAccessGrantsEnabled": true, + "serviceAccountsEnabled": true, + "publicClient": false, + "frontchannelLogout": true, + "protocol": "openid-connect", + "attributes": { + "realm_client": "false", + "oidc.ciba.grant.enabled": "false", + "client.secret.creation.time": "1764768782", + "backchannel.logout.session.required": "true", + "post.logout.redirect.uris": "+", + "display.on.consent.screen": "false", + "oauth2.device.authorization.grant.enabled": "false", + "backchannel.logout.revoke.offline.tokens": "false" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": true, + "nodeReRegistrationTimeout": -1, + "protocolMappers": [ + { + "id": "9df7044a-e35f-4606-84aa-e3dc5ff43060", + "name": "Role Mapper", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "aggregate.attrs": "false", + "introspection.token.claim": "true", + "multivalued": "false", + "userinfo.token.claim": "true", + "user.attribute": "role", + "id.token.claim": "true", + "lightweight.claim": "false", + "access.token.claim": "true", + "claim.name": "role", + "jsonType.label": "String" + } + }, + { + "id": "024ae3b1-f483-46d1-b18d-7cfcf54a804d", + "name": "Client IP Address", + "protocol": "openid-connect", + "protocolMapper": "oidc-usersessionmodel-note-mapper", + "consentRequired": false, + "config": { + "user.session.note": "clientAddress", + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "clientAddress", + "jsonType.label": "String" + } + }, + { + "id": "e41fd604-43b1-431b-8782-18f3df11e795", + "name": "Client Host", + "protocol": "openid-connect", + "protocolMapper": "oidc-usersessionmodel-note-mapper", + "consentRequired": false, + "config": { + "user.session.note": "clientHost", + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "clientHost", + "jsonType.label": "String" + } + }, + { + "id": "ee66a355-5ea6-4c1c-b075-7a08433fb389", + "name": "aas-env-aud-mapper", + "protocol": "openid-connect", + "protocolMapper": "oidc-audience-mapper", + "consentRequired": false, + "config": { + "included.client.audience": "discovery-service", + "id.token.claim": "false", + "lightweight.claim": "false", + "introspection.token.claim": "true", + "access.token.claim": "true", + "userinfo.token.claim": "false" + } + }, + { + "id": "0d366b07-a8e3-40f6-92d8-d8699501876a", + "name": "Client ID", + "protocol": "openid-connect", + "protocolMapper": "oidc-usersessionmodel-note-mapper", + "consentRequired": false, + "config": { + "user.session.note": "client_id", + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "client_id", + "jsonType.label": "String" + } + }, + { + "id": "852d8141-eaa5-4f80-affb-0cf04d93d4ce", + "name": "Clearance Mapper", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "aggregate.attrs": "false", + "introspection.token.claim": "true", + "multivalued": "false", + "userinfo.token.claim": "true", + "user.attribute": "clear", + "id.token.claim": "true", + "lightweight.claim": "false", + "access.token.claim": "true", + "claim.name": "clear", + "jsonType.label": "String" + } + } + ], + "defaultClientScopes": [ + "web-origins", + "acr", + "role", + "profile", + "roles", + "clear", + "basic", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "organization", + "microprofile-jwt" + ] + }, + { + "id": "5056cdec-06ed-4c3b-b478-90a524521a69", + "clientId": "account", + "name": "${client_account}", + "rootUrl": "${authBaseUrl}", + "baseUrl": "/realms/basyx/account/", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": [ + "/realms/basyx/account/*" + ], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "realm_client": "false", + "post.logout.redirect.uris": "+" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "acr", + "profile", + "roles", + "basic", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "organization", + "microprofile-jwt" + ] + }, + { + "id": "ad273746-da54-45f6-8b9a-759fcca085e9", + "clientId": "account-console", + "name": "${client_account-console}", + "rootUrl": "${authBaseUrl}", + "baseUrl": "/realms/basyx/account/", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": [ + "/realms/basyx/account/*" + ], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "realm_client": "false", + "post.logout.redirect.uris": "+", + "pkce.code.challenge.method": "S256" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "protocolMappers": [ + { + "id": "c06bb2ad-8f94-4ac0-86ca-ff03cc3b0896", + "name": "audience resolve", + "protocol": "openid-connect", + "protocolMapper": "oidc-audience-resolve-mapper", + "consentRequired": false, + "config": {} + } + ], + "defaultClientScopes": [ + "web-origins", + "acr", + "profile", + "roles", + "basic", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "organization", + "microprofile-jwt" + ] + }, + { + "id": "2be1fdd4-9929-4cfd-a761-6bb66726c41c", + "clientId": "admin-cli", + "name": "${client_admin-cli}", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": false, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": true, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "realm_client": "false", + "client.use.lightweight.access.token.enabled": "true", + "post.logout.redirect.uris": "+" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": true, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "acr", + "profile", + "roles", + "basic", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "organization", + "microprofile-jwt" + ] + }, + { + "id": "a931544a-636e-4030-a0af-427f00873ff5", + "clientId": "basyx-ui", + "name": "", + "description": "", + "rootUrl": "", + "adminUrl": "", + "baseUrl": "", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": [ + "http://localhost:3000/*", + "*" + ], + "webOrigins": [ + "http://localhost:3000", + "*" + ], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": true, + "directAccessGrantsEnabled": true, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": true, + "protocol": "openid-connect", + "attributes": { + "realm_client": "false", + "oidc.ciba.grant.enabled": "false", + "backchannel.logout.session.required": "true", + "post.logout.redirect.uris": "http://localhost:3000/*##*", + "display.on.consent.screen": "false", + "oauth2.device.authorization.grant.enabled": "false", + "backchannel.logout.revoke.offline.tokens": "false" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": true, + "nodeReRegistrationTimeout": -1, + "protocolMappers": [ + { + "id": "900ab17f-a3f5-49a0-a6cd-91d7be0df0eb", + "name": "Role Mapper", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "aggregate.attrs": "false", + "introspection.token.claim": "true", + "multivalued": "false", + "userinfo.token.claim": "true", + "user.attribute": "role", + "id.token.claim": "true", + "lightweight.claim": "false", + "access.token.claim": "true", + "claim.name": "role", + "jsonType.label": "String" + } + }, + { + "id": "87d7e16b-8156-4410-95d0-59dcee3240fc", + "name": "discovery-service-aud-mapper", + "protocol": "openid-connect", + "protocolMapper": "oidc-audience-mapper", + "consentRequired": false, + "config": { + "included.client.audience": "discovery-service", + "id.token.claim": "false", + "lightweight.claim": "false", + "introspection.token.claim": "true", + "access.token.claim": "true", + "userinfo.token.claim": "false" + } + }, + { + "id": "a0f45fb3-5d14-4535-8475-12971aefdfc2", + "name": "Clearance Mapper", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "aggregate.attrs": "false", + "introspection.token.claim": "true", + "multivalued": "false", + "userinfo.token.claim": "true", + "user.attribute": "clear", + "id.token.claim": "true", + "lightweight.claim": "false", + "access.token.claim": "true", + "claim.name": "clear", + "jsonType.label": "String" + } + } + ], + "defaultClientScopes": [ + "web-origins", + "acr", + "profile", + "roles", + "basic", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "organization", + "microprofile-jwt" + ] + }, + { + "id": "20974092-14b8-4258-a260-12cccbb34ce1", + "clientId": "broker", + "name": "${client_broker}", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": true, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "realm_client": "true", + "post.logout.redirect.uris": "+" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "acr", + "profile", + "roles", + "basic", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "organization", + "microprofile-jwt" + ] + }, + { + "id": "988bf103-59ae-4ea9-9301-34d973e69c4d", + "clientId": "discovery-service", + "name": "", + "description": "", + "rootUrl": "", + "adminUrl": "", + "baseUrl": "", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "redirectUris": [ + "http://localhost:5004/auth/callback" + ], + "webOrigins": [ + "http://localhost:5004" + ], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": true, + "serviceAccountsEnabled": true, + "authorizationServicesEnabled": true, + "publicClient": false, + "frontchannelLogout": true, + "protocol": "openid-connect", + "attributes": { + "realm_client": "false", + "oidc.ciba.grant.enabled": "false", + "client.secret.creation.time": "1761290465", + "backchannel.logout.session.required": "true", + "post.logout.redirect.uris": "+", + "display.on.consent.screen": "false", + "oauth2.device.authorization.grant.enabled": "false", + "backchannel.logout.revoke.offline.tokens": "false" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": true, + "nodeReRegistrationTimeout": -1, + "protocolMappers": [ + { + "id": "f96009e8-5aad-4ff6-ae77-1eefdabf02dd", + "name": "discovery-service-aud-mapper", + "protocol": "openid-connect", + "protocolMapper": "oidc-audience-mapper", + "consentRequired": false, + "config": { + "included.client.audience": "discovery-service", + "id.token.claim": "false", + "lightweight.claim": "false", + "introspection.token.claim": "true", + "access.token.claim": "true", + "userinfo.token.claim": "false" + } + }, + { + "id": "b0882d11-06e0-4a0f-b0ea-f8dabdb3c448", + "name": "Client ID", + "protocol": "openid-connect", + "protocolMapper": "oidc-usersessionmodel-note-mapper", + "consentRequired": false, + "config": { + "user.session.note": "client_id", + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "client_id", + "jsonType.label": "String" + } + }, + { + "id": "e7e7053a-bc36-4284-979e-466817df4514", + "name": "Client Host", + "protocol": "openid-connect", + "protocolMapper": "oidc-usersessionmodel-note-mapper", + "consentRequired": false, + "config": { + "user.session.note": "clientHost", + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "clientHost", + "jsonType.label": "String" + } + }, + { + "id": "b5d5f8f4-2565-4aef-9f28-9097b60333ee", + "name": "Client IP Address", + "protocol": "openid-connect", + "protocolMapper": "oidc-usersessionmodel-note-mapper", + "consentRequired": false, + "config": { + "user.session.note": "clientAddress", + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "clientAddress", + "jsonType.label": "String" + } + } + ], + "defaultClientScopes": [ + "web-origins", + "acr", + "profile", + "roles", + "basic", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "organization", + "microprofile-jwt" + ], + "authorizationSettings": { + "allowRemoteResourceManagement": true, + "policyEnforcementMode": "ENFORCING", + "resources": [ + { + "name": "Default Resource", + "type": "urn:discovery-service:resources:default", + "ownerManagedAccess": false, + "attributes": {}, + "uris": [ + "/*" + ] + } + ], + "policies": [], + "scopes": [], + "decisionStrategy": "UNANIMOUS" + } + }, + { + "id": "d66f233e-c934-40d3-912e-cccb235a254e", + "clientId": "realm-management", + "name": "${client_realm-management}", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": true, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "realm_client": "true", + "post.logout.redirect.uris": "+" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "acr", + "profile", + "roles", + "basic", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "organization", + "microprofile-jwt" + ] + }, + { + "id": "a5e5ed2c-da66-4140-a531-93cd3c8a72e8", + "clientId": "security-admin-console", + "name": "${client_security-admin-console}", + "rootUrl": "${authAdminUrl}", + "baseUrl": "/admin/basyx/console/", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": [ + "/admin/basyx/console/*" + ], + "webOrigins": [ + "+" + ], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "realm_client": "false", + "client.use.lightweight.access.token.enabled": "true", + "post.logout.redirect.uris": "+", + "pkce.code.challenge.method": "S256" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": true, + "nodeReRegistrationTimeout": 0, + "protocolMappers": [ + { + "id": "15c7c7b6-e884-4187-97c4-77340ba73cd2", + "name": "locale", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "locale", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "locale", + "jsonType.label": "String" + } + } + ], + "defaultClientScopes": [ + "web-origins", + "acr", + "profile", + "roles", + "basic", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "organization", + "microprofile-jwt" + ] + } + ], + "clientScopes": [ + { + "id": "b8b3b5b9-3459-454b-b82d-a6bac51af5b3", + "name": "offline_access", + "description": "OpenID Connect built-in scope: offline_access", + "protocol": "openid-connect", + "attributes": { + "consent.screen.text": "${offlineAccessScopeConsentText}", + "display.on.consent.screen": "true" + } + }, + { + "id": "4bcecc4f-5950-41e3-8717-160268400a55", + "name": "microprofile-jwt", + "description": "Microprofile - JWT built-in scope", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "false" + }, + "protocolMappers": [ + { + "id": "d8e45bd1-c127-44a8-b7b4-cbfe16bff068", + "name": "upn", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "username", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "upn", + "jsonType.label": "String" + } + }, + { + "id": "0492aae7-91d2-431d-83f0-599d28803fdd", + "name": "groups", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-realm-role-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "multivalued": "true", + "userinfo.token.claim": "true", + "user.attribute": "foo", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "groups", + "jsonType.label": "String" + } + } + ] + }, + { + "id": "f186e47a-9cc2-4445-a74d-7b595e941863", + "name": "email", + "description": "OpenID Connect built-in scope: email", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "consent.screen.text": "${emailScopeConsentText}", + "display.on.consent.screen": "true" + }, + "protocolMappers": [ + { + "id": "d1b9d43c-6dff-493d-8fa7-8201bfea77ff", + "name": "email verified", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "emailVerified", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "email_verified", + "jsonType.label": "boolean" + } + }, + { + "id": "bd23bff3-039b-4175-86fd-d283527fdd97", + "name": "email", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "email", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "email", + "jsonType.label": "String" + } + } + ] + }, + { + "id": "c4a31b61-afc9-40cc-9471-ad6d809b86f0", + "name": "role", + "description": "", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "display.on.consent.screen": "true", + "gui.order": "", + "consent.screen.text": "" + }, + "protocolMappers": [ + { + "id": "20e9e916-6202-471a-bdf2-5235c9fb7b96", + "name": "Role Mapper", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "role", + "id.token.claim": "true", + "lightweight.claim": "false", + "access.token.claim": "true", + "jsonType.label": "String" + } + } + ] + }, + { + "id": "46e2fd9d-c240-424d-9b43-bd5ddae9f35c", + "name": "roles", + "description": "OpenID Connect scope for add user roles to the access token", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "consent.screen.text": "${rolesScopeConsentText}", + "display.on.consent.screen": "true" + }, + "protocolMappers": [ + { + "id": "634a4e5d-29a7-42a0-b3b1-26b092b4943c", + "name": "audience resolve", + "protocol": "openid-connect", + "protocolMapper": "oidc-audience-resolve-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "access.token.claim": "true" + } + }, + { + "id": "93ee8212-db42-46da-8726-3b9613d7521f", + "name": "realm roles", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-realm-role-mapper", + "consentRequired": false, + "config": { + "user.attribute": "foo", + "introspection.token.claim": "true", + "access.token.claim": "true", + "claim.name": "realm_access.roles", + "jsonType.label": "String", + "multivalued": "true" + } + }, + { + "id": "59fbac50-9683-4475-9f22-cdc5169be292", + "name": "client roles", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-client-role-mapper", + "consentRequired": false, + "config": { + "user.attribute": "foo", + "introspection.token.claim": "true", + "access.token.claim": "true", + "claim.name": "resource_access.${client_id}.roles", + "jsonType.label": "String", + "multivalued": "true" + } + } + ] + }, + { + "id": "0a0d5f60-0400-4c77-be35-70ae05f4a28e", + "name": "basic", + "description": "OpenID Connect scope for add all basic claims to the token", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "display.on.consent.screen": "false" + }, + "protocolMappers": [ + { + "id": "40f7f9b9-106e-4366-aabd-a8e5460edfb1", + "name": "sub", + "protocol": "openid-connect", + "protocolMapper": "oidc-sub-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "access.token.claim": "true" + } + }, + { + "id": "0d61dc04-8d7c-432e-98cc-1365e47d2a3b", + "name": "auth_time", + "protocol": "openid-connect", + "protocolMapper": "oidc-usersessionmodel-note-mapper", + "consentRequired": false, + "config": { + "user.session.note": "AUTH_TIME", + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "auth_time", + "jsonType.label": "long" + } + } + ] + }, + { + "id": "58a65e6c-3220-4afa-9a6a-9061169ce4ba", + "name": "phone", + "description": "OpenID Connect built-in scope: phone", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "consent.screen.text": "${phoneScopeConsentText}", + "display.on.consent.screen": "true" + }, + "protocolMappers": [ + { + "id": "a58baf7d-880b-4f6d-950a-1e90ede92147", + "name": "phone number verified", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "phoneNumberVerified", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "phone_number_verified", + "jsonType.label": "boolean" + } + }, + { + "id": "6ecb691c-3ae6-4f38-9e8a-0085e0a34e52", + "name": "phone number", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "phoneNumber", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "phone_number", + "jsonType.label": "String" + } + } + ] + }, + { + "id": "f2089154-114e-4aec-88d3-338d8aa1b928", + "name": "role_list", + "description": "SAML role list", + "protocol": "saml", + "attributes": { + "consent.screen.text": "${samlRoleListScopeConsentText}", + "display.on.consent.screen": "true" + }, + "protocolMappers": [ + { + "id": "7933c532-b209-4380-8fed-1f41ac1c6033", + "name": "role list", + "protocol": "saml", + "protocolMapper": "saml-role-list-mapper", + "consentRequired": false, + "config": { + "single": "false", + "attribute.nameformat": "Basic", + "attribute.name": "Role" + } + } + ] + }, + { + "id": "ed51bc06-4f76-4c9a-b85c-144c25cab0bc", + "name": "profile", + "description": "OpenID Connect built-in scope: profile", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "consent.screen.text": "${profileScopeConsentText}", + "display.on.consent.screen": "true" + }, + "protocolMappers": [ + { + "id": "d783a21c-02b5-477f-9171-bc9d4f72d4ad", + "name": "website", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "website", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "website", + "jsonType.label": "String" + } + }, + { + "id": "6b40a39c-8f05-4fa6-afe3-c8b417068bb3", + "name": "birthdate", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "birthdate", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "birthdate", + "jsonType.label": "String" + } + }, + { + "id": "65dd6f99-b8f3-4bd2-ad8b-9e812121a3aa", + "name": "locale", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "locale", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "locale", + "jsonType.label": "String" + } + }, + { + "id": "facd5278-166b-407d-aa0c-3956b9579d95", + "name": "picture", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "picture", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "picture", + "jsonType.label": "String" + } + }, + { + "id": "36a6da28-e6c5-403b-8d82-a526c1028359", + "name": "gender", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "gender", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "gender", + "jsonType.label": "String" + } + }, + { + "id": "ef96dc72-0487-4784-943a-bfa5d0b24a00", + "name": "updated at", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "updatedAt", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "updated_at", + "jsonType.label": "long" + } + }, + { + "id": "3974137e-614e-4b09-bf9d-98cee313470f", + "name": "zoneinfo", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "zoneinfo", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "zoneinfo", + "jsonType.label": "String" + } + }, + { + "id": "ce63a167-6f55-4f33-98f7-a1185414464f", + "name": "given name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "firstName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "given_name", + "jsonType.label": "String" + } + }, + { + "id": "225b832f-d568-4168-8880-f7bae2a95b8f", + "name": "nickname", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "nickname", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "nickname", + "jsonType.label": "String" + } + }, + { + "id": "13c8306b-84e2-4aee-9e89-d7d0d8ec8ed9", + "name": "username", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "username", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "preferred_username", + "jsonType.label": "String" + } + }, + { + "id": "0dd8bc3e-28da-4be5-9604-dd80cfbcdfac", + "name": "family name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "lastName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "family_name", + "jsonType.label": "String" + } + }, + { + "id": "cc414e8f-71af-43e1-9108-547da19dc44e", + "name": "profile", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "profile", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "profile", + "jsonType.label": "String" + } + }, + { + "id": "e6d5473d-baf5-401a-9c1f-ce000173f264", + "name": "full name", + "protocol": "openid-connect", + "protocolMapper": "oidc-full-name-mapper", + "consentRequired": false, + "config": { + "id.token.claim": "true", + "introspection.token.claim": "true", + "access.token.claim": "true", + "userinfo.token.claim": "true" + } + }, + { + "id": "58952da3-e089-4f2d-b22a-400fe51369b1", + "name": "middle name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "middleName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "middle_name", + "jsonType.label": "String" + } + } + ] + }, + { + "id": "0fc957e8-55a0-444d-91fb-0b66b73b6c31", + "name": "saml_organization", + "description": "Organization Membership", + "protocol": "saml", + "attributes": { + "display.on.consent.screen": "false" + }, + "protocolMappers": [ + { + "id": "4acafcd1-ef09-4539-9121-45dc4f0ab452", + "name": "organization", + "protocol": "saml", + "protocolMapper": "saml-organization-membership-mapper", + "consentRequired": false, + "config": {} + } + ] + }, + { + "id": "3da35a14-4743-464b-9a80-4d669245ce39", + "name": "address", + "description": "OpenID Connect built-in scope: address", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "consent.screen.text": "${addressScopeConsentText}", + "display.on.consent.screen": "true" + }, + "protocolMappers": [ + { + "id": "8a266f60-51d7-4743-89b8-6c11eed62814", + "name": "address", + "protocol": "openid-connect", + "protocolMapper": "oidc-address-mapper", + "consentRequired": false, + "config": { + "user.attribute.formatted": "formatted", + "user.attribute.country": "country", + "introspection.token.claim": "true", + "user.attribute.postal_code": "postal_code", + "userinfo.token.claim": "true", + "user.attribute.street": "street", + "id.token.claim": "true", + "user.attribute.region": "region", + "access.token.claim": "true", + "user.attribute.locality": "locality" + } + } + ] + }, + { + "id": "a59b7b48-d77a-4dac-9e78-e85e2fac6753", + "name": "web-origins", + "description": "OpenID Connect scope for add allowed web origins to the access token", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "consent.screen.text": "", + "display.on.consent.screen": "false" + }, + "protocolMappers": [ + { + "id": "51196a78-0f5a-47bc-a315-dc6424452962", + "name": "allowed web origins", + "protocol": "openid-connect", + "protocolMapper": "oidc-allowed-origins-mapper", + "consentRequired": false, + "config": { + "access.token.claim": "true", + "introspection.token.claim": "true" + } + } + ] + }, + { + "id": "f5b839fa-3262-4592-aadf-c929b7d67551", + "name": "acr", + "description": "OpenID Connect scope for add acr (authentication context class reference) to the token", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "display.on.consent.screen": "false" + }, + "protocolMappers": [ + { + "id": "fda282ce-db26-4f08-808a-0055581450ed", + "name": "acr loa level", + "protocol": "openid-connect", + "protocolMapper": "oidc-acr-mapper", + "consentRequired": false, + "config": { + "id.token.claim": "true", + "access.token.claim": "true", + "introspection.token.claim": "true", + "userinfo.token.claim": "true" + } + } + ] + }, + { + "id": "d8db6f87-6b98-4729-971d-a25737b3f1c4", + "name": "organization", + "description": "Additional claims about the organization a subject belongs to", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "consent.screen.text": "${organizationScopeConsentText}", + "display.on.consent.screen": "true" + }, + "protocolMappers": [ + { + "id": "7500d7d2-2a78-4521-9c85-2fde78a896e1", + "name": "organization", + "protocol": "openid-connect", + "protocolMapper": "oidc-organization-membership-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "multivalued": "true", + "userinfo.token.claim": "true", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "organization", + "jsonType.label": "String" + } + } + ] + }, + { + "id": "80d225df-e562-4a72-92f8-3ba5a7007ca5", + "name": "clear", + "description": "", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "display.on.consent.screen": "true", + "gui.order": "", + "consent.screen.text": "" + }, + "protocolMappers": [ + { + "id": "4c1bfa53-934e-4e5f-b45a-86b9f1420abc", + "name": "Clearance Mapper", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "clear", + "id.token.claim": "true", + "lightweight.claim": "false", + "access.token.claim": "true", + "jsonType.label": "String" + } + } + ] + } + ], + "defaultDefaultClientScopes": [ + "role_list", + "saml_organization", + "profile", + "email", + "roles", + "web-origins", + "acr", + "basic" + ], + "defaultOptionalClientScopes": [ + "offline_access", + "address", + "phone", + "microprofile-jwt", + "organization" + ], + "browserSecurityHeaders": { + "contentSecurityPolicyReportOnly": "", + "xContentTypeOptions": "nosniff", + "referrerPolicy": "no-referrer", + "xRobotsTag": "none", + "xFrameOptions": "SAMEORIGIN", + "contentSecurityPolicy": "frame-src 'self'; frame-ancestors 'self'; object-src 'none';", + "xXSSProtection": "1; mode=block", + "strictTransportSecurity": "max-age=31536000; includeSubDomains" + }, + "smtpServer": {}, + "eventsEnabled": false, + "eventsListeners": [ + "jboss-logging" + ], + "enabledEventTypes": [], + "adminEventsEnabled": false, + "adminEventsDetailsEnabled": false, + "identityProviders": [], + "identityProviderMappers": [], + "components": { + "org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy": [ + { + "id": "3d66e2fb-c54c-4ec7-ab75-440d89325eae", + "name": "Consent Required", + "providerId": "consent-required", + "subType": "anonymous", + "subComponents": {}, + "config": {} + }, + { + "id": "741033cb-8d97-4407-b21b-1e1df2aa177a", + "name": "Trusted Hosts", + "providerId": "trusted-hosts", + "subType": "anonymous", + "subComponents": {}, + "config": { + "host-sending-registration-request-must-match": [ + "true" + ], + "client-uris-must-match": [ + "true" + ] + } + }, + { + "id": "9ec57834-3be7-46d2-96d5-b91a0c928cef", + "name": "Allowed Protocol Mapper Types", + "providerId": "allowed-protocol-mappers", + "subType": "anonymous", + "subComponents": {}, + "config": { + "allowed-protocol-mapper-types": [ + "oidc-address-mapper", + "oidc-usermodel-property-mapper", + "saml-user-attribute-mapper", + "saml-user-property-mapper", + "oidc-usermodel-attribute-mapper", + "saml-role-list-mapper", + "oidc-sha256-pairwise-sub-mapper", + "oidc-full-name-mapper" + ] + } + }, + { + "id": "7e49e253-e765-426d-83f1-9d71cc880e90", + "name": "Allowed Protocol Mapper Types", + "providerId": "allowed-protocol-mappers", + "subType": "authenticated", + "subComponents": {}, + "config": { + "allowed-protocol-mapper-types": [ + "oidc-full-name-mapper", + "oidc-sha256-pairwise-sub-mapper", + "oidc-usermodel-property-mapper", + "saml-role-list-mapper", + "saml-user-property-mapper", + "oidc-usermodel-attribute-mapper", + "saml-user-attribute-mapper", + "oidc-address-mapper" + ] + } + }, + { + "id": "1d763900-c324-45c7-a08d-ec64849605dd", + "name": "Allowed Client Scopes", + "providerId": "allowed-client-templates", + "subType": "anonymous", + "subComponents": {}, + "config": { + "allow-default-scopes": [ + "true" + ] + } + }, + { + "id": "b0a4c28b-1e91-405c-9e04-d340ef422c1f", + "name": "Max Clients Limit", + "providerId": "max-clients", + "subType": "anonymous", + "subComponents": {}, + "config": { + "max-clients": [ + "200" + ] + } + }, + { + "id": "d0c193a1-3739-4057-9d7f-bacb6c6f1fd8", + "name": "Full Scope Disabled", + "providerId": "scope", + "subType": "anonymous", + "subComponents": {}, + "config": {} + }, + { + "id": "678c9871-17be-4f3d-a5be-51914a665105", + "name": "Allowed Client Scopes", + "providerId": "allowed-client-templates", + "subType": "authenticated", + "subComponents": {}, + "config": { + "allow-default-scopes": [ + "true" + ] + } + } + ], + "org.keycloak.userprofile.UserProfileProvider": [ + { + "id": "a986d230-d3cc-4ec0-9b61-61340207a68d", + "providerId": "declarative-user-profile", + "subComponents": {}, + "config": { + "kc.user.profile.config": [ + "{\"attributes\":[{\"name\":\"username\",\"displayName\":\"${username}\",\"validations\":{\"length\":{\"min\":3,\"max\":255},\"username-prohibited-characters\":{},\"up-username-not-idn-homograph\":{}},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"multivalued\":false},{\"name\":\"email\",\"displayName\":\"${email}\",\"validations\":{\"email\":{},\"length\":{\"max\":255}},\"required\":{\"roles\":[\"user\"]},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"multivalued\":false},{\"name\":\"firstName\",\"displayName\":\"${firstName}\",\"validations\":{\"length\":{\"max\":255},\"person-name-prohibited-characters\":{}},\"required\":{\"roles\":[\"user\"]},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"multivalued\":false},{\"name\":\"lastName\",\"displayName\":\"${lastName}\",\"validations\":{\"length\":{\"max\":255},\"person-name-prohibited-characters\":{}},\"required\":{\"roles\":[\"user\"]},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"multivalued\":false},{\"name\":\"role\",\"displayName\":\"Role\",\"validations\":{},\"annotations\":{},\"permissions\":{\"view\":[],\"edit\":[\"admin\"]},\"multivalued\":false},{\"name\":\"clear\",\"displayName\":\"Clearance\",\"validations\":{},\"annotations\":{},\"permissions\":{\"view\":[],\"edit\":[\"admin\"]},\"multivalued\":false}],\"groups\":[{\"name\":\"user-metadata\",\"displayHeader\":\"User metadata\",\"displayDescription\":\"Attributes, which refer to user metadata\"}]}" + ] + } + } + ], + "org.keycloak.keys.KeyProvider": [ + { + "id": "f39d4e1f-20e2-4cca-a010-9cdd316fc7c8", + "name": "hmac-generated-hs512", + "providerId": "hmac-generated", + "subComponents": {}, + "config": { + "kid": [ + "6dcdd780-a14e-4d5a-9a1a-e1ef894e3a3a" + ], + "secret": [ + "6o21jWCZ38XFgKrXRQ8u0IprO1k8QaYQiQ6H0_Jl8nlbUdaKQ4dN3UfW3UeTMPiNjMzkdZDq_bb1NULm_yWl8E42NW-EHOwKnlwzuNkjDv5ABRoqLJwxu0ZxfJUmKiohIwPb1NSZVxz6IrT-IohVv7c3iBIM-tVm4sfcP6V6ebA" + ], + "priority": [ + "100" + ], + "algorithm": [ + "HS512" + ] + } + }, + { + "id": "38766ab2-ebbe-40d3-af33-76dcd3f55a0d", + "name": "rsa-generated", + "providerId": "rsa-generated", + "subComponents": {}, + "config": { + "privateKey": [ + "MIIEowIBAAKCAQEAqL9dPI1YX4A/RzmFv83ygWUZmnl1wia37GhO++QIFTuTLWmvIZhZtNGcEMg1L4kif6R/1PBYjobNBvMNGccuroSh/kcoCYeO5waC9K08lRnBUQ40G+hLI3B/bwuddScq5sYTsdzLM+sWnDo8YndtYLaLDpjtjv0Vo3GJkMbKRqIxVdq5pdGIEDLouE3KjESjFTKbS12b8DAUetx8vWUxHchfkixYzsr54io/b7dzkWSxvJfpWMk5iCc4Nl71MgkpmcJ46//dj3qq7G3nTysEYzhr5g2vl2xW3dFqufOUgOQX/IidSncoSoN1Tkep5o1gUb3PB87Oh9BxtMMDUDKCcQIDAQABAoIBAAuZBWczPrrnlVHHnA/r72ohwPH7PZLvts3eeGk7Cawt6UZigFkif63cByonHHKtLewQagHAWBHJpX9ABqs6I5T2hCy2BsQq5zEtIyR+YI7N05nGzGGLpFhl87g11+dUnw/31qQvjN6/XlEz9nD9DM0sFqAU9iTQ86MFW2NSKlZS1CK7p/rnGnlwaKxpeQzPOhL+KxKZVCM4izib4DqKmdy2HDLM0eUtdvfw0VCgpgOmm2l2inVx0NHGX2sywy07W4aIYPSoFWnWSaweaycLRJCUGFSu6UAl/EZiYw5T3i5i/2K2PnLfOvTfVWCa6BXa4MjwXJTGaE525JNyYqagJ50CgYEA6m3oW9YB9p+W6FBeMeDXox86e0SMoO7vIlU2vSIQ4+rJ6i/vBf8kZJ8c6yeisnz7KDSYAxbTTQrVgdbDFq/K0VveaHpwtIpZW50WhWPJa/QZaMZUbq8HGieYVTju6VYnIxHgZFUQzBSjmcYWvkXH3JdOozC+M5WjYDlRPjLrIVUCgYEAuEZKcuw1n2s+vikYpdM8wNx6pLi+m/k+a4Yw1V15TogBvvKkfygt9MsHO7tb8kvVelotzF67aUB6+lvKZVnCve0a5YuSw+oqIggix8GOF1sXg95HQpS/wGgJdaDoONtbijX4epi/jwBGzOLep6NjVoa4WG8K+VQBrByLx97JDK0CgYEAlNzV//sVpBYTLdJa/jFYvSzHZh9RbaBMGfEioVdQgmpFbYCit5wc8AhZxLmWhuD2W8GKBewooXOPwLMvjuhyUh+US6P0jbCMrbBC7NFAxlxrBi1q0B401FbwVK2iiGk80Pg5FX0u/WjdungfWRPWpi0uslHxdbA/3oqHHIgY50ECgYAu3dG5gNHyhbgjbRhTtHHTK0AV/NadnLp/ZlWtLmTX0EeBZPzpSjLF+40PaAtuiFL3F1BmlgFcN4YPfqDvPfEFlPQuRV1Cbp/gn+kYnOWikwxcAYBmMqbCLLObMx1cuI2DjU5w/8BYgl1/ZoPyZt+w9fqUo0lLOE5kk64JW2QO0QKBgCHAJ5CECWjRi5JV6Y4tjcv1gvncGwWp2echFfXMHv65VycUs4tZQxkYDmzOpnUYJvB81aJL6jXEcc7lrFqV0KJZe2T/ZDtHGDi0JaE0tvDpTFEeMdnT3c3zzL1MvtvRt470fbtj7dcCPyyVor89lxaI3faRpKNprOCOlazAIVnZ" + ], + "certificate": [ + "MIICmTCCAYECBgGaFVZtlDANBgkqhkiG9w0BAQsFADAQMQ4wDAYDVQQDDAViYXN5eDAeFw0yNTEwMjQwODI3NTdaFw0zNTEwMjQwODI5MzdaMBAxDjAMBgNVBAMMBWJhc3l4MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqL9dPI1YX4A/RzmFv83ygWUZmnl1wia37GhO++QIFTuTLWmvIZhZtNGcEMg1L4kif6R/1PBYjobNBvMNGccuroSh/kcoCYeO5waC9K08lRnBUQ40G+hLI3B/bwuddScq5sYTsdzLM+sWnDo8YndtYLaLDpjtjv0Vo3GJkMbKRqIxVdq5pdGIEDLouE3KjESjFTKbS12b8DAUetx8vWUxHchfkixYzsr54io/b7dzkWSxvJfpWMk5iCc4Nl71MgkpmcJ46//dj3qq7G3nTysEYzhr5g2vl2xW3dFqufOUgOQX/IidSncoSoN1Tkep5o1gUb3PB87Oh9BxtMMDUDKCcQIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQAIYip9w0sGe1QIDOEsWCvAKBR5ssgaQxdL3GjRDql84bW7eODUD4+zj032k30MlTYMh6Cm9h1P9p+PiQP8FyZWSf1kAqXwmXs5qsA8UwbALpA2pa9xE13y9qJ90V9Ts/Ya429hjJM//HXfa54tA0Bxm+DZqOgIm72bB406iky3NlxnsB+Azuy2RX0RW1RaBBVJESA2cba/KUyGhoWNo7oIQio+M79pf/K3qh4d9dBQirwHmztUW728l5FIOliwBeNKUZNNS34Edva4InSwduept2WGy0AiftB+avgpOb15jMcjBvXrWfstUjktjvOdOBdDr0RsNS4RHWP2Cwd42Yg9" + ], + "priority": [ + "100" + ] + } + }, + { + "id": "79669e2a-829d-4b52-ae56-ba97f595db3e", + "name": "aes-generated", + "providerId": "aes-generated", + "subComponents": {}, + "config": { + "kid": [ + "549385c7-3644-4378-8db3-62d01eb8e6e7" + ], + "secret": [ + "goX6rQlS1kWubykYKn857w" + ], + "priority": [ + "100" + ] + } + }, + { + "id": "84db8e8f-afe5-4768-a5fa-8638d3716c6a", + "name": "rsa-enc-generated", + "providerId": "rsa-enc-generated", + "subComponents": {}, + "config": { + "privateKey": [ + "MIIEowIBAAKCAQEAqQmpZE4rdSvoxRSnkHXcaAcpMXb8WhIycO9F/AXl7sjQrg/PGz1PJzcdhYSK/jpDoNEP7NaqSrEmzgR6akedPi64ZBuozv9sZ4HOI7bFnlOlfGOKycHqjoHO6VUQlfAOdGyq2DL+8qD5kxLJhB2j2J2h9i6XGWaVOp4w/lE/hbqOONEuH9RVdXsgSExh+cfzl5zxy3/ccFVHE8/e0MVjpKM5CzyDYvFpjdxy/h+T3xmIGNUZEun7mu8FNdEIsphNgBm0G8AWzATkuQCsdFuL6HQGRDltDUxeQCRv1aYFfHHaUlCP/V8wZLbleXRTVJpP0WIreU6ESv2kYKsxjguQxQIDAQABAoIBAACZfDksgTR0iaorSTxDfFrlGmhAKD1HvvFa5xtkyCly5/4tQa2MNKvqfHqrZ+4zaQDlkbu9qvoO8bJXRNNI+j3AEiwOug6z5ex73IfDzFfw3k+LSQp8QaRfdJgSX54i7Ull7XkAI03bTgKCyLKxttG1np9K9oLvs9wZNz2SFOc/RIVV41FrJUjKuldUFA+J39hTqfZMR89d71+2NnfaEZBJILHJlkcd+xMbIfHLAagKcAo+rCjA9PoaiaE3LgwdScZ/t/vvDZXmEVdGTHfOerKeA1O1iV6r4TNdXdeUVSrRjgKweX6+6mulcGHcyOXsycYtY2iBmaz+UxirFiE1DJkCgYEA09PxF7d5ll4TAC6o52fQqS99gyLktBhzhi4hZ5/9xNMrLLEa6doBslr3bM3MbpYqE1C9LddqmvBfZlwHM1AP16iy3rsLV60T4qGxmMQXlVqDXAIy1fHenUkUkRGKT3an0cLBCpvFgTBAIu7ff8MEygsXy4rXGDBLnNFyCn5PK10CgYEAzElxZtnwk6iL05toIUpJd3L1+uXKx9Dr5UyPC5OG5rqua30eR21zAEkT/p3ZZXB6oMxf8LXHz2Q55tFoaIbIPM7DTq8+Y6eqbO1ADVmmeINbDuS6ycI5FjZ6hlXI10fmFbpc7s85W1Os99ff7JzjOJxRG9JDdc1+OVi6LGjpDIkCgYEAnHoHstlZ+/XqW0wcgTRzM0ddlC2GfHNDg284RfAt6eOEFTOPCgh9EF+aPsmXpmlPE42k8eQbX/EIx/hbaVBPI6P+3gGV02KLOfLv2kWgljeSqbkGDHzrUYzWoIMwhJrGRXF0YH3JXDFkb2m9uAc71nRzU2xwj/G9KU6ey5maqhECgYAjNGzkip5Y8+zU1K1HP2QVv6wARuWBNdHRPDZSimPvEzDHuVIkgQoWfIGDmXRDdPTNDStjchAy/1SzIFdb3A5Z3E/wGWcpCVXnW6N0KYT0s75XfLdr2Zq45z6KM/JelzdhezJUvUVnJa5jL8KZJhhKQzX/E2cov/cGrvG2gYXX8QKBgD7G1B44vf062QgXgLezGYmnQ8zED/dSXvpFJW8DtawsAPjIHp5N1cw2NvCT7XTiIlP6KbJT3DJLjLxxy2Sqn7/SbYsV1rXkQxenwrclFshKdY6uXadCN1a37yEHyONnUZuYakpIJa8jHpQI9gOnMIsCe0bIUxm+Bm6e7AmPeYLG" + ], + "certificate": [ + "MIICmTCCAYECBgGaFVZt9DANBgkqhkiG9w0BAQsFADAQMQ4wDAYDVQQDDAViYXN5eDAeFw0yNTEwMjQwODI3NTdaFw0zNTEwMjQwODI5MzdaMBAxDjAMBgNVBAMMBWJhc3l4MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqQmpZE4rdSvoxRSnkHXcaAcpMXb8WhIycO9F/AXl7sjQrg/PGz1PJzcdhYSK/jpDoNEP7NaqSrEmzgR6akedPi64ZBuozv9sZ4HOI7bFnlOlfGOKycHqjoHO6VUQlfAOdGyq2DL+8qD5kxLJhB2j2J2h9i6XGWaVOp4w/lE/hbqOONEuH9RVdXsgSExh+cfzl5zxy3/ccFVHE8/e0MVjpKM5CzyDYvFpjdxy/h+T3xmIGNUZEun7mu8FNdEIsphNgBm0G8AWzATkuQCsdFuL6HQGRDltDUxeQCRv1aYFfHHaUlCP/V8wZLbleXRTVJpP0WIreU6ESv2kYKsxjguQxQIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQBOqFKRkJeWGJnnqrlr3XFilMYI5ko1GASnSGvfVrWg7Pk6yDGwBe2v+nd7OG/yNJtbS97xPePeoVIXCEwzA8rhZDzfsYlrDvakn/5p8GpwJKAUtk1yRcI26hzANXAqKMWqAEtxtfEWtIn3j/asAe17Ara47MZMonsm5VxeqyFB1oDu94ht+Cq4vomjnucmC1DRUnliXTnKSBmLdWK/LrqR0Pgq7KrplKyiHlWBZEYFCKXmiRmtDJqF3QYFtHqxr/HjiPdlrJhUEhxyeKoi0q+dTYRhrpRa7MWwFlX/HTAWGWmW5VtaxlqqGctz9AWTNUzB86NdCguNYQq4uFllJal7" + ], + "priority": [ + "100" + ], + "algorithm": [ + "RSA-OAEP" + ] + } + } + ] + }, + "internationalizationEnabled": false, + "supportedLocales": [], + "authenticationFlows": [ + { + "id": "af0ffca2-f529-4e0c-8eb4-01c038b8836e", + "alias": "Account verification options", + "description": "Method with which to verity the existing account", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "idp-email-verification", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "ALTERNATIVE", + "priority": 20, + "autheticatorFlow": true, + "flowAlias": "Verify Existing Account by Re-authentication", + "userSetupAllowed": false + } + ] + }, + { + "id": "a747c2ad-0d8a-44c1-a75c-a176f8035bf4", + "alias": "Browser - Conditional OTP", + "description": "Flow to determine if the OTP is required for the authentication", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "auth-otp-form", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "922860b5-49e7-4b5a-b5a8-4efcef3008b5", + "alias": "Browser - Conditional Organization", + "description": "Flow to determine if the organization identity-first login is to be used", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "organization", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "3c27bad3-36ed-47f0-a03f-58a919ddcc5d", + "alias": "Direct Grant - Conditional OTP", + "description": "Flow to determine if the OTP is required for the authentication", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "direct-grant-validate-otp", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "52fe5237-4826-45e4-998b-f76d182b3a46", + "alias": "First Broker Login - Conditional Organization", + "description": "Flow to determine if the authenticator that adds organization members is to be used", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "idp-add-organization-member", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "86aab927-3928-42f0-ab71-2823232f740b", + "alias": "First broker login - Conditional OTP", + "description": "Flow to determine if the OTP is required for the authentication", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "auth-otp-form", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "0ba72201-1926-4f68-8ef9-04a0b8fedbda", + "alias": "Handle Existing Account", + "description": "Handle what to do if there is existing account with same email/username like authenticated identity provider", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "idp-confirm-link", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": true, + "flowAlias": "Account verification options", + "userSetupAllowed": false + } + ] + }, + { + "id": "56cb4036-7ebc-4cca-ae8d-ebc3bf61eeae", + "alias": "Organization", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticatorFlow": true, + "requirement": "CONDITIONAL", + "priority": 10, + "autheticatorFlow": true, + "flowAlias": "Browser - Conditional Organization", + "userSetupAllowed": false + } + ] + }, + { + "id": "ba9fadf4-e884-4ab9-bf10-513970afc696", + "alias": "Reset - Conditional OTP", + "description": "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "reset-otp", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "4da5a8e6-b854-407d-80fd-ec018cdfe4aa", + "alias": "User creation or linking", + "description": "Flow for the existing/non-existing user alternatives", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticatorConfig": "create unique user config", + "authenticator": "idp-create-user-if-unique", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "ALTERNATIVE", + "priority": 20, + "autheticatorFlow": true, + "flowAlias": "Handle Existing Account", + "userSetupAllowed": false + } + ] + }, + { + "id": "b56dbe8a-b7e5-424d-bb12-062eef357d98", + "alias": "Verify Existing Account by Re-authentication", + "description": "Reauthentication of existing account", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "idp-username-password-form", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "CONDITIONAL", + "priority": 20, + "autheticatorFlow": true, + "flowAlias": "First broker login - Conditional OTP", + "userSetupAllowed": false + } + ] + }, + { + "id": "8ab99073-7164-4de3-ae15-031f7ead63dc", + "alias": "browser", + "description": "Browser based authentication", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "auth-cookie", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "auth-spnego", + "authenticatorFlow": false, + "requirement": "DISABLED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "identity-provider-redirector", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 25, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "ALTERNATIVE", + "priority": 26, + "autheticatorFlow": true, + "flowAlias": "Organization", + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "ALTERNATIVE", + "priority": 30, + "autheticatorFlow": true, + "flowAlias": "forms", + "userSetupAllowed": false + } + ] + }, + { + "id": "d98a4fe6-7392-4e6b-a779-e9d567f36a92", + "alias": "clients", + "description": "Base authentication for clients", + "providerId": "client-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "client-secret", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "client-jwt", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "client-secret-jwt", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 30, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "client-x509", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 40, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "13744817-8b7d-42cc-b370-d94057f0c57a", + "alias": "direct grant", + "description": "OpenID Connect Resource Owner Grant", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "direct-grant-validate-username", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "direct-grant-validate-password", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "CONDITIONAL", + "priority": 30, + "autheticatorFlow": true, + "flowAlias": "Direct Grant - Conditional OTP", + "userSetupAllowed": false + } + ] + }, + { + "id": "0598b349-373f-452e-864e-7c9b0d5be266", + "alias": "docker auth", + "description": "Used by Docker clients to authenticate against the IDP", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "docker-http-basic-authenticator", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "580c4af6-6480-41ad-9123-f672c253eb42", + "alias": "first broker login", + "description": "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticatorConfig": "review profile config", + "authenticator": "idp-review-profile", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": true, + "flowAlias": "User creation or linking", + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "CONDITIONAL", + "priority": 50, + "autheticatorFlow": true, + "flowAlias": "First Broker Login - Conditional Organization", + "userSetupAllowed": false + } + ] + }, + { + "id": "05ecbd6b-1170-4460-a6e2-420e8d32ab07", + "alias": "forms", + "description": "Username, password, otp and other auth forms.", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "auth-username-password-form", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "CONDITIONAL", + "priority": 20, + "autheticatorFlow": true, + "flowAlias": "Browser - Conditional OTP", + "userSetupAllowed": false + } + ] + }, + { + "id": "5f743ce3-87da-441f-8d99-46b1a1535740", + "alias": "registration", + "description": "Registration flow", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "registration-page-form", + "authenticatorFlow": true, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": true, + "flowAlias": "registration form", + "userSetupAllowed": false + } + ] + }, + { + "id": "9815c239-18a5-4d42-bce5-649516ee6194", + "alias": "registration form", + "description": "Registration form", + "providerId": "form-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "registration-user-creation", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "registration-password-action", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 50, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "registration-recaptcha-action", + "authenticatorFlow": false, + "requirement": "DISABLED", + "priority": 60, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "registration-terms-and-conditions", + "authenticatorFlow": false, + "requirement": "DISABLED", + "priority": 70, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "2323a309-e3f9-4fa5-98c7-fbac4a3370ca", + "alias": "reset credentials", + "description": "Reset credentials for a user if they forgot their password or something", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "reset-credentials-choose-user", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "reset-credential-email", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "reset-password", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 30, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "CONDITIONAL", + "priority": 40, + "autheticatorFlow": true, + "flowAlias": "Reset - Conditional OTP", + "userSetupAllowed": false + } + ] + }, + { + "id": "eb2d3a0a-5e7f-4216-b2a9-f9e764879c78", + "alias": "saml ecp", + "description": "SAML ECP Profile Authentication Flow", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "http-basic-authenticator", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + } + ], + "authenticatorConfig": [ + { + "id": "83f1e02a-3909-4009-a586-6e79515dfd4a", + "alias": "create unique user config", + "config": { + "require.password.update.after.registration": "false" + } + }, + { + "id": "3a97fec7-4b67-45ff-9e8b-50dd7ad8c010", + "alias": "review profile config", + "config": { + "update.profile.on.first.login": "missing" + } + } + ], + "requiredActions": [ + { + "alias": "CONFIGURE_TOTP", + "name": "Configure OTP", + "providerId": "CONFIGURE_TOTP", + "enabled": true, + "defaultAction": false, + "priority": 10, + "config": {} + }, + { + "alias": "TERMS_AND_CONDITIONS", + "name": "Terms and Conditions", + "providerId": "TERMS_AND_CONDITIONS", + "enabled": false, + "defaultAction": false, + "priority": 20, + "config": {} + }, + { + "alias": "UPDATE_PASSWORD", + "name": "Update Password", + "providerId": "UPDATE_PASSWORD", + "enabled": true, + "defaultAction": false, + "priority": 30, + "config": {} + }, + { + "alias": "UPDATE_PROFILE", + "name": "Update Profile", + "providerId": "UPDATE_PROFILE", + "enabled": true, + "defaultAction": false, + "priority": 40, + "config": {} + }, + { + "alias": "VERIFY_EMAIL", + "name": "Verify Email", + "providerId": "VERIFY_EMAIL", + "enabled": true, + "defaultAction": false, + "priority": 50, + "config": {} + }, + { + "alias": "delete_account", + "name": "Delete Account", + "providerId": "delete_account", + "enabled": false, + "defaultAction": false, + "priority": 60, + "config": {} + }, + { + "alias": "webauthn-register", + "name": "Webauthn Register", + "providerId": "webauthn-register", + "enabled": true, + "defaultAction": false, + "priority": 70, + "config": {} + }, + { + "alias": "webauthn-register-passwordless", + "name": "Webauthn Register Passwordless", + "providerId": "webauthn-register-passwordless", + "enabled": true, + "defaultAction": false, + "priority": 80, + "config": {} + }, + { + "alias": "VERIFY_PROFILE", + "name": "Verify Profile", + "providerId": "VERIFY_PROFILE", + "enabled": true, + "defaultAction": false, + "priority": 90, + "config": {} + }, + { + "alias": "delete_credential", + "name": "Delete Credential", + "providerId": "delete_credential", + "enabled": true, + "defaultAction": false, + "priority": 100, + "config": {} + }, + { + "alias": "update_user_locale", + "name": "Update User Locale", + "providerId": "update_user_locale", + "enabled": true, + "defaultAction": false, + "priority": 1000, + "config": {} + } + ], + "browserFlow": "browser", + "registrationFlow": "registration", + "directGrantFlow": "direct grant", + "resetCredentialsFlow": "reset credentials", + "clientAuthenticationFlow": "clients", + "dockerAuthenticationFlow": "docker auth", + "firstBrokerLoginFlow": "first broker login", + "attributes": { + "cibaBackchannelTokenDeliveryMode": "poll", + "cibaAuthRequestedUserHint": "login_hint", + "clientOfflineSessionMaxLifespan": "0", + "oauth2DevicePollingInterval": "5", + "clientSessionIdleTimeout": "0", + "clientOfflineSessionIdleTimeout": "0", + "cibaInterval": "5", + "realmReusableOtpCode": "false", + "cibaExpiresIn": "120", + "oauth2DeviceCodeLifespan": "600", + "parRequestUriLifespan": "60", + "clientSessionMaxLifespan": "0", + "frontendUrl": "", + "organizationsEnabled": "false", + "acr.loa.map": "{}" + }, + "keycloakVersion": "26.0.6", + "userManagedAccessAllowed": false, + "organizationsEnabled": false, + "clientProfiles": { + "profiles": [] + }, + "clientPolicies": { + "policies": [] + } +} diff --git a/examples/securedExample/security_env/access-rules.json b/examples/securedExample/security_env/access-rules.json new file mode 100644 index 00000000..5d790af8 --- /dev/null +++ b/examples/securedExample/security_env/access-rules.json @@ -0,0 +1,115 @@ +{ + "AllAccessPermissionRules": { + "DEFATTRIBUTES": [ + { "name": "anonymous_attr", "attributes": [{ "GLOBAL": "ANONYMOUS" }] }, + { "name": "role_attr", "attributes": [{ "CLAIM": "role" }] } + ], + "DEFOBJECTS": [ + { + "name": "all_api", + "objects": [ + { "ROUTE": "/health" }, + { "ROUTE": "/description" }, + { "ROUTE": "/shell-descriptors" }, + { "ROUTE": "/shell-descriptors/*" }, + { "ROUTE": "/submodel-descriptors" }, + { "ROUTE": "/submodel-descriptors/*" }, + { "ROUTE": "/lookup/shells" }, + { "ROUTE": "/lookup/shells/*" }, + { "ROUTE": "/lookup/shellsByAssetLink" }, + { "ROUTE": "/shells" }, + { "ROUTE": "/shells/*" }, + { "ROUTE": "/submodels" }, + { "ROUTE": "/submodels/*" }, + { "ROUTE": "/concept-descriptions" }, + { "ROUTE": "/concept-descriptions/*" } + ] + }, + { + "name": "anonymous_allowed_identifiables", + "objects": [ + { "IDENTIFIABLE": "$aas(\"https://mm-software.com/aas/aasTemplate\")" }, + { "IDENTIFIABLE": "$sm(\"https://admin-shell.io/idta/SubmodelTemplate/DigitalNameplate/3/0\")" }, + { "IDENTIFIABLE": "$sm(\"https://admin-shell.io/idta/SubmodelTemplate/CarbonFootprint/1/0\")" }, + { "DESCRIPTOR": "$aasdesc(\"https://mm-software.com/aas/aasTemplate\")" }, + { "DESCRIPTOR": "$smdesc(\"https://admin-shell.io/idta/SubmodelTemplate/DigitalNameplate/3/0\")" }, + { "DESCRIPTOR": "$smdesc(\"https://admin-shell.io/idta/SubmodelTemplate/CarbonFootprint/1/0\")" } + ] + }, + { + "name": "viewer_allowed_identifiables", + "objects": [ + { "IDENTIFIABLE": "$aas(\"https://mm-software.com/aas/aasTemplate\")" }, + { "IDENTIFIABLE": "$sm(\"https://admin-shell.io/idta/SubmodelTemplate/DigitalNameplate/3/0\")" }, + { "IDENTIFIABLE": "$sm(\"https://admin-shell.io/idta/SubmodelTemplate/CarbonFootprint/1/0\")" }, + { "IDENTIFIABLE": "$sm(\"https://admin-shell.io/idta/SubmodelTemplate/ContactInformation/1/0\")" }, + { "IDENTIFIABLE": "$sm(\"https://admin-shell.io/idta/SubmodelTemplate/HandoverDocumentation/2/0\")" }, + { "DESCRIPTOR": "$aasdesc(\"https://mm-software.com/aas/aasTemplate\")" }, + { "DESCRIPTOR": "$smdesc(\"https://admin-shell.io/idta/SubmodelTemplate/DigitalNameplate/3/0\")" }, + { "DESCRIPTOR": "$smdesc(\"https://admin-shell.io/idta/SubmodelTemplate/CarbonFootprint/1/0\")" }, + { "DESCRIPTOR": "$smdesc(\"https://admin-shell.io/idta/SubmodelTemplate/ContactInformation/1/0\")" }, + { "DESCRIPTOR": "$smdesc(\"https://admin-shell.io/idta/SubmodelTemplate/HandoverDocumentation/2/0\")" } + ] + }, + { + "name": "anonymous_concept_descriptions_all", + "objects": [ + { "ROUTE": "/concept-descriptions" }, + { "ROUTE": "/concept-descriptions/*" } + ] + } + ], + "DEFACLS": [ + { + "name": "anonymous_read", + "acl": { "USEATTRIBUTES": "anonymous_attr", "RIGHTS": ["READ"], "ACCESS": "ALLOW" } + }, + { + "name": "viewer_read", + "acl": { "USEATTRIBUTES": "role_attr", "RIGHTS": ["READ"], "ACCESS": "ALLOW" } + }, + { + "name": "admin_all", + "acl": { "USEATTRIBUTES": "role_attr", "RIGHTS": ["ALL"], "ACCESS": "ALLOW" } + } + ], + "DEFFORMULAS": [ + { "name": "always_true", "formula": { "$boolean": true } }, + { + "name": "is_admin", + "formula": { "$eq": [{ "$attribute": { "CLAIM": "role" } }, { "$strVal": "admin" }] } + }, + { + "name": "is_viewer", + "formula": { "$eq": [{ "$attribute": { "CLAIM": "role" } }, { "$strVal": "viewer" }] } + } + ], + "rules": [ + { + "USEACL": "anonymous_read", + "USEOBJECTS": ["anonymous_allowed_identifiables"], + "FORMULA": { "$boolean": true } + }, + { + "USEACL": "anonymous_read", + "USEOBJECTS": ["anonymous_concept_descriptions_all"], + "FORMULA": { "$boolean": true } + }, + { + "USEACL": "viewer_read", + "USEOBJECTS": ["viewer_allowed_identifiables"], + "USEFORMULA": "is_viewer" + }, + { + "USEACL": "viewer_read", + "USEOBJECTS": ["anonymous_concept_descriptions_all"], + "USEFORMULA": "is_viewer" + }, + { + "USEACL": "admin_all", + "USEOBJECTS": ["all_api"], + "USEFORMULA": "is_admin" + } + ] + } +} diff --git a/examples/securedExample/security_env/trustlist.json b/examples/securedExample/security_env/trustlist.json new file mode 100644 index 00000000..d7f57095 --- /dev/null +++ b/examples/securedExample/security_env/trustlist.json @@ -0,0 +1,7 @@ +[ + { + "issuer": "http://keycloak.localhost:9090/realms/basyx", + "audience": "account", + "scopes": ["email", "profile"] + } +] diff --git a/example/aas/CarbonFootprint.xml b/examples/shared/aas/CarbonFootprint.xml similarity index 100% rename from example/aas/CarbonFootprint.xml rename to examples/shared/aas/CarbonFootprint.xml diff --git a/example/aas/HandoverDocumentation.xml b/examples/shared/aas/HandoverDocumentation.xml similarity index 100% rename from example/aas/HandoverDocumentation.xml rename to examples/shared/aas/HandoverDocumentation.xml diff --git a/example/aas/MaintenanceInstructions.xml b/examples/shared/aas/MaintenanceInstructions.xml similarity index 100% rename from example/aas/MaintenanceInstructions.xml rename to examples/shared/aas/MaintenanceInstructions.xml diff --git a/example/aas/Nameplate.xml b/examples/shared/aas/Nameplate.xml similarity index 100% rename from example/aas/Nameplate.xml rename to examples/shared/aas/Nameplate.xml diff --git a/example/aas/ShellTemplate.xml b/examples/shared/aas/ShellTemplate.xml similarity index 100% rename from example/aas/ShellTemplate.xml rename to examples/shared/aas/ShellTemplate.xml diff --git a/example/aas/TechnicalData.xml b/examples/shared/aas/TechnicalData.xml similarity index 100% rename from example/aas/TechnicalData.xml rename to examples/shared/aas/TechnicalData.xml diff --git a/example/data/checkmark.png b/examples/shared/data/checkmark.png similarity index 100% rename from example/data/checkmark.png rename to examples/shared/data/checkmark.png diff --git a/example/data/dummy_document.jpg b/examples/shared/data/dummy_document.jpg similarity index 100% rename from example/data/dummy_document.jpg rename to examples/shared/data/dummy_document.jpg diff --git a/example/data/dummy_document.pdf b/examples/shared/data/dummy_document.pdf similarity index 100% rename from example/data/dummy_document.pdf rename to examples/shared/data/dummy_document.pdf diff --git a/example/data/product1-1.png b/examples/shared/data/product1-1.png similarity index 100% rename from example/data/product1-1.png rename to examples/shared/data/product1-1.png diff --git a/example/data/product1.jpg b/examples/shared/data/product1.jpg similarity index 100% rename from example/data/product1.jpg rename to examples/shared/data/product1.jpg diff --git a/example/data/product2.jpg b/examples/shared/data/product2.jpg similarity index 100% rename from example/data/product2.jpg rename to examples/shared/data/product2.jpg diff --git a/example/data/product3-1.png b/examples/shared/data/product3-1.png similarity index 100% rename from example/data/product3-1.png rename to examples/shared/data/product3-1.png diff --git a/example/data/product3.jpg b/examples/shared/data/product3.jpg similarity index 100% rename from example/data/product3.jpg rename to examples/shared/data/product3.jpg diff --git a/example/logo/MM_Logo.svg b/examples/shared/logo/MM_Logo.svg similarity index 100% rename from example/logo/MM_Logo.svg rename to examples/shared/logo/MM_Logo.svg diff --git a/example/nginx/default.conf.template b/examples/shared/nginx/default.conf.template similarity index 96% rename from example/nginx/default.conf.template rename to examples/shared/nginx/default.conf.template index 5202530a..aa4a2100 100644 --- a/example/nginx/default.conf.template +++ b/examples/shared/nginx/default.conf.template @@ -74,7 +74,7 @@ server { limit_except GET OPTIONS { deny all; } - proxy_pass http://template-repository:8081; + proxy_pass http://template-repository-registry:8082; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; @@ -86,7 +86,7 @@ server { limit_except GET OPTIONS { deny all; } - proxy_pass http://template-repository:8081; + proxy_pass http://template-repository-registry:8082; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; @@ -135,7 +135,7 @@ server { limit_except GET OPTIONS { deny all; } - proxy_pass http://sm-template-registry:8080; + proxy_pass http://template-repository-registry:8082; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; diff --git a/examples/shared/postgres/00_init_basyx_db.sql b/examples/shared/postgres/00_init_basyx_db.sql new file mode 100644 index 00000000..2499c52c --- /dev/null +++ b/examples/shared/postgres/00_init_basyx_db.sql @@ -0,0 +1,5 @@ +-- Create an additional database for BaSyx Go components in the same Postgres instance. +SELECT 'CREATE DATABASE "basyxTestDB"' +WHERE NOT EXISTS ( + SELECT FROM pg_database WHERE datname = 'basyxTestDB' +)\gexec diff --git a/example/postgres/01_init_tables.sql b/examples/shared/postgres/01_init_tables.sql similarity index 100% rename from example/postgres/01_init_tables.sql rename to examples/shared/postgres/01_init_tables.sql diff --git a/example/postgres/02_init_data.sql b/examples/shared/postgres/02_init_data.sql similarity index 100% rename from example/postgres/02_init_data.sql rename to examples/shared/postgres/02_init_data.sql diff --git a/example/postgres/schema/01_core_asset_tables.sql.inc b/examples/shared/postgres/schema/01_core_asset_tables.sql.inc similarity index 100% rename from example/postgres/schema/01_core_asset_tables.sql.inc rename to examples/shared/postgres/schema/01_core_asset_tables.sql.inc diff --git a/example/postgres/schema/02_nameplate_carbonfootprint_technicaldata.sql.inc b/examples/shared/postgres/schema/02_nameplate_carbonfootprint_technicaldata.sql.inc similarity index 100% rename from example/postgres/schema/02_nameplate_carbonfootprint_technicaldata.sql.inc rename to examples/shared/postgres/schema/02_nameplate_carbonfootprint_technicaldata.sql.inc diff --git a/example/postgres/schema/03_MaintenanceInstructions.sql.inc b/examples/shared/postgres/schema/03_MaintenanceInstructions.sql.inc similarity index 100% rename from example/postgres/schema/03_MaintenanceInstructions.sql.inc rename to examples/shared/postgres/schema/03_MaintenanceInstructions.sql.inc diff --git a/example/postgres/schema/04_handoverdocumentation.sql.inc b/examples/shared/postgres/schema/04_handoverdocumentation.sql.inc similarity index 100% rename from example/postgres/schema/04_handoverdocumentation.sql.inc rename to examples/shared/postgres/schema/04_handoverdocumentation.sql.inc diff --git a/example/postgres/seed/01_core_asset_tables.sql.inc b/examples/shared/postgres/seed/01_core_asset_tables.sql.inc similarity index 78% rename from example/postgres/seed/01_core_asset_tables.sql.inc rename to examples/shared/postgres/seed/01_core_asset_tables.sql.inc index 9b4d1e70..f6adbc2f 100644 --- a/example/postgres/seed/01_core_asset_tables.sql.inc +++ b/examples/shared/postgres/seed/01_core_asset_tables.sql.inc @@ -16,9 +16,11 @@ INSERT INTO "Asset" ( 'https://mm-software.com/ids/assets/000-001', 'https://mm-software.com/ids/aas/000-001', 'image/jpeg', -'https://raw.githubusercontent.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/example/data/product1.jpg', +('https://raw.githubusercontent.com/AAS-TwinEngine/' || +'AAS.TwinEngine.DataEngine/refs/heads/main/examples/shared/data/product1.jpg'), TRUE, -'https://raw.githubusercontent.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/example/data/product1.jpg', +('https://raw.githubusercontent.com/AAS-TwinEngine/' || +'AAS.TwinEngine.DataEngine/refs/heads/main/examples/shared/data/product1.jpg'), 'FM-ABC-1234', 'FMABC1234', 'FM11-ABC22-123456', @@ -40,7 +42,8 @@ TRUE, 'https://mmsoftwaregmbh.sharepoint.com/_api/siteiconmanager/getsitelogo?type=%271%27&hash=638518734598723853', '123456', 'EEA-EX-200-S/47-Q3', -'https://raw.githubusercontent.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/example/data/product1.jpg', +('https://raw.githubusercontent.com/AAS-TwinEngine/' || +'AAS.TwinEngine.DataEngine/refs/heads/main/examples/shared/data/product1.jpg'), 'https://mmsoftwaregmbh.sharepoint.com/_api/siteiconmanager/getsitelogo?type=%271%27&hash=638518734598723853', 'Restricted use', 'Eingeschränkte Nutzung', @@ -62,9 +65,11 @@ TRUE, 'https://mm-software.com/ids/assets/000-002', 'https://mm-software.com/ids/aas/000-002', 'image/jpeg', -'https://raw.githubusercontent.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/example/data/product2.jpg', +('https://raw.githubusercontent.com/AAS-TwinEngine/' || +'AAS.TwinEngine.DataEngine/refs/heads/main/examples/shared/data/product2.jpg'), FALSE, -'https://raw.githubusercontent.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/example/data/product2.jpg', +('https://raw.githubusercontent.com/AAS-TwinEngine/' || +'AAS.TwinEngine.DataEngine/refs/heads/main/examples/shared/data/product2.jpg'), 'FM-ABC-1235', 'FMABC1238', 'FM11-ABC22-123458', @@ -86,7 +91,8 @@ FALSE, 'https://mmsoftwaregmbh.sharepoint.com/_api/siteiconmanager/getsitelogo?type=%271%27&hash=638518734598723853', '123456', 'EEA-EX-200-S/47-Q4', -'https://raw.githubusercontent.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/example/data/product2.jpg', +('https://raw.githubusercontent.com/AAS-TwinEngine/' || +'AAS.TwinEngine.DataEngine/refs/heads/main/examples/shared/data/product2.jpg'), 'https://mmsoftwaregmbh.sharepoint.com/_api/siteiconmanager/getsitelogo?type=%271%27&hash=638518734598723853', 'Restricted use', 'Eingeschränkte Nutzung', @@ -108,9 +114,11 @@ FALSE, 'https://mm-software.com/ids/assets/001-001', 'https://mm-software.com/ids/aas/001-001', 'image/jpeg', -'https://raw.githubusercontent.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/example/data/product3.jpg', +('https://raw.githubusercontent.com/AAS-TwinEngine/' || +'AAS.TwinEngine.DataEngine/refs/heads/main/examples/shared/data/product3.jpg'), TRUE, -'https://raw.githubusercontent.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/example/data/product3.jpg', +('https://raw.githubusercontent.com/AAS-TwinEngine/' || +'AAS.TwinEngine.DataEngine/refs/heads/main/examples/shared/data/product3.jpg'), 'TM-ABC-1680', 'TMABC1680', 'TM11-ABC22-123456', @@ -132,7 +140,8 @@ TRUE, 'https://mmsoftwaregmbh.sharepoint.com/_api/siteiconmanager/getsitelogo?type=%271%27&hash=638518734598723853', '123456', 'EEA-EX-200-S/47-Q5', -'https://raw.githubusercontent.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/example/data/product3.jpg', +('https://raw.githubusercontent.com/AAS-TwinEngine/' || +'AAS.TwinEngine.DataEngine/refs/heads/main/examples/shared/data/product3.jpg'), 'https://mmsoftwaregmbh.sharepoint.com/_api/siteiconmanager/getsitelogo?type=%271%27&hash=638518734598723853', 'Restricted use', 'Eingeschränkte Nutzung', diff --git a/example/postgres/seed/02_nameplate_carbonfootprint_technicaldata.sql.inc b/examples/shared/postgres/seed/02_nameplate_carbonfootprint_technicaldata.sql.inc similarity index 92% rename from example/postgres/seed/02_nameplate_carbonfootprint_technicaldata.sql.inc rename to examples/shared/postgres/seed/02_nameplate_carbonfootprint_technicaldata.sql.inc index 6ec0625e..32560e0c 100644 --- a/example/postgres/seed/02_nameplate_carbonfootprint_technicaldata.sql.inc +++ b/examples/shared/postgres/seed/02_nameplate_carbonfootprint_technicaldata.sql.inc @@ -4,19 +4,19 @@ INSERT INTO "Marking" VALUES (0,'0173-1#07-DAA603#004','KEMA99IECEX1105/128','2022-01-01','2030-01-01','additional information on the marking - 00', ('https://raw.githubusercontent.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/' || - 'main/example/data/checkmark.png')), + 'main/examples/shared/data/checkmark.png')), (0,'0173-1#07-DAA603#005','KEMA99IECEX1105/129','2022-02-01','2030-02-01','additional information on the marking - 01', ('https://raw.githubusercontent.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/' || - 'main/example/data/checkmark.png')), + 'main/examples/shared/data/checkmark.png')), (1,'0173-1#07-DAA603#006','KEMA99IECEX1105/130','2022-03-01','2030-03-01','additional information on the marking - 02', ('https://raw.githubusercontent.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/' || - 'main/example/data/checkmark.png')), + 'main/examples/shared/data/checkmark.png')), (0,'0173-1#07-DAA603#007','KEMA99IECEX1105/131','2022-04-01','2030-04-01','additional information on the marking - 03', ('https://raw.githubusercontent.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/' || - 'main/example/data/checkmark.png')), + 'main/examples/shared/data/checkmark.png')), (1,'0173-1#07-DAA603#008','KEMA99IECEX1105/132','2022-05-01','2030-05-01','additional information on the marking - 04', ('https://raw.githubusercontent.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/' || - 'main/example/data/checkmark.png')); + 'main/examples/shared/data/checkmark.png')); -- ============================================================ -- Asset-Marking Relationships @@ -47,7 +47,7 @@ VALUES 1, 0, ('https://raw.githubusercontent.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/' || - 'main/example/data/product1.jpg'), + 'main/examples/shared/data/product1.jpg'), 'Front view of the machine showing external and structure', 'Frontansicht der Maschine, die äußere und strukturelle Ansicht zeigt' ), @@ -56,7 +56,7 @@ VALUES 2, 1, ('https://raw.githubusercontent.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/' || - 'develop/example/data/product1-1.png'), + 'develop/examples/shared/data/product1-1.png'), 'Side view of the machine showing external and structure', 'Seitenansicht der Maschine, die äußere und strukturelle Ansicht zeigt' ), @@ -65,7 +65,7 @@ VALUES 3, 0, ('https://raw.githubusercontent.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/' || - 'main/example/data/product2.jpg'), + 'main/examples/shared/data/product2.jpg'), 'Front view of the machine showing external and structure', 'Frontansicht der Maschine, die äußere und strukturelle Ansicht zeigt' ), @@ -74,7 +74,7 @@ VALUES 4, 1, ('https://raw.githubusercontent.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/' || - 'develop/example/data/product3-1.png'), + 'develop/examples/shared/data/product3-1.png'), 'Side view of the machine showing external and structure', 'Seitenansicht der Maschine, die äußere und strukturelle Ansicht zeigt' ), @@ -83,7 +83,7 @@ VALUES 5, 0, ('https://raw.githubusercontent.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/' || - 'main/example/data/product3.jpg'), + 'main/examples/shared/data/product3.jpg'), 'Front view of the machine showing external and structure', 'Frontansicht der Maschine, die äußere und strukturelle Ansicht zeigt' ); diff --git a/example/postgres/seed/03_MaintenanceInstructions.sql.inc b/examples/shared/postgres/seed/03_MaintenanceInstructions.sql.inc similarity index 90% rename from example/postgres/seed/03_MaintenanceInstructions.sql.inc rename to examples/shared/postgres/seed/03_MaintenanceInstructions.sql.inc index ecd21fed..78c0e122 100644 --- a/example/postgres/seed/03_MaintenanceInstructions.sql.inc +++ b/examples/shared/postgres/seed/03_MaintenanceInstructions.sql.inc @@ -30,7 +30,7 @@ INSERT INTO "MaintenanceInstructionsForSpecificInterval" ( 'Stromversorgung trennen; Gegen Wiedereinschalten sichern; Spannungsfreiheit prüfen', 6,'months', ('https://raw.githubusercontent.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/' || -'main/example/data/dummy_document.pdf'), +'main/examples/shared/data/dummy_document.pdf'), 2, 'Qualified maintenance technician required', 'Qualifizierter Wartungstechniker erforderlich', @@ -47,7 +47,7 @@ INSERT INTO "MaintenanceInstructionsForSpecificInterval" ( 'Schutzhandschuhe tragen; System trennen; Filter entsorgen', 12,'months', ('https://raw.githubusercontent.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/' || -'main/example/data/dummy_document.pdf'), +'main/examples/shared/data/dummy_document.pdf'), 1, 'Certified technician required', 'Zertifizierter Techniker erforderlich', @@ -64,7 +64,7 @@ INSERT INTO "MaintenanceInstructionsForSpecificInterval" ( 'Fahrzeug sichern; Unterstellböcke verwenden; Schutzbrille tragen', 3,'months', ('https://raw.githubusercontent.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/' || -'main/example/data/dummy_document.pdf'), +'main/examples/shared/data/dummy_document.pdf'), 0, 'IEC/EN 60079-14 knowledge required', 'IEC/EN 60079-14 Kenntnisse erforderlich', @@ -81,7 +81,7 @@ INSERT INTO "MaintenanceInstructionsForSpecificInterval" ( 'Motor abkühlen lassen; Deckel langsam öffnen; Kontakt vermeiden', 4,'months', ('https://raw.githubusercontent.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/' || -'main/example/data/dummy_document.pdf'), +'main/examples/shared/data/dummy_document.pdf'), 1, 'IEC/EN 60079-19 knowledge required', 'IEC/EN 60079-19 Kenntnisse erforderlich', @@ -98,7 +98,7 @@ INSERT INTO "MaintenanceInstructionsForSpecificInterval" ( 'Batterie trennen; Funken vermeiden; Handschuhe tragen', 9,'months', ('https://raw.githubusercontent.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/' || -'main/example/data/dummy_document.pdf'), +'main/examples/shared/data/dummy_document.pdf'), 2, 'IEC/EN 61009-1 knowledge required', 'IEC/EN 61009-1 Kenntnisse erforderlich', @@ -239,22 +239,22 @@ INSERT INTO "Email" "PublicKey_en","PublicKey_de", "TypeOfPublicKey_en","TypeOfPublicKey_de") VALUES -(1,'aarav.sharma@example.in','0173-1#07-AAS754#001', +(1,'aarav.sharma@examples/shared.in','0173-1#07-AAS754#001', 'A1B2C3D4E5F67890ABCDEF1234567890ABCDEF12','A1B2C3D4E5F67890ABCDEF1234567890ABCDEF13', 'RSA Encryption','RSA-Verschlüsselung'), -(2,'lukas.mueller@example.de','0173-1#07-AAS756#001', +(2,'lukas.mueller@examples/shared.de','0173-1#07-AAS756#001', 'B2C3D4E5F67890ABCDEF1234567890ABCDEF1234','B2C3D4E5F67890ABCDEF1234567890ABCDEF1235', 'ECC Encryption','ECC-Verschlüsselung'), -(3,'priya.mehta@example.in','0173-1#07-AAS757#001', +(3,'priya.mehta@examples/shared.in','0173-1#07-AAS757#001', 'C3D4E5F67890ABCDEF1234567890ABCDEF123456','C3D4E5F67890ABCDEF1234567890ABCDEF123457', 'DSA Signature','DSA-Signatur'), -(4,'anna.schneider@example.de','0173-1#07-AAS758#001', +(4,'anna.schneider@examples/shared.de','0173-1#07-AAS758#001', 'E5F67890ABCDEF1234567890ABCDEF1234567890','E5F67890ABCDEF1234567890ABCDEF1234567891', 'EdDSA Signature','EdDSA-Signatur'), -(5,'wei.li@example.cn','0173-1#07-AAS754#001', +(5,'wei.li@examples/shared.cn','0173-1#07-AAS754#001', 'F67890ABCDEF1234567890ABCDEF1234567890AB','F67890ABCDEF1234567890ABCDEF1234567890AB', 'RSA Encryption','RSA-Verschlüsselung'), -(6,'johann.becker@example.de','0173-1#07-AAS756#001', +(6,'johann.becker@examples/shared.de','0173-1#07-AAS756#001', 'D4E5F67890ABCDEF1234567890ABCDEF12345678','D4E5F67890ABCDEF1234567890ABCDEF12345679', 'ECC Encryption','ECC-Verschlüsselung'); @@ -361,7 +361,7 @@ VALUES 'System is powered off','System ist ausgeschaltet', 'Power still active','Strom noch aktiv', ('https://raw.githubusercontent.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/' || -'main/example/data/dummy_document.pdf'), +'main/examples/shared/data/dummy_document.pdf'), 5,'minutes'), (1,'MS-002',0,0,NULL,2,TRUE,FALSE, 'Apply safety lockout','Sicherheitsverriegelung anwenden', @@ -370,7 +370,7 @@ VALUES 'Lockout applied','Verriegelung aktiv', 'Lockout failed','Verriegelung fehlgeschlagen', ('https://raw.githubusercontent.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/' || -'main/example/data/dummy_document.pdf'), +'main/examples/shared/data/dummy_document.pdf'), 10,'minutes'), (0,'MS-003',1,0,NULL,2,TRUE,FALSE, 'Inspect equipment','Gerät prüfen', @@ -379,7 +379,7 @@ VALUES 'No damage found','Keine Schäden gefunden', 'Damage detected','Schaden festgestellt', ('https://raw.githubusercontent.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/' || -'main/example/data/dummy_document.pdf'), +'main/examples/shared/data/dummy_document.pdf'), 15,'minutes'), (0,'MS-004',2,20,'ml',3,TRUE,FALSE, 'Replace filter','Filter austauschen', @@ -388,7 +388,7 @@ VALUES 'Filter OK','Filter in Ordnung', 'Fit issue','Problem erkannt', ('https://raw.githubusercontent.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/' || -'main/example/data/dummy_document.pdf'), +'main/examples/shared/data/dummy_document.pdf'), 20,'minutes'), (1,'MS-005',1,50,'ml',1,TRUE,FALSE, 'Add lubricant','Schmiermittel hinzufügen', @@ -397,7 +397,7 @@ VALUES 'Lubrication OK','Schmierung OK', 'Leak found','Leck erkannt', ('https://raw.githubusercontent.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/' || -'main/example/data/dummy_document.pdf'), +'main/examples/shared/data/dummy_document.pdf'), 10,'minutes'), (2,'MS-006',0,0,NULL,2,TRUE,FALSE, 'Test system','System testen', @@ -406,7 +406,7 @@ VALUES 'Test passed','Test bestanden', 'Test failed','Test fehlgeschlagen', ('https://raw.githubusercontent.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/' || -'main/example/data/dummy_document.pdf'), +'main/examples/shared/data/dummy_document.pdf'), 15,'minutes'), (1,'MS-007',0,0,NULL,1,TRUE,FALSE, 'Reconnect power','Stromversorgung wiederherstellen', @@ -415,7 +415,7 @@ VALUES 'Power OK','Strom OK', 'Failure','Fehler', ('https://raw.githubusercontent.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/' || -'main/example/data/dummy_document.pdf'), +'main/examples/shared/data/dummy_document.pdf'), 5,'minutes'), (1,'MS-008',0,0,NULL,1,TRUE,TRUE, 'End maintenance','Wartung beenden', @@ -424,7 +424,7 @@ VALUES 'Completed','Abgeschlossen', '-','-', ('https://raw.githubusercontent.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/' || -'main/example/data/dummy_document.pdf'), +'main/examples/shared/data/dummy_document.pdf'), 5,'minutes'); INSERT INTO "MaintenanceInstructionsForSpecificIntervalMaintenanceStep" @@ -450,39 +450,39 @@ INSERT INTO "MaintenanceTool" ( "MaxQuantityOfTool" ) VALUES -(0,'TL-001','BOSCH-TRX-T20','https://tools.example.com/t20', +(0,'TL-001','BOSCH-TRX-T20','https://tools.examples/shared.com/t20', 'Torx Screwdriver T20','Torx Schraubendreher T20', 'Bosch Tools','Bosch Werkzeuge', 'Torx screwdriver size T20, non-insulated, 100 mm length', 'Torx Schraubendreher Größe T20, nicht isoliert, 100 mm Länge', 2), -(1,'TL-002','SKF-WRENCH-SET','https://tools.example.com/wrench-set', +(1,'TL-002','SKF-WRENCH-SET','https://tools.examples/shared.com/wrench-set', 'Wrench Set','Schraubenschlüssel Set', 'SKF Industrial Tools','SKF Industrie Werkzeuge', 'Set of metric wrenches from 8 mm to 24 mm', 'Satz metrischer Schraubenschlüssel von 8 mm bis 24 mm', 1), -(0,'TL-003','FLUKE-MULTI-115','https://tools.example.com/multimeter', +(0,'TL-003','FLUKE-MULTI-115','https://tools.examples/shared.com/multimeter', 'Digital Multimeter','Digitales Multimeter', 'Fluke Corporation','Fluke Unternehmen', 'Digital multimeter for voltage, resistance, and continuity testing', 'Digitalmultimeter für Spannung, Widerstand und Durchgangsprüfung', 1), -(0,'TL-004','FACOM-PLIERS-SET','https://tools.example.com/pliers', +(0,'TL-004','FACOM-PLIERS-SET','https://tools.examples/shared.com/pliers', 'Pliers Set','Zangenset', 'Facom Tools','Facom Werkzeuge', 'Set of combination and needle-nose pliers for general maintenance', 'Satz aus Kombi- und Spitzzangen für allgemeine Wartung', 2), -(1,'TL-005','MAKITA-DRILL-18V','https://tools.example.com/drill', +(1,'TL-005','MAKITA-DRILL-18V','https://tools.examples/shared.com/drill', 'Cordless Drill','Akku-Bohrmaschine', 'Makita Corporation','Makita Unternehmen', '18V cordless drill with adjustable torque and battery system', '18V Akku-Bohrmaschine mit Drehmomentregelung und Batteriesystem', 1), -(2,'TL-006','STAHLWILLE-TORQUE-50','https://tools.example.com/torque-wrench', +(2,'TL-006','STAHLWILLE-TORQUE-50','https://tools.examples/shared.com/torque-wrench', 'Torque Wrench','Drehmomentschlüssel', 'Stahlwille GmbH','Stahlwille GmbH', 'Torque wrench up to 50 Nm for precise tightening', @@ -512,7 +512,7 @@ INSERT INTO "MaintenanceConsumable" ( "QuantityOfConsumable" ) VALUES -(0,'CS-001','ml','CASTROL-OIL-80W','https://consumables.example.com/oil', +(0,'CS-001','ml','CASTROL-OIL-80W','https://consumables.examples/shared.com/oil', 'Lubricating Oil','Schmieröl', 'Castrol Ltd','Castrol GmbH', 'High-performance mineral gear oil, SAE 80W, reduces wear and ensures smooth operation', @@ -520,7 +520,7 @@ VALUES 'Dispose via certified waste company. Avoid release into environment.', 'Entsorgung nur durch Fachbetrieb. Freisetzung in Umwelt vermeiden.', 50), -(1,'CS-002','pcs','KIMBERLY-CLOTH-BLUE','https://consumables.example.com/cloth', +(1,'CS-002','pcs','KIMBERLY-CLOTH-BLUE','https://consumables.examples/shared.com/cloth', 'Cleaning Cloth','Reinigungstuch', 'Kimberly-Clark','Kimberly-Clark GmbH', 'Blue industrial cleaning cloth, 380x380 mm, highly absorbent', @@ -528,7 +528,7 @@ VALUES 'Dispose as industrial waste. Do not reuse if contaminated.', 'Als Industrieabfall entsorgen. Nicht wiederverwenden bei Verschmutzung.', 20), -(2,'CS-003','ml','LOCTITE-THREADLOCK-243','https://consumables.example.com/loctite', +(2,'CS-003','ml','LOCTITE-THREADLOCK-243','https://consumables.examples/shared.com/loctite', 'Threadlocker Fluid','Schraubensicherungsmittel', 'Henkel AG','Henkel AG', 'Medium-strength threadlocker for securing bolts', @@ -536,7 +536,7 @@ VALUES 'Dispose as hazardous chemical waste. Avoid skin contact.', 'Als Sondermüll entsorgen. Hautkontakt vermeiden.', 10), -(0,'CS-004','g','MOLYKOTE-GREASE-HP','https://consumables.example.com/grease', +(0,'CS-004','g','MOLYKOTE-GREASE-HP','https://consumables.examples/shared.com/grease', 'Industrial Grease','Industrieschmierfett', 'Dow Chemical','Dow Chemical GmbH', 'High-performance grease for bearings', @@ -544,7 +544,7 @@ VALUES 'Dispose per hazardous waste regulations.', 'Entsorgung gemäß Vorschriften für gefährliche Abfälle.', 30), -(0,'CS-005','ml','DISTILLED-WATER-5L','https://consumables.example.com/water', +(0,'CS-005','ml','DISTILLED-WATER-5L','https://consumables.examples/shared.com/water', 'Distilled Water','Destilliertes Wasser', 'AquaPure Supplies','AquaPure Lieferanten', 'Purified water for cooling and cleaning', @@ -575,7 +575,7 @@ INSERT INTO "MaintenanceSparePart" ( "QuantityOfSparePart" ) VALUES -(0,'SP-001','BOSCH-BEARING-6205','https://spareparts.example.com/bearing', +(0,'SP-001','BOSCH-BEARING-6205','https://spareparts.examples/shared.com/bearing', 'Ball Bearing 6205','Kugellager 6205', 'Bosch Industrial','Bosch Industrie', 'Deep groove ball bearing, size 6205, high durability', @@ -583,7 +583,7 @@ VALUES 'Dispose via metal recycling.', 'Über Metallrecycling entsorgen.', 2), -(0,'SP-002','SKF-SEAL-RING-45','https://spareparts.example.com/seal', +(0,'SP-002','SKF-SEAL-RING-45','https://spareparts.examples/shared.com/seal', 'Seal Ring 45 mm','Dichtungsring 45 mm', 'SKF Group','SKF Gruppe', 'Rubber sealing ring 45 mm diameter', @@ -591,7 +591,7 @@ VALUES 'Dispose as rubber waste.', 'Als Gummiabfall entsorgen.', 1), -(0,'SP-003','SIEMENS-SENSOR-TEMP','https://spareparts.example.com/sensor', +(0,'SP-003','SIEMENS-SENSOR-TEMP','https://spareparts.examples/shared.com/sensor', 'Temperature Sensor','Temperatursensor', 'Siemens AG','Siemens AG', 'Industrial temperature sensor', @@ -599,7 +599,7 @@ VALUES 'Dispose as electronic waste.', 'Als Elektroschrott entsorgen.', 1), -(1,'SP-004','PANASONIC-BATTERY-CR2032','https://spareparts.example.com/battery', +(1,'SP-004','PANASONIC-BATTERY-CR2032','https://spareparts.examples/shared.com/battery', 'Button Cell Battery','Knopfzelle Batterie', 'Panasonic Corporation','Panasonic Unternehmen', 'Lithium button cell CR2032, 3V', diff --git a/example/postgres/seed/04_handoverdocumentation.sql.inc b/examples/shared/postgres/seed/04_handoverdocumentation.sql.inc similarity index 94% rename from example/postgres/seed/04_handoverdocumentation.sql.inc rename to examples/shared/postgres/seed/04_handoverdocumentation.sql.inc index f31e3195..6d626b3f 100644 --- a/example/postgres/seed/04_handoverdocumentation.sql.inc +++ b/examples/shared/postgres/seed/04_handoverdocumentation.sql.inc @@ -88,7 +88,7 @@ INSERT INTO "DocumentVersion" ( ( 0, 'https://docs.google.com/viewer?url=https://raw.githubusercontent.com/' - 'AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/example/data/dummy_document.pdf', + 'AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/examples/shared/data/dummy_document.pdf', '1', '2023-01-01', 'Released', @@ -103,13 +103,13 @@ INSERT INTO "DocumentVersion" ( 'DSLR, Camera, Photography, User Guide, Setup', 'DSLR, Kamera, Fotografie, Benutzerhandbuch, Einrichtung', 'https://raw.githubusercontent.com/' - 'AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/example/data/dummy_document.jpg' + 'AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/examples/shared/data/dummy_document.jpg' ), ( 1, 'https://docs.google.com/viewer?url=https://raw.githubusercontent.com/' - 'AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/example/data/dummy_document.pdf', + 'AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/examples/shared/data/dummy_document.pdf', '1.1', '2024-05-05', 'InReview', @@ -124,13 +124,13 @@ INSERT INTO "DocumentVersion" ( 'Mirrorless, Camera, Specs, Imaging, Performance', 'Spiegellos, Kamera, Spezifikationen, Bildgebung, Leistung', 'https://raw.githubusercontent.com/' - 'AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/example/data/dummy_document.jpg' + 'AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/examples/shared/data/dummy_document.jpg' ), ( 0, 'https://docs.google.com/viewer?url=https://raw.githubusercontent.com/' - 'AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/example/data/dummy_document.pdf', + 'AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/examples/shared/data/dummy_document.pdf', '2.1', '2026-01-01', 'Released', @@ -145,13 +145,13 @@ INSERT INTO "DocumentVersion" ( 'Lens, Maintenance, Cleaning, Professional, Care', 'Objektiv, Wartung, Reinigung, Professionell, Pflege', 'https://raw.githubusercontent.com/' - 'AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/example/data/dummy_document.jpg' + 'AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/examples/shared/data/dummy_document.jpg' ), ( 0, 'https://docs.google.com/viewer?url=https://raw.githubusercontent.com/' - 'AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/example/data/dummy_document.pdf', + 'AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/examples/shared/data/dummy_document.pdf', '2.3', '2025-10-10', 'InReview', @@ -166,13 +166,13 @@ INSERT INTO "DocumentVersion" ( 'Wide-Angle, Lens, Installation, Setup, Kit', 'Weitwinkel, Objektiv, Installation, Einrichtung, Set', 'https://raw.githubusercontent.com/' - 'AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/example/data/dummy_document.jpg' + 'AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/examples/shared/data/dummy_document.jpg' ), ( 0, 'https://docs.google.com/viewer?url=https://raw.githubusercontent.com/' - 'AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/example/data/dummy_document.pdf', + 'AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/examples/shared/data/dummy_document.pdf', '0.9', '2024-01-01', 'Released', @@ -187,13 +187,13 @@ INSERT INTO "DocumentVersion" ( 'Telephoto, Lens, Data Sheet, Specifications, Optics', 'Teleobjektiv, Objektiv, Datenblatt, Spezifikationen, Optik', 'https://raw.githubusercontent.com/' - 'AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/example/data/dummy_document.jpg' + 'AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/examples/shared/data/dummy_document.jpg' ), ( 0, 'https://docs.google.com/viewer?url=https://raw.githubusercontent.com/' - 'AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/example/data/dummy_document.pdf', + 'AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/examples/shared/data/dummy_document.pdf', '1.2', '2024-03-03', 'InReview', @@ -208,13 +208,13 @@ INSERT INTO "DocumentVersion" ( 'Safety, Camera, Accessories, Guidelines, Handling', 'Sicherheit, Kamera, Zubehör, Richtlinien, Handhabung', 'https://raw.githubusercontent.com/' - 'AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/example/data/dummy_document.jpg' + 'AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/examples/shared/data/dummy_document.jpg' ), ( 1, 'https://docs.google.com/viewer?url=https://raw.githubusercontent.com/' - 'AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/example/data/dummy_document.pdf', + 'AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/examples/shared/data/dummy_document.pdf', '1.4', '2023-01-01', 'Released', @@ -229,13 +229,13 @@ INSERT INTO "DocumentVersion" ( 'Perfume, Fragrance, Luxury, Catalog, Collection', 'Parfum, Duft, Luxus, Katalog, Kollektion', 'https://raw.githubusercontent.com/' - 'AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/example/data/dummy_document.jpg' + 'AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/examples/shared/data/dummy_document.jpg' ), ( 2, 'https://docs.google.com/viewer?url=https://raw.githubusercontent.com/' - 'AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/example/data/dummy_document.pdf', + 'AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/examples/shared/data/dummy_document.pdf', '2', '2024-03-03', 'InReview', @@ -250,13 +250,13 @@ INSERT INTO "DocumentVersion" ( 'Packaging, Perfume, Bottles, Caps, Compliance', 'Verpackung, Parfum, Flaschen, Verschlüsse, Konformität', 'https://raw.githubusercontent.com/' - 'AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/example/data/dummy_document.jpg' + 'AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/examples/shared/data/dummy_document.jpg' ), ( 0, 'https://docs.google.com/viewer?url=https://raw.githubusercontent.com/' - 'AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/example/data/dummy_document.pdf', + 'AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/examples/shared/data/dummy_document.pdf', '1', '2022-02-02', 'Released', @@ -271,7 +271,7 @@ INSERT INTO "DocumentVersion" ( 'Perfume, Fragrance, Luxury, Catalog, Collection', 'Parfum, Duft, Luxus, Katalog, Kollektion', 'https://raw.githubusercontent.com/' - 'AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/example/data/dummy_document.jpg' + 'AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/examples/shared/data/dummy_document.jpg' ); -- ============================================================ diff --git a/source/AAS.TwinEngine.Plugin.TestPlugin/Example/README.md b/source/AAS.TwinEngine.Plugin.TestPlugin/Example/README.md index eac771fa..29d0e497 100644 --- a/source/AAS.TwinEngine.Plugin.TestPlugin/Example/README.md +++ b/source/AAS.TwinEngine.Plugin.TestPlugin/Example/README.md @@ -5,9 +5,9 @@ This project provides a basic setup to demonstrate how **TwinEngine** can be int This example includes three submodels: -- Nameplate +- CustomSubmodel - ContactInformation -- Reliability +- HandoverDocumentation --- ## Default configuration @@ -15,6 +15,8 @@ This example includes three submodels: - `example/aas/` — contains default submodel templates (Nameplate, ContactInformation, Reliability). - `plugin/`— contain JSON files mounted into the plugin containers: Changes to these JSON files on the host not visible to the running containers, you must restart the container. +- BaSyx template repository runs as `eclipsebasyx/aasenvironment-go:SNAPSHOT`. +- BaSyx metadata storage is initialized through Postgres and `basyxconfigurationservice-go`. - Two services are built from local sources in the repo: @@ -28,10 +30,10 @@ Rebuild all images then restart: ``` bash # rebuild images -docker-compose build --no-cache +docker compose build --no-cache # restart the stack -docker-compose up -d +docker compose up -d ``` --- @@ -39,9 +41,9 @@ docker-compose up -d - If http://localhost:8080/aas-ui/ doesn't load: - Check docker-compose logs nginx for errors + Check `docker compose logs nginx` for errors - Make sure port **8080, 8081, 8082, 8083, 8085, 8086** is not used by another service. + Make sure port **8080, 8081, 8082, 8085, 8086** is not used by another service. - If a container fails to start because of bind port, stop whatever uses that port or change the mapping in `docker-compose.yml`. @@ -51,4 +53,4 @@ docker-compose up -d ``` - Verify the host path for the mounted volume is correct relative to the example folder. ---- \ No newline at end of file +--- diff --git a/source/AAS.TwinEngine.Plugin.TestPlugin/Example/docker-compose.yml b/source/AAS.TwinEngine.Plugin.TestPlugin/Example/docker-compose.yml index 863e4594..bd4f98e7 100644 --- a/source/AAS.TwinEngine.Plugin.TestPlugin/Example/docker-compose.yml +++ b/source/AAS.TwinEngine.Plugin.TestPlugin/Example/docker-compose.yml @@ -2,9 +2,12 @@ networks: dataengine-network: name: dataengine-network +volumes: + postgres-data: + services: nginx: - image: nginx:latest + image: nginx:trixie-perl container_name: nginx ports: - "8080:80" @@ -13,12 +16,8 @@ services: - ./nginx/default.conf.template:/etc/nginx/templates/default.conf.template restart: always depends_on: - aas-template-registry: - condition: service_healthy - sm-template-registry: - condition: service_healthy - template-repository: - condition: service_healthy + template-repository-registry: + condition: service_started networks: - dataengine-network @@ -28,7 +27,7 @@ services: dockerfile: ./AAS.TwinEngine.DataEngine/Dockerfile image: twinengine-dataengine:latest ports: - - '8085:8080' + - "8085:8080" container_name: twinengine-dataengine depends_on: twinengine-plugin: @@ -58,32 +57,32 @@ services: - TemplateManagement__TemplateMappingRules__AasIdExtractionRules__0__Pattern=/ - TemplateManagement__TemplateMappingRules__AasIdExtractionRules__0__Index=5 - TemplateManagement__AasTemplateRepository__Name=AasTemplateRepository - - TemplateManagement__AasTemplateRepository__baseUrl=http://template-repository:8081 - - TemplateManagement__AasTemplateRepository__healthEndpoint=/actuator/health + - TemplateManagement__AasTemplateRepository__baseUrl=http://template-repository-registry:8082 + - TemplateManagement__AasTemplateRepository__healthEndpoint=/health - TemplateManagement__AasTemplateRepository__headerMappings__0__source=Authorization - TemplateManagement__AasTemplateRepository__headerMappings__0__target=Authorization - TemplateManagement__AasTemplateRepository__headerMappings__0__required=false - TemplateManagement__SubmodelTemplateRepository__Name=SubmodelTemplateRepository - - TemplateManagement__SubmodelTemplateRepository__baseUrl=http://template-repository:8081 - - TemplateManagement__SubmodelTemplateRepository__healthEndpoint=/actuator/health + - TemplateManagement__SubmodelTemplateRepository__baseUrl=http://template-repository-registry:8082 + - TemplateManagement__SubmodelTemplateRepository__healthEndpoint=/health - TemplateManagement__SubmodelTemplateRepository__headerMappings__0__source=Authorization - TemplateManagement__SubmodelTemplateRepository__headerMappings__0__target=Authorization - TemplateManagement__SubmodelTemplateRepository__headerMappings__0__required=false - TemplateManagement__ConceptDescriptionTemplateRepository__Name=ConceptDescriptionTemplateRepository - - TemplateManagement__ConceptDescriptionTemplateRepository__baseUrl=http://template-repository:8081 - - TemplateManagement__ConceptDescriptionTemplateRepository__healthEndpoint=/actuator/health + - TemplateManagement__ConceptDescriptionTemplateRepository__baseUrl=http://template-repository-registry:8082 + - TemplateManagement__ConceptDescriptionTemplateRepository__healthEndpoint=/health - TemplateManagement__ConceptDescriptionTemplateRepository__headerMappings__0__source=Authorization - TemplateManagement__ConceptDescriptionTemplateRepository__headerMappings__0__target=Authorization - TemplateManagement__ConceptDescriptionTemplateRepository__headerMappings__0__required=false - TemplateManagement__AasTemplateRegistry__Name=AasTemplateRegistry - - TemplateManagement__AasTemplateRegistry__baseUrl=http://aas-template-registry:8080 - - TemplateManagement__AasTemplateRegistry__healthEndpoint=/actuator/health + - TemplateManagement__AasTemplateRegistry__baseUrl=http://template-repository-registry:8082 + - TemplateManagement__AasTemplateRegistry__healthEndpoint=/health - TemplateManagement__AasTemplateRegistry__headerMappings__0__source=Authorization - TemplateManagement__AasTemplateRegistry__headerMappings__0__target=Authorization - TemplateManagement__AasTemplateRegistry__headerMappings__0__required=false - TemplateManagement__SubmodelTemplateRegistry__Name=SubmodelTemplateRegistry - - TemplateManagement__SubmodelTemplateRegistry__baseUrl=http://sm-template-registry:8080 - - TemplateManagement__SubmodelTemplateRegistry__healthEndpoint=/actuator/health + - TemplateManagement__SubmodelTemplateRegistry__baseUrl=http://template-repository-registry:8082 + - TemplateManagement__SubmodelTemplateRegistry__healthEndpoint=/health - TemplateManagement__SubmodelTemplateRegistry__headerMappings__0__source=Authorization - TemplateManagement__SubmodelTemplateRegistry__headerMappings__0__target=Authorization - TemplateManagement__SubmodelTemplateRegistry__headerMappings__0__required=false @@ -96,7 +95,7 @@ services: dockerfile: ./AAS.TwinEngine.Plugin.TestPlugin/Dockerfile image: twinengine-plugin:latest ports: - - '8086:8080' + - "8086:8080" container_name: twinengine-plugin restart: always volumes: @@ -111,47 +110,57 @@ services: networks: - dataengine-network - template-repository: - image: eclipsebasyx/aas-environment:2.0.0-SNAPSHOT - container_name: template-repository + template-repository-registry: + image: eclipsebasyx/aasenvironment-go:SNAPSHOT + container_name: template-repository-registry ports: - - "8081:8081" + - "8082:8082" + command: ["/app/aasenvironmentservice"] volumes: - - ./aas:/application/aas - - ./basyx/aas-env.properties:/application/application.properties + - ./aas:/app/preconfiguration:ro environment: - BASYX_EXTERNALURL : http://localhost:8080 + - SERVER_PORT=8082 + - CORS_ALLOWEDORIGINS=* + - CORS_ALLOWEDHEADERS=* + - CORS_ALLOWEDCREDENTIALS=true + - CORS_ALLOWEDMETHODS=GET,OPTIONS + - POSTGRES_HOST=postgres + - POSTGRES_PORT=5432 + - POSTGRES_USER=postgres + - POSTGRES_PASSWORD=admin + - POSTGRES_DBNAME=basyxTestDB + - POSTGRES_MAXOPENCONNECTIONS=500 + - POSTGRES_MAXIDLECONNECTIONS=500 + - POSTGRES_CONNMAXLIFETIMEMINUTES=5 + - ABAC_ENABLED=false + - GENERAL_AASREGISTRYINTEGRATION=true + - GENERAL_SUBMODELREGISTRYINTEGRATION=true + - GENERAL_DISCOVERYINTEGRATION=true + - GENERAL_EXTERNALURL=http://localhost:8080 + - GENERAL_AAS_PRECONFIG_PATHS=/app/preconfiguration restart: always depends_on: - aas-template-registry: - condition: service_healthy - sm-template-registry: - condition: service_healthy + basyx_configuration: + condition: service_completed_successfully networks: - dataengine-network - aas-template-registry: - image: eclipsebasyx/aas-registry-log-mongodb:2.0.0-SNAPSHOT - container_name: aas-template-registry - ports: - - '8082:8080' - restart: always - depends_on: - - mongo + basyx_configuration: + container_name: basyx_configuration + image: eclipsebasyx/basyxconfigurationservice-go:SNAPSHOT + pull_policy: always environment: - - SPRING_DATA_MONGODB_URI=mongodb://mongoAdmin:mongoPassword@mongo:27017 - networks: - - dataengine-network - - sm-template-registry: - image: eclipsebasyx/submodel-registry-log-mongodb:2.0.0-SNAPSHOT - container_name: sm-template-registry - ports: - - '8083:8080' + - POSTGRES_HOST=postgres + - POSTGRES_PORT=5432 + - POSTGRES_USER=postgres + - POSTGRES_PASSWORD=admin + - POSTGRES_DBNAME=basyxTestDB + - POSTGRES_MAXOPENCONNECTIONS=500 + - POSTGRES_MAXIDLECONNECTIONS=500 + - POSTGRES_CONNMAXLIFETIMEMINUTES=5 depends_on: - - mongo - environment: - - SPRING_DATA_MONGODB_URI=mongodb://mongoAdmin:mongoPassword@mongo:27017 + postgres: + condition: service_healthy networks: - dataengine-network @@ -172,16 +181,40 @@ services: PRIMARY_LIGHT_COLOR: "#041b2b" restart: always depends_on: - template-repository: - condition: service_healthy + template-repository-registry: + condition: service_started + networks: + - dataengine-network + + postgres: + image: postgres:16-alpine + container_name: postgres + environment: + POSTGRES_DB: basyxTestDB + POSTGRES_USER: postgres + POSTGRES_PASSWORD: admin + volumes: + - postgres-data:/var/lib/postgresql/data + restart: always + healthcheck: + test: ["CMD-SHELL", "pg_isready -U postgres -d basyxTestDB"] + interval: 10s + timeout: 5s + retries: 5 networks: - dataengine-network - mongo: - image: mongo:6.0 - container_name: mongo + pgadmin: + image: dpage/pgadmin4:snapshot + container_name: pgadmin + ports: + - "8081:80" environment: - MONGO_INITDB_ROOT_USERNAME: mongoAdmin - MONGO_INITDB_ROOT_PASSWORD: mongoPassword + PGADMIN_DEFAULT_EMAIL: admin@example.com + PGADMIN_DEFAULT_PASSWORD: admin + depends_on: + postgres: + condition: service_healthy + restart: always networks: - dataengine-network diff --git a/source/AAS.TwinEngine.Plugin.TestPlugin/Example/nginx/default.conf.template b/source/AAS.TwinEngine.Plugin.TestPlugin/Example/nginx/default.conf.template index c87e0440..7d6a9586 100644 --- a/source/AAS.TwinEngine.Plugin.TestPlugin/Example/nginx/default.conf.template +++ b/source/AAS.TwinEngine.Plugin.TestPlugin/Example/nginx/default.conf.template @@ -75,7 +75,7 @@ server { limit_except GET OPTIONS { deny all; } - proxy_pass http://template-repository:8081; + proxy_pass http://template-repository-registry:8081; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; @@ -87,7 +87,7 @@ server { limit_except GET OPTIONS { deny all; } - proxy_pass http://template-repository:8081; + proxy_pass http://template-repository-registry:8081; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; @@ -142,4 +142,4 @@ server { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } -} \ No newline at end of file +}