diff --git a/ODPC.Server/Apis/Odrc/OdrcClientFactory.cs b/ODPC.Server/Apis/Odrc/OdrcClientFactory.cs index e8217d2..a7d561a 100644 --- a/ODPC.Server/Apis/Odrc/OdrcClientFactory.cs +++ b/ODPC.Server/Apis/Odrc/OdrcClientFactory.cs @@ -1,5 +1,4 @@ using System.Net.Http.Headers; -using Microsoft.Extensions.Options; using ODPC.Authentication; namespace ODPC.Apis.Odrc @@ -9,22 +8,17 @@ public interface IOdrcClientFactory HttpClient Create(OdpUser user, string handeling); } - public class OdrcClientFactory(IHttpClientFactory httpClientFactory, IOptions options) : IOdrcClientFactory + public class OdrcClientFactory(IHttpClientFactory httpClientFactory, IConfiguration config) : IOdrcClientFactory { - private readonly IHttpClientFactory _httpClientFactory = httpClientFactory; - private readonly IOptions _options = options; - public HttpClient Create(OdpUser user, string? handeling) { - var config = _options.Value; - var client = _httpClientFactory.CreateClient(); - client.BaseAddress = new(config.BaseUrl); - client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Token", config.ApiKey); //dit doet nog niets. nog niet geimplementeerd aan odrc kant. nb nog niet duidelijk of dit de juiste manier zal zijn voor het meesturen van het token + var client = httpClientFactory.CreateClient(); + client.BaseAddress = new(config["ODRC_BASE_URL"]!); + client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Token", config["ODRC_API_KEY"]); //dit doet nog niets. nog niet geimplementeerd aan odrc kant. nb nog niet duidelijk of dit de juiste manier zal zijn voor het meesturen van het token client.DefaultRequestHeaders.Add("Audit-User-ID", user.Id); client.DefaultRequestHeaders.Add("Audit-User-Representation", user.FullName); client.DefaultRequestHeaders.Add("Audit-Remarks", handeling); return client; } - } } diff --git a/ODPC.Server/Apis/Odrc/OdrcConfig.cs b/ODPC.Server/Apis/Odrc/OdrcConfig.cs deleted file mode 100644 index 1e82d8f..0000000 --- a/ODPC.Server/Apis/Odrc/OdrcConfig.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System.Globalization; - -namespace ODPC.Apis.Odrc -{ - public class OdrcConfig - { - public required string BaseUrl { get; set; } - public required string ApiKey { get; set; } - - } -} diff --git a/ODPC.Server/Features/Publicaties/PublicatieRegistreren/PublicatieRegistrerenController.cs b/ODPC.Server/Features/Publicaties/PublicatieRegistreren/PublicatieRegistrerenController.cs index 5f81a98..c9b78af 100644 --- a/ODPC.Server/Features/Publicaties/PublicatieRegistreren/PublicatieRegistrerenController.cs +++ b/ODPC.Server/Features/Publicaties/PublicatieRegistreren/PublicatieRegistrerenController.cs @@ -22,7 +22,7 @@ public async Task Post(Publicatie publicatie) var client = _clientFactory.Create(user, "Publicatie geregistreerd"); - var response = await client.PostAsJsonAsync("/api/v1/publicaties/", publicatie, new CancellationToken()); + var response = await client.PostAsJsonAsync("/api/v1/publicaties", publicatie, new CancellationToken()); response.EnsureSuccessStatusCode(); diff --git a/ODPC.Server/Features/WaardeLijstenOverzicht/WaardelijstenController.cs b/ODPC.Server/Features/WaardeLijstenOverzicht/WaardelijstenController.cs index 9b78d70..6390570 100644 --- a/ODPC.Server/Features/WaardeLijstenOverzicht/WaardelijstenController.cs +++ b/ODPC.Server/Features/WaardeLijstenOverzicht/WaardelijstenController.cs @@ -20,7 +20,7 @@ public async Task> GetAsync() //user en audit log handeling meegeven is misschien nog niet nodig, maar doet geen kwaad var client = clientFactory.Create(user, "Waardelijsten ophalen"); - var response = await client.GetAsync("/api/v1/informatiecategorieen/", new CancellationToken()); + var response = await client.GetAsync("/api/v1/informatiecategorieen", new CancellationToken()); response.EnsureSuccessStatusCode(); diff --git a/ODPC.Server/Program.cs b/ODPC.Server/Program.cs index 79deb6d..6da69d7 100644 --- a/ODPC.Server/Program.cs +++ b/ODPC.Server/Program.cs @@ -40,7 +40,6 @@ var connStr = $"Username={builder.Configuration["POSTGRES_USER"]};Password={builder.Configuration["POSTGRES_PASSWORD"]};Host={builder.Configuration["POSTGRES_HOST"]};Database={builder.Configuration["POSTGRES_DB"]};Port={builder.Configuration["POSTGRES_PORT"]}"; builder.Services.AddDbContext(opt => opt.UseNpgsql(connStr)); - builder.Services.Configure(builder.Configuration.GetSection("Odrc")); builder.Services.AddScoped(); diff --git a/ODPC.Server/appsettings.json b/ODPC.Server/appsettings.json index 83558f8..1c2a521 100644 --- a/ODPC.Server/appsettings.json +++ b/ODPC.Server/appsettings.json @@ -16,10 +16,7 @@ "OIDC_NAME_CLAIM_TYPE": "", "OIDC_ROLE_CLAIM_TYPE": "", "OIDC_ID_CLAIM_TYPE": "", - "AllowedHosts": "*", - - "Odrc": { - "BaseUrl": "https://woo-publicaties.test.opengem.nl/", - "ApiKey": "..." - } + "ODRC_BASE_URL": "", + "ODRC_API_KEY": "", + "AllowedHosts": "*" } \ No newline at end of file diff --git a/README.md b/README.md index e1bdfb9..08988ef 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,18 @@ # ODPC +## Lokaal opstarten met Docker Compose +Je kan ODPC lokaal opstarten door het volgende commando uit te voeren in de rootmap van de repository: `docker compose up` +### ODRC als afhankelijkheid in Docker Compose +We hebben ervoor gekozen om ODRC als afhankelijkheid op te nemen in Docker Compose. Dit houdt in dat er een instantie van ODRC wordt opgestart. -# Omgevingsvariabelen +De configuratie en benodigde bestanden zijn overgenomen uit [De github repository van ODRC](https://github.com/GeneriekPublicatiePlatformWoo/registratie-component). Als daar iets in wijzigt, zullen we dat hier moeten doorvoeren. + +Als je met een separate installatie (bijvoorbeeld een testomgeving) van ODRC wil koppelen, moet je de variabelen `ODRC_BASE_URL` en `ODRC_API_KEY` aanpassen. Dit kun je ofwel in het docker-compose.yml bestand aanpassen (zorg dat je dit niet incheckt!), ofwel in je [user secrets bestand](https://learn.microsoft.com/en-us/aspnet/core/security/app-secrets). In het laatste geval moet je de variabelen verwijderen uit het docker-compose.yml bestand. + +Standaard wordt bij het draaien van `docker compose up` de laatste versie van het image van ODRC opgehaald. Als je dit wil forceren kan je het commando `docker compose pull odrc-django` uitvoeren. + +Als je een specifieke versie van het image van ODRC wil vastpinnen, zet je dit in de enviroment variable `ODRC_VERSION` + +## Omgevingsvariabelen | Variabele | Uitleg | | --------------------------------- | -------------------------------------------------------------------------------------------- | | `POSTGRES_DB` | Naam van de database bij ODPC | @@ -13,4 +25,6 @@ | `OIDC_CLIENT_SECRET` | Secret voor de OpenID Connect Identity Provider
Meer informatie Bijvoorbeeld: `VM2B!ccnebNe.M*gxH63*NXc8iTiAGhp`
| | `OIDC_ROLE_CLAIM_TYPE` | De naam van de claim in het JWT token van de OpenID Connect Provider waarin de rollen van de ingelogde gebruiker staan.
(default waarde is `roles`)| | `OIDC_ID_CLAIM_TYPE` | De naam van de claim in het JWT token van de OpenID Connect Provider waarin de unieke identificatie van de ingelogde gebruiker staat.
(default waarde is `preferred_username` met een fallback op `email`)| -| `OIDC_NAME_CLAIM_TYPE` | De naam van de claim in het JWT token van de OpenID Connect Provider waarin de volledige naam van de ingelogde gebruiker staat
(default waarde is `name`) \ No newline at end of file +| `OIDC_NAME_CLAIM_TYPE` | De naam van de claim in het JWT token van de OpenID Connect Provider waarin de volledige naam van de ingelogde gebruiker staat
(default waarde is `name`)| +| `ODRC_BASE_URL` | De base url van de ODRC (Registratiecomponent) waarmee gekoppeld moet worden.
Meer informatie Bijvoorbeeld: `https://odrc.mijn-gemeente.nl`
| +| `ODRC_API_KEY` | De geheime sleutel voor de ODRC (Registratiecomponent) waarmee gekoppeld moet worden.
Meer informatie Bijvoorbeeld: `VM2B!ccnebNe.M*gxH63*NXc8iTiAGhp`
| \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 9d7a73c..85e25eb 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -7,6 +7,8 @@ services: - POSTGRES_USER=postgres - POSTGRES_PASSWORD=localdev - ASPNETCORE_FORWARDEDHEADERS_ENABLED=true + - ODRC_BASE_URL=http://odrc/ + - ODRC_API_KEY=xxx image: ${DOCKER_REGISTRY-}odpc build: context: . @@ -16,14 +18,123 @@ services: depends_on: - postgres-db postgres-db: - image: postgres + image: postgis/postgis:${PG_VERSION:-16-master} volumes: - - db:/var/lib/postgresql/data + - postgres-db:/var/lib/postgresql/data + - ./docker/odrc/db/init-db.sql:/docker-entrypoint-initdb.d/init_db.sql + - ./docker/open-zaak/db/0001-init-open-zaak-db.sql:/docker-entrypoint-initdb.d/0001-init-open-zaak-db.sql + - ./docker/open-zaak/db/0002-extensions.sh:/docker-entrypoint-initdb.d/0002-extensions.sh environment: - POSTGRES_PASSWORD=localdev restart: always ports: - "5432:5432" + redis: + image: redis:7 + command: ["redis-server", "--appendonly", "yes"] + volumes: + - redis-data:/data + + openzaak-web: + image: openzaak/open-zaak:${OPENZAAK_VERSION:-1.14.0} + environment: &openzaak_web_env + - DJANGO_SETTINGS_MODULE=openzaak.conf.patched_settings + - SECRET_KEY=${SECRET_KEY:-django-insecure-^#9nzgn*@-@0szv+$$)6th!i+$$ks^+bt@&ejcgzqt==7af(a(u3} + - ALLOWED_HOSTS=openzaak-web,openzaak.docker.internal,localhost + - DB_NAME=openzaak + - DB_USER=postgres + - DB_PASSWORD=localdev + - DB_HOST=postgres-db + - IS_HTTPS=no + - CACHE_DEFAULT=redis:6379/1 + - CACHE_AXES=redis:6379/1 + - SUBPATH=${SUBPATH:-/} + - OPENZAAK_SUPERUSER_USERNAME=admin + - DJANGO_SUPERUSER_PASSWORD=admin + - OPENZAAK_SUPERUSER_EMAIL=admin@localhost + - DISABLE_2FA=true + - CELERY_BROKER_URL=redis://redis:6379/2 + - CELERY_RESULT_BACKEND=redis://redis:6379/2 + - NOTIFICATIONS_DISABLED=true + - JWT_EXPIRY=99999999999 # Roughly 3170 years. This is required for tests with time frozen to work + - CELERY_WORKER_CONCURRENCY=${CELERY_WORKER_CONCURRENCY:-2} + volumes: + &openzaak_web_volumes # mount fixtures dir to automatically populate the DB + - ./docker/open-zaak/fixtures/:/app/fixtures + - ./docker/open-zaak/patched_settings.py:/app/src/openzaak/conf/patched_settings.py + - oz-media:/app/media # Shared media volume to get access to saved OAS files + - oz-private-media:/app/private-media + depends_on: + - postgres-db + - redis + - openzaak-celery + extra_hosts: + - "host.docker.internal:host-gateway" + ports: + - 8001:8000 + + openzaak-celery: + image: openzaak/open-zaak:${OPENZAAK_VERSION:-1.14.0} + environment: *openzaak_web_env + volumes: *openzaak_web_volumes + command: /celery_worker.sh + depends_on: + - postgres-db + - redis + + odrc-django: &odrc_build + image: maykinmedia/woo-publications:${ODRC_VERSION:-latest} + pull_policy: always + environment: &odrc_env + - DJANGO_SETTINGS_MODULE=woo_publications.conf.docker + - SECRET_KEY=${SECRET_KEY:-django-insecure-fgggi4*bl2wdg&@0&)t7ewy5-2!b3l4lhx4_+^zpw%x2i28v8} + - DB_NAME=woo_publications + - DB_USER=postgres + - DB_HOST=postgres-db + - DB_PASSWORD=localdev + - CACHE_DEFAULT=redis:6379/0 + - CACHE_AXES=redis:6379/0 + - ODRC_SUPERUSER_USERNAME=admin + - ODRC_SUPERUSER_EMAIL=admin@host.docker.internal + - DISABLE_2FA=true + - DJANGO_SUPERUSER_PASSWORD=admin + - ALLOWED_HOSTS=* + # Environment labeling + - SHOW_ENVIRONMENT=yes + - ENVIRONMENT_LABEL=docker-compose + - ENVIRONMENT_BACKGROUND_COLOR=#1d63ed + - ENVIRONMENT_FOREGROUND_COLOR=white + - DEBUG=True + volumes: &odrc_volumes + - ./docker/odrc/fixtures/:/app/fixtures + - media:/app/media + - log:/app/log + extra_hosts: + - "host.docker.internal:host-gateway" + # required because Open Zaak otherwise treats our /catalogi/api/v1/ endpoints as + # internal + - "openzaak.docker.internal:host-gateway" + ports: + - 8000:8000 + depends_on: + - postgres-db + - redis + +# we need a reverse proxy for odrc because django doesn't support chunked requests + odrc: + image: nginx:stable-alpine + restart: always + ports: + - 8002:80 + volumes: + - ./docker/nginx:/etc/nginx/conf.d/ + depends_on: + - odrc-django volumes: - db: + postgres-db: + redis-data: + oz-media: + oz-private-media: + log: + media: diff --git a/docker/nginx/nginx.conf b/docker/nginx/nginx.conf new file mode 100644 index 0000000..7aadf47 --- /dev/null +++ b/docker/nginx/nginx.conf @@ -0,0 +1,12 @@ + +server { + listen 80 default_server; + + location / { + proxy_pass http://odrc-django:8000/; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + } + +} \ No newline at end of file diff --git a/docker/odrc/db/init-db.sql b/docker/odrc/db/init-db.sql new file mode 100644 index 0000000..6428201 --- /dev/null +++ b/docker/odrc/db/init-db.sql @@ -0,0 +1,2 @@ +CREATE USER woo_publications; +CREATE DATABASE woo_publications WITH OWNER woo_publications; diff --git a/docker/odrc/fixtures/woo-publications.json b/docker/odrc/fixtures/woo-publications.json new file mode 100644 index 0000000..01d114b --- /dev/null +++ b/docker/odrc/fixtures/woo-publications.json @@ -0,0 +1,37 @@ +[ +{ + "model": "zgw_consumers.service", + "pk": 1, + "fields": { + "label": "Documenten API [Open Zaak]", + "oas": "http://openzaak.docker.internal:8001/documenten/api/v1/openapi.yaml", + "oas_file": "", + "uuid": "4f88855e-e0a3-4d4b-80fb-c7774d965a92", + "slug": "documenten-api", + "api_type": "drc", + "api_root": "http://openzaak.docker.internal:8001/documenten/api/v1/", + "api_connection_check_path": "", + "client_id": "woo-publications-dev", + "secret": "insecure-yQL9Rzh4eHGVmYx5w3J2gu", + "auth_type": "zgw", + "header_key": "", + "header_value": "", + "nlx": "", + "user_id": "woo-publications-dev", + "user_representation": "Woo Publications (dev)", + "client_certificate": null, + "server_certificate": null, + "timeout": 10 + } +}, +{ + "model": "zgw_consumers.nlxconfig", + "pk": 1, + "fields": { + "directory": "", + "outway": "", + "certificate": "", + "certificate_key": "" + } +} +] diff --git a/docker/open-zaak/README.md b/docker/open-zaak/README.md new file mode 100644 index 0000000..3f0b7ae --- /dev/null +++ b/docker/open-zaak/README.md @@ -0,0 +1,65 @@ +# Open Zaak docker configuration + +This directory contains supporting configuration and infrastructure to run Open Zaak +via `docker compose`. + +You need Docker Engine v20.10 or newer for the documented setup to work. + +## Spinning up the services + +In the root of the project, spin up Open Zaak via `compose`: + +```bash +docker compose up --detach openzaak-web # or just `docker compose up` to bring everything up +``` + +Open Zaak binds to port 8001 on the host system. + +## Accessing the admin environment + +Open your browser and navigate to http://localhost:8001/admin/, where you can log in +with the credentials `admin` / `admin`. + +## API client + +One API client is configured, with all permissions enabled. The credentials are: + +* Client ID: `woo-publications-dev` +* Secret: `insecure-yQL9Rzh4eHGVmYx5w3J2gu` + +## API connection from Open Zaak to WOO Publications + +Open Zaak will make certain API calls to API endpoints exposed by WOO Publications. This +requires some specific setup - most notably the Woo Publications must be listening on +port 8000 on the host system. + +If you're bringing up the whole compose stack, this is taken care of already. If you run +the development server, it's easiest to bind to all ports: + +```bash +src/manage.py runserver 0.0.0.0:8000 +``` + +## Dumping the fixture + +The service automatically loads the fixtures provided in the `fixtures` directory. When +making changes in the web interface to the configuration, you must update these +fixtures: + +```bash +# from the root of the repository +docker compose run openzaak-web \ + python src/manage.py dumpdata \ + --indent=4 \ + --output /app/fixtures/configuration.json \ + authorizations.applicatie \ + vng_api_common.jwtsecret \ + config \ + zgw_consumers +``` + +Depending on your OS and local user ID, you may need to grant additional write permissions: + +```bash +chmod -R o+rwx ./docker/open-zaak/fixtures +``` diff --git a/docker/open-zaak/db/0001-init-open-zaak-db.sql b/docker/open-zaak/db/0001-init-open-zaak-db.sql new file mode 100644 index 0000000..b3eb038 --- /dev/null +++ b/docker/open-zaak/db/0001-init-open-zaak-db.sql @@ -0,0 +1,2 @@ +CREATE USER openzaak; +CREATE DATABASE openzaak WITH OWNER openzaak; diff --git a/docker/open-zaak/db/0002-extensions.sh b/docker/open-zaak/db/0002-extensions.sh new file mode 100644 index 0000000..1adfaee --- /dev/null +++ b/docker/open-zaak/db/0002-extensions.sh @@ -0,0 +1,7 @@ +#!/bin/bash +set -e + +psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "openzaak" <<-EOSQL + CREATE EXTENSION postgis; + CREATE EXTENSION pg_trgm; +EOSQL diff --git a/docker/open-zaak/fixtures/configuration.json b/docker/open-zaak/fixtures/configuration.json new file mode 100644 index 0000000..89ce25c --- /dev/null +++ b/docker/open-zaak/fixtures/configuration.json @@ -0,0 +1,143 @@ +[ +{ + "model": "authorizations.applicatie", + "pk": 1, + "fields": { + "uuid": "4dd384d6-a941-4523-9b68-49746921e78d", + "client_ids": "[\"woo-publications-dev\"]", + "label": "WOO Publicatiebank", + "heeft_alle_autorisaties": true + } +}, +{ + "model": "vng_api_common.jwtsecret", + "pk": 1, + "fields": { + "identifier": "woo-publications-dev", + "secret": "insecure-yQL9Rzh4eHGVmYx5w3J2gu" + } +}, +{ + "model": "config.internalservice", + "pk": 1, + "fields": { + "api_type": "ac", + "enabled": true + } +}, +{ + "model": "config.internalservice", + "pk": 2, + "fields": { + "api_type": "zrc", + "enabled": false + } +}, +{ + "model": "config.internalservice", + "pk": 3, + "fields": { + "api_type": "ztc", + "enabled": false + } +}, +{ + "model": "config.internalservice", + "pk": 4, + "fields": { + "api_type": "drc", + "enabled": true + } +}, +{ + "model": "config.internalservice", + "pk": 5, + "fields": { + "api_type": "brc", + "enabled": false + } +}, +{ + "model": "config.featureflags", + "pk": 1, + "fields": { + "allow_unpublished_typen": false + } +}, +{ + "model": "zgw_consumers.service", + "pk": 1, + "fields": { + "label": "VNG Selectielijst", + "oas": "https://selectielijst.openzaak.nl/api/v1/schema/openapi.yaml", + "oas_file": "", + "uuid": "fd46ec3f-db03-4915-b406-b874a706a1b4", + "api_type": "orc", + "api_root": "https://selectielijst.openzaak.nl/api/v1/", + "client_id": "", + "secret": "", + "auth_type": "no_auth", + "header_key": "", + "header_value": "", + "nlx": "", + "user_id": "", + "user_representation": "", + "client_certificate": null, + "server_certificate": null + } +}, +{ + "model": "zgw_consumers.service", + "pk": 2, + "fields": { + "label": "Woo Publications (docker)", + "oas": "http://host.docker.internal:8000/catalogi/api/v1/", + "oas_file": "", + "uuid": "120d62ff-5f95-44ee-8439-19c162a020c1", + "api_type": "orc", + "api_root": "http://host.docker.internal:8000/catalogi/api/v1/", + "client_id": "", + "secret": "", + "auth_type": "no_auth", + "header_key": "Authorization", + "header_value": "Token :future:", + "nlx": "", + "user_id": "", + "user_representation": "", + "client_certificate": null, + "server_certificate": null + } +}, +{ + "model": "zgw_consumers.service", + "pk": 3, + "fields": { + "label": "Woo Publications (automated tests)", + "oas": "http://host.docker.internal:8100/catalogi/api/v1/", + "oas_file": "", + "uuid": "97ccb23d-7fec-498a-8f16-b8930e91d383", + "api_type": "orc", + "api_root": "http://host.docker.internal:8100/catalogi/api/v1/", + "client_id": "", + "secret": "", + "auth_type": "no_auth", + "header_key": "Authorization", + "header_value": "Token :future:", + "nlx": "", + "user_id": "", + "user_representation": "", + "client_certificate": null, + "server_certificate": null + } +}, +{ + "model": "zgw_consumers.nlxconfig", + "pk": 1, + "fields": { + "directory": "", + "outway": "", + "certificate": "", + "certificate_key": "" + } +} +] diff --git a/docker/open-zaak/patched_settings.py b/docker/open-zaak/patched_settings.py new file mode 100644 index 0000000..a7731d2 --- /dev/null +++ b/docker/open-zaak/patched_settings.py @@ -0,0 +1,3 @@ +from .docker import * + +NOTIFICATIONS_DISABLED = config("NOTIFICATIONS_DISABLED", default=True)