Skip to content

Commit 8d45ecf

Browse files
Enable OIDC
1 parent 4f79d30 commit 8d45ecf

File tree

10 files changed

+223
-11
lines changed

10 files changed

+223
-11
lines changed

compose.yaml

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# For the hostnames to work an entry in /etc/hosts is needed:
2-
# 127.0.0.1 orthos2.orthos2.test cobbler.orthos2.test netbox.orthos2.test
2+
# 127.0.0.1 authentik.orthos2.test orthos2.orthos2.test cobbler.orthos2.test netbox.orthos2.test
33
services:
44
proxy:
55
image: traefik:v3.6
@@ -11,13 +11,23 @@ services:
1111
- --providers.docker.exposedbydefault=false
1212
- --entrypoints.web.address=:80
1313
- --entrypoints.websecure.address=:443
14+
- --providers.file.directory=/etc/traefik/dynamic
15+
- --providers.file.watch=true
1416
ports:
1517
- "80:80"
1618
- "443:443"
1719
- "8080:8080"
1820
volumes:
19-
- /var/run/docker.sock:/var/run/docker.sock:ro,z
21+
- /var/run/docker.sock:/var/run/docker.sock:ro
22+
- ./traefik_certs:/certs:ro
23+
- ./traefik_certs/authentik.orthos2.test_certificate.crt:/certs/authentik.orthos2.test_certificate.crt:ro
24+
- ./traefik_certs/authentik.orthos2.test_private_key.key:/certs/authentik.orthos2.test_private_key.key:ro
25+
- ./traefik_certs/dynamic_conf.yaml:/etc/traefik/dynamic/certs.yaml:ro
2026
restart: always
27+
networks:
28+
orthos:
29+
aliases:
30+
- authentik.orthos2.test
2131
security_opt:
2232
- label:disable
2333
orthos2:
@@ -31,6 +41,8 @@ services:
3141
- NET_RAW
3242
volumes:
3343
- ./:/code:z
44+
networks:
45+
- orthos
3446
depends_on:
3547
orthos2_database:
3648
condition: service_healthy
@@ -43,10 +55,8 @@ services:
4355
retries: 5
4456
labels:
4557
- "traefik.enable=true"
46-
- "traefik.http.routers.orthos2-http.rule=Host(`orthos2.orthos2.test`)"
47-
- "traefik.http.routers.orthos2-http.entrypoints=web"
48-
- "traefik.http.routers.orthos2-http.middlewares=orthos2-https"
49-
- "traefik.http.middlewares.orthos2-https.redirectScheme.scheme=https"
58+
- "traefik.http.routers.orthos2.rule=Host(`orthos2.orthos2.test`)"
59+
- "traefik.http.routers.orthos2.entrypoints=web"
5060
- "traefik.http.routers.orthos2-https.rule=Host(`orthos2.orthos2.test`)"
5161
- "traefik.http.routers.orthos2-https.entrypoints=websecure"
5262
- "traefik.http.routers.orthos2-https.tls=true"
@@ -63,6 +73,8 @@ services:
6373
- NET_RAW
6474
volumes:
6575
- ./:/code
76+
networks:
77+
- orthos
6678
depends_on:
6779
orthos2_database:
6880
condition: service_healthy
@@ -74,6 +86,8 @@ services:
7486
hostname: database.orthos2.test
7587
env_file:
7688
- "docker/orthos/db.env"
89+
networks:
90+
- orthos
7791
healthcheck:
7892
test:
7993
[
@@ -90,21 +104,25 @@ services:
90104
dockerfile: cobbler.dockerfile
91105
labels:
92106
- "traefik.enable=true"
93-
- "traefik.http.routers.cobbler-http.rule=Host(`cobbler.orthos2.test`)"
94-
- "traefik.http.routers.cobbler-http.entrypoints=web"
107+
- "traefik.http.routers.cobbler.rule=Host(`cobbler.orthos2.test`)"
108+
- "traefik.http.routers.cobbler.entrypoints=web"
95109
- "traefik.http.routers.cobbler-https.rule=Host(`cobbler.orthos2.test`)"
96110
- "traefik.http.routers.cobbler-https.entrypoints=websecure"
97111
- "traefik.http.routers.cobbler-https.tls=true"
98112
- "traefik.http.services.cobbler.loadbalancer.server.port=80"
99113
serial_console:
100114
hostname: sconsole.orthos2.test
115+
networks:
116+
- orthos
101117
build:
102118
context: docker/serial-console
103119
dockerfile: serial-console.dockerfile
104120
#ports:
105121
# - 22:22
106122
machine_bmc:
107123
hostname: bmc.orthos2.test
124+
networks:
125+
- orthos
108126
build:
109127
context: docker/bmc
110128
dockerfile: bmc.dockerfile
@@ -113,6 +131,8 @@ services:
113131
# Netbox part below taken and adjusted from https://github.com/netbox-community/netbox-docker
114132
netbox: &netbox
115133
image: ${IMAGE-docker.io/netboxcommunity/netbox:latest}
134+
networks:
135+
- orthos
116136
depends_on:
117137
postgres:
118138
condition: service_healthy
@@ -135,6 +155,8 @@ services:
135155
- /opt/netbox/venv/bin/python
136156
- /opt/netbox/netbox/manage.py
137157
- rqworker
158+
networks:
159+
- orthos
138160
depends_on:
139161
netbox:
140162
condition: service_healthy
@@ -147,6 +169,8 @@ services:
147169
<<: *netbox
148170
command:
149171
- /opt/netbox/housekeeping.sh
172+
networks:
173+
- orthos
150174
depends_on:
151175
netbox:
152176
condition: service_healthy
@@ -159,6 +183,8 @@ services:
159183
postgres:
160184
image: docker.io/postgres:17-alpine
161185
env_file: docker/netbox/postgres.env
186+
networks:
187+
- orthos
162188
healthcheck:
163189
test:
164190
[
@@ -176,6 +202,8 @@ services:
176202
- -c # this is to evaluate the $REDIS_PASSWORD from the env
177203
- valkey-server --save "" --appendonly no --requirepass $$REDIS_PASSWORD ## $$ because of docker-compose
178204
env_file: docker/netbox/redis.env
205+
networks:
206+
- orthos
179207
healthcheck:
180208
test: '[ $$(valkey-cli --pass "$${REDIS_PASSWORD}" ping) = ''PONG'' ]'
181209
start_period: 5s
@@ -186,3 +214,8 @@ services:
186214
<<: *redis
187215
env_file: docker/netbox/redis-cache.env
188216

217+
volumes:
218+
database:
219+
driver: local
220+
networks:
221+
orthos:

docker/authentik/.keep

Whitespace-only changes.
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# yaml-language-server: $schema=https://goauthentik.io/blueprints/schema.json
2+
3+
version: 1
4+
context: {}
5+
entries:
6+
- attrs:
7+
access_code_validity: minutes=1
8+
access_token_validity: minutes=5
9+
authentication_flow: null
10+
authorization_flow: !Find [authentik_flows.flow, [slug, default-provider-authorization-implicit-consent]]
11+
client_id: AdmUlMJHqXTSzQ3hYx1nsYbOF9uw6FRMLoPCe7nP
12+
client_secret: hY2oN6RmQFmDGcGUKbS0rsOchSB0dlFzSjTiGi4zEU3akvI3KPebOhE3NwKCoyVpFahOMGbxYFvhtNxkzUvloiwDcAVrc5cs17TQwMyVzrk8KRTrBFvTn5gONpT7eKxX
13+
client_type: confidential
14+
encryption_key: null
15+
include_claims_in_id_token: true
16+
invalidation_flow: !Find [authentik_flows.flow, [slug, default-provider-invalidation-flow]]
17+
issuer_mode: per_provider
18+
jwt_federation_providers: []
19+
jwt_federation_sources: []
20+
logout_method: backchannel
21+
logout_uri: ''
22+
name: Provider for orthos
23+
property_mappings:
24+
- !Find [authentik_providers_oauth2.scopemapping, [name, 'authentik default OAuth Mapping: OpenID ''openid''']]
25+
- !Find [authentik_providers_oauth2.scopemapping, [name, 'authentik default OAuth Mapping: OpenID ''email''']]
26+
- !Find [authentik_providers_oauth2.scopemapping, [name, 'authentik default OAuth Mapping: OpenID ''profile''']]
27+
redirect_uris:
28+
- matching_mode: strict
29+
url: http://orthos2.orthos2.test/complete/oidc/
30+
refresh_token_threshold: hours=1
31+
refresh_token_validity: days=30
32+
signing_key: !Find [authentik_crypto.certificatekeypair, [name, 'authentik Self-signed Certificate']]
33+
sub_mode: hashed_user_id
34+
conditions: []
35+
id: orthos-provider
36+
identifiers:
37+
name: orthos-provider
38+
model: authentik_providers_oauth2.oauth2provider
39+
permissions: []
40+
state: present
41+
42+
- attrs:
43+
backchannel_providers: []
44+
group: ''
45+
meta_description: ''
46+
meta_icon: ''
47+
meta_launch_url: ''
48+
meta_publisher: ''
49+
name: orthos
50+
open_in_new_tab: false
51+
policy_engine_mode: any
52+
provider: !Find [authentik_providers_oauth2.oauth2provider, [name, 'orthos-provider']]
53+
slug: orthos
54+
conditions: []
55+
id: something_with_orthos
56+
identifiers:
57+
name: something_with_orthos
58+
model: authentik_core.application
59+
permissions: []
60+
state: present
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
services:
2+
authentik-postgresql:
3+
env_file:
4+
- docker/authentik/authentik.env
5+
environment:
6+
POSTGRES_DB: ${PG_DB:-authentik}
7+
POSTGRES_USER: ${PG_USER:-authentik}
8+
networks:
9+
- orthos
10+
healthcheck:
11+
interval: 30s
12+
retries: 5
13+
start_period: 20s
14+
test:
15+
- CMD-SHELL
16+
- pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}
17+
timeout: 5s
18+
image: docker.io/library/postgres:16-alpine
19+
restart: unless-stopped
20+
volumes:
21+
- database:/var/lib/postgresql/data
22+
23+
authentik-server:
24+
command: server
25+
depends_on:
26+
authentik-postgresql:
27+
condition: service_healthy
28+
networks:
29+
- orthos
30+
env_file:
31+
- docker/authentik/authentik.env
32+
environment:
33+
AUTHENTIK_POSTGRESQL__HOST: authentik-postgresql
34+
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2026.2.1}
35+
ports:
36+
- ${COMPOSE_PORT_HTTP:-9000}:9000
37+
- ${COMPOSE_PORT_HTTPS:-9443}:9443
38+
restart: unless-stopped
39+
shm_size: 512mb
40+
volumes:
41+
- ./data:/data
42+
- ./custom-templates:/templates
43+
- ./traefik_certs:/certs
44+
- ./docker/authentik/blueprints:/blueprints/custom:ro,z
45+
security_opt:
46+
- label:disable
47+
labels:
48+
- "traefik.enable=true"
49+
- "traefik.http.routers.authentik-rtr.entrypoints=websecure"
50+
- "traefik.http.routers.authentik-rtr.tls=true"
51+
- "traefik.http.routers.authentik-rtr.rule=Host(`authentik.orthos2.test`)"
52+
- "traefik.http.routers.authentik-output-rtr.rule=HostRegexp(`{subdomain:[a-z0-9-]+}.orthos2.test`) && PathPrefix(`/outpost.goauthentik.io/`)"
53+
- "traefik.http.routers.authentik-rtr.service=authentik-svc"
54+
- "traefik.http.services.authentik-svc.loadbalancer.server.port=9000"
55+
56+
authentik-worker:
57+
command: worker
58+
depends_on:
59+
authentik-postgresql:
60+
condition: service_healthy
61+
env_file:
62+
- docker/authentik/authentik.env
63+
networks:
64+
- orthos
65+
environment:
66+
AUTHENTIK_POSTGRESQL__HOST: authentik-postgresql
67+
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2026.2.1}
68+
restart: unless-stopped
69+
shm_size: 512mb
70+
user: root
71+
volumes:
72+
- /var/run/docker.sock:/var/run/docker.sock:z
73+
- ./data:/data
74+
- ./certs:/certs
75+
- ./custom-templates:/templates:ro,z
76+
- ./traefik_certs:/certs
77+
- ./docker/authentik/blueprints:/blueprints/custom:ro,z
78+
security_opt:
79+
- label:disable

