From cd398a51d02971130d3b7f5b1de3fc567ffedce0 Mon Sep 17 00:00:00 2001 From: Benno Evers Date: Thu, 23 May 2024 16:17:19 +0200 Subject: [PATCH] Add initial content (#1) * Add initial content * Readjust Actions for centralized platform deployment * Fix typos etc. --------- Co-authored-by: Benno Evers --- .github/workflows/deploy-to-staging.yaml | 37 ++++++ .github/workflows/platform-release.yaml | 120 +++++++++++++++++ .gitmodules | 6 + README.md | 26 +++- components/app | 1 + components/dex/Dockerfile | 11 ++ components/dex/dex.tenzir-entrypoint.sh | 36 ++++++ components/seaweed/Dockerfile | 11 ++ .../seaweed/seaweed.tenzir-entrypoint.sh | 26 ++++ components/tenant-manager | 1 + examples/localdev/docker-compose.yaml | 121 ++++++++++++++++++ examples/localdev/env.example | 53 ++++++++ .../onprem-integrated/docker-compose.yaml | 118 +++++++++++++++++ examples/onprem-integrated/env.example | 67 ++++++++++ 14 files changed, 632 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/deploy-to-staging.yaml create mode 100644 .github/workflows/platform-release.yaml create mode 100644 .gitmodules create mode 160000 components/app create mode 100644 components/dex/Dockerfile create mode 100755 components/dex/dex.tenzir-entrypoint.sh create mode 100644 components/seaweed/Dockerfile create mode 100755 components/seaweed/seaweed.tenzir-entrypoint.sh create mode 160000 components/tenant-manager create mode 100644 examples/localdev/docker-compose.yaml create mode 100644 examples/localdev/env.example create mode 100644 examples/onprem-integrated/docker-compose.yaml create mode 100644 examples/onprem-integrated/env.example diff --git a/.github/workflows/deploy-to-staging.yaml b/.github/workflows/deploy-to-staging.yaml new file mode 100644 index 0000000..0465854 --- /dev/null +++ b/.github/workflows/deploy-to-staging.yaml @@ -0,0 +1,37 @@ +name: Deploy submodule updates to the staging environment + +on: + push: + branches: [main] + +jobs: + cloud_deployment: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v3 + with: + submodules: true + + - name: Get tenant-manager submodule commit hash + id: tenant-manager-commit + run: | + cd ./components/tenant-manager + echo "::set-output name=commit::$(git rev-parse HEAD)" + + - name: Deploy tenant manager + uses: benc-uk/workflow-dispatch@v1 + with: + workflow: tzcp-deploy-staging.yaml + repo: tenzir/event-horizon + token: "${{ secrets.REPO_SCOPE_ACCESS_TOKEN }}" + ref: ${{ steps.tenant-manager-commit.outputs.commit }}" + # inputs: '{ "message": "blah blah", "something": false }' + + # App deployments to staging are done automatically by Vercel atm. + # - name: Deploy app + # uses: benc-uk/workflow-dispatch@v1 + # with: + # workflow: deploy-staging.yaml + # repo: tenzir/app + # ref: ${{ steps.app-commit.outputs.commit }}" diff --git a/.github/workflows/platform-release.yaml b/.github/workflows/platform-release.yaml new file mode 100644 index 0000000..3920351 --- /dev/null +++ b/.github/workflows/platform-release.yaml @@ -0,0 +1,120 @@ +name: Create Sovereign Edition containers and also push a new production Cloud Deployment + +on: + release: + types: [created] + +jobs: + cloud_deployment: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v3 + with: + submodules: true + + - name: Get app submodule commit hash + id: app-commit + run: | + cd ./components/app + echo "::set-output name=commit::$(git rev-parse HEAD)" + + - name: Get tenant-manager submodule commit hash + id: tenant-manager-commit + run: | + cd ./components/tenant-manager + echo "::set-output name=commit::$(git rev-parse HEAD)" + + - name: Deploy tenant manager + uses: benc-uk/workflow-dispatch@v1 + with: + workflow: tzcp-deploy-production.yaml + repo: tenzir/event-horizon + token: "${{ secrets.REPO_SCOPE_ACCESS_TOKEN }}" + ref: ${{ steps.tenant-manager-commit.outputs.commit }}" + + - name: Deploy app + uses: benc-uk/workflow-dispatch@v1 + with: + workflow: push-to-production.yaml + repo: tenzir/app + token: "${{ secrets.REPO_SCOPE_ACCESS_TOKEN }}" + ref: ${{ steps.app-commit.outputs.commit }}" + + attach_release_artifacts: + runs-on: ubuntu-latest + steps: + - name: Create tarball + run: | + tar cf platform.tar README.md LICENSE examples/ + - name: Publish tarball to the GitHub Release + if: ${{ github.event_name == 'release' }} + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ github.event.release.upload_url }} + asset_path: "platform.tar" + asset_name: "platform.tar" + asset_content_type: application/x-tar + + build_and_push_containers: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + name: Check out code + + - uses: mr-smithers-excellent/docker-build-push@v6 + name: Build & push Docker image + with: + image: tenzir-dex + tags: platform-${{ github.event.release.tag_name }} + registry: ghcr.io + directory: components/dex + dockerfile: components/dex/Dockerfile + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - uses: mr-smithers-excellent/docker-build-push@v6 + name: Build & push Docker image + with: + image: tenzir-seaweed + tags: platform-${{ github.event.release.tag_name }} + registry: ghcr.io + directory: components/seaweed + dockerfile: components/seaweed/Dockerfile + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - uses: mr-smithers-excellent/docker-build-push@v6 + name: Build & push Docker image + with: + image: platform + tags: platform-${{ github.event.release.tag_name }} + registry: ghcr.io + directory: components/tenant-manager/platform/tenant_manager + dockerfile: components/tenant-manager/platform/tenant_manager/Dockerfile + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - uses: mr-smithers-excellent/docker-build-push@v6 + name: Build & push Docker image + with: + image: tenzir-platform + tags: platform-${{ github.event.release.tag_name }} + registry: ghcr.io + directory: components/tenant-manager/platform/public_cli + dockerfile: components/tenant-manager/platform/public_cli/Dockerfile + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - uses: mr-smithers-excellent/docker-build-push@v6 + name: Build & push Docker image + with: + image: tenzir-app + tags: platform-${{ github.event.release.tag_name }} + registry: ghcr.io + directory: components/app + dockerfile: components/app/Dockerfile + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..d808580 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,6 @@ +[submodule "components/app"] + path = components/app + url = git@github.com:tenzir/app.git +[submodule "components/tenant-manager"] + path = components/tenant-manager + url = git@github.com:tenzir/event-horizon.git diff --git a/README.md b/README.md index af88506..fd2dcc8 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,24 @@ -# platform -On-premise version of the Tenzir Platform +# Tenzir Platform + +On-premise version of the Tenzir Platform. + +**NOTE**: The examples and files in this repository are only +usable in combination with Sovereign Edition access token. +Please [contact sales](https://tenzir.com/pricing) for more +information. + +## Quick Start + +For detailed instructions, visit our [documentation](https://docs.tenzir.com/setup-guides/deploy-the-platform). + +``` +echo | docker login ghcr.io -u tenzir-distribution --password-stdin +cd examples/localdev +mv env.example .env +vim .env +docker compose up -d +docker compose logs -f +``` + + +For Tenzir employees, it's instead recommended to start with [this version](https://github.com/tenzir/event-horizon/tree/main/platform/compose) that ties into our deployed infrastructure. diff --git a/components/app b/components/app new file mode 160000 index 0000000..e000d6e --- /dev/null +++ b/components/app @@ -0,0 +1 @@ +Subproject commit e000d6e57aabf48ab06c512f566afe241569331e diff --git a/components/dex/Dockerfile b/components/dex/Dockerfile new file mode 100644 index 0000000..8e474d2 --- /dev/null +++ b/components/dex/Dockerfile @@ -0,0 +1,11 @@ +# A fork of the upstream dex container that +# allows configuring the initial user and +# password via environment variables, by writing a +# config file to `/etc/dex/tenzir-config.yaml` + +FROM dexidp/dex:v2.38.0 + +COPY dex.tenzir-entrypoint.sh /tenzir-entrypoint.sh + +ENTRYPOINT /tenzir-entrypoint.sh + diff --git a/components/dex/dex.tenzir-entrypoint.sh b/components/dex/dex.tenzir-entrypoint.sh new file mode 100755 index 0000000..b1ea162 --- /dev/null +++ b/components/dex/dex.tenzir-entrypoint.sh @@ -0,0 +1,36 @@ +#!/bin/sh + +# Custom entrypoint to work around some options of dex being +# only configurable via config file and not via environment +# variable. + +cat < /etc/dex/tenzir-config.yaml +issuer: ${TENZIR_PLATFORM_OIDC_PROVIDER_ISSUER_URL} + +storage: + type: sqlite3 + +web: + http: 0.0.0.0:5556 + +staticClients: + - id: tenzir-app + redirectURIs: + - '${TENZIR_PLATFORM_DOMAIN}/auth/callback/dex' + name: 'Tenzir App' + secret: ${TENZIR_PLATFORM_OIDC_PROVIDER_CLIENT_SECRET} + +enablePasswordDB: true + +staticPasswords: +- email: "${DEX_EMAIL}" + hash: "${DEX_PASSWORD_HASH}" + username: "${DEX_USER}" + userID: "08a8684b-db88-4b73-90a9-3cd1661f5466" +EOF + +# Chain into the entrypoint of the upstream dexidp/dex image +exec /usr/local/bin/docker-entrypoint "$@" + + + diff --git a/components/seaweed/Dockerfile b/components/seaweed/Dockerfile new file mode 100644 index 0000000..a265b49 --- /dev/null +++ b/components/seaweed/Dockerfile @@ -0,0 +1,11 @@ +# A fork of the official seaweed container that +# allows configuring the bucket name and access +# keys via environment variables, by writing a +# config file to `/config.json` + +FROM chrislusf/seaweedfs + +COPY seaweed.tenzir-entrypoint.sh /tenzir-entrypoint.sh + +ENTRYPOINT /tenzir-entrypoint.sh + diff --git a/components/seaweed/seaweed.tenzir-entrypoint.sh b/components/seaweed/seaweed.tenzir-entrypoint.sh new file mode 100755 index 0000000..43ef12d --- /dev/null +++ b/components/seaweed/seaweed.tenzir-entrypoint.sh @@ -0,0 +1,26 @@ +#!/bin/sh + +cat < /config.json +{ + "identities": [ + { + "name": "tenzir-platform", + "credentials": [ + { + "accessKey": "${TENZIR_PLATFORM_INTERNAL_ACCESS_KEY_ID}", + "secretKey": "${TENZIR_PLATFORM_INTERNAL_SECRET_ACCESS_KEY}" + } + ], + "actions": [ + "Read:${TENZIR_PLATFORM_INTERNAL_BUCKET_NAME}", + "Write:${TENZIR_PLATFORM_INTERNAL_BUCKET_NAME}", + "List:${TENZIR_PLATFORM_INTERNAL_BUCKET_NAME}", + "Tagging:${TENZIR_PLATFORM_INTERNAL_BUCKET_NAME}", + "Admin:${TENZIR_PLATFORM_INTERNAL_BUCKET_NAME}" + ] + } + ] +} +EOF + +exec /entrypoint.sh "$@" diff --git a/components/tenant-manager b/components/tenant-manager new file mode 160000 index 0000000..725edd4 --- /dev/null +++ b/components/tenant-manager @@ -0,0 +1 @@ +Subproject commit 725edd4c5340fbd514855fe58bcbddd3eeae7e8c diff --git a/examples/localdev/docker-compose.yaml b/examples/localdev/docker-compose.yaml new file mode 100644 index 0000000..c636648 --- /dev/null +++ b/examples/localdev/docker-compose.yaml @@ -0,0 +1,121 @@ +# A completely self-contained configuration using a bundled +# postgres database and a bundled identity provider with one +# hardcoded user. +# +# Useful for prototyping or local development with no available +# infrastructure. Container ports are mapped to the range 3000-3004. + + + +services: + platform: + image: ghcr.io/tenzir/platform:${TENZIR_PLATFORM_VERSION:-latest} + command: ["tenant_manager/rest/server/local.py"] + environment: + - BASE_PATH= + - GATEWAY_WS_ENDPOINT=${TENZIR_PLATFORM_CONTROL_ENDPOINT} + - GATEWAY_HTTP_ENDPOINT=http://websocket-gateway:5000 + - TENZIR_DEMO_NODE_IMAGE=${TENZIR_PLATFORM_DEMO_NODE_IMAGE:-tenzir/tenzir-demo:latest} + - TENANT_MANAGER_APP_API_KEY=${TENZIR_PLATFORM_INTERNAL_APP_API_KEY} + - TENANT_MANAGER_TENANT_TOKEN_ENCRYPTION_KEY=${TENZIR_PLATFORM_INTERNAL_TENANT_TOKEN_ENCRYPTION_KEY} + - TENANT_MANAGER_AUTH__ENABLE_SELF_SIGNED=false + - TENANT_MANAGER_AUTH__TRUSTED_AUDIENCES=${TENZIR_PLATFORM_OIDC_TRUSTED_AUDIENCES} + - TENANT_MANAGER_AUTH__ADMIN_FUNCTIONS=${TENZIR_PLATFORM_OIDC_ADMIN_RULES} + - STORE__TYPE=${TENZIR_PLATFORM_STORE_TYPE} + - STORE__POSTGRES_URI=postgresql://${TENZIR_PLATFORM_POSTGRES_USER}:${TENZIR_PLATFORM_POSTGRES_PASSWORD}@${TENZIR_PLATFORM_POSTGRES_HOSTNAME}/${TENZIR_PLATFORM_POSTGRES_DB} + # seaweedfs s3 connection + - TENANT_MANAGER_SIDEPATH_BUCKET_NAME=${TENZIR_PLATFORM_INTERNAL_BUCKET_NAME} + - BLOB_STORAGE__ENDPOINT_URL=http://seaweed:8333 + - BLOB_STORAGE__PUBLIC_ENDPOINT_URL=${TENZIR_PLATFORM_BLOBS_ENDPOINT} + - BLOB_STORAGE__ACCESS_KEY_ID=${TENZIR_PLATFORM_INTERNAL_ACCESS_KEY_ID} + - BLOB_STORAGE__SECRET_ACCESS_KEY=${TENZIR_PLATFORM_INTERNAL_SECRET_ACCESS_KEY} + volumes: + # The docker socket gets mapped into the container in order to enable spawning new + # demo nodes. + - /var/run/docker.sock:/var/run/docker.sock + ports: + - 3001:5000 + depends_on: + - websocket-gateway + - postgres + + websocket-gateway: + image: ghcr.io/tenzir/platform:${TENZIR_PLATFORM_VERSION:-latest} + environment: + - BASE_PATH= + - TENZIR_PROXY_TIMEOUT=60 + - TENANT_MANAGER_APP_API_KEY=${TENZIR_PLATFORM_INTERNAL_APP_API_KEY} + - TENANT_MANAGER_TENANT_TOKEN_ENCRYPTION_KEY=${TENZIR_PLATFORM_INTERNAL_TENANT_TOKEN_ENCRYPTION_KEY} + - STORE__TYPE=${TENZIR_PLATFORM_STORE_TYPE} + - STORE__POSTGRES_URI=postgresql://${TENZIR_PLATFORM_POSTGRES_USER}:${TENZIR_PLATFORM_POSTGRES_PASSWORD}@${TENZIR_PLATFORM_POSTGRES_HOSTNAME}/${TENZIR_PLATFORM_POSTGRES_DB} + depends_on: + - postgres + command: ["tenant_manager/ws/server/local.py"] + ports: + - 3002:5000 + + postgres: + image: postgres:14.5 + restart: always + environment: + - POSTGRES_USER=${TENZIR_PLATFORM_POSTGRES_USER} + - POSTGRES_PASSWORD=${TENZIR_PLATFORM_POSTGRES_PASSWORD} + - POSTGRES_DB=${TENZIR_PLATFORM_POSTGRES_DB} + volumes: + - postgres_data:/var/lib/postgresql/data + + # Note the ~25 seconds startup delay before the seaweed server + # becomes ready. + seaweed: + image: chrislusf/seaweedfs + environment: + - TENZIR_PLATFORM_INTERNAL_ACCESS_KEY_ID + - TENZIR_PLATFORM_INTERNAL_SECRET_ACCESS_KEY + - TENZIR_PLATFORM_INTERNAL_BUCKET_NAME + entrypoint: ["/tenzir-entrypoint.sh"] + command: ["server", "-dir=/var/lib/seaweedfs", "-s3", "-s3.config=/config.json"] + volumes: + - ./config/seaweed.tenzir-entrypoint.sh:/tenzir-entrypoint.sh + - seaweed_data:/var/lib/seaweedfs + ports: + - '3003:8333' + + dex: + image: ghcr.io/tenzir/tenzir-dex:${TENZIR_PLATFORM_VERSION:-latest} + environment: + - TENZIR_PLATFORM_DOMAIN + - TENZIR_PLATFORM_OIDC_PROVIDER_CLIENT_SECRET + - TENZIR_PLATFORM_OIDC_PROVIDER_ISSUER_URL + - DEX_USER=admin + - DEX_EMAIL=admin@example.org + # escaped bcrypt hash of the arbitary random password "062c73c4cf36ba07c0ab5f205ce3d011", generated with + # echo 062c73c4cf36ba07c0ab5f205ce3d011 | htpasswd -BinC 10 admin | cut -d: -f2 | sed 's,\$,$$,g' + - DEX_PASSWORD_HASH=$$2y$$10$$cXl69JddxraqvWN5Ae01xuSSNJ5ONoJfMJIr058bXzIAIfwhj7k3C + ports: + - "3004:5556" + command: ['dex', 'serve', '/etc/dex/tenzir-config.yaml'] + + app: + image: ghcr.io/tenzir/app:${TENZIR_PLATFORM_VERSION:-latest} + environment: + - AUTH_TRUST_HOST=true + - PUBLIC_ENABLE_HIGHLIGHT=false + - ORIGIN=${TENZIR_PLATFORM_DOMAIN} + - PRIVATE_OIDC_PROVIDER_CLIENT_ID=${TENZIR_PLATFORM_OIDC_PROVIDER_CLIENT_ID} + - PRIVATE_OIDC_PROVIDER_CLIENT_SECRET=${TENZIR_PLATFORM_OIDC_PROVIDER_CLIENT_SECRET} + - PRIVATE_OIDC_PROVIDER_ISSUER_URL=${TENZIR_PLATFORM_OIDC_PROVIDER_ISSUER_URL} + - PRIVATE_OIDC_PROVIDER_NAME=${TENZIR_PLATFORM_OIDC_PROVIDER_NAME} + - PUBLIC_OIDC_PROVIDER_ID=${TENZIR_PLATFORM_OIDC_PROVIDER_NAME} + - PRIVATE_USER_ENDPOINT=http://platform:5000/user + - PRIVATE_WEBAPP_ENDPOINT=http://platform:5000/webapp + - PRIVATE_WEBAPP_KEY=${TENZIR_PLATFORM_INTERNAL_APP_API_KEY} + - AUTH_SECRET=${TENZIR_PLATFORM_INTERNAL_AUTH_SECRET} + + ports: + - "3000:3000" + +volumes: + postgres_data: + driver: local + seaweed_data: + driver: local diff --git a/examples/localdev/env.example b/examples/localdev/env.example new file mode 100644 index 0000000..b118a24 --- /dev/null +++ b/examples/localdev/env.example @@ -0,0 +1,53 @@ +# The `platform.local` placeholder domain needs to be +# replaced by an ip or hostname under which the host running +# the docker compose file is reachable. +# +# **NOTE**: The issuer URL must be a hostname or ip address +# that can be used to reach the container *both* from within +# the docker network and from a user's browser. In particular +# `localhost` will not work. + +TENZIR_PLATFORM_DOMAIN=http://platform.local:3000 +TENZIR_PLATFORM_API_ENDPOINT=http://platform.local:3001 +TENZIR_PLATFORM_CONTROL_ENDPOINT=ws://platform.local:3002 +TENZIR_PLATFORM_BLOBS_ENDPOINT=http://platform.local:3003 +TENZIR_PLATFORM_OIDC_PROVIDER_ISSUER_URL=http://platform.local:3004 + +TENZIR_PLATFORM_OIDC_PROVIDER_NAME=dex +TENZIR_PLATFORM_OIDC_PROVIDER_CLIENT_ID=tenzir-app +TENZIR_PLATFORM_OIDC_PROVIDER_CLIENT_SECRET=ZXhhbXBsZS1hcHAtc2VjcmV0 +TENZIR_PLATFORM_OIDC_TRUSTED_AUDIENCES='{"issuer": "http://platform.local:3004","audiences": ["tenzir-app"]}' +TENZIR_PLATFORM_OIDC_ADMIN_RULES='[{"auth_fn":"auth_user","user_id":"08a8684b-db88-4b73-90a9-3cd1661f5466"}]' + +# Database connection +TENZIR_PLATFORM_STORE_TYPE=postgres +TENZIR_PLATFORM_POSTGRES_USER=postgres +TENZIR_PLATFORM_POSTGRES_PASSWORD=postgres +TENZIR_PLATFORM_POSTGRES_DB=platform +TENZIR_PLATFORM_POSTGRES_HOSTNAME=postgres:5432 + + +# ------------------------------------------------------------------------------------------- +# Variables that are not user-facing, these should move into a separate file later on. +# ------------------------------------------------------------------------------------------- + +# Secrets used by the platform +# - AUTH_SECRET: +# An arbitrary random string used as key to encrypt frontend cookies. +# Generate with `openssl rand -hex 32`. +# - TENANT_TOKEN_ENCRYPTION_KEY: +# Encryption key used to generate user keys +# Generate with `openssl rand 32 | base64`. +# - APP_API_KEY: +# An arbitrary random string used by the app to access the `/webapp` API. +# Generate with `openssl rand -hex 32`. +TENZIR_PLATFORM_INTERNAL_AUTH_SECRET=4b13cc4a8b936b17b64e91a0d7c144a0d8fa739d073f9a7c24ac62634b28686d +TENZIR_PLATFORM_INTERNAL_TENANT_TOKEN_ENCRYPTION_KEY=CBOXE4x37RKRLHyUNKeAsfg8Tbejm2N251aKnBXakpU= +TENZIR_PLATFORM_INTERNAL_APP_API_KEY=d3d185cc4d9a1bde0e07e24c2eb0bfe9d2726acb3a386f8882113727ac6e90cf + +# The access key must be valid and must have read and write permissions on the bucket. +# When using the bundled seaweed instance, these are also arbitrary strings that +# are automatically written into `/config.json` in the seaweed container. +TENZIR_PLATFORM_INTERNAL_BUCKET_NAME=platform-bucket +TENZIR_PLATFORM_INTERNAL_ACCESS_KEY_ID=86ac27778503b3396e934126cea384bc +TENZIR_PLATFORM_INTERNAL_SECRET_ACCESS_KEY=db973c3a1f67b7024c4a77d2fe41ca63 diff --git a/examples/onprem-integrated/docker-compose.yaml b/examples/onprem-integrated/docker-compose.yaml new file mode 100644 index 0000000..5e1df03 --- /dev/null +++ b/examples/onprem-integrated/docker-compose.yaml @@ -0,0 +1,118 @@ +# Docker Compose setup for a platform deployment that integrates +# with existing local infrastructure, eg. a dedicated auth provider and +# a centrally managed database. +# +# Assumptions: +# +# - An external identity provider exists and is configured +# in the `.env` file: +# TENZIR_PLATFORM_OIDC_PROVIDER_ISSUER_URL +# TENZIR_PLATFORM_OIDC_PROVIDER_CLIENT_ID +# TENZIR_PLATFORM_OIDC_PROVIDER_CLIENT_SECRET +# +# - An external postgres database exists and is accessible +# via TCP connection. +# TENZIR_PLATFORM_POSTGRES_USER +# TENZIR_PLATFORM_POSTGRES_PASSWORD +# TENZIR_PLATFORM_POSTGRES_HOSTNAME +# TENZIR_PLATFORM_POSTGRES_DB +# +# - A reverse proxy is configured to terminate TLS for the +# domains under which the platform is reachable. +# TENZIR_PLATFORM_DOMAIN +# TENZIR_PLATFORM_CONTROL_ENDPOINT +# TENZIR_PLATFORM_BLOBS_ENDPOINT +# TENZIR_PLATFORM_API_ENDPOINT [only used by the CLI] + +services: + platform: + image: ghcr.io/tenzir/platform:${TENZIR_PLATFORM_VERSION:-latest} + command: ["tenant_manager/rest/server/local.py"] + environment: + - BASE_PATH= + - GATEWAY_WS_ENDPOINT=${TENZIR_PLATFORM_CONTROL_ENDPOINT} + - GATEWAY_HTTP_ENDPOINT=http://websocket-gateway:5000 + - TENZIR_DEMO_NODE_IMAGE=${TENZIR_PLATFORM_DEMO_NODE_IMAGE:-} + - TENANT_MANAGER_APP_API_KEY=${TENZIR_PLATFORM_INTERNAL_APP_API_KEY} + - TENANT_MANAGER_TENANT_TOKEN_ENCRYPTION_KEY=${TENZIR_PLATFORM_INTERNAL_TENANT_TOKEN_ENCRYPTION_KEY} + - TENANT_MANAGER_AUTH__ENABLE_SELF_SIGNED=false + - TENANT_MANAGER_AUTH__TRUSTED_AUDIENCES=${TENZIR_PLATFORM_OIDC_TRUSTED_AUDIENCES} + - TENANT_MANAGER_AUTH__ADMIN_FUNCTIONS=${TENZIR_PLATFORM_OIDC_ADMIN_RULES} + - STORE__TYPE=${TENZIR_PLATFORM_STORE_TYPE} + - STORE__POSTGRES_URI=postgresql://${TENZIR_PLATFORM_POSTGRES_USER}:${TENZIR_PLATFORM_POSTGRES_PASSWORD}@${TENZIR_PLATFORM_POSTGRES_HOSTNAME}/${TENZIR_PLATFORM_POSTGRES_DB} + # seaweedfs connection + - TENANT_MANAGER_SIDEPATH_BUCKET_NAME=${TENZIR_PLATFORM_INTERNAL_BUCKET_NAME} + - BLOB_STORAGE__ENDPOINT_URL=http://seaweed:8333 + - BLOB_STORAGE__PUBLIC_ENDPOINT_URL=${TENZIR_PLATFORM_BLOBS_ENDPOINT} + - BLOB_STORAGE__ACCESS_KEY_ID=${TENZIR_PLATFORM_INTERNAL_ACCESS_KEY_ID} + - BLOB_STORAGE__SECRET_ACCESS_KEY=${TENZIR_PLATFORM_INTERNAL_SECRET_ACCESS_KEY} + depends_on: + - websocket-gateway + volumes: + - /var/run/docker.sock:/var/run/docker.sock + ports: + - 5000:5000 + + websocket-gateway: + image: ghcr.io/tenzir/platform:${TENZIR_PLATFORM_VERSION:-latest} + environment: + - BASE_PATH= + - TENZIR_PROXY_TIMEOUT=60 + - TENANT_MANAGER_APP_API_KEY=${TENZIR_PLATFORM_INTERNAL_APP_API_KEY} + - TENANT_MANAGER_TENANT_TOKEN_ENCRYPTION_KEY=${TENZIR_PLATFORM_INTERNAL_TENANT_TOKEN_ENCRYPTION_KEY} + - STORE__TYPE=${TENZIR_PLATFORM_STORE_TYPE} + - STORE__POSTGRES_URI=postgresql://${TENZIR_PLATFORM_POSTGRES_USER}:${TENZIR_PLATFORM_POSTGRES_PASSWORD}@${TENZIR_PLATFORM_POSTGRES_HOSTNAME}/${TENZIR_PLATFORM_POSTGRES_DB} + command: ["tenant_manager/ws/server/local.py"] + ports: + - 5001:5000 + + app: + image: ghcr.io/tenzir/app:${TENZIR_PLATFORM_VERSION:-latest} + environment: + AUTH_TRUST_HOST: true + PUBLIC_ENABLE_HIGHLIGHT: false + ORIGIN: ${TENZIR_PLATFORM_DOMAIN} + PRIVATE_OIDC_PROVIDER_CLIENT_ID: ${TENZIR_PLATFORM_APP_CLIENT_ID} + PRIVATE_OIDC_PROVIDER_CLIENT_SECRET: ${TENZIR_PLATFORM_APP_CLIENT_SECRET} + PRIVATE_OIDC_PROVIDER_ISSUER_URL: ${TENZIR_PLATFORM_OIDC_PROVIDER_ISSUER_URL} + PRIVATE_OIDC_PROVIDER_NAME: ${TENZIR_PLATFORM_OIDC_PROVIDER_NAME} + PUBLIC_OIDC_PROVIDER_ID: ${TENZIR_PLATFORM_OIDC_PROVIDER_NAME} + PRIVATE_USER_ENDPOINT: http://platform:5000/user + PRIVATE_WEBAPP_ENDPOINT: http://platform:5000/webapp + PRIVATE_WEBAPP_KEY: ${TENZIR_PLATFORM_INTERNAL_APP_API_KEY} + AUTH_SECRET: ${TENZIR_PLATFORM_INTERNAL_AUTH_SECRET} + PUBLIC_DISABLE_DEMO_NODE_AND_TOUR: true + ports: + - "3000:3000" + + # Note the ~25 seconds startup delay before the seaweed server + # becomes ready. + seaweed: + image: ghcr.io/tenzir/tenzir-seaweedfs:${TENZIR_PLATFORM_VERSION:-latest} + environment: + - TENZIR_PLATFORM_INTERNAL_ACCESS_KEY_ID + - TENZIR_PLATFORM_INTERNAL_SECRET_ACCESS_KEY + - TENZIR_PLATFORM_INTERNAL_BUCKET_NAME + command: ["server", "-dir=/var/lib/seaweedfs", "-s3", "-s3.config=/config.json"] + volumes: + - seaweed_data:/var/lib/seaweedfs + ports: + - '8333:8333' + + cli: + image: ghcr.io/tenzir/tenzir-platform:${TENZIR_PLATFORM_VERSION:-latest} + profiles: + - donotstart + volumes: + - cli_cache:/cache/tenzir-platform + environment: + - XDG_CACHE_HOME=/cache/ + - TENZIR_PLATFORM_CLI_API_ENDPOINT=http://platform:5000/ + - TENZIR_PLATFORM_CLI_ISSUER_URL=${TENZIR_PLATFORM_OIDC_PROVIDER_ISSUER_URL} + - TENZIR_PLATFORM_CLI_CLIENT_ID=${TENZIR_PLATFORM_CLI_CLIENT_ID} + +volumes: + seaweed_data: + driver: local + cli_cache: + driver: local diff --git a/examples/onprem-integrated/env.example b/examples/onprem-integrated/env.example new file mode 100644 index 0000000..b85983c --- /dev/null +++ b/examples/onprem-integrated/env.example @@ -0,0 +1,67 @@ +# The domain under which the platform frontend is reachable. +TENZIR_PLATFORM_DOMAIN= + +# The endpoint to which tenzir nodes should connect. +# Should a url with `ws://` or `wss://` scheme. +TENZIR_PLATFORM_CONTROL_ENDPOINT= + +# The url where the blob storage is exposed. +TENZIR_PLATFORM_BLOBS_ENDPOINT= + +# Platform OIDC Policy Configuration +# - OIDC_PROVIDER_NAME: A short identifier for the OIDC provider. (e.g. 'auth0', 'keycloak', ...) +# - OIDC_PROVIDER_ISSUER_URL: The OIDC provider used for logging into the platform. +# - TRUSTED_AUDIENCES: A JSON object containing the OIDC issuer and audiences that should be accepted +# by the platform. Example: '{"issuer": "keycloak.example.org", "audiences": ["tenzir_platform"]}' +# - ADMIN_FUNCTIONS: A JSON list of rules granting access to the admin API. +# See the documentation for a description of available rules. +# Example: '[{"connection": "google-oauth2","organization_claim": "tenzir/org","organization": "TenzirPlatformAdmins","auth_fn": "auth_organization"}]' +# This example rule grants admin access to all users with a valid signed id_token containing +# the fields `{"connection": "google-oauth2", "tenzir/org": "TenzirPlatformAdmins"}`. +TENZIR_PLATFORM_OIDC_PROVIDER_NAME= +TENZIR_PLATFORM_OIDC_PROVIDER_ISSUER_URL= +TENZIR_PLATFORM_OIDC_TRUSTED_AUDIENCES= +TENZIR_PLATFORM_OIDC_ADMIN_RULES= + +# Specific OIDC Settings for the CLI. +# The Device Code flow must be enabled for this client. +# The returned audience must match the client id. +TENZIR_PLATFORM_CLI_CLIENT_ID= + +# Specific OIDC Settings for the frontend. +# The Authorization Code flow must be enabled for this client. +# The returned audience must match the client id. +TENZIR_PLATFORM_APP_CLIENT_ID= +TENZIR_PLATFORM_APP_CLIENT_SECRET= + +# Database connection +TENZIR_PLATFORM_STORE_TYPE=postgres +TENZIR_PLATFORM_POSTGRES_USER= +TENZIR_PLATFORM_POSTGRES_PASSWORD= +TENZIR_PLATFORM_POSTGRES_DB= +TENZIR_PLATFORM_POSTGRES_HOSTNAME= + + +# ------------------------------------------------------------------------------------------- +# Variables that are not user-facing, these should move into a separate file later on. +# ------------------------------------------------------------------------------------------- + +# Secrets used by the platform +# - AUTH_SECRET: +# An arbitrary random string used as key to encrypt frontend cookies. +# Generate with `openssl rand -hex 32`. +# - TENANT_TOKEN_ENCRYPTION_KEY: +# Encryption key used to generate user keys +# Generate with `openssl rand 32 | base64encode`. +# - APP_API_KEY: +# An arbitrary random string used by the app to access the `/webapp` API. +# Generate with `openssl rand -hex 32`. +TENZIR_PLATFORM_AUTH_SECRET= +TENZIR_PLATFORM_INTERNAL_TENANT_TOKEN_ENCRYPTION_KEY= +TENZIR_PLATFORM_INTERNAL_APP_API_KEY= + +# The access key must be valid and must have read and write permissions on the bucket. +# When using the bundled seaweed instance, this means they must match the values in `seaweed/config.json` +TENZIR_PLATFORM_INTERNAL_BUCKET_NAME=platform-bucket +TENZIR_PLATFORM_INTERNAL_ACCESS_KEY_ID=86ac27778503b3396e934126cea384bc +TENZIR_PLATFORM_INTERNAL_SECRET_ACCESS_KEY=db973c3a1f67b7024c4a77d2fe41ca63