feat: refractor CIE auth stack configuration for improved environment variable management and docker compatibility
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
CIE_AUTH_ALLOWED_HOSTS=cie-auth.example.it,auth.example.it
|
||||
DJANGO_TRUST_ANCHOR=https://federation-authority.example.it
|
||||
DJANGO_PROVIDER_ISSUER=https://provider.example.it/oidc/op
|
||||
DJANGO_RP_BACKEND_EXCHANGE_URL=https://visione-backend.example.it/api/v1/auth/cie/exchange
|
||||
DJANGO_RP_SHARED_SECRET=change-me
|
||||
FEDERATION_AUTHORITY_SECRET_KEY=change-me
|
||||
PROVIDER_SECRET_KEY=change-me
|
||||
RELYING_PARTY_SECRET_KEY=change-me
|
||||
@@ -1,60 +1,58 @@
|
||||
# Visione Local CIE Stack
|
||||
# Visione CIE Auth Stack
|
||||
|
||||
This folder is a ready-to-run local stack for CIE auth integration with Visione.
|
||||
|
||||
Included services:
|
||||
This folder contains deployable CIE auth services for Visione:
|
||||
- `federation-authority`
|
||||
- `provider`
|
||||
- `relying-party`
|
||||
|
||||
They run through one compose file and use the modified relying party bridge for Visione.
|
||||
It is now structured to work with Docker Compose and Dokploy without host networking.
|
||||
|
||||
## Prerequisites
|
||||
- Visione backend running on `http://127.0.0.1:5555`
|
||||
- Docker with Compose
|
||||
## Configuration
|
||||
Copy [.env.example](/workspace/cie-auth/.env.example) to `.env` and set only what changes in real deploy:
|
||||
- public domains / internal URLs
|
||||
- Django secret keys
|
||||
- shared secret between relying party and Visione backend
|
||||
|
||||
## Visione config
|
||||
Set in `config.json`:
|
||||
Main variables:
|
||||
- `CIE_AUTH_ALLOWED_HOSTS`
|
||||
- `DJANGO_TRUST_ANCHOR`
|
||||
- `DJANGO_PROVIDER_ISSUER`
|
||||
- `DJANGO_RP_BACKEND_EXCHANGE_URL`
|
||||
- `DJANGO_RP_SHARED_SECRET`
|
||||
- `FEDERATION_AUTHORITY_SECRET_KEY`
|
||||
- `PROVIDER_SECRET_KEY`
|
||||
- `RELYING_PARTY_SECRET_KEY`
|
||||
|
||||
```json
|
||||
"cie_auth": {
|
||||
"service_base_url": "http://127.0.0.1:8001",
|
||||
"start_path": "/visione/start",
|
||||
"shared_secret": "change-me-for-local-dev",
|
||||
"state_ttl_minutes": 10,
|
||||
"default_frontend_redirect_uri": "http://localhost:3000/auth/cie/callback"
|
||||
}
|
||||
```
|
||||
## Deploy with Dokploy
|
||||
Use [docker-compose.yml](/workspace/cie-auth/docker-compose.yml) as compose source.
|
||||
Expose:
|
||||
- `federation-authority` on port `8000`
|
||||
- `provider` on port `8002`
|
||||
- `relying-party` on port `8001`
|
||||
|
||||
Keep same secret also in:
|
||||
- `relying_party/relying_party/settingslocal.py`
|
||||
`VISIONE_SHARED_SECRET`
|
||||
Each service persists its own SQLite DB in a named volume.
|
||||
|
||||
## Start stack
|
||||
From repo root:
|
||||
## Local start
|
||||
|
||||
```bash
|
||||
docker compose up -d
|
||||
docker compose -f infra/cie-auth/docker-compose.yml up --build -d
|
||||
docker compose up --build -d
|
||||
```
|
||||
|
||||
This starts:
|
||||
- MySQL + Mailpit from root compose
|
||||
- authority on `127.0.0.1:8000`
|
||||
- provider on `127.0.0.1:8002`
|
||||
- relying party on `127.0.0.1:8001`
|
||||
## Visione backend
|
||||
Visione backend must expose exchange endpoint configured in `DJANGO_RP_BACKEND_EXCHANGE_URL`.
|
||||
Shared secret must match backend `cie_auth.shared_secret`.
|
||||
|
||||
## Start Visione
|
||||
From repo root:
|
||||
## Bootstrap behavior
|
||||
On first boot, each Django service:
|
||||
1. runs migrations
|
||||
2. loads `dumps/example.json` only if DB is empty
|
||||
|
||||
```bash
|
||||
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug
|
||||
cmake --build build
|
||||
./build/visione-backend
|
||||
```
|
||||
Disable fixture import per service with:
|
||||
- `FEDERATION_AUTHORITY_LOAD_FIXTURE_ON_EMPTY_DB=false`
|
||||
- `PROVIDER_LOAD_FIXTURE_ON_EMPTY_DB=false`
|
||||
- `RELYING_PARTY_LOAD_FIXTURE_ON_EMPTY_DB=false`
|
||||
|
||||
## Smoke test
|
||||
Start login:
|
||||
|
||||
```bash
|
||||
curl -sS -X POST http://127.0.0.1:5555/api/v1/auth/cie/start \
|
||||
@@ -62,45 +60,19 @@ curl -sS -X POST http://127.0.0.1:5555/api/v1/auth/cie/start \
|
||||
-d '{"frontend_redirect_uri":"http://localhost:3000/auth/cie/callback"}'
|
||||
```
|
||||
|
||||
Expected JSON:
|
||||
- `authorization_url`
|
||||
- `state`
|
||||
|
||||
Then:
|
||||
1. open `authorization_url` in browser
|
||||
2. complete demo CIE login
|
||||
3. browser lands on `http://localhost:3000/auth/cie/callback?state=...`
|
||||
|
||||
Poll result:
|
||||
Then complete login and poll:
|
||||
|
||||
```bash
|
||||
curl -sS http://127.0.0.1:5555/api/v1/auth/cie/session/<state>
|
||||
```
|
||||
|
||||
Expected success:
|
||||
- `status = "authenticated"`
|
||||
- `auth.token` present
|
||||
|
||||
## Frontend flow
|
||||
1. call `POST /api/v1/auth/cie/start`
|
||||
2. redirect browser to `authorization_url`
|
||||
3. callback page reads `state`
|
||||
4. poll `GET /api/v1/auth/cie/session/{state}`
|
||||
5. when authenticated, save `auth.token`
|
||||
6. call `GET /api/v1/me`
|
||||
|
||||
## Reset local auth DBs
|
||||
If you want a clean auth stack:
|
||||
## Reset data
|
||||
|
||||
```bash
|
||||
rm -f infra/cie-auth/federation_authority/db.sqlite3
|
||||
rm -f infra/cie-auth/provider/db.sqlite3
|
||||
rm -f infra/cie-auth/relying_party/db.sqlite3
|
||||
docker compose -f infra/cie-auth/docker-compose.yml down
|
||||
docker compose -f infra/cie-auth/docker-compose.yml up --build -d
|
||||
docker compose down -v
|
||||
```
|
||||
|
||||
## Logs
|
||||
```bash
|
||||
docker compose -f infra/cie-auth/docker-compose.yml logs -f
|
||||
docker compose logs -f
|
||||
```
|
||||
|
||||
+37
-3
@@ -3,33 +3,67 @@ services:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
network_mode: host
|
||||
working_dir: /app/federation_authority
|
||||
command: ["/app/federation_authority", "8000"]
|
||||
environment:
|
||||
DJANGO_SECRET_KEY: ${FEDERATION_AUTHORITY_SECRET_KEY:-visione-cie-authority-local-dev}
|
||||
DJANGO_ALLOWED_HOSTS: ${CIE_AUTH_ALLOWED_HOSTS:-*}
|
||||
DJANGO_TRUST_ANCHOR: ${DJANGO_TRUST_ANCHOR:-http://federation-authority:8000}
|
||||
LOAD_FIXTURE_ON_EMPTY_DB: ${FEDERATION_AUTHORITY_LOAD_FIXTURE_ON_EMPTY_DB:-true}
|
||||
ports:
|
||||
- "${FEDERATION_AUTHORITY_PORT:-8000}:8000"
|
||||
volumes:
|
||||
- ./federation_authority:/app/federation_authority
|
||||
- federation-authority-data:/app/federation_authority/db
|
||||
restart: unless-stopped
|
||||
|
||||
provider:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
network_mode: host
|
||||
working_dir: /app/provider
|
||||
command: ["/app/provider", "8002"]
|
||||
environment:
|
||||
DJANGO_SECRET_KEY: ${PROVIDER_SECRET_KEY:-visione-cie-provider-local-dev}
|
||||
DJANGO_ALLOWED_HOSTS: ${CIE_AUTH_ALLOWED_HOSTS:-*}
|
||||
DJANGO_TRUST_ANCHOR: ${DJANGO_TRUST_ANCHOR:-http://federation-authority:8000}
|
||||
DJANGO_PROVIDER_ISSUER: ${DJANGO_PROVIDER_ISSUER:-http://provider:8002/oidc/op}
|
||||
LOAD_FIXTURE_ON_EMPTY_DB: ${PROVIDER_LOAD_FIXTURE_ON_EMPTY_DB:-true}
|
||||
ports:
|
||||
- "${PROVIDER_PORT:-8002}:8002"
|
||||
volumes:
|
||||
- ./provider:/app/provider
|
||||
- provider-data:/app/provider/db
|
||||
depends_on:
|
||||
- federation-authority
|
||||
restart: unless-stopped
|
||||
|
||||
relying-party:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
network_mode: host
|
||||
working_dir: /app/relying_party
|
||||
command: ["/app/relying_party", "8001"]
|
||||
environment:
|
||||
DJANGO_SECRET_KEY: ${RELYING_PARTY_SECRET_KEY:-visione-cie-rp-local-dev}
|
||||
DJANGO_ALLOWED_HOSTS: ${CIE_AUTH_ALLOWED_HOSTS:-*}
|
||||
DJANGO_TRUST_ANCHOR: ${DJANGO_TRUST_ANCHOR:-http://federation-authority:8000}
|
||||
DJANGO_PROVIDER_ISSUER: ${DJANGO_PROVIDER_ISSUER:-http://provider:8002/oidc/op}
|
||||
DJANGO_RP_BACKEND_EXCHANGE_URL: ${DJANGO_RP_BACKEND_EXCHANGE_URL:-http://visione-backend:5555/api/v1/auth/cie/exchange}
|
||||
DJANGO_RP_SHARED_SECRET: ${DJANGO_RP_SHARED_SECRET:-change-me-for-local-dev}
|
||||
DJANGO_RP_DEFAULT_PROVIDER: ${DJANGO_RP_DEFAULT_PROVIDER:-http://provider:8002/oidc/op}
|
||||
LOAD_FIXTURE_ON_EMPTY_DB: ${RELYING_PARTY_LOAD_FIXTURE_ON_EMPTY_DB:-true}
|
||||
ports:
|
||||
- "${RELYING_PARTY_PORT:-8001}:8001"
|
||||
volumes:
|
||||
- ./relying_party:/app/relying_party
|
||||
- relying-party-data:/app/relying_party/db
|
||||
depends_on:
|
||||
- federation-authority
|
||||
- provider
|
||||
restart: unless-stopped
|
||||
|
||||
volumes:
|
||||
federation-authority-data:
|
||||
provider-data:
|
||||
relying-party-data:
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ cd "$APP_DIR"
|
||||
|
||||
mkdir -p logs static
|
||||
|
||||
if [ ! -f db.sqlite3 ]; then
|
||||
if [ ! -f "$APP_DIR/db.sqlite3" ] && [ "${LOAD_FIXTURE_ON_EMPTY_DB:-true}" = "true" ]; then
|
||||
python manage.py migrate
|
||||
python manage.py loaddata dumps/example.json
|
||||
else
|
||||
|
||||
@@ -3,12 +3,18 @@ import os
|
||||
|
||||
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
SECRET_KEY = 'visione-cie-authority-local-dev'
|
||||
DEBUG = True
|
||||
def env_bool(name, default=False):
|
||||
value = os.getenv(name)
|
||||
if value is None:
|
||||
return default
|
||||
return value.lower() in {"1", "true", "yes", "on"}
|
||||
|
||||
SECRET_KEY = os.getenv('DJANGO_SECRET_KEY', 'visione-cie-authority-local-dev')
|
||||
DEBUG = env_bool('DJANGO_DEBUG', False)
|
||||
ADMIN_PATH = 'admin/'
|
||||
APPEND_SLASH = False
|
||||
|
||||
OIDCFED_DEFAULT_TRUST_ANCHOR = "http://127.0.0.1:8000"
|
||||
OIDCFED_DEFAULT_TRUST_ANCHOR = os.getenv("DJANGO_TRUST_ANCHOR", "http://127.0.0.1:8000")
|
||||
OIDCFED_TRUST_ANCHORS = [OIDCFED_DEFAULT_TRUST_ANCHOR]
|
||||
OIDCFED_PROVIDER_PROFILE = "spid"
|
||||
OIDCFED_PROVIDER_MAX_REFRESH = 10
|
||||
@@ -28,7 +34,7 @@ LOGIN_REDIRECT_URL = "/oidc/rp/echo_attributes"
|
||||
LOGOUT_REDIRECT_URL = "/oidc/rp/landing"
|
||||
LOGIN_URL = "/oidc/rp/landing"
|
||||
|
||||
ALLOWED_HOSTS = ['*']
|
||||
ALLOWED_HOSTS = [item.strip() for item in os.getenv('DJANGO_ALLOWED_HOSTS', '*').split(',') if item.strip()]
|
||||
AUTH_USER_MODEL = 'spid_cie_oidc_accounts.User'
|
||||
|
||||
INSTALLED_APPS = [
|
||||
@@ -85,7 +91,7 @@ LOGGING = {
|
||||
'handlers': {
|
||||
'console': {
|
||||
'formatter': 'default',
|
||||
'level': 'DEBUG',
|
||||
'level': 'INFO',
|
||||
'class': 'logging.StreamHandler',
|
||||
},
|
||||
},
|
||||
|
||||
@@ -3,23 +3,32 @@ import os
|
||||
|
||||
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
SECRET_KEY = 'visione-cie-provider-local-dev'
|
||||
DEBUG = True
|
||||
def env_bool(name, default=False):
|
||||
value = os.getenv(name)
|
||||
if value is None:
|
||||
return default
|
||||
return value.lower() in {"1", "true", "yes", "on"}
|
||||
|
||||
|
||||
SECRET_KEY = os.getenv('DJANGO_SECRET_KEY', 'visione-cie-provider-local-dev')
|
||||
DEBUG = env_bool('DJANGO_DEBUG', False)
|
||||
ADMIN_PATH = 'admin/'
|
||||
APPEND_SLASH = False
|
||||
|
||||
OIDCFED_DEFAULT_TRUST_ANCHOR = "http://127.0.0.1:8000"
|
||||
OIDCFED_DEFAULT_TRUST_ANCHOR = os.getenv("DJANGO_TRUST_ANCHOR", "http://127.0.0.1:8000")
|
||||
OIDCFED_TRUST_ANCHORS = [OIDCFED_DEFAULT_TRUST_ANCHOR]
|
||||
OIDCFED_PROVIDER_PROFILE = "cie"
|
||||
OIDCFED_PROVIDER_MAX_CONSENT_TIMEFRAME = 3600
|
||||
OIDCFED_REQUIRED_TRUST_MARKS = []
|
||||
|
||||
provider_issuer = os.getenv("DJANGO_PROVIDER_ISSUER", "http://127.0.0.1:8002/oidc/op")
|
||||
|
||||
OIDCFED_IDENTITY_PROVIDERS = {
|
||||
"spid": {
|
||||
"http://127.0.0.1:8000/oidc/op": OIDCFED_DEFAULT_TRUST_ANCHOR,
|
||||
f"{OIDCFED_DEFAULT_TRUST_ANCHOR}/oidc/op": OIDCFED_DEFAULT_TRUST_ANCHOR,
|
||||
},
|
||||
"cie": {
|
||||
"http://127.0.0.1:8002/oidc/op": OIDCFED_DEFAULT_TRUST_ANCHOR,
|
||||
provider_issuer: OIDCFED_DEFAULT_TRUST_ANCHOR,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -32,7 +41,7 @@ LOGIN_REDIRECT_URL = "/oidc/op/landing"
|
||||
LOGOUT_REDIRECT_URL = "/oidc/op/landing"
|
||||
LOGIN_URL = "/oidc/op/landing"
|
||||
|
||||
ALLOWED_HOSTS = ['*']
|
||||
ALLOWED_HOSTS = [item.strip() for item in os.getenv('DJANGO_ALLOWED_HOSTS', '*').split(',') if item.strip()]
|
||||
AUTH_USER_MODEL = 'spid_cie_oidc_accounts.User'
|
||||
|
||||
INSTALLED_APPS = [
|
||||
@@ -86,7 +95,7 @@ LOGGING = {
|
||||
'handlers': {
|
||||
'console': {
|
||||
'formatter': 'default',
|
||||
'level': 'DEBUG',
|
||||
'level': 'INFO',
|
||||
'class': 'logging.StreamHandler',
|
||||
},
|
||||
},
|
||||
|
||||
@@ -3,21 +3,30 @@ import os
|
||||
|
||||
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
SECRET_KEY = 'visione-cie-rp-local-dev'
|
||||
DEBUG = True
|
||||
def env_bool(name, default=False):
|
||||
value = os.getenv(name)
|
||||
if value is None:
|
||||
return default
|
||||
return value.lower() in {"1", "true", "yes", "on"}
|
||||
|
||||
|
||||
SECRET_KEY = os.getenv('DJANGO_SECRET_KEY', 'visione-cie-rp-local-dev')
|
||||
DEBUG = env_bool('DJANGO_DEBUG', False)
|
||||
ADMIN_PATH = 'admin/'
|
||||
APPEND_SLASH = False
|
||||
|
||||
OIDCFED_DEFAULT_TRUST_ANCHOR = "http://127.0.0.1:8000"
|
||||
OIDCFED_DEFAULT_TRUST_ANCHOR = os.getenv("DJANGO_TRUST_ANCHOR", "http://127.0.0.1:8000")
|
||||
OIDCFED_TRUST_ANCHORS = [OIDCFED_DEFAULT_TRUST_ANCHOR]
|
||||
OIDCFED_REQUIRED_TRUST_MARKS = []
|
||||
|
||||
provider_issuer = os.getenv("DJANGO_PROVIDER_ISSUER", "http://127.0.0.1:8002/oidc/op")
|
||||
|
||||
OIDCFED_IDENTITY_PROVIDERS = {
|
||||
"spid": {
|
||||
"http://127.0.0.1:8000/oidc/op": OIDCFED_DEFAULT_TRUST_ANCHOR,
|
||||
f"{OIDCFED_DEFAULT_TRUST_ANCHOR}/oidc/op": OIDCFED_DEFAULT_TRUST_ANCHOR,
|
||||
},
|
||||
"cie": {
|
||||
"http://127.0.0.1:8002/oidc/op": OIDCFED_DEFAULT_TRUST_ANCHOR,
|
||||
provider_issuer: OIDCFED_DEFAULT_TRUST_ANCHOR,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -30,12 +39,15 @@ LOGIN_REDIRECT_URL = "/visione/complete"
|
||||
LOGOUT_REDIRECT_URL = "/oidc/rp/landing"
|
||||
LOGIN_URL = "/oidc/rp/landing"
|
||||
|
||||
VISIONE_BACKEND_EXCHANGE_URL = "http://127.0.0.1:5555/api/v1/auth/cie/exchange"
|
||||
VISIONE_SHARED_SECRET = "change-me-for-local-dev"
|
||||
VISIONE_DEFAULT_PROVIDER = "http://127.0.0.1:8002/oidc/op"
|
||||
VISIONE_BACKEND_EXCHANGE_URL = os.getenv(
|
||||
"DJANGO_RP_BACKEND_EXCHANGE_URL",
|
||||
"http://127.0.0.1:5555/api/v1/auth/cie/exchange"
|
||||
)
|
||||
VISIONE_SHARED_SECRET = os.getenv("DJANGO_RP_SHARED_SECRET", "change-me-for-local-dev")
|
||||
VISIONE_DEFAULT_PROVIDER = os.getenv("DJANGO_RP_DEFAULT_PROVIDER", provider_issuer)
|
||||
VISIONE_DEFAULT_PROFILE = "cie"
|
||||
|
||||
ALLOWED_HOSTS = ['*']
|
||||
ALLOWED_HOSTS = [item.strip() for item in os.getenv('DJANGO_ALLOWED_HOSTS', '*').split(',') if item.strip()]
|
||||
AUTH_USER_MODEL = 'spid_cie_oidc_accounts.User'
|
||||
|
||||
INSTALLED_APPS = [
|
||||
@@ -89,7 +101,7 @@ LOGGING = {
|
||||
'handlers': {
|
||||
'console': {
|
||||
'formatter': 'default',
|
||||
'level': 'DEBUG',
|
||||
'level': 'INFO',
|
||||
'class': 'logging.StreamHandler',
|
||||
},
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user