From 348821d43d2c342e1e025906a705853734a9543c Mon Sep 17 00:00:00 2001 From: Thomas Bayer Date: Sun, 8 Feb 2026 21:13:28 +0100 Subject: [PATCH 1/2] docs(security, examples): update JDBC API Key Store tutorial for consistency and clarity - Improved Docker and PostgreSQL setup steps. - Simplified JDBC configuration properties and corrected password values. - Enhanced API key usage demonstration with updated testing instructions. - Made YAML configurations more concise and aligned with global standards. - Refined scope logic and logging messages for better readability. --- .../api-key/jdbc-api-key-store/README.md | 53 +++++++++---------- .../api-key/jdbc-api-key-store/apis.yaml | 43 +++++++-------- .../examples/security/api-key/rbac/apis.yaml | 32 ++++++----- 3 files changed, 64 insertions(+), 64 deletions(-) diff --git a/distribution/examples/security/api-key/jdbc-api-key-store/README.md b/distribution/examples/security/api-key/jdbc-api-key-store/README.md index 8a8b40870a..783d4da24c 100644 --- a/distribution/examples/security/api-key/jdbc-api-key-store/README.md +++ b/distribution/examples/security/api-key/jdbc-api-key-store/README.md @@ -5,52 +5,49 @@ A quick guide to setting up a JDBC-based API key store using PostgreSQL. ### Prerequisite - **Docker installed:** - - If Docker is already installed, skip to the next step. - Otherwise, install Docker from [https://docs.docker.com/get-started/get-docker/](https://docs.docker.com/get-started/get-docker/). --- 1. **Run Database Container:** + - Start a database container (e.g., PostgreSQL) with: - - Start a database container (e.g., PostgreSQL) with: - - ```shell - docker run --name postgres -e POSTGRES_USER=user -e POSTGRES_PASSWORD=password -p 5432:5432 -d postgres - ``` + ```shell + docker run --rm --name postgres -e POSTGRES_PASSWORD=secret -p 5432:5432 postgres + ``` 2. **Download JDBC Driver:** - - - Download the PostgreSQL JDBC driver from the official - site: [https://jdbc.postgresql.org/download/](https://jdbc.postgresql.org/download/). - - Place it in the `lib` directory of your Membrane installation. + - Download the PostgreSQL JDBC driver from the official + site: [https://jdbc.postgresql.org/download/](https://jdbc.postgresql.org/download/). + - Place it in the `lib` directory of your Membrane installation. 3. **Take a look at the configuration in the [`apis.yaml`](apis.yaml)** -4. **run the membrane.sh script:** +4. **Run the membrane.sh script:** -```shell -./membrane.sh -``` + ```shell + ./membrane.sh + ``` 5. **Run SQL File in your Docker Container:** + - Make sure that Membrane was running before to create the database tables. + - Run this command: -- Run this command: - -```shell -docker exec -i postgres psql -U user -d postgres < ./insert_apikeys.sql -``` + ```shell + docker exec -i postgres psql -U postgres -d postgres < ./insert_apikeys.sql + ``` -- test + - test -```shell -docker exec -i postgres psql -U user -d postgres -c "SELECT * FROM key;" -``` + ```shell + docker exec -i postgres psql -U postgres -d postgres -c "SELECT * FROM key;" + ``` -6. **You can test it using curl:** +6. **Test it using curl:** -```shell -curl localhost:2000 -H "x-api-key:unsecure2000" -``` + ```shell + curl localhost:2000 -H "x-api-key:unsecure2000" + ``` -- if the API key is valid, you will be redirected to ```https://api.predic8.de```. \ No newline at end of file +- if the API key is valid, you will be forwarded to ```https://api.predic8.de```. \ No newline at end of file diff --git a/distribution/examples/security/api-key/jdbc-api-key-store/apis.yaml b/distribution/examples/security/api-key/jdbc-api-key-store/apis.yaml index 247b93bc5a..5317b3f9cd 100644 --- a/distribution/examples/security/api-key/jdbc-api-key-store/apis.yaml +++ b/distribution/examples/security/api-key/jdbc-api-key-store/apis.yaml @@ -5,33 +5,30 @@ components: bean: class: org.apache.commons.dbcp2.BasicDataSource properties: - - property: - name: driverClassName - value: org.postgresql.Driver - - property: - name: url - value: jdbc:postgresql://localhost:5432/postgres - - property: - name: username - value: user - - property: - name: password - value: password + - name: driverClassName + value: org.postgresql.Driver + - name: url + value: jdbc:postgresql://localhost:5432/postgres + - name: username + value: postgres + - name: password + value: secret --- +global: + - apiKey: + stores: + - databaseApiKeyStore: + datasource: '#/components/dataSource' + keyTable: + name: key + scopeTable: + name: scope + extractors: + - headerExtractor: {} +--- api: port: 2000 - flow: - - apiKey: - stores: - - databaseApiKeyStore: - datasource: '#/components/dataSource' - keyTable: - name: key - scopeTable: - name: scope - extractors: - - headerExtractor: {} target: url: https://api.predic8.de diff --git a/distribution/examples/security/api-key/rbac/apis.yaml b/distribution/examples/security/api-key/rbac/apis.yaml index 134a86d624..0e1cc23064 100644 --- a/distribution/examples/security/api-key/rbac/apis.yaml +++ b/distribution/examples/security/api-key/rbac/apis.yaml @@ -4,43 +4,49 @@ # In this instance, we use an `ApiKeyFileStore`, which fetches API keys from a specified file. # For global access across all API key interceptors, declare the stores as shown here. # If an interceptor-specific store is needed, embed the store directly within the interceptor. + components: keys: apiKeyFileStore: location: ./demo-keys.txt --- -# API key authorization providing key is optional. Certain scopes allow for additional access rights. +global: + - apiKey: + # API key authorization is optional. + # But certain scopes allow for additional access rights. + required: false + extractors: + - headerExtractor: + name: X-Key + +--- api: port: 2000 flow: - - apiKey: - required: false - extractors: - - headerExtractor: - name: X-Key - request: + - log: + message: "Scopes: ${scopes()}" - if: test: hasScope('admin') - language: spel flow: - template: src: | - Only for admins! - Caller scopes: ${fn.scopes()} + Only admins! + Scopes: ${fn.scopes()} - return: status: 200 - if: - test: hasScope({'finance','accounting'}) - language: spel + test: hasScope('finance') or hasScope('accounting') flow: - template: src: | - Only for finance or accounting! - Caller scopes: ${fn.scopes()} + Only finance or accounting! + Scopes: ${fn.scopes()} - return: status: 200 - template: src: Normal API - return: status: 200 + From bf19606eebb60e79b750e4e640b1f5f1f75a1650 Mon Sep 17 00:00:00 2001 From: Thomas Bayer Date: Tue, 10 Feb 2026 14:36:56 +0100 Subject: [PATCH 2/2] Update APIKeyRBACExampleTest assertions for improved scope clarity - Adjusted test assertions to use more descriptive text for scopes (`"Only finance or accounting!"` and `"Only admins!"`). - Updated expected output values to refine validation logic, ensuring alignment with clarified roles. --- .../withoutinternet/test/APIKeyRBACExampleTest.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/distribution/src/test/java/com/predic8/membrane/examples/withoutinternet/test/APIKeyRBACExampleTest.java b/distribution/src/test/java/com/predic8/membrane/examples/withoutinternet/test/APIKeyRBACExampleTest.java index 1259a899a0..ae1488ff6e 100644 --- a/distribution/src/test/java/com/predic8/membrane/examples/withoutinternet/test/APIKeyRBACExampleTest.java +++ b/distribution/src/test/java/com/predic8/membrane/examples/withoutinternet/test/APIKeyRBACExampleTest.java @@ -34,7 +34,7 @@ void normalScope() { .get("http://localhost:2000") .then().assertThat() .statusCode(200) - .body(containsString("Caller scopes")) + .body(containsString("Only finance or accounting!")) .body(containsString("accounting")) .body(containsString("finance")); } @@ -47,8 +47,7 @@ void conditionalScope() { .get("http://localhost:2000") .then().assertThat() .statusCode(200) - .body(containsString("Caller scopes")) - .body(not(containsString("accounting"))) - .body(containsString("admin")); + .body(containsString("Only admins!")) + .body(containsString("[admin]")); } }