docker/develop-tw.dockerfile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,9 @@ RUN zypper in -y \
2929
python3-urllib3 \
3030
python3-pytz \
3131
python3-django-auth-ldap \
32-
python3-django-test-migrations
32+
python3-django-test-migrations \
33+
python3-social-auth-app-django \
34+
python3-social-auth-core
3335

3436
# Test dependencies
3537
RUN zypper in -y \

docker/manage-secrets.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@
2828
orthos_db_password = get_random_string(12)
2929
orthos_superuser_password = get_random_string(12)
3030

31+
authentik_postgresql_password=get_random_string(12)
32+
authentik_postgresql_user=get_random_string(12)
33+
authentik_postgresql_name=get_random_string(12)
34+
authentik_secret_key=get_random_secret_key()
35+
3136
# netbox.env
3237
# DB_PASSWORD, REDIS_CACHE_PASSWORD, REDIS_PASSWORD, SECRET_KEY, SUPERUSER_API_TOKEN, SUPERUSER_PASSWORD
3338

@@ -120,3 +125,13 @@
120125
'CSRF_ALLOWED_ORIGIN="https://orthos2.orthos2.test"\n'
121126
'CROSS_ORIGINS_WHITELIST="https://orthos2.orthos2.test"\n',
122127
)
128+
129+
# authentik.env
130+
131+
(script_directory / "orthos" / "orthos2.env").write_text(
132+
f"AUTHENTIK_POSTGRESQL__PASSWORD={authentik_postgresql_password}"
133+
f"AUTHENTIK_POSTGRESQL__USER={authentik_postgresql_user}"
134+
f"AUTHENTIK_POSTGRESQL__NAME={authentik_postgresql_name}"
135+
f"AUTHENTIK_SECRET_KEY={authentik_secret_key}"
136+
"AUTHENTIK_ERROR_REPORTING__ENABLED=true"
137+
)

