diff --git a/README.md b/README.md index 0929c1d..40d5e96 100644 --- a/README.md +++ b/README.md @@ -39,13 +39,13 @@ Before running the Secutils.dev server, you need to configure the database and [ and an Ory Kratos servers running, you [can run them locally with the following Docker Compose file:](https://docs.docker.com/language/rust/develop/) ```shell -docker-compose -f ./dev/docker/postgres-and-kratos.yml up --build --force-recreate +docker-compose -f ./dev/docker/postgres-and-kratos.yml --env-file ./.env up --build --force-recreate ``` To remove everything and start from scratch, run: ```shell -docker-compose -f ./dev/docker/postgres-and-kratos.yml down --volumes --remove-orphans +docker-compose -f ./dev/docker/postgres-and-kratos.yml --env-file ./.env down --volumes --remove-orphans ``` Make sure to replace `POSTGRES_HOST_AUTH_METHOD=trust` in Docker Compose file with a more secure authentication method if you're @@ -118,6 +118,13 @@ SECUTILS_CONFIG=${PWD}/secutils.toml # Secret key used to sign and verify JSON Web Tokens for API access # openssl rand -hex 16 SECUTILS_SECURITY__JWT_SECRET=8ffe0cc38d7ff1afa78b6cd5696f2e21 + +# JWT used by Kratos to authenticate requests to the API. +# Requires config: security.operators = ["@kratos"] +# Generated with: cargo run -p jwt_tools generate --secret 8ffe0cc38d7ff1afa78b6cd5696f2e21 --sub @kratos --exp 1year +SELFSERVICE_FLOWS_REGISTRATION_AFTER_PASSWORD_HOOKS_0_CONFIG_AUTH_CONFIG_VALUE="Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE3NDcyMDExNTcsInN1YiI6IkBrcmF0b3MifQ.O506N__dZu7ZM6p-rEr_QkMn3jp0mRyBwKP7jstRHV8" +SELFSERVICE_FLOWS_REGISTRATION_AFTER_WEBAUTHN_HOOKS_0_CONFIG_AUTH_CONFIG_VALUE="Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE3NDcyMDExNTcsInN1YiI6IkBrcmF0b3MifQ.O506N__dZu7ZM6p-rEr_QkMn3jp0mRyBwKP7jstRHV8" +COURIER_HTTP_REQUEST_CONFIG_AUTH_CONFIG_VALUE="Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE3NDcyMDExNTcsInN1YiI6IkBrcmF0b3MifQ.O506N__dZu7ZM6p-rEr_QkMn3jp0mRyBwKP7jstRHV8" ``` ### Usage diff --git a/dev/docker/kratos.local.toml b/dev/docker/kratos.toml similarity index 71% rename from dev/docker/kratos.local.toml rename to dev/docker/kratos.toml index ced1983..e304d07 100644 --- a/dev/docker/kratos.local.toml +++ b/dev/docker/kratos.toml @@ -5,7 +5,7 @@ dsn = "postgres://postgres@secutils_db:5432/secutils?sslmode=disable&max_conns=2 [serve] public.base_url = "http://127.0.0.1:7171" -admin.base_url = "http://kratos:4433" +admin.base_url = "http://127.0.0.1:4433" [log] level = "info" @@ -36,21 +36,17 @@ verification = { enabled = true } [selfservice.flows.registration.after.password] hooks = [ # `body is base64 version of "function(ctx) { id: ctx.identity.id, email: ctx.identity.traits.email }", see https://www.ory.sh/docs/guides/integrate-with-ory-cloud-through-webhooks - { hook = "web_hook", config = { method = "POST", url = "http://host.docker.internal:7070/api/users/signup", response.ignore = true, body = "base64://ZnVuY3Rpb24oY3R4KSB7IGlkZW50aXR5OiBjdHguaWRlbnRpdHkgfQ==", auth = { type = "api_key", config.name = "Authorization", config.value = "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjIwMzEwNDc4MzksInN1YiI6IkBrcmF0b3MubG9jYWwifQ._tU8TYz7RJfS4yhSrSZ8b7jICm4fhvxKDcVYqA5iP80", config.in = "header" } } }, + { hook = "web_hook", config = { method = "POST", url = "http://host.docker.internal:7070/api/users/signup", response = { ignore = false, parse = false }, body = "base64://ZnVuY3Rpb24oY3R4KSB7IGlkZW50aXR5OiBjdHguaWRlbnRpdHkgfQ==", auth = { type = "api_key", config.name = "Authorization", config.in = "header" } } }, { hook = "session" } ] [selfservice.flows.registration.after.webauthn] hooks = [ # `body is base64 version of "function(ctx) { id: ctx.identity.id, email: ctx.identity.traits.email }", see https://www.ory.sh/docs/guides/integrate-with-ory-cloud-through-webhooks - { hook = "web_hook", config = { method = "POST", url = "http://host.docker.internal:7070/api/users/signup", response.ignore = true, body = "base64://ZnVuY3Rpb24oY3R4KSB7IGlkZW50aXR5OiBjdHguaWRlbnRpdHkgfQ==", auth = { type = "api_key", config.name = "Authorization", config.value = "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjIwMzEwNDc4MzksInN1YiI6IkBrcmF0b3MubG9jYWwifQ._tU8TYz7RJfS4yhSrSZ8b7jICm4fhvxKDcVYqA5iP80", config.in = "header" } } }, + { hook = "web_hook", config = { method = "POST", url = "http://host.docker.internal:7070/api/users/signup", response = { ignore = false, parse = false }, body = "base64://ZnVuY3Rpb24oY3R4KSB7IGlkZW50aXR5OiBjdHguaWRlbnRpdHkgfQ==", auth = { type = "api_key", config.name = "Authorization", config.in = "header" } } }, { hook = "session" } ] -[secrets] -cookie = ["PLEASE-CHANGE-ME-I-AM-VERY-INSECURE"] -cipher = ["32-LONG-SECRET-NOT-SECURE-AT-ALL"] - [courier] delivery_strategy = "http" -http = { request_config = { url = "http://host.docker.internal:7070/api/users/email", method = "POST", body = "base64://ZnVuY3Rpb24oY3R4KSB7CiAgcmVjaXBpZW50OiBjdHgucmVjaXBpZW50LAogIHRlbXBsYXRlX3R5cGU6IGN0eC50ZW1wbGF0ZV90eXBlLAogIGlkZW50aXR5OiBjdHgudGVtcGxhdGVfZGF0YS5pZGVudGl0eSwKICByZWNvdmVyeV9jb2RlOiBpZiAidGVtcGxhdGVfZGF0YSIgaW4gY3R4ICYmICJyZWNvdmVyeV9jb2RlIiBpbiBjdHgudGVtcGxhdGVfZGF0YSB0aGVuIGN0eC50ZW1wbGF0ZV9kYXRhLnJlY292ZXJ5X2NvZGUgZWxzZSBudWxsLAogIHJlY292ZXJ5X3VybDogaWYgInRlbXBsYXRlX2RhdGEiIGluIGN0eCAmJiAicmVjb3ZlcnlfdXJsIiBpbiBjdHgudGVtcGxhdGVfZGF0YSB0aGVuIGN0eC50ZW1wbGF0ZV9kYXRhLnJlY292ZXJ5X3VybCBlbHNlIG51bGwsCiAgdmVyaWZpY2F0aW9uX3VybDogaWYgInRlbXBsYXRlX2RhdGEiIGluIGN0eCAmJiAidmVyaWZpY2F0aW9uX3VybCIgaW4gY3R4LnRlbXBsYXRlX2RhdGEgdGhlbiBjdHgudGVtcGxhdGVfZGF0YS52ZXJpZmljYXRpb25fdXJsIGVsc2UgbnVsbCwKICB2ZXJpZmljYXRpb25fY29kZTogaWYgInRlbXBsYXRlX2RhdGEiIGluIGN0eCAmJiAidmVyaWZpY2F0aW9uX2NvZGUiIGluIGN0eC50ZW1wbGF0ZV9kYXRhIHRoZW4gY3R4LnRlbXBsYXRlX2RhdGEudmVyaWZpY2F0aW9uX2NvZGUgZWxzZSBudWxsCn0=", headers = { "Content-Type" = "application/json" }, auth = { type = "api_key", config.name = "Authorization", config.value = "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjIwMzEwNDc4MzksInN1YiI6IkBrcmF0b3MubG9jYWwifQ._tU8TYz7RJfS4yhSrSZ8b7jICm4fhvxKDcVYqA5iP80", config.in = "header" } } } +http = { request_config = { url = "http://host.docker.internal:7070/api/users/email", method = "POST", body = "base64://ZnVuY3Rpb24oY3R4KSB7CiAgcmVjaXBpZW50OiBjdHgucmVjaXBpZW50LAogIHRlbXBsYXRlX3R5cGU6IGN0eC50ZW1wbGF0ZV90eXBlLAogIGlkZW50aXR5OiBjdHgudGVtcGxhdGVfZGF0YS5pZGVudGl0eSwKICByZWNvdmVyeV9jb2RlOiBpZiAidGVtcGxhdGVfZGF0YSIgaW4gY3R4ICYmICJyZWNvdmVyeV9jb2RlIiBpbiBjdHgudGVtcGxhdGVfZGF0YSB0aGVuIGN0eC50ZW1wbGF0ZV9kYXRhLnJlY292ZXJ5X2NvZGUgZWxzZSBudWxsLAogIHJlY292ZXJ5X3VybDogaWYgInRlbXBsYXRlX2RhdGEiIGluIGN0eCAmJiAicmVjb3ZlcnlfdXJsIiBpbiBjdHgudGVtcGxhdGVfZGF0YSB0aGVuIGN0eC50ZW1wbGF0ZV9kYXRhLnJlY292ZXJ5X3VybCBlbHNlIG51bGwsCiAgdmVyaWZpY2F0aW9uX3VybDogaWYgInRlbXBsYXRlX2RhdGEiIGluIGN0eCAmJiAidmVyaWZpY2F0aW9uX3VybCIgaW4gY3R4LnRlbXBsYXRlX2RhdGEgdGhlbiBjdHgudGVtcGxhdGVfZGF0YS52ZXJpZmljYXRpb25fdXJsIGVsc2UgbnVsbCwKICB2ZXJpZmljYXRpb25fY29kZTogaWYgInRlbXBsYXRlX2RhdGEiIGluIGN0eCAmJiAidmVyaWZpY2F0aW9uX2NvZGUiIGluIGN0eC50ZW1wbGF0ZV9kYXRhIHRoZW4gY3R4LnRlbXBsYXRlX2RhdGEudmVyaWZpY2F0aW9uX2NvZGUgZWxzZSBudWxsCn0=", headers = { "Content-Type" = "application/json" }, auth = { type = "api_key", config.name = "Authorization", config.in = "header" } } } diff --git a/dev/docker/postgres-and-kratos.yml b/dev/docker/postgres-and-kratos.yml index b9e03d5..48ca8e8 100644 --- a/dev/docker/postgres-and-kratos.yml +++ b/dev/docker/postgres-and-kratos.yml @@ -20,7 +20,7 @@ services: - secutils_db volumes: - type: bind - source: ./kratos.local.toml + source: ./kratos.toml target: /etc/config/kratos/kratos.toml command: -c /etc/config/kratos/kratos.toml migrate sql -e --yes restart: on-failure @@ -29,6 +29,12 @@ services: kratos: image: oryd/kratos:d9dbaadc3 + environment: + - SECRETS_COOKIE=${SECRETS_COOKIE:-some_very_very_secure_cookie_key} + - SECRETS_CIPHER=${SECRETS_CIPHER:-some_very_very_secure_cipher_key} + - SELFSERVICE_FLOWS_REGISTRATION_AFTER_PASSWORD_HOOKS_0_CONFIG_AUTH_CONFIG_VALUE=${SELFSERVICE_FLOWS_REGISTRATION_AFTER_PASSWORD_HOOKS_0_CONFIG_AUTH_CONFIG_VALUE} + - SELFSERVICE_FLOWS_REGISTRATION_AFTER_WEBAUTHN_HOOKS_0_CONFIG_AUTH_CONFIG_VALUE=${SELFSERVICE_FLOWS_REGISTRATION_AFTER_WEBAUTHN_HOOKS_0_CONFIG_AUTH_CONFIG_VALUE} + - COURIER_HTTP_REQUEST_CONFIG_AUTH_CONFIG_VALUE=${COURIER_HTTP_REQUEST_CONFIG_AUTH_CONFIG_VALUE} ports: - '4433:4433' # public - '4434:4434' # admin @@ -38,10 +44,10 @@ services: - secutils_db volumes: - type: bind - source: ./kratos.local.toml + source: ./kratos.toml target: /etc/config/kratos/kratos.toml - type: bind - source: ../../config/user_identity.schema.json + source: ./user_identity.schema.json target: /etc/config/kratos/user_identity.schema.json command: serve -c /etc/config/kratos/kratos.toml --dev --watch-courier --sqa-opt-out networks: diff --git a/config/user_identity.schema.json b/dev/docker/user_identity.schema.json similarity index 100% rename from config/user_identity.schema.json rename to dev/docker/user_identity.schema.json