diff --git a/docker-compose.yml b/docker-compose.yml index b3d2ae3d..e421a7bc 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -174,3 +174,78 @@ services: ipv4_address: 10.10.10.70 ports: - "27017:27017" + + kratos-migrate: + image: oryd/kratos:v0.5.4-alpha.1 + container_name: kratos-migrate + restart: unless-stopped + logging: *default-logging + environment: + - DSN=mysql://root:${MYSQL_ROOT_PASSWORD}@tcp(mysqld:3306)/mysql?max_conns=20&max_idle_conns=4 + volumes: + - ./docker/kratos/config:/etc/config/kratos + command: -c /etc/config/kratos/kratos.yml migrate sql -e --yes + networks: + shared: + ipv4_address: 10.10.10.80 + + kratos: + image: oryd/kratos:v0.5.4-alpha.1 + container_name: kratos + restart: unless-stopped + logging: *default-logging + expose: + - 4433 # public + - 4434 # admin + environment: + - DSN=mysql://root:${MYSQL_ROOT_PASSWORD}@tcp(mysqld:3306)/mysql?max_conns=20&max_idle_conns=4 + - LOG_LEVEL=trace + command: serve -c /etc/config/kratos/kratos.yml + volumes: + - ./docker/kratos/config:/etc/config/kratos + networks: + shared: + ipv4_address: 10.10.10.81 + depends_on: + - kratos-migrate + + kratos-selfservice-ui-node: + image: oryd/kratos-selfservice-ui-node:v0.5.0-alpha.1 + container_name: kratos-selfservice-ui-node + restart: unless-stopped + logging: *default-logging + expose: + - 4455 + environment: + - PORT=4455 + - SECURITY_MODE= + - BASE_URL=https://siasky.net/secure/ + - KRATOS_BROWSER_URL=https://siasky.net/secure/ + - KRATOS_PUBLIC_URL=http://kratos:4433/ + - KRATOS_ADMIN_URL=http://kratos:4434/ + networks: + shared: + ipv4_address: 10.10.10.82 + + mailslurper: + image: oryd/mailslurper:latest-smtps + container_name: mailslurper + restart: unless-stopped + logging: *default-logging + expose: + - 4436 + - 4437 + networks: + shared: + ipv4_address: 10.10.10.85 + + mysqld: + image: mysql:5.7 + container_name: mysqld + expose: + - 3306 + env_file: + - .env + networks: + shared: + ipv4_address: 10.10.10.90 diff --git a/docker/kratos/config/indentity.schema.json b/docker/kratos/config/indentity.schema.json new file mode 100644 index 00000000..80995401 --- /dev/null +++ b/docker/kratos/config/indentity.schema.json @@ -0,0 +1,45 @@ +{ + "$id": "https://schemas.ory.sh/presets/kratos/quickstart/email-password/identity.schema.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Person", + "type": "object", + "properties": { + "traits": { + "type": "object", + "properties": { + "email": { + "type": "string", + "format": "email", + "title": "E-Mail", + "minLength": 3, + "ory.sh/kratos": { + "credentials": { + "password": { + "identifier": true + } + }, + "verification": { + "via": "email" + }, + "recovery": { + "via": "email" + } + } + }, + "name": { + "type": "object", + "properties": { + "first": { + "type": "string" + }, + "last": { + "type": "string" + } + } + } + }, + "required": ["email"], + "additionalProperties": false + } + } +} diff --git a/docker/kratos/config/kratos.yml b/docker/kratos/config/kratos.yml new file mode 100644 index 00000000..fdf2ca27 --- /dev/null +++ b/docker/kratos/config/kratos.yml @@ -0,0 +1,78 @@ +version: v0.5.4-alpha.1 + +dsn: memory + +serve: + public: + base_url: https://siasky.net/secure/ + cors: + enabled: true + admin: + base_url: https://siasky.net/admin/ + +selfservice: + default_browser_return_url: https://siasky.net/secure/ + whitelisted_return_urls: + - https://siasky.net/secure + + methods: + password: + enabled: true + + flows: + error: + ui_url: https://siasky.net/secure/error + + settings: + ui_url: https://siasky.net/secure/settings + privileged_session_max_age: 15m + + recovery: + enabled: true + ui_url: https://siasky.net/secure/recovery + + verification: + enabled: true + ui_url: https://siasky.net/secure/verify + after: + default_browser_return_url: https://siasky.net/secure/ + + logout: + after: + default_browser_return_url: https://siasky.net/secure/auth/login + + login: + ui_url: https://siasky.net/secure/auth/login + lifespan: 10m + + registration: + lifespan: 10m + ui_url: https://siasky.net/secure/auth/registration + after: + password: + hooks: + - hook: session + +log: + level: debug + format: text + leak_sensitive_values: true + +secrets: + cookie: + - PLEASE-CHANGE-ME-I-AM-VERY-INSECURE + +hashers: + argon2: + parallelism: 1 + memory: 131072 + iterations: 2 + salt_length: 16 + key_length: 16 + +identity: + default_schema_url: file:///etc/config/kratos/identity.schema.json + +courier: + smtp: + connection_uri: smtps://test:test@mailslurper:1025/?skip_ssl_verify=true diff --git a/docker/kratos/config/oidc/identity.traits.schema.json b/docker/kratos/config/oidc/identity.traits.schema.json new file mode 100644 index 00000000..62de3d1b --- /dev/null +++ b/docker/kratos/config/oidc/identity.traits.schema.json @@ -0,0 +1,37 @@ +{ + "$id": "https://schemas.ory.sh/presets/kratos/quickstart/email-password/identity.schema.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Person", + "type": "object", + "properties": { + "traits": { + "type": "object", + "properties": { + "email": { + "type": "string", + "format": "email", + "title": "E-Mail", + "minLength": 3, + "ory.sh/kratos": { + "credentials": { + "password": { + "identifier": true + } + }, + "verification": { + "via": "email" + }, + "recovery": { + "via": "email" + } + } + }, + "website": { + "type": "object" + } + }, + "required": ["website", "email"], + "additionalProperties": false + } + } +} diff --git a/docker/kratos/config/oidc/oidc.github.jsonnet b/docker/kratos/config/oidc/oidc.github.jsonnet new file mode 100644 index 00000000..06b92bf9 --- /dev/null +++ b/docker/kratos/config/oidc/oidc.github.jsonnet @@ -0,0 +1,17 @@ +local claims = { + email_verified: false +} + std.extVar('claims'); + +{ + identity: { + traits: { + // Allowing unverified email addresses enables account + // enumeration attacks, especially if the value is used for + // e.g. verification or as a password login identifier. + // + // Therefore we only return the email if it (a) exists and (b) is marked verified + // by GitHub. + [if "email" in claims && claims.email_verified then "email" else null]: claims.email, + }, + }, +} diff --git a/docker/nginx/conf.d/client.conf b/docker/nginx/conf.d/client.conf index b832931c..d641e148 100644 --- a/docker/nginx/conf.d/client.conf +++ b/docker/nginx/conf.d/client.conf @@ -318,6 +318,16 @@ server { proxy_pass http://127.0.0.1/$uri?attachment=true&$args; } + location /secure { + rewrite /secure/(.*) /$1 break; + proxy_pass http://kratos-selfservice-ui-node:4455; + } + + location /secure/self-service { + rewrite /secure/(.*) /$1 break; + proxy_pass http://kratos:4433; + } + # include custom locations, specific to the server include /etc/nginx/conf.d/server-override/*; } diff --git a/setup-scripts/README.md b/setup-scripts/README.md index 7d047421..8e41b078 100644 --- a/setup-scripts/README.md +++ b/setup-scripts/README.md @@ -83,6 +83,7 @@ At this point we have almost everything running, we just need to set up your wal - `CLOUDFLARE_AUTH_TOKEN` (optional) if using cloudflare as dns loadbalancer (need to change it in Caddyfile too) - `AWS_ACCESS_KEY_ID` (optional) if using route53 as a dns loadbalancer - `AWS_SECRET_ACCESS_KEY` (optional) if using route53 as a dns loadbalancer + - `MYSQL_ROOT_PASSWORD` (optional) if you're integrating accounts - it's the database password for accounts management 1. if you have a custom domain and you configured it in `DOMAIN_NAME`, edit `/home/user/skynet-webportal/docker/caddy/Caddyfile` and uncomment `import custom.domain` 1. only for siasky.net domain instances: edit `/home/user/skynet-webportal/docker/caddy/Caddyfile`, uncomment `import siasky.net` 1. `docker-compose up -d` to restart the services so they pick up new env variables diff --git a/setup-scripts/setup-docker-services.sh b/setup-scripts/setup-docker-services.sh index fbe063f9..78a6b414 100755 --- a/setup-scripts/setup-docker-services.sh +++ b/setup-scripts/setup-docker-services.sh @@ -29,10 +29,12 @@ docker-compose --version # sanity check # * AWS_SECRET_ACCESS_KEY - (optional) if using route53 as a dns loadbalancer # * API_PORT - (optional) the port on which siad is listening, defaults to 9980 # * PORTAL_NAME - the name of the portal, required by the discord bot -# * DISCORD_BOT_TOKEN - required by the discord bot +# * DISCORD_BOT_TOKEN - (optional) only required if you're using the discord notifications integration +# * MYSQL_ROOT_PASSWORD - (optional) if you're integrating accounts - it's the database password for accounts management if ! [ -f /home/user/skynet-webportal/.env ]; then HSD_API_KEY=$(openssl rand -base64 32) # generate safe random key for handshake - printf "DOMAIN_NAME=example.com\nEMAIL_ADDRESS=email@example.com\nSIA_WALLET_PASSWORD=\nHSD_API_KEY=${HSD_API_KEY}\nCLOUDFLARE_AUTH_TOKEN=\nAWS_ACCESS_KEY_ID=\nAWS_SECRET_ACCESS_KEY=\nPORTAL_NAME=\nDISCORD_BOT_TOKEN=\n" > /home/user/skynet-webportal/.env + MYSQL_ROOT_PASSWORD=$(openssl rand -base64 32) # generate safe random key for mysql database + printf "DOMAIN_NAME=example.com\nEMAIL_ADDRESS=email@example.com\nSIA_WALLET_PASSWORD=\nHSD_API_KEY=${HSD_API_KEY}\nCLOUDFLARE_AUTH_TOKEN=\nAWS_ACCESS_KEY_ID=\nAWS_SECRET_ACCESS_KEY=\nPORTAL_NAME=\nDISCORD_BOT_TOKEN=\nMYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}\n" > /home/user/skynet-webportal/.env fi # Start docker container with nginx and client