orthos2/frontend/templates/frontend/registration/login.html

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@
3232
<div class="row" style="margin: 5px;">
3333
<button class="btn btn-block" type="submit">Login</button>
3434
</div>
35+
<div class="row" style="margin: 5px;">
36+
<a href="{% url 'social:begin' backend='oidc' %}" class="btn btn-block">Login with Authentik</a>
37+
</div>
3538
</form>
3639
</div>
3740
</div>

orthos2/settings.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,10 @@ def _environ_get_and_map(
7070
CSRF_ALLOWED_ORIGIN = _environ_get_and_map("CSRF_ALLOWED_ORIGIN", "", _AS_LIST)
7171
CROSS_ORIGINS_WHITELIST = _environ_get_and_map("CROSS_ORIGINS_WHITELIST", "", _AS_LIST)
7272

73-
# Application definition
73+
# Trust a specific Cert
74+
os.environ['REQUESTS_CA_BUNDLE'] = '/code/traefik_certs/authentik.orthos2.test_certificate.crt'
7475

76+
# Application definition
7577
INSTALLED_APPS = [
7678
"orthos2.data.apps.DataConfig",
7779
"orthos2.frontend.apps.FrontendConfig",
@@ -88,8 +90,16 @@ def _environ_get_and_map(
8890
"orthos2.api.apps.APIConfig",
8991
"rest_framework",
9092
"rest_framework.authtoken",
93+
"social_django",
9194
]
9295

96+
REMOTE_AUTH_BACKEND = 'social_core.backends.open_id_connect.OpenIdConnectAuth'
97+
SOCIAL_AUTH_OIDC_OIDC_ENDPOINT = 'https://authentik.orthos2.test/application/o/orthos'
98+
SOCIAL_AUTH_OIDC_KEY = os.environ.get("OIDC_KEY", "default")
99+
SOCIAL_AUTH_OIDC_SECRET = os.environ.get("OIDC_SECRET", "default")
100+
101+
SOCIAL_AUTH_JSONFIELD_ENABLED = True
102+
93103
MIDDLEWARE = [
94104
"django.middleware.security.SecurityMiddleware",
95105
"django.contrib.sessions.middleware.SessionMiddleware",
@@ -248,6 +258,10 @@ def _environ_get_and_map(
248258
},
249259
},
250260
}
261+
AUTHENTICATION_BACKENDS = (
262+
'social_core.backends.open_id_connect.OpenIdConnectAuth',
263+
'django.contrib.auth.backends.ModelBackend',
264+
)
251265

252266
logging.config.dictConfig(LOGGING)
253267
logger = logging.getLogger("orthos")
@@ -259,6 +273,7 @@ def _environ_get_and_map(
259273

260274
# Login URL
261275
LOGIN_URL = "/login/"
276+
LOGIN_REDIRECT_URL = '/'
262277

263278
# On logout, go back to the starting page
264279
LOGOUT_REDIRECT_URL = "/"

0 commit comments

Comments
 (0)