feat: Add automated invitation stage configuration for Authentik
Implements automatic invitation stage creation and enrollment flow binding: **Features:** - Creates invitation stage via YAML blueprint - Binds stage to enrollment flow (designation: enrollment) - Allows enrollment to proceed without invitation token - Fully automated via Ansible deployment **Implementation:** - New blueprint: ansible/roles/authentik/files/invitation-flow.yaml - New task file: ansible/roles/authentik/tasks/invitation.yml - Blueprint creates invitationstage model - Binds stage to enrollment flow at order=0 **Blueprint Configuration:** ```yaml model: authentik_stages_invitation.invitationstage name: default-enrollment-invitation continue_flow_without_invitation: true ``` **Testing:** ✅ Deployed to dev server successfully ✅ Invitation stage created and verified ✅ Stage bound to default-source-enrollment flow ✅ Verification: {"found": true, "count": 1} Resolves Authentik warning: "No invitation stage is bound to any flow" 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
2d94df6a8a
commit
90a92fca5a
3 changed files with 124 additions and 0 deletions
25
ansible/roles/authentik/files/invitation-flow.yaml
Normal file
25
ansible/roles/authentik/files/invitation-flow.yaml
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
version: 1
|
||||||
|
metadata:
|
||||||
|
name: invitation-flow-configuration
|
||||||
|
labels:
|
||||||
|
blueprints.goauthentik.io/description: "Configure invitation stage for enrollment"
|
||||||
|
blueprints.goauthentik.io/instantiate: "true"
|
||||||
|
|
||||||
|
entries:
|
||||||
|
# 1. CREATE INVITATION STAGE
|
||||||
|
- model: authentik_stages_invitation.invitationstage
|
||||||
|
identifiers:
|
||||||
|
name: default-enrollment-invitation
|
||||||
|
id: invitation-stage
|
||||||
|
attrs:
|
||||||
|
continue_flow_without_invitation: true
|
||||||
|
|
||||||
|
# 2. BIND INVITATION STAGE TO ENROLLMENT FLOW
|
||||||
|
- model: authentik_flows.flowstagebinding
|
||||||
|
identifiers:
|
||||||
|
target: !Find [authentik_flows.flow, [designation, enrollment]]
|
||||||
|
stage: !KeyOf invitation-stage
|
||||||
|
order: 0
|
||||||
|
attrs:
|
||||||
|
evaluate_on_plan: true
|
||||||
|
re_evaluate_policies: false
|
||||||
94
ansible/roles/authentik/tasks/invitation.yml
Normal file
94
ansible/roles/authentik/tasks/invitation.yml
Normal file
|
|
@ -0,0 +1,94 @@
|
||||||
|
---
|
||||||
|
# Configure invitation stage for enrollment flow
|
||||||
|
|
||||||
|
- name: Use bootstrap token for API access
|
||||||
|
set_fact:
|
||||||
|
authentik_api_token: "{{ client_secrets.authentik_bootstrap_token }}"
|
||||||
|
|
||||||
|
- name: Wait for Authentik API to be ready
|
||||||
|
uri:
|
||||||
|
url: "https://{{ authentik_domain }}/api/v3/root/config/"
|
||||||
|
method: GET
|
||||||
|
validate_certs: no
|
||||||
|
status_code: 200
|
||||||
|
register: api_result
|
||||||
|
until: api_result.status == 200
|
||||||
|
retries: 12
|
||||||
|
delay: 5
|
||||||
|
|
||||||
|
- name: Create blueprints directory on server
|
||||||
|
file:
|
||||||
|
path: /opt/config/authentik/blueprints
|
||||||
|
state: directory
|
||||||
|
mode: '0755'
|
||||||
|
|
||||||
|
- name: Copy invitation flow blueprint to server
|
||||||
|
copy:
|
||||||
|
src: invitation-flow.yaml
|
||||||
|
dest: /opt/config/authentik/blueprints/invitation-flow.yaml
|
||||||
|
mode: '0644'
|
||||||
|
register: invitation_blueprint_copied
|
||||||
|
|
||||||
|
- name: Copy blueprint into authentik-worker container
|
||||||
|
shell: |
|
||||||
|
docker cp /opt/config/authentik/blueprints/invitation-flow.yaml authentik-worker:/blueprints/invitation-flow.yaml
|
||||||
|
|
||||||
|
- name: Copy blueprint into authentik-server container
|
||||||
|
shell: |
|
||||||
|
docker cp /opt/config/authentik/blueprints/invitation-flow.yaml authentik-server:/blueprints/invitation-flow.yaml
|
||||||
|
|
||||||
|
- name: Wait for blueprint to be discovered and applied
|
||||||
|
shell: |
|
||||||
|
echo "Waiting for invitation blueprint to be discovered and applied..."
|
||||||
|
sleep 10
|
||||||
|
# Check if blueprint instance was created
|
||||||
|
i=1
|
||||||
|
while [ $i -le 24 ]; do
|
||||||
|
result=$(docker exec authentik-server curl -sf -H 'Authorization: Bearer {{ authentik_api_token }}' \
|
||||||
|
'http://localhost:9000/api/v3/managed/blueprints/' 2>/dev/null || echo '')
|
||||||
|
if echo "$result" | grep -q 'invitation-flow-configuration'; then
|
||||||
|
echo "Blueprint instance found"
|
||||||
|
if echo "$result" | grep -A 10 'invitation-flow-configuration' | grep -q 'successful'; then
|
||||||
|
echo "Blueprint applied successfully"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
sleep 5
|
||||||
|
i=$((i+1))
|
||||||
|
done
|
||||||
|
echo "Blueprint deployment in progress (may take 1-2 minutes)"
|
||||||
|
register: invitation_blueprint_result
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
- name: Verify invitation stage was created
|
||||||
|
shell: |
|
||||||
|
docker exec authentik-server curl -sf -H 'Authorization: Bearer {{ authentik_api_token }}' \
|
||||||
|
'http://localhost:9000/api/v3/stages/all/?name=default-enrollment-invitation' | \
|
||||||
|
python3 -c "import sys, json; d = json.load(sys.stdin); print(json.dumps({'found': len(d.get('results', [])) > 0, 'count': len(d.get('results', []))}))"
|
||||||
|
register: invitation_stage_check
|
||||||
|
changed_when: false
|
||||||
|
failed_when: false
|
||||||
|
|
||||||
|
- name: Display invitation stage configuration status
|
||||||
|
debug:
|
||||||
|
msg: |
|
||||||
|
========================================
|
||||||
|
Authentik Invitation Stage Configuration
|
||||||
|
========================================
|
||||||
|
|
||||||
|
Configuration Method: YAML Blueprints
|
||||||
|
Blueprint File: /blueprints/invitation-flow.yaml
|
||||||
|
|
||||||
|
✓ Blueprint Deployed: {{ invitation_blueprint_copied.changed | default(false) }}
|
||||||
|
✓ Blueprint Applied: {{ 'In Progress' if invitation_blueprint_result.rc != 0 else 'Complete' }}
|
||||||
|
|
||||||
|
Verification: {{ invitation_stage_check.stdout | default('{}') }}
|
||||||
|
|
||||||
|
Note: Authentik applies blueprints asynchronously.
|
||||||
|
Changes should be visible within 1-2 minutes.
|
||||||
|
|
||||||
|
To verify manually:
|
||||||
|
- Login to https://{{ authentik_domain }}
|
||||||
|
- Check Admin > Flows > Stages for "default-enrollment-invitation"
|
||||||
|
- Check Admin > Flows > default-source-enrollment for invitation binding
|
||||||
|
========================================
|
||||||
|
|
@ -26,3 +26,8 @@
|
||||||
include_tasks: mfa.yml
|
include_tasks: mfa.yml
|
||||||
when: authentik_bootstrap | default(true)
|
when: authentik_bootstrap | default(true)
|
||||||
tags: ['authentik', 'mfa', '2fa']
|
tags: ['authentik', 'mfa', '2fa']
|
||||||
|
|
||||||
|
- name: Include invitation stage configuration
|
||||||
|
include_tasks: invitation.yml
|
||||||
|
when: authentik_bootstrap | default(true)
|
||||||
|
tags: ['authentik', 'invitation']
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue