From c072d69358b3f42bda3a8a2f2bba8931bd64ee67 Mon Sep 17 00:00:00 2001 From: b-long Date: Thu, 18 Dec 2025 16:13:37 -0500 Subject: [PATCH 1/9] run 'npm install --save raw-loader' --- package-lock.json | 71 +++++++++++++++++++++++++++++++++++++++++++++++ package.json | 1 + 2 files changed, 72 insertions(+) diff --git a/package-lock.json b/package-lock.json index 18d2b8b..2bffe5b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,6 +26,7 @@ "octokit": "^4.0.2", "plugin-image-zoom": "^1.2.0", "prism-react-renderer": "^2.4.0", + "raw-loader": "^4.0.2", "react": "^18.0.0", "react-dom": "^18.0.0", "react-error-boundary": "^4.1.2", @@ -20241,6 +20242,76 @@ "node": ">= 0.8" } }, + "node_modules/raw-loader": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-4.0.2.tgz", + "integrity": "sha512-ZnScIV3ag9A4wPX/ZayxL/jZH+euYb6FcUinPcgiQW0+UBtEv0O6Q3lGd3cqJ+GHH+rksEv3Pj99oxJ3u3VIKA==", + "license": "MIT", + "dependencies": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/raw-loader/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "license": "MIT", + "peer": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/raw-loader/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "license": "MIT", + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/raw-loader/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "license": "MIT" + }, + "node_modules/raw-loader/node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, "node_modules/rc": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", diff --git a/package.json b/package.json index 0607a80..89e9271 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,7 @@ "octokit": "^4.0.2", "plugin-image-zoom": "^1.2.0", "prism-react-renderer": "^2.4.0", + "raw-loader": "^4.0.2", "react": "^18.0.0", "react-dom": "^18.0.0", "react-error-boundary": "^4.1.2", From f4d6651bbb376bf098750e9fb2ccbc1d849531e1 Mon Sep 17 00:00:00 2001 From: b-long Date: Thu, 18 Dec 2025 16:14:20 -0500 Subject: [PATCH 2/9] move docker-compose content to external file --- docs/getting-started/docker-compose.yaml | 281 ++++++++++++++++++++++ docs/getting-started/index.mdx | 287 +---------------------- 2 files changed, 286 insertions(+), 282 deletions(-) create mode 100644 docs/getting-started/docker-compose.yaml diff --git a/docs/getting-started/docker-compose.yaml b/docs/getting-started/docker-compose.yaml new file mode 100644 index 0000000..ccf0676 --- /dev/null +++ b/docs/getting-started/docker-compose.yaml @@ -0,0 +1,281 @@ +name: opentdf +volumes: + configs: + keys: + caddy_data: +configs: + caddy_config: + content: | + { + log { + level INFO + output stdout + } + } + https://keycloak.opentdf.local:9443 { + tls internal + reverse_proxy keycloak:8888 + } + https://platform.opentdf.local:8443 { + tls internal + reverse_proxy { + to h2c://platform:8080 + transport http { + versions h2c 2 1.1 # Enable gRPC proxying + } + } + + } +services: + caddy: + image: caddy:alpine + command: ['caddy','run', '--config', '/etc/caddy/Caddyfile'] + configs: + - source: caddy_config + target: /etc/caddy/Caddyfile + ports: + - '9443:9443' + - '8443:8443' + volumes: + - caddy_data:/data + restart: unless-stopped + healthcheck: + test: ["CMD-SHELL", "wget -q --server-response --tries=1 http://127.0.0.1:2019/metrics 2>&1 | awk '/^ HTTP/{print $2}' | grep -q '200'"] + interval: 5s + timeout: 5s + retries: 3 + check-certs: + image: bash:latest + volumes: + - type: volume + source: caddy_data + target: /etc/ssl/certs + volume: + subpath: caddy/certificates/local/keycloak.opentdf.local/ + command: + - bash + - -c + - | + echo "Checking certificates" + ls -alh /etc/ssl/certs + cat /etc/ssl/certs/keycloak.opentdf.local.crt + depends_on: + caddy: + condition: service_healthy + ensure-permissions: + condition: service_completed_successfully + ensure-permissions: + image: alpine + command: + - 'sh' + - '-c' + - | + chmod -R 777 /configs + ls -alh /configs + chmod -R 777 /keys + ls -alh /keys + chmod -R 777 /data + ls -alh /data + volumes: + - configs:/configs + - keys:/keys + - caddy_data:/data + + #================================================================ + +# Start Keycloak + + #---------------------------------------------------------------- + keycloak: + image: keycloak/keycloak:25.0 + restart: unless-stopped + command: ['start-dev'] + environment: + KC_DB: postgres + KC_DB_URL_HOST: keycloak-db + KC_DB_URL_PORT: 5432 + KC_DB_URL_DATABASE: keycloak + KC_DB_USERNAME: postgres + KC_DB_PASSWORD: changeme + KC_HOSTNAME: 'https://keycloak.opentdf.local:9443' + KC_HOSTNAME_ADMIN: 'https://keycloak.opentdf.local:9443' + KC_HTTP_ENABLED: 'true' + KC_HTTP_PORT: 8888 + KEYCLOAK_ADMIN: admin + KEYCLOAK_ADMIN_PASSWORD: changeme + KC_FEATURES: 'preview,token-exchange' + KC_HEALTH_ENABLED: 'true' + JAVA_OPTS_APPEND: '${JAVA_OPTS_APPEND:-}' + healthcheck: + test: ['CMD-SHELL', '[ -f /tmp/HealthCheck.java ] || echo "public class HealthCheck { public static void main(String[] args) throws java.lang.Throwable { System.exit(java.net.HttpURLConnection.HTTP_OK == ((java.net.HttpURLConnection)new java.net.URL(args[0]).openConnection()).getResponseCode() ? 0 : 1); } }" > /tmp/HealthCheck.java && java ${JAVA_OPTS_APPEND} /tmp/HealthCheck.java http://localhost:9000/health/ready'] + interval: 5s + timeout: 10s + retries: 3 + start_period: 5m + depends_on: + keycloak-db: + condition: service_healthy + restart: true + keycloak-db: + image: postgres:15-alpine + restart: unless-stopped + environment: + POSTGRES_PASSWORD: changeme + POSTGRES_USER: postgres + POSTGRES_DB: keycloak + healthcheck: + test: ["CMD-SHELL", "pg_isready -U postgres"] + interval: 5s + timeout: 5s + retries: 10 + start_period: 2m + download-keycloak-config: + image: curlimages/curl:latest + volumes: + - configs:/configs + command: ['-o', '/configs/keycloak-config.yaml', 'https://raw.githubusercontent.com/opentdf/platform/main/service/cmd/keycloak_data.yaml'] + depends_on: + ensure-permissions: + condition: service_completed_successfully + #================================================================ + +# Provisioning Keycloak with expected realm, clients, and users + + #---------------------------------------------------------------- + keycloak-provisioning: + image: registry.opentdf.io/platform:nightly + volumes: + - configs:/configs + command: + [ + 'provision', + 'keycloak', + '-e', + 'http://keycloak:8888', + '-f', + '/configs/keycloak-config.yaml', + ] + depends_on: + keycloak: + condition: service_healthy + restart: true + download-keycloak-config: + condition: service_completed_successfully + restart: true + #================================================================ + +# Start the OpenTDF service + + #---------------------------------------------------------------- + download-platform-config: + image: curlimages/curl:latest + volumes: + - configs:/configs + command: ['-o', '/configs/.opentdf.yaml', 'https://raw.githubusercontent.com/opentdf/platform/main/opentdf-dev.yaml'] + depends_on: + ensure-permissions: + condition: service_completed_successfully + modify-platform-config: + image: bash:latest + volumes: + - configs:/configs + command: + - bash + - -c + - | + echo "Modifying /configs/.opentdf.yaml" + echo "$( Docker Compose -```yaml -name: opentdf -volumes: - configs: - keys: - caddy_data: -configs: - caddy_config: - content: | - { - log { - level INFO - output stdout - } - } - https://keycloak.opentdf.local:9443 { - tls internal - reverse_proxy keycloak:8888 - } - https://platform.opentdf.local:8443 { - tls internal - reverse_proxy { - to h2c://platform:8080 - transport http { - versions h2c 2 1.1 # Enable gRPC proxying - } - } - - } -services: - caddy: - image: caddy:alpine - command: ['caddy','run', '--config', '/etc/caddy/Caddyfile'] - configs: - - source: caddy_config - target: /etc/caddy/Caddyfile - ports: - - '9443:9443' - - '8443:8443' - volumes: - - caddy_data:/data - restart: unless-stopped - healthcheck: - test: ["CMD-SHELL", "wget -q --server-response --tries=1 http://127.0.0.1:2019/metrics 2>&1 | awk '/^ HTTP/{print $2}' | grep -q '200'"] - interval: 5s - timeout: 5s - retries: 3 - check-certs: - image: bash:latest - volumes: - - type: volume - source: caddy_data - target: /etc/ssl/certs - volume: - subpath: caddy/certificates/local/keycloak.opentdf.local/ - command: - - bash - - -c - - | - echo "Checking certificates" - ls -alh /etc/ssl/certs - cat /etc/ssl/certs/keycloak.opentdf.local.crt - depends_on: - caddy: - condition: service_healthy - ensure-permissions: - condition: service_completed_successfully - ensure-permissions: - image: alpine - command: - - 'sh' - - '-c' - - | - chmod -R 777 /configs - ls -alh /configs - chmod -R 777 /keys - ls -alh /keys - chmod -R 777 /data - ls -alh /data - volumes: - - configs:/configs - - keys:/keys - - caddy_data:/data - - #================================================================ - -# Start Keycloak - - #---------------------------------------------------------------- - keycloak: - image: keycloak/keycloak:25.0 - restart: unless-stopped - command: ['start-dev'] - environment: - KC_DB: postgres - KC_DB_URL_HOST: keycloak-db - KC_DB_URL_PORT: 5432 - KC_DB_URL_DATABASE: keycloak - KC_DB_USERNAME: postgres - KC_DB_PASSWORD: changeme - KC_HOSTNAME: 'https://keycloak.opentdf.local:9443' - KC_HOSTNAME_ADMIN: 'https://keycloak.opentdf.local:9443' - KC_HTTP_ENABLED: 'true' - KC_HTTP_PORT: 8888 - KEYCLOAK_ADMIN: admin - KEYCLOAK_ADMIN_PASSWORD: changeme - KC_FEATURES: 'preview,token-exchange' - KC_HEALTH_ENABLED: 'true' - JAVA_OPTS_APPEND: '${JAVA_OPTS_APPEND:-}' - healthcheck: - test: ['CMD-SHELL', '[ -f /tmp/HealthCheck.java ] || echo "public class HealthCheck { public static void main(String[] args) throws java.lang.Throwable { System.exit(java.net.HttpURLConnection.HTTP_OK == ((java.net.HttpURLConnection)new java.net.URL(args[0]).openConnection()).getResponseCode() ? 0 : 1); } }" > /tmp/HealthCheck.java && java ${JAVA_OPTS_APPEND} /tmp/HealthCheck.java http://localhost:9000/health/ready'] - interval: 5s - timeout: 10s - retries: 3 - start_period: 5m - depends_on: - keycloak-db: - condition: service_healthy - restart: true - keycloak-db: - image: postgres:15-alpine - restart: unless-stopped - environment: - POSTGRES_PASSWORD: changeme - POSTGRES_USER: postgres - POSTGRES_DB: keycloak - healthcheck: - test: ["CMD-SHELL", "pg_isready -U postgres"] - interval: 5s - timeout: 5s - retries: 10 - start_period: 2m - download-keycloak-config: - image: curlimages/curl:latest - volumes: - - configs:/configs - command: ['-o', '/configs/keycloak-config.yaml', 'https://raw.githubusercontent.com/opentdf/platform/main/service/cmd/keycloak_data.yaml'] - depends_on: - ensure-permissions: - condition: service_completed_successfully - #================================================================ - -# Provisioning Keycloak with expected realm, clients, and users - - #---------------------------------------------------------------- - keycloak-provisioning: - image: registry.opentdf.io/platform:nightly - volumes: - - configs:/configs - command: - [ - 'provision', - 'keycloak', - '-e', - 'http://keycloak:8888', - '-f', - '/configs/keycloak-config.yaml', - ] - depends_on: - keycloak: - condition: service_healthy - restart: true - download-keycloak-config: - condition: service_completed_successfully - restart: true - #================================================================ - -# Start the OpenTDF service - - #---------------------------------------------------------------- - download-platform-config: - image: curlimages/curl:latest - volumes: - - configs:/configs - command: ['-o', '/configs/.opentdf.yaml', 'https://raw.githubusercontent.com/opentdf/platform/main/opentdf-dev.yaml'] - depends_on: - ensure-permissions: - condition: service_completed_successfully - modify-platform-config: - image: bash:latest - volumes: - - configs:/configs - command: - - bash - - -c - - | - echo "Modifying /configs/.opentdf.yaml" - echo "$({dockerComposeContent} From 4ee684c729ca8fef725a2d908455138e8be0e211 Mon Sep 17 00:00:00 2001 From: b-long Date: Thu, 18 Dec 2025 16:27:12 -0500 Subject: [PATCH 3/9] Create a Github Action to deploy the compose stack --- .github/workflows/docker-compose-test.yml | 96 +++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 .github/workflows/docker-compose-test.yml diff --git a/.github/workflows/docker-compose-test.yml b/.github/workflows/docker-compose-test.yml new file mode 100644 index 0000000..17afea1 --- /dev/null +++ b/.github/workflows/docker-compose-test.yml @@ -0,0 +1,96 @@ +name: Docker Compose Stack Test + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + workflow_dispatch: + +jobs: + test-stack: + runs-on: ubuntu-latest + timeout-minutes: 15 + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Add hosts entries + run: | + echo -e "127.0.0.1 platform.opentdf.local\n127.0.0.1 keycloak.opentdf.local" | sudo tee -a /etc/hosts + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Setup Docker's apt repository + run: | + # Add Docker's official GPG key: + sudo apt update + sudo apt install ca-certificates curl + sudo install -m 0755 -d /etc/apt/keyrings + sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc + sudo chmod a+r /etc/apt/keyrings/docker.asc + + # Add the repository to Apt sources: + sudo tee /etc/apt/sources.list.d/docker.sources </dev/null || echo "") + + if [ -n "$response" ]; then + http_code=$(echo "$response" | tail -n1) + body=$(echo "$response" | head -n1) + + echo "HTTP Code: $http_code" + echo "Response Body: $body" + + if [ "$http_code" = "200" ] && echo "$body" | grep -q '"status":"SERVING"'; then + echo "✓ Platform is ready!" + exit 0 + fi + fi + + sleep $interval + elapsed=$((elapsed + interval)) + done + + echo "✗ Timeout waiting for platform to become ready" + exit 1 + + - name: Show container logs on failure + if: failure() + working-directory: docs/getting-started + run: | + docker compose ps + docker compose logs From ff9af5ac1d430ff92ea11f8fd313e9cd40df010c Mon Sep 17 00:00:00 2001 From: b-long Date: Thu, 18 Dec 2025 16:36:09 -0500 Subject: [PATCH 4/9] improve the compose file --- docs/getting-started/docker-compose.yaml | 572 ++++++++++++++++------- 1 file changed, 412 insertions(+), 160 deletions(-) diff --git a/docs/getting-started/docker-compose.yaml b/docs/getting-started/docker-compose.yaml index ccf0676..d070d4a 100644 --- a/docs/getting-started/docker-compose.yaml +++ b/docs/getting-started/docker-compose.yaml @@ -1,8 +1,7 @@ -name: opentdf -volumes: - configs: - keys: - caddy_data: +networks: + default: + name: opentdf_platform + configs: caddy_config: content: | @@ -24,8 +23,8 @@ configs: versions h2c 2 1.1 # Enable gRPC proxying } } - } + services: caddy: image: caddy:alpine @@ -34,16 +33,21 @@ services: - source: caddy_config target: /etc/caddy/Caddyfile ports: - - '9443:9443' - - '8443:8443' + - "8443:8443" + - "9443:9443" + - "2019:2019" volumes: - caddy_data:/data - restart: unless-stopped + depends_on: + ensure-permissions: + condition: service_completed_successfully healthcheck: - test: ["CMD-SHELL", "wget -q --server-response --tries=1 http://127.0.0.1:2019/metrics 2>&1 | awk '/^ HTTP/{print $2}' | grep -q '200'"] + test: ["CMD", "wget", "--spider", "-q", "http://127.0.0.1:2019/metrics"] interval: 5s timeout: 5s retries: 3 + restart: unless-stopped + check-certs: image: bash:latest volumes: @@ -64,218 +68,466 @@ services: condition: service_healthy ensure-permissions: condition: service_completed_successfully + restart: "no" + ensure-permissions: image: alpine command: - 'sh' - '-c' - | - chmod -R 777 /configs - ls -alh /configs - chmod -R 777 /keys - ls -alh /keys - chmod -R 777 /data - ls -alh /data + chmod -R 755 /data volumes: - - configs:/configs - - keys:/keys - caddy_data:/data + restart: "no" - #================================================================ - -# Start Keycloak - - #---------------------------------------------------------------- keycloak: + volumes: + - keys:/keys:ro image: keycloak/keycloak:25.0 - restart: unless-stopped - command: ['start-dev'] + restart: always + depends_on: + fix-keys-permissions: + condition: service_completed_successfully + command: + - "start-dev" + - "--verbose" + - "-Djavax.net.ssl.trustStorePassword=password" + - "-Djavax.net.ssl.HostnameVerifier=AllowAll" + - "-Djavax.net.ssl.trustStore=/keys/ca.jks" + - "--spi-truststore-file-hostname-verification-policy=ANY" environment: - KC_DB: postgres - KC_DB_URL_HOST: keycloak-db - KC_DB_URL_PORT: 5432 - KC_DB_URL_DATABASE: keycloak - KC_DB_USERNAME: postgres - KC_DB_PASSWORD: changeme - KC_HOSTNAME: 'https://keycloak.opentdf.local:9443' - KC_HOSTNAME_ADMIN: 'https://keycloak.opentdf.local:9443' - KC_HTTP_ENABLED: 'true' - KC_HTTP_PORT: 8888 + KC_PROXY: edge + KC_HTTP_RELATIVE_PATH: /auth + KC_HOSTNAME_STRICT: "false" + KC_HOSTNAME_STRICT_BACKCHANNEL: "false" + KC_HOSTNAME_STRICT_HTTPS: "false" + KC_HTTP_ENABLED: "true" + KC_HTTP_PORT: "8888" + KC_HTTPS_PORT: "8443" + KC_HTTP_MANAGEMENT_PORT: "9001" KEYCLOAK_ADMIN: admin KEYCLOAK_ADMIN_PASSWORD: changeme - KC_FEATURES: 'preview,token-exchange' - KC_HEALTH_ENABLED: 'true' - JAVA_OPTS_APPEND: '${JAVA_OPTS_APPEND:-}' + #KC_HOSTNAME_URL: http://localhost:8888/auth + KC_FEATURES: "preview,token-exchange" + KC_HEALTH_ENABLED: "true" + KC_HTTPS_KEY_STORE_PASSWORD: "password" + KC_HTTPS_KEY_STORE_FILE: "/keys/ca.jks" + KC_HTTPS_CERTIFICATE_FILE: "/keys/localhost.crt" + KC_HTTPS_CERTIFICATE_KEY_FILE: "/keys/localhost.key" + KC_HTTPS_CLIENT_AUTH: "request" + ### + # The following environment variable resolves SIGILL with Code 134 when running Java processes on Apple M4 chips + # + # On Apple Silicon (M4 chip): + # export JAVA_OPTS_APPEND="-XX:UseSVE=0" + # docker-compose up + # + # On other architectures: + # export JAVA_OPTS_APPEND="" + # docker-compose up + # + # Or set directly: JAVA_OPTS_APPEND="-XX:UseSVE=0" docker-compose up + JAVA_OPTS_APPEND: "${JAVA_OPTS_APPEND:-}" + ### + # ports: + # - "${KC_EXPOSE_PORT:-8443}:8443" + # - "${KC_EXPOSE_PORT_HTTP:-8888}:8888" + # - "${KC_EXPOSE_PORT_MGMT:-9001}:9001" healthcheck: - test: ['CMD-SHELL', '[ -f /tmp/HealthCheck.java ] || echo "public class HealthCheck { public static void main(String[] args) throws java.lang.Throwable { System.exit(java.net.HttpURLConnection.HTTP_OK == ((java.net.HttpURLConnection)new java.net.URL(args[0]).openConnection()).getResponseCode() ? 0 : 1); } }" > /tmp/HealthCheck.java && java ${JAVA_OPTS_APPEND} /tmp/HealthCheck.java http://localhost:9000/health/ready'] - interval: 5s + test: + - CMD-SHELL + - | + [ -f /tmp/HealthCheck.java ] || echo "public class HealthCheck { + public static void main(String[] args) throws java.lang.Throwable { + javax.net.ssl.HttpsURLConnection.setDefaultHostnameVerifier((hostname, session) -> true); + javax.net.ssl.SSLContext sc = javax.net.ssl.SSLContext.getInstance(\"SSL\"); + sc.init(null, new javax.net.ssl.TrustManager[]{ + new javax.net.ssl.X509TrustManager() { + public java.security.cert.X509Certificate[] getAcceptedIssuers() { return null; } + public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) {} + public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) {} + } + }, new java.security.SecureRandom()); + javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); + java.net.HttpURLConnection conn = (java.net.HttpURLConnection)new java.net.URL(args[0]).openConnection(); + System.exit(java.net.HttpURLConnection.HTTP_OK == conn.getResponseCode() ? 0 : 1); + } + }" > /tmp/HealthCheck.java && java ${JAVA_OPTS_APPEND} /tmp/HealthCheck.java http://localhost:8888/auth 2>/dev/null + interval: 10s timeout: 10s - retries: 3 - start_period: 5m - depends_on: - keycloak-db: - condition: service_healthy - restart: true - keycloak-db: + retries: 10 + start_period: 3m + opentdfdb: image: postgres:15-alpine - restart: unless-stopped + restart: always + user: postgres environment: - POSTGRES_PASSWORD: changeme POSTGRES_USER: postgres - POSTGRES_DB: keycloak + POSTGRES_PASSWORD: changeme + POSTGRES_DB: opentdf healthcheck: - test: ["CMD-SHELL", "pg_isready -U postgres"] + test: ["CMD-SHELL", "pg_isready"] interval: 5s timeout: 5s retries: 10 - start_period: 2m - download-keycloak-config: - image: curlimages/curl:latest + ports: + - "${POSTGRES_EXPOSE_PORT:-5432}:5432" + + jaeger: + image: jaegertracing/all-in-one:latest + environment: + COLLECTOR_OTLP_ENABLED: "true" + ports: + - "16686:16686" # Web UI + - "4317:4317" # OTLP gRPC + - "4318:4318" # OTLP HTTP + - "14250:14250" # Model/collector gRPC + profiles: + - tracing + restart: always + + # Provision Keycloak with initial configuration + platform-provision-keycloak: + image: registry.opentdf.io/platform:nightly + command: ["provision", "keycloak", "-e", "https://keycloak.opentdf.local:9443/auth", "-f", "/configs/keycloak_data.yaml"] + depends_on: + keycloak: + condition: service_healthy + opentdfdb: + condition: service_healthy + patch-platform-config: + condition: service_completed_successfully + download-keycloak-data: + condition: service_completed_successfully + generate-keys: + condition: service_completed_successfully + volumes: + - configs:/configs:ro + - keys:/keys:ro + environment: + - OPENTDF_CONFIG_FILE=/configs/opentdf.yaml + restart: "no" + extra_hosts: + - "keycloak.opentdf.local:host-gateway" + # Prepare fixtures directory structure - create symlink to expected location + prepare-fixtures: + image: alpine:latest volumes: - configs:/configs - command: ['-o', '/configs/keycloak-config.yaml', 'https://raw.githubusercontent.com/opentdf/platform/main/service/cmd/keycloak_data.yaml'] depends_on: - ensure-permissions: + download-fixtures: condition: service_completed_successfully - #================================================================ - -# Provisioning Keycloak with expected realm, clients, and users + command: + - sh + - -c + - | + mkdir -p /configs/service/internal/fixtures + cd /configs + ln -sf /configs/service/internal/fixtures ./service + restart: "no" - #---------------------------------------------------------------- - keycloak-provisioning: + # Add sample attributes and metadata + platform-provision-fixtures: image: registry.opentdf.io/platform:nightly + command: ["provision", "fixtures", "--config-file", "/configs/opentdf.yaml"] + working_dir: /configs + depends_on: + platform-provision-keycloak: + condition: service_completed_successfully + opentdfdb: + condition: service_healthy + prepare-fixtures: + condition: service_completed_successfully + generate-keys: + condition: service_completed_successfully volumes: - - configs:/configs + - configs:/configs:ro + - keys:/keys:ro + restart: "no" + + # Prepare CA certificates bundle with Caddy cert + prepare-ca-certs: + image: alpine:latest + volumes: + - type: volume + source: caddy_data + target: /caddy-certs + read_only: true + volume: + subpath: caddy/certificates/local/keycloak.opentdf.local + - platform_certs:/etc/ssl/certs + depends_on: + caddy: + condition: service_healthy command: - [ - 'provision', - 'keycloak', - '-e', - 'http://keycloak:8888', - '-f', - '/configs/keycloak-config.yaml', - ] + - sh + - -c + - | + # Install ca-certificates package + apk add --no-cache ca-certificates + # Copy Caddy certificate to CA bundle + cp /caddy-certs/keycloak.opentdf.local.crt /usr/local/share/ca-certificates/ + update-ca-certificates + # Copy the updated CA bundle to shared volume + cp -r /etc/ssl/certs/* /etc/ssl/certs/ + echo "CA certificates prepared successfully" + restart: "no" + + # Main OpenTDF Platform server + platform: + image: registry.opentdf.io/platform:nightly + command: ["start", "--config-file", "/configs/opentdf.yaml"] depends_on: + platform-provision-fixtures: + condition: service_completed_successfully keycloak: condition: service_healthy - restart: true - download-keycloak-config: + opentdfdb: + condition: service_healthy + generate-keys: condition: service_completed_successfully - restart: true - #================================================================ + prepare-ca-certs: + condition: service_completed_successfully + ports: + - "8080:8080" + volumes: + - configs:/configs:ro + - keys:/keys:ro + - platform_certs:/etc/ssl/certs:ro + extra_hosts: + - "keycloak.opentdf.local:host-gateway" + restart: unless-stopped -# Start the OpenTDF service + # Initialize volume permissions + init-volumes: + image: alpine:latest + volumes: + - configs:/configs + - keys:/keys + command: + - sh + - -c + - | + chmod 777 /configs /keys + mkdir -p /configs/service/internal/fixtures + chmod -R 777 /configs + restart: "no" - #---------------------------------------------------------------- + # Fix keys permissions after generation + fix-keys-permissions: + image: alpine:latest + volumes: + - keys:/keys + depends_on: + generate-keys: + condition: service_completed_successfully + command: + - sh + - -c + - | + chmod -R 755 /keys + chmod 644 /keys/* + restart: "no" + + # Download platform configuration file download-platform-config: image: curlimages/curl:latest volumes: - configs:/configs - command: ['-o', '/configs/.opentdf.yaml', 'https://raw.githubusercontent.com/opentdf/platform/main/opentdf-dev.yaml'] depends_on: - ensure-permissions: + init-volumes: condition: service_completed_successfully - modify-platform-config: - image: bash:latest + command: ['-o', '/configs/opentdf.yaml', 'https://raw.githubusercontent.com/opentdf/platform/main/opentdf-example.yaml'] + restart: "no" + + # Patch platform configuration to use keycloak.opentdf.local:9443 + patch-platform-config: + image: alpine:latest volumes: - configs:/configs + depends_on: + download-platform-config: + condition: service_completed_successfully command: - - bash + - sh - -c - | - echo "Modifying /configs/.opentdf.yaml" - echo "$( /tmp/ecparams.tmp + openssl req -x509 -nodes -newkey ec:/tmp/ecparams.tmp -subj "/CN=kas" -keyout /keys/kas-ec-private.pem -out /keys/kas-ec-cert.pem -days 365 + + # Generate CA + openssl req -x509 -nodes -newkey RSA:2048 -subj "/CN=ca" -keyout /keys/keycloak-ca-private.pem -out /keys/keycloak-ca.pem -days 365 + + # Generate localhost certificate + printf "subjectAltName=DNS:localhost,IP:127.0.0.1" > /tmp/sanX509.conf + printf "[req]\ndistinguished_name=req_distinguished_name\n[req_distinguished_name]\n[alt_names]\nDNS.1=localhost\nIP.1=127.0.0.1" > /tmp/req.conf + openssl req -new -nodes -newkey rsa:2048 -keyout /keys/localhost.key -out /tmp/localhost.req -batch -subj "/CN=localhost" -config /tmp/req.conf + openssl x509 -req -in /tmp/localhost.req -CA /keys/keycloak-ca.pem -CAkey /keys/keycloak-ca-private.pem -CAcreateserial -out /keys/localhost.crt -days 3650 -sha256 -extfile /tmp/sanX509.conf + + # Generate sample user certificate + openssl req -new -nodes -newkey rsa:2048 -keyout /keys/sampleuser.key -out /tmp/sampleuser.req -batch -subj "/CN=sampleuser" + openssl x509 -req -in /tmp/sampleuser.req -CA /keys/keycloak-ca.pem -CAkey /keys/keycloak-ca-private.pem -CAcreateserial -out /keys/sampleuser.crt -days 3650 + + # Convert to PKCS12 + openssl pkcs12 -export -in /keys/keycloak-ca.pem -inkey /keys/keycloak-ca-private.pem -out /keys/ca.p12 -nodes -passout pass:password + + # Convert PKCS12 to JKS using keytool (no Docker needed) + keytool -importkeystore \ + -srckeystore /keys/ca.p12 \ + -srcstoretype PKCS12 \ + -destkeystore /keys/ca.jks \ + -deststoretype JKS \ + -srcstorepass "password" \ + -deststorepass "password" \ + -noprompt + + echo "Keys generated successfully" environment: - POSTGRES_USER: postgres - POSTGRES_PASSWORD: changeme - POSTGRES_DB: opentdf - healthcheck: - test: ["CMD-SHELL", "pg_isready -U postgres"] - interval: 5s - timeout: 5s - retries: 10 + JAVA_OPTS_APPEND: "${JAVA_OPTS_APPEND:-}" + restart: "no" + +volumes: + keys: + name: opentdf_keys + configs: + name: opentdf_configs + caddy_data: + platform_certs: + name: opentdf_platform_certs From 4af75f3a0f5071ef82306f0becb3800c0c9255c1 Mon Sep 17 00:00:00 2001 From: b-long Date: Thu, 18 Dec 2025 16:47:25 -0500 Subject: [PATCH 5/9] pin Caddy docker image --- docs/getting-started/docker-compose.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/getting-started/docker-compose.yaml b/docs/getting-started/docker-compose.yaml index d070d4a..938f422 100644 --- a/docs/getting-started/docker-compose.yaml +++ b/docs/getting-started/docker-compose.yaml @@ -27,7 +27,7 @@ configs: services: caddy: - image: caddy:alpine + image: caddy:2.8.4-alpine command: ['caddy','run', '--config', '/etc/caddy/Caddyfile'] configs: - source: caddy_config From bb959b9b518e52270420d2c5537923c39fdbb42b Mon Sep 17 00:00:00 2001 From: b-long Date: Fri, 19 Dec 2025 09:17:32 -0500 Subject: [PATCH 6/9] pin alpine docker image --- docs/getting-started/docker-compose.yaml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/getting-started/docker-compose.yaml b/docs/getting-started/docker-compose.yaml index 938f422..5cdb74f 100644 --- a/docs/getting-started/docker-compose.yaml +++ b/docs/getting-started/docker-compose.yaml @@ -71,7 +71,7 @@ services: restart: "no" ensure-permissions: - image: alpine + image: alpine:3.23 command: - 'sh' - '-c' @@ -212,7 +212,7 @@ services: - "keycloak.opentdf.local:host-gateway" # Prepare fixtures directory structure - create symlink to expected location prepare-fixtures: - image: alpine:latest + image: alpine:3.23 volumes: - configs:/configs depends_on: @@ -248,7 +248,7 @@ services: # Prepare CA certificates bundle with Caddy cert prepare-ca-certs: - image: alpine:latest + image: alpine:3.23 volumes: - type: volume source: caddy_data @@ -301,7 +301,7 @@ services: # Initialize volume permissions init-volumes: - image: alpine:latest + image: alpine:3.23 volumes: - configs:/configs - keys:/keys @@ -316,7 +316,7 @@ services: # Fix keys permissions after generation fix-keys-permissions: - image: alpine:latest + image: alpine:3.23 volumes: - keys:/keys depends_on: @@ -343,7 +343,7 @@ services: # Patch platform configuration to use keycloak.opentdf.local:9443 patch-platform-config: - image: alpine:latest + image: alpine:3.23 volumes: - configs:/configs depends_on: @@ -467,7 +467,7 @@ services: # Generate keys without Docker dependency generate-keys: - image: alpine:latest + image: alpine:3.23 volumes: - configs:/configs - keys:/keys From 1d744bdff15a60a697b4bcb2cceb078a4945fa82 Mon Sep 17 00:00:00 2001 From: b-long Date: Fri, 19 Dec 2025 09:23:37 -0500 Subject: [PATCH 7/9] update check-certs service to use alpine image --- docs/getting-started/docker-compose.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/getting-started/docker-compose.yaml b/docs/getting-started/docker-compose.yaml index 5cdb74f..d8db819 100644 --- a/docs/getting-started/docker-compose.yaml +++ b/docs/getting-started/docker-compose.yaml @@ -49,7 +49,7 @@ services: restart: unless-stopped check-certs: - image: bash:latest + image: alpine:3.23 volumes: - type: volume source: caddy_data @@ -57,7 +57,7 @@ services: volume: subpath: caddy/certificates/local/keycloak.opentdf.local/ command: - - bash + - sh - -c - | echo "Checking certificates" From 30bdc3b97caa3b4315fdae32245f10f5261fc833 Mon Sep 17 00:00:00 2001 From: b-long Date: Fri, 19 Dec 2025 09:31:08 -0500 Subject: [PATCH 8/9] replace curl with wget and update images to alpine for download services --- docs/getting-started/docker-compose.yaml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/getting-started/docker-compose.yaml b/docs/getting-started/docker-compose.yaml index d8db819..3279890 100644 --- a/docs/getting-started/docker-compose.yaml +++ b/docs/getting-started/docker-compose.yaml @@ -332,13 +332,13 @@ services: # Download platform configuration file download-platform-config: - image: curlimages/curl:latest + image: alpine:3.23 volumes: - configs:/configs depends_on: init-volumes: condition: service_completed_successfully - command: ['-o', '/configs/opentdf.yaml', 'https://raw.githubusercontent.com/opentdf/platform/main/opentdf-example.yaml'] + command: ['wget', '-O', '/configs/opentdf.yaml', 'https://raw.githubusercontent.com/opentdf/platform/main/opentdf-example.yaml'] restart: "no" # Patch platform configuration to use keycloak.opentdf.local:9443 @@ -360,7 +360,7 @@ services: # Download Keycloak provisioning data download-keycloak-data: - image: curlimages/curl:latest + image: alpine:3.23 volumes: - configs:/configs depends_on: @@ -377,7 +377,7 @@ services: for i in $$(seq 1 $$MAX_ATTEMPTS); do echo "Attempt $$i of $$MAX_ATTEMPTS: Downloading keycloak_data.yaml..." - if curl -f -o "$$OUTPUT" "$$URL"; then + if wget -O "$$OUTPUT" "$$URL"; then echo "Download successful" # Validate the downloaded file @@ -408,18 +408,18 @@ services: # Download fixtures data download-fixtures: - image: curlimages/curl:latest + image: alpine:3.23 volumes: - configs:/configs depends_on: init-volumes: condition: service_completed_successfully - command: ['-o', '/configs/service/internal/fixtures/policy_fixtures.yaml', 'https://raw.githubusercontent.com/opentdf/platform/main/service/internal/fixtures/policy_fixtures.yaml'] + command: ['wget', '-O', '/configs/service/internal/fixtures/policy_fixtures.yaml', 'https://raw.githubusercontent.com/opentdf/platform/main/service/internal/fixtures/policy_fixtures.yaml'] restart: "no" # Download init-temp-keys script download-init-script: - image: curlimages/curl:latest + image: alpine:3.23 volumes: - configs:/configs depends_on: @@ -436,7 +436,7 @@ services: for i in $$(seq 1 $$MAX_ATTEMPTS); do echo "Attempt $$i of $$MAX_ATTEMPTS: Downloading init-temp-keys.sh..." - if curl -f -o "$$OUTPUT" "$$URL"; then + if wget -O "$$OUTPUT" "$$URL"; then echo "Download successful" # Validate the downloaded file From 36fb4cfbcb0b7f6a7e452b7664a14c8e3752d1e9 Mon Sep 17 00:00:00 2001 From: b-long Date: Fri, 19 Dec 2025 15:05:23 -0500 Subject: [PATCH 9/9] restrict access to database port --- docs/getting-started/docker-compose.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/getting-started/docker-compose.yaml b/docs/getting-started/docker-compose.yaml index 3279890..39f505d 100644 --- a/docs/getting-started/docker-compose.yaml +++ b/docs/getting-started/docker-compose.yaml @@ -171,8 +171,6 @@ services: interval: 5s timeout: 5s retries: 10 - ports: - - "${POSTGRES_EXPOSE_PORT:-5432}:5432" jaeger: image: jaegertracing/all-in-one:latest