From f5c050f70a5c458a12ac17a0b30273af5e3e877e Mon Sep 17 00:00:00 2001 From: Kian Parvin Date: Fri, 23 Aug 2024 13:41:50 +0200 Subject: [PATCH] simplify Docker compose and OpenFGA setup --- docker-compose.yaml | 50 +-- local/openfga/Dockerfile | 21 +- local/openfga/authorisation_model.json | 449 ++++++++++++++++++++++++- local/openfga/entrypoint.sh | 22 ++ 4 files changed, 492 insertions(+), 50 deletions(-) mode change 120000 => 100644 local/openfga/authorisation_model.json create mode 100755 local/openfga/entrypoint.sh diff --git a/docker-compose.yaml b/docker-compose.yaml index 89bda35e9..8846788ce 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -93,65 +93,21 @@ services: cap_add: - IPC_LOCK - migrateopenfga: - image: openfga/openfga:v1.2.0 - container_name: migrateopenfga - command: migrate --datastore-engine postgres --datastore-uri 'postgresql://jimm:jimm@db/jimm?sslmode=disable' - depends_on: - db: - condition: service_healthy - - insert-hardcoded-store: - image: governmentpaas/psql - container_name: insert-hardcoded-store - command: psql -Atx postgresql://jimm:jimm@db/jimm?sslmode=disable -c "INSERT INTO store (id,name,created_at,updated_at) VALUES ('01GP1254CHWJC1MNGVB0WDG1T0','jimm',NOW(),NOW());" - depends_on: - migrateopenfga: - condition: service_completed_successfully - openfga: - # We use our 'image' to mimic juju standard. - # image: openfga/openfga:latest build: - context: . - dockerfile: ./local/openfga/Dockerfile + context: ./local/openfga/ + dockerfile: Dockerfile container_name: openfga environment: OPENFGA_AUTHN_METHOD: "preshared" OPENFGA_AUTHN_PRESHARED_KEYS: "jimm" OPENFGA_DATASTORE_ENGINE: "postgres" OPENFGA_DATASTORE_URI: "postgresql://jimm:jimm@db/jimm?sslmode=disable" - command: run ports: - 8080:8080 - 3000:3000 depends_on: - migrateopenfga: - condition: service_completed_successfully - insert-hardcoded-store: - condition: service_completed_successfully - healthcheck: - test: [ "CMD", "curl", "http://0.0.0.0:8080/healthz" ] - interval: 5s - timeout: 5s - retries: 10 - - # Adds the auth model and updates its authorisation model id to be the expected hard-coded id such that our local JIMM can utilise it for queries. - # The auth model json is retrieved from file via volume mount. - insert-hardcoded-auth-model: - profiles: ["dev", "test"] - image: governmentpaas/psql - container_name: insert-hardcoded-auth-model - volumes: - - ./local/openfga/authorisation_model.json:/authorisation_model.json - command: - - /bin/sh - - -c - - | - wget -q -O - --header 'Content-Type: application/json' --header 'Authorization: Bearer jimm' --post-file authorisation_model.json openfga:8080/stores/01GP1254CHWJC1MNGVB0WDG1T0/authorization-models - psql -Atx postgresql://jimm:jimm@db/jimm?sslmode=disable -c "UPDATE authorization_model SET authorization_model_id = '01GP1EC038KHGB6JJ2XXXXCXKB' WHERE store = '01GP1254CHWJC1MNGVB0WDG1T0';" - depends_on: - openfga: + db: condition: service_healthy keycloak: diff --git a/local/openfga/Dockerfile b/local/openfga/Dockerfile index e2c9b06a7..7f24e2857 100644 --- a/local/openfga/Dockerfile +++ b/local/openfga/Dockerfile @@ -1,9 +1,26 @@ # syntax=docker/dockerfile:1.3.1 FROM ubuntu:20.04 AS build -RUN apt-get -qq update && apt-get -qq install -y ca-certificates curl + +# Install some tools necessary heath checks and setup. +RUN apt-get -qq update && apt-get -qq install -y ca-certificates curl wget postgresql-client + EXPOSE 8081 EXPOSE 8080 + WORKDIR /app + +# Copy OpenFGA binaries from upstream image COPY --from=openfga/openfga:v1.2.0 /openfga /app/openfga COPY --from=openfga/openfga:v1.2.0 /assets /app/assets -ENTRYPOINT ["/app/openfga"] + +COPY entrypoint.sh /app/entrypoint.sh +COPY authorisation_model.json /app/authorisation_model.json + +ENTRYPOINT [ "/app/entrypoint.sh" ] + +HEALTHCHECK \ + --start-period=5s \ + --interval=1s \ + --timeout=5s \ + --retries=10 \ + CMD [ "curl", "http://0.0.0.0:8080/healthz" ] diff --git a/local/openfga/authorisation_model.json b/local/openfga/authorisation_model.json deleted file mode 120000 index 97998ba1b..000000000 --- a/local/openfga/authorisation_model.json +++ /dev/null @@ -1 +0,0 @@ -../../openfga/authorisation_model.json \ No newline at end of file diff --git a/local/openfga/authorisation_model.json b/local/openfga/authorisation_model.json new file mode 100644 index 000000000..7787b5ff0 --- /dev/null +++ b/local/openfga/authorisation_model.json @@ -0,0 +1,448 @@ +{ + "schema_version": "1.1", + "type_definitions": [ + { + "metadata": { + "relations": { + "administrator": { + "directly_related_user_types": [ + { + "type": "user" + }, + { + "type": "user", + "wildcard": {} + }, + { + "relation": "member", + "type": "group" + } + ] + }, + "consumer": { + "directly_related_user_types": [ + { + "type": "user" + }, + { + "type": "user", + "wildcard": {} + }, + { + "relation": "member", + "type": "group" + } + ] + }, + "model": { + "directly_related_user_types": [ + { + "type": "model" + } + ] + }, + "reader": { + "directly_related_user_types": [ + { + "type": "user" + }, + { + "type": "user", + "wildcard": {} + }, + { + "relation": "member", + "type": "group" + } + ] + } + } + }, + "relations": { + "administrator": { + "union": { + "child": [ + { + "this": {} + }, + { + "tupleToUserset": { + "computedUserset": { + "relation": "administrator" + }, + "tupleset": { + "relation": "model" + } + } + } + ] + } + }, + "consumer": { + "union": { + "child": [ + { + "this": {} + }, + { + "computedUserset": { + "relation": "administrator" + } + } + ] + } + }, + "model": { + "this": {} + }, + "reader": { + "union": { + "child": [ + { + "this": {} + }, + { + "computedUserset": { + "relation": "consumer" + } + } + ] + } + } + }, + "type": "applicationoffer" + }, + { + "metadata": { + "relations": { + "administrator": { + "directly_related_user_types": [ + { + "type": "user" + }, + { + "type": "user", + "wildcard": {} + }, + { + "relation": "member", + "type": "group" + } + ] + }, + "can_addmodel": { + "directly_related_user_types": [ + { + "type": "user" + }, + { + "type": "user", + "wildcard": {} + }, + { + "relation": "member", + "type": "group" + } + ] + }, + "controller": { + "directly_related_user_types": [ + { + "type": "controller" + } + ] + } + } + }, + "relations": { + "administrator": { + "union": { + "child": [ + { + "this": {} + }, + { + "tupleToUserset": { + "computedUserset": { + "relation": "administrator" + }, + "tupleset": { + "relation": "controller" + } + } + } + ] + } + }, + "can_addmodel": { + "union": { + "child": [ + { + "this": {} + }, + { + "computedUserset": { + "relation": "administrator" + } + } + ] + } + }, + "controller": { + "this": {} + } + }, + "type": "cloud" + }, + { + "metadata": { + "relations": { + "administrator": { + "directly_related_user_types": [ + { + "type": "user" + }, + { + "type": "user", + "wildcard": {} + }, + { + "relation": "member", + "type": "group" + } + ] + }, + "audit_log_viewer": { + "directly_related_user_types": [ + { + "type": "user" + }, + { + "type": "user", + "wildcard": {} + }, + { + "relation": "member", + "type": "group" + } + ] + }, + "controller": { + "directly_related_user_types": [ + { + "type": "controller" + } + ] + } + } + }, + "relations": { + "administrator": { + "union": { + "child": [ + { + "this": {} + }, + { + "tupleToUserset": { + "computedUserset": { + "relation": "administrator" + }, + "tupleset": { + "relation": "controller" + } + } + } + ] + } + }, + "audit_log_viewer": { + "union": { + "child": [ + { + "this": {} + }, + { + "computedUserset": { + "relation": "administrator" + } + } + ] + } + }, + "controller": { + "this": {} + } + }, + "type": "controller" + }, + { + "metadata": { + "relations": { + "member": { + "directly_related_user_types": [ + { + "type": "user" + }, + { + "type": "user", + "wildcard": {} + }, + { + "relation": "member", + "type": "group" + } + ] + } + } + }, + "relations": { + "member": { + "this": {} + } + }, + "type": "group" + }, + { + "metadata": { + "relations": { + "administrator": { + "directly_related_user_types": [ + { + "type": "user" + }, + { + "type": "user", + "wildcard": {} + }, + { + "relation": "member", + "type": "group" + } + ] + }, + "controller": { + "directly_related_user_types": [ + { + "type": "controller" + } + ] + }, + "reader": { + "directly_related_user_types": [ + { + "type": "user" + }, + { + "type": "user", + "wildcard": {} + }, + { + "relation": "member", + "type": "group" + } + ] + }, + "writer": { + "directly_related_user_types": [ + { + "type": "user" + }, + { + "type": "user", + "wildcard": {} + }, + { + "relation": "member", + "type": "group" + } + ] + } + } + }, + "relations": { + "administrator": { + "union": { + "child": [ + { + "this": {} + }, + { + "tupleToUserset": { + "computedUserset": { + "relation": "administrator" + }, + "tupleset": { + "relation": "controller" + } + } + } + ] + } + }, + "controller": { + "this": {} + }, + "reader": { + "union": { + "child": [ + { + "this": {} + }, + { + "computedUserset": { + "relation": "writer" + } + } + ] + } + }, + "writer": { + "union": { + "child": [ + { + "this": {} + }, + { + "computedUserset": { + "relation": "administrator" + } + } + ] + } + } + }, + "type": "model" + }, + { + "type": "user" + }, + { + "metadata": { + "relations": { + "administrator": { + "directly_related_user_types": [ + { + "type": "user" + }, + { + "type": "user", + "wildcard": {} + }, + { + "relation": "member", + "type": "group" + } + ] + } + } + }, + "relations": { + "administrator": { + "this": {} + } + }, + "type": "serviceaccount" + } + ] +} diff --git a/local/openfga/entrypoint.sh b/local/openfga/entrypoint.sh new file mode 100755 index 000000000..a229fd4a6 --- /dev/null +++ b/local/openfga/entrypoint.sh @@ -0,0 +1,22 @@ +#!/bin/sh + +# This script starts the OpenFGA server, migrates the associated database and applies JIMM's auth model. +# It also manually edits the authorization_model_id to a hardcoded value for easier testing. + +set -e + +# Migrate the database +./openfga migrate --datastore-engine postgres --datastore-uri "$OPENFGA_DATASTORE_URI" + +./openfga run & +sleep 5 + +# Cleanup old auth model from previous starts +psql -Atx "$OPENFGA_DATASTORE_URI" -c "DELETE FROM authorization_model;" +# Adds the auth model and updates its authorisation model id to be the expected hard-coded id such that our local JIMM can utilise it for queries. +wget -q -O - --header 'Content-Type: application/json' --header 'Authorization: Bearer jimm' --post-file authorisation_model.json localhost:8080/stores/01GP1254CHWJC1MNGVB0WDG1T0/authorization-models +psql -Atx "$OPENFGA_DATASTORE_URI" -c "INSERT INTO store (id,name,created_at,updated_at) VALUES ('01GP1254CHWJC1MNGVB0WDG1T0','jimm',NOW(),NOW()) ON CONFLICT DO NOTHING;" +psql -Atx "$OPENFGA_DATASTORE_URI" -c "UPDATE authorization_model SET authorization_model_id = '01GP1EC038KHGB6JJ2XXXXCXKB' WHERE store = '01GP1254CHWJC1MNGVB0WDG1T0';" + +# Keep container alive +tail -f /dev/null & trap 'kill %1' TERM ; wait