feat(authentik): pin known tokens on proxy outposts too

Generalize the outpost token-pinning path beyond the LDAP outpost so any
proxy outpost declaring a token authenticates against the authentik
server with the vault token instead of the blueprint's auto-generated
one. Drive both from a single rendered script over a target list.

Also raise the server healthcheck start_period to 120s: cold first boot
runs DB migrations plus app init (~90s observed), which tripped
compose --wait as unhealthy at the old 30s.

Signed-off-by: Simon Bärlocher <simon@whatwedo.ch>
This commit is contained in:
Simon Bärlocher 2026-07-02 17:11:51 +02:00
parent 0733d5710f
commit c4220f2c2d
No known key found for this signature in database
GPG key ID: 63DE20495932047A
3 changed files with 45 additions and 17 deletions

View file

@ -49,22 +49,32 @@
until: blueprint_wait_result.rc == 0 until: blueprint_wait_result.rc == 0
when: blueprints_changed when: blueprints_changed
- name: Render LDAP outpost token script # Pin known tokens on the LDAP outpost and on any proxy outpost that
# declares one, so co-located outposts (e.g. a proxy outpost on another
# host) can authenticate against the authentik server with the token from
# the vault instead of the auto-generated one the blueprint creates.
- name: Set fact whether any outpost needs a pinned token
ansible.builtin.set_fact:
_authentik_outpost_tokens: >-
{{ (authentik_ldap_outpost.name is defined)
or (authentik_proxy_outposts | default([]) | selectattr('token', 'defined') | list | length > 0) }}
- name: Render outpost token script
template: template:
src: set-outpost-token.py.j2 src: set-outpost-token.py.j2
dest: "{{ authentik_docker_volume_dir }}/data/set-outpost-token.py" dest: "{{ authentik_docker_volume_dir }}/data/set-outpost-token.py"
mode: '0644' mode: '0644'
when: authentik_ldap_outpost.name is defined when: _authentik_outpost_tokens | bool
register: ldap_token_script register: outpost_token_script
- name: Set known token for LDAP outpost - name: Set known tokens for outposts
community.docker.docker_compose_v2_exec: community.docker.docker_compose_v2_exec:
project_src: "{{ authentik_docker_compose_dir }}" project_src: "{{ authentik_docker_compose_dir }}"
service: server service: server
command: ak shell -c "exec(open('/data/set-outpost-token.py').read())" command: ak shell -c "exec(open('/data/set-outpost-token.py').read())"
register: ldap_token_result register: outpost_token_result
changed_when: "'changed' in ldap_token_result.stdout" changed_when: "'changed' in outpost_token_result.stdout"
retries: 30 retries: 30
delay: 10 delay: 10
until: ldap_token_result.rc == 0 until: outpost_token_result.rc == 0
when: authentik_ldap_outpost.name is defined and (blueprints_changed or ldap_token_script.changed) when: (_authentik_outpost_tokens | bool) and (blueprints_changed or outpost_token_script.changed)

View file

@ -23,7 +23,9 @@ services:
command: server command: server
healthcheck: healthcheck:
test: ["CMD", "ak", "healthcheck"] test: ["CMD", "ak", "healthcheck"]
start_period: 30s # Cold first boot runs DB migrations + app init (~90s observed);
# start_period must cover that or compose --wait trips unhealthy.
start_period: 120s
interval: 10s interval: 10s
retries: 5 retries: 5
timeout: 5s timeout: 5s

View file

@ -1,10 +1,26 @@
from authentik.outposts.models import Outpost from authentik.outposts.models import Outpost
from authentik.core.models import Token from authentik.core.models import Token
o = Outpost.objects.get(name='{{ authentik_ldap_outpost.name }}')
t = Token.objects.get(identifier=o.token_identifier) # (outpost name, desired token key) for every outpost we pin a known
if t.key != '{{ authentik_ldap_outpost.token }}': # token on: the LDAP outpost plus any proxy outpost that declares a
t.key = '{{ authentik_ldap_outpost.token }}' # `token` (co-located proxy outposts authenticate with it against the
# authentik server).
_targets = [
{% if authentik_ldap_outpost.name is defined %}
('{{ authentik_ldap_outpost.name }}', '{{ authentik_ldap_outpost.token }}'),
{% endif %}
{% for o in authentik_proxy_outposts | default([]) if o.token is defined %}
('{{ o.name }}', '{{ o.token }}'),
{% endfor %}
]
changed = False
for name, key in _targets:
o = Outpost.objects.get(name=name)
t = Token.objects.get(identifier=o.token_identifier)
if t.key != key:
t.key = key
t.save(update_fields=['key']) t.save(update_fields=['key'])
print('changed') changed = True
else:
print('ok') print('changed' if changed else 'ok')