Merge branch 'ansible-lane'
This commit is contained in:
76
ansible-role/README.md
Normal file
76
ansible-role/README.md
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
# dangerousthings.authforge
|
||||||
|
|
||||||
|
Ansible role that installs and configures [AuthForge](https://github.com/dangerousthings/authforge),
|
||||||
|
the FIDO2 / U2F / TOTP MFA stack for Ubuntu, on fleet hosts.
|
||||||
|
|
||||||
|
The role:
|
||||||
|
|
||||||
|
1. Adds the `ppa:dangerousthings/authforge` PPA.
|
||||||
|
2. Installs `authforge-daemon`, `authforge-pam`, and `authforge-cli` (and
|
||||||
|
optionally `authforge-gui` for desktop fleets).
|
||||||
|
3. Renders a TOML fleet policy file at `/etc/authforge/policy.d/90-fleet.conf`
|
||||||
|
from your variables.
|
||||||
|
4. Restarts `authforge-daemon.service` whenever the policy file changes.
|
||||||
|
5. Seeds first-login pending-enrollment flags via `authforgectl pending set`.
|
||||||
|
|
||||||
|
The role talks to AuthForge exclusively through `authforgectl` and the
|
||||||
|
documented config-file shape - it does not touch daemon state directly.
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
- Target host: Ubuntu 22.04 (jammy) or 24.04 (noble).
|
||||||
|
- Control host: Ansible 2.14 or newer.
|
||||||
|
- The host must be able to reach `ppa.launchpad.net` (or your internal
|
||||||
|
mirror - override `authforge_ppa` to point at it).
|
||||||
|
|
||||||
|
## Role variables
|
||||||
|
|
||||||
|
All variables and their defaults live in `defaults/main.yml`.
|
||||||
|
|
||||||
|
| Variable | Default | Description |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `authforge_install_gui` | `false` | Also install the `authforge-gui` package (only useful on desktop fleets). |
|
||||||
|
| `authforge_ppa` | `ppa:dangerousthings/authforge` | Source PPA. Override to use an internal mirror. |
|
||||||
|
| `authforge_stacks` | `{}` | Map of PAM stack name to `{ mode, methods }`. `mode` is one of `disabled`, `optional`, `required`. `methods` is a list e.g. `["fido2", "totp"]`. |
|
||||||
|
| `authforge_storage_backend` | `per-user` | Credential storage backend. `per-user` writes under each user's home; `central` uses `authforge_storage_central_path`. |
|
||||||
|
| `authforge_storage_central_path` | `""` | Path for the central storage backend. Ignored when `authforge_storage_backend` is `per-user`. |
|
||||||
|
| `authforge_firstrun_methods` | `["fido2"]` | Methods accepted during first-login enrollment. |
|
||||||
|
| `authforge_firstrun_deadline_hours` | `0` | Hours before an unenrolled pending user is locked out. `0` disables the deadline. |
|
||||||
|
| `authforge_pending_users` | `[]` | List of `{ user, methods }` to mark as pending-enrollment. |
|
||||||
|
|
||||||
|
## Example playbook
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- hosts: workstations
|
||||||
|
become: true
|
||||||
|
roles:
|
||||||
|
- role: dangerousthings.authforge
|
||||||
|
vars:
|
||||||
|
authforge_stacks:
|
||||||
|
sudo:
|
||||||
|
mode: required
|
||||||
|
methods: [fido2]
|
||||||
|
sshd:
|
||||||
|
mode: optional
|
||||||
|
methods: [fido2, totp]
|
||||||
|
authforge_pending_users:
|
||||||
|
- user: alice
|
||||||
|
methods: [fido2]
|
||||||
|
```
|
||||||
|
|
||||||
|
A runnable copy lives at `examples/playbook.yml`.
|
||||||
|
|
||||||
|
## Idempotence notes
|
||||||
|
|
||||||
|
- The `apt_repository`, `apt`, `template`, and `file` tasks are all
|
||||||
|
idempotent; only the `authforgectl pending set` loop is forced to
|
||||||
|
`changed_when: true` because the CLI does not currently expose a clean
|
||||||
|
"is this user already pending?" check that's cheap to call from Ansible.
|
||||||
|
Running `pending set` against an already-pending user is a no-op on
|
||||||
|
the daemon side.
|
||||||
|
- The handler restarts `authforge-daemon` only when the policy file
|
||||||
|
contents actually change.
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
Apache-2.0. Same as the rest of AuthForge.
|
||||||
31
ansible-role/defaults/main.yml
Normal file
31
ansible-role/defaults/main.yml
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
---
|
||||||
|
# Whether to additionally pull the GUI package. Headless fleets should leave
|
||||||
|
# this off; desktop fleets that want the AuthForge settings panel can flip it.
|
||||||
|
authforge_install_gui: false
|
||||||
|
|
||||||
|
# PPA to install from. Override if you mirror packages internally.
|
||||||
|
authforge_ppa: "ppa:dangerousthings/authforge"
|
||||||
|
|
||||||
|
# Map of stack name -> { mode, methods }. mode is one of
|
||||||
|
# "disabled" | "optional" | "required". methods is a list e.g. ["fido2", "totp"].
|
||||||
|
# Default is empty so the role can be applied for "install only" runs.
|
||||||
|
authforge_stacks: {}
|
||||||
|
|
||||||
|
# Credential storage backend. "per-user" stores credentials under each user's
|
||||||
|
# home directory; "central" stores them at authforge_storage_central_path so
|
||||||
|
# they survive home-directory wipes (e.g. AD-managed boxes).
|
||||||
|
authforge_storage_backend: "per-user"
|
||||||
|
authforge_storage_central_path: ""
|
||||||
|
|
||||||
|
# First-login enforcement. Users who exist in the pending list will be required
|
||||||
|
# to enroll one of these methods on their next interactive login.
|
||||||
|
authforge_firstrun_methods:
|
||||||
|
- "fido2"
|
||||||
|
|
||||||
|
# How long after the pending flag is set before the user is locked out if they
|
||||||
|
# have not enrolled. 0 means no deadline (warn forever).
|
||||||
|
authforge_firstrun_deadline_hours: 0
|
||||||
|
|
||||||
|
# Users to mark as pending-enrollment via `authforgectl pending set`.
|
||||||
|
# Each entry: { user: "alice", methods: ["fido2"] }.
|
||||||
|
authforge_pending_users: []
|
||||||
31
ansible-role/examples/playbook.yml
Normal file
31
ansible-role/examples/playbook.yml
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
---
|
||||||
|
# Example playbook that applies the dangerousthings.authforge role to a
|
||||||
|
# fleet of headless Ubuntu workstations.
|
||||||
|
#
|
||||||
|
# Run from the parent of this `ansible-role/` directory with:
|
||||||
|
#
|
||||||
|
# ansible-playbook -i inventory ansible-role/examples/playbook.yml
|
||||||
|
#
|
||||||
|
# (You'll need the role linked into your roles_path, or to install it from
|
||||||
|
# Galaxy as `dangerousthings.authforge`.)
|
||||||
|
|
||||||
|
- name: Roll out AuthForge to engineering workstations
|
||||||
|
hosts: workstations
|
||||||
|
become: true
|
||||||
|
roles:
|
||||||
|
- role: dangerousthings.authforge
|
||||||
|
vars:
|
||||||
|
authforge_install_gui: false
|
||||||
|
authforge_stacks:
|
||||||
|
sudo:
|
||||||
|
mode: required
|
||||||
|
methods:
|
||||||
|
- fido2
|
||||||
|
authforge_storage_backend: per-user
|
||||||
|
authforge_firstrun_methods:
|
||||||
|
- fido2
|
||||||
|
authforge_firstrun_deadline_hours: 72
|
||||||
|
authforge_pending_users:
|
||||||
|
- user: alice
|
||||||
|
methods:
|
||||||
|
- fido2
|
||||||
5
ansible-role/handlers/main.yml
Normal file
5
ansible-role/handlers/main.yml
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
- name: restart authforge-daemon
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: authforge-daemon
|
||||||
|
state: restarted
|
||||||
30
ansible-role/meta/main.yml
Normal file
30
ansible-role/meta/main.yml
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
---
|
||||||
|
galaxy_info:
|
||||||
|
role_name: authforge
|
||||||
|
namespace: dangerousthings
|
||||||
|
author: Dangerous Things
|
||||||
|
description: >
|
||||||
|
Install and configure AuthForge (FIDO2 / U2F / TOTP MFA for Ubuntu) on
|
||||||
|
fleet hosts. Adds the project PPA, installs the headless component
|
||||||
|
packages, drops a fleet policy file, and seeds first-login pending
|
||||||
|
enrollment flags.
|
||||||
|
license: Apache-2.0
|
||||||
|
min_ansible_version: "2.14"
|
||||||
|
|
||||||
|
platforms:
|
||||||
|
- name: Ubuntu
|
||||||
|
versions:
|
||||||
|
- jammy
|
||||||
|
- noble
|
||||||
|
|
||||||
|
galaxy_tags:
|
||||||
|
- authforge
|
||||||
|
- mfa
|
||||||
|
- fido2
|
||||||
|
- u2f
|
||||||
|
- totp
|
||||||
|
- pam
|
||||||
|
- security
|
||||||
|
- ubuntu
|
||||||
|
|
||||||
|
dependencies: []
|
||||||
52
ansible-role/tasks/main.yml
Normal file
52
ansible-role/tasks/main.yml
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
---
|
||||||
|
- name: Add the AuthForge PPA
|
||||||
|
ansible.builtin.apt_repository:
|
||||||
|
repo: "{{ authforge_ppa }}"
|
||||||
|
state: present
|
||||||
|
update_cache: true
|
||||||
|
|
||||||
|
- name: Install AuthForge headless components
|
||||||
|
ansible.builtin.apt:
|
||||||
|
name:
|
||||||
|
- authforge-daemon
|
||||||
|
- authforge-pam
|
||||||
|
- authforge-cli
|
||||||
|
state: present
|
||||||
|
update_cache: true
|
||||||
|
|
||||||
|
- name: Install AuthForge GUI (optional)
|
||||||
|
ansible.builtin.apt:
|
||||||
|
name: authforge-gui
|
||||||
|
state: present
|
||||||
|
when: authforge_install_gui | bool
|
||||||
|
|
||||||
|
- name: Ensure /etc/authforge/policy.d exists
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: /etc/authforge/policy.d
|
||||||
|
state: directory
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: "0755"
|
||||||
|
|
||||||
|
- name: Render fleet policy file
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: policy.conf.j2
|
||||||
|
dest: /etc/authforge/policy.d/90-fleet.conf
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: "0644"
|
||||||
|
notify: restart authforge-daemon
|
||||||
|
|
||||||
|
- name: Mark users as pending-enrollment
|
||||||
|
ansible.builtin.command:
|
||||||
|
argv:
|
||||||
|
- authforgectl
|
||||||
|
- pending
|
||||||
|
- set
|
||||||
|
- "{{ item.user }}"
|
||||||
|
- --methods
|
||||||
|
- "{{ item.methods | join(',') }}"
|
||||||
|
loop: "{{ authforge_pending_users }}"
|
||||||
|
loop_control:
|
||||||
|
label: "{{ item.user }}"
|
||||||
|
changed_when: true
|
||||||
18
ansible-role/templates/policy.conf.j2
Normal file
18
ansible-role/templates/policy.conf.j2
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# {{ ansible_managed }}
|
||||||
|
# Fleet-managed AuthForge policy. Hand-edits will be overwritten on the next
|
||||||
|
# Ansible run. To override locally, drop a higher-numbered file in
|
||||||
|
# /etc/authforge/policy.d/ (e.g. 99-local.conf).
|
||||||
|
|
||||||
|
{% for stack, cfg in authforge_stacks.items() %}
|
||||||
|
[stacks.{{ stack }}]
|
||||||
|
mode = "{{ cfg.mode }}"
|
||||||
|
methods = {{ cfg.methods | to_json }}
|
||||||
|
|
||||||
|
{% endfor %}
|
||||||
|
[storage]
|
||||||
|
backend = "{{ authforge_storage_backend }}"
|
||||||
|
central_path = "{{ authforge_storage_central_path }}"
|
||||||
|
|
||||||
|
[firstrun]
|
||||||
|
default_required_methods = {{ authforge_firstrun_methods | to_json }}
|
||||||
|
deadline_hours = {{ authforge_firstrun_deadline_hours }}
|
||||||
Reference in New Issue
Block a user