Initial work on PAM config. Has issues, deploy with care
This commit is contained in:
commit
bd86a9e1f9
3
ansible.cfg
Normal file
3
ansible.cfg
Normal file
@ -0,0 +1,3 @@
|
||||
[defaults]
|
||||
inventory = inventory
|
||||
host_key_checking = False
|
||||
8
group_vars/all.yml
Normal file
8
group_vars/all.yml
Normal file
@ -0,0 +1,8 @@
|
||||
---
|
||||
|
||||
# Default user source. Overridden in other groups.
|
||||
user_source: "local"
|
||||
|
||||
kanidm_uri: "https://idm.ezri.dev"
|
||||
|
||||
kanidm_supplemental: []
|
||||
5
group_vars/desktop.yml
Normal file
5
group_vars/desktop.yml
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
|
||||
user_source: "kanidm-native"
|
||||
|
||||
allowed_groups: "{{ [ 'desktop_users' ] }}"
|
||||
15
inventory
Normal file
15
inventory
Normal file
@ -0,0 +1,15 @@
|
||||
; -*-conf-windows-*-
|
||||
|
||||
[container_runners]
|
||||
horizon.servers.ezri.dev
|
||||
|
||||
[kanidm_native]
|
||||
normandy.network.ezri.dev
|
||||
tycho.vpn.ezri.dev
|
||||
rocinante.vpn.ezri.dev
|
||||
serenity.wlan.ezri.dev
|
||||
|
||||
[desktop]
|
||||
;normandy ansible_connection=ssh ansible_become=true
|
||||
serenity ansible_connection=ssh ansible_become=true
|
||||
|
||||
8
playbooks/deploy-desktop.yml
Normal file
8
playbooks/deploy-desktop.yml
Normal file
@ -0,0 +1,8 @@
|
||||
---
|
||||
|
||||
- name: Configure desktop systems
|
||||
hosts: desktop
|
||||
roles:
|
||||
- aur
|
||||
- kanidm_native
|
||||
- 2fa
|
||||
6
playbooks/deploy-kanidm-native.yml
Normal file
6
playbooks/deploy-kanidm-native.yml
Normal file
@ -0,0 +1,6 @@
|
||||
---
|
||||
|
||||
- name: Kanidm native unixd clients
|
||||
hosts: kanidm_native
|
||||
roles:
|
||||
- kanidm_native
|
||||
8
playbooks/roles/2fa/files/common-account
Normal file
8
playbooks/roles/2fa/files/common-account
Normal file
@ -0,0 +1,8 @@
|
||||
#%PAM-1.0 -*- mode: conf-space; tab-width: 10 -*-
|
||||
|
||||
-account [success=2 default=ignore] pam_systemd_home.so
|
||||
account [success=1 default=ignore] pam_unix.so
|
||||
# If any of the above account lines fail, they'll jump here, which kills the authorization attempt.
|
||||
account [default=die] pam_deny.so
|
||||
account optional pam_permit.so
|
||||
account required pam_time.so
|
||||
7
playbooks/roles/2fa/files/common-auth
Normal file
7
playbooks/roles/2fa/files/common-auth
Normal file
@ -0,0 +1,7 @@
|
||||
#%PAM-1.0 -*- mode: conf-space; tab-width: 8 -*-
|
||||
|
||||
auth include first-factor
|
||||
auth include second-factor
|
||||
auth optional pam_permit.so
|
||||
auth required pam_env.so
|
||||
auth required pam_faillock.so authsucc
|
||||
6
playbooks/roles/2fa/files/common-password
Normal file
6
playbooks/roles/2fa/files/common-password
Normal file
@ -0,0 +1,6 @@
|
||||
#%PAM-1.0 -*- mode: conf-space; tab-width: 10 -*-
|
||||
|
||||
-password [success=2 default=ignore] pam_systemd_home.so
|
||||
password [success=1 default=ignore] pam_unix.so try_first_pass nullok shadow sha512
|
||||
password [default=die] pam_deny.so
|
||||
password optional pam_permit.so
|
||||
6
playbooks/roles/2fa/files/common-session
Normal file
6
playbooks/roles/2fa/files/common-session
Normal file
@ -0,0 +1,6 @@
|
||||
#%PAM-1.0 -*- mode: conf-space; tab-width: 10 -*-
|
||||
|
||||
session required pam_limits.so
|
||||
session [success=1 default=ignore] pam_unix.so
|
||||
session [default=die] pam_deny.so
|
||||
session optional pam_permit.so
|
||||
6
playbooks/roles/2fa/files/first-factor
Normal file
6
playbooks/roles/2fa/files/first-factor
Normal file
@ -0,0 +1,6 @@
|
||||
#%PAM-1.0 -*- mode: conf-space; tab-width: 8 -*-
|
||||
|
||||
auth requisite pam_faillock.so preauth
|
||||
auth [success=2 default=ignore] pam_unix.so try_first_pass nullok
|
||||
-auth [success=1 default=ignore] pam_systemd_home.so
|
||||
auth [default=die] pam_faillock.so authfail
|
||||
2
playbooks/roles/2fa/files/remote-switch.access.conf
Normal file
2
playbooks/roles/2fa/files/remote-switch.access.conf
Normal file
@ -0,0 +1,2 @@
|
||||
+:ALL:LOCAL
|
||||
-:ALL:ALL
|
||||
6
playbooks/roles/2fa/files/system-auth
Normal file
6
playbooks/roles/2fa/files/system-auth
Normal file
@ -0,0 +1,6 @@
|
||||
#%PAM-1.0 -*- mode: conf-space; tab-width: 10 -*-
|
||||
|
||||
auth include common-auth
|
||||
account include common-account
|
||||
password include common-password
|
||||
session include common-session
|
||||
74
playbooks/roles/2fa/tasks/main.yml
Normal file
74
playbooks/roles/2fa/tasks/main.yml
Normal file
@ -0,0 +1,74 @@
|
||||
---
|
||||
|
||||
- name: 'Install TOTP authenticator and pam_u2f'
|
||||
ansible.builtin.apt:
|
||||
name:
|
||||
- libpam-google-authenticator
|
||||
- libpam-u2f
|
||||
- pamu2fcfg
|
||||
state: present
|
||||
when: ansible_pkg_mgr == "apt"
|
||||
|
||||
- name: 'Install TOTP authenticator'
|
||||
community.general.pacman:
|
||||
name:
|
||||
- libpam-google-authenticator
|
||||
- pam-u2f
|
||||
state: present
|
||||
when: ansible_pkg_mgr == "pacman"
|
||||
|
||||
- name: 'Deploy PAM remote-user allowlist'
|
||||
ansible.builtin.copy:
|
||||
src: remote-switch.access.conf
|
||||
dest: /etc/security/remote-switch.access.conf
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0644"
|
||||
|
||||
- name: 'Deploy local-users first auth factor'
|
||||
ansible.builtin.copy:
|
||||
src: first-factor
|
||||
dest: /etc/pam.d/first-factor
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0644"
|
||||
# Only deploy when we're not using Kanidm for native or ldap
|
||||
when: user_source == "local"
|
||||
|
||||
- name: 'Deploy local-access second auth factor'
|
||||
ansible.builtin.template:
|
||||
src: second-factor.j2
|
||||
dest: /etc/pam.d/second-factor
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0644"
|
||||
|
||||
- name: 'Deploy PAM common-auth file'
|
||||
ansible.builtin.copy:
|
||||
src: common-auth
|
||||
dest: /etc/pam.d/
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0644"
|
||||
|
||||
- name: 'Deploy PAM system-auth file'
|
||||
ansible.builtin.copy:
|
||||
src: system-auth
|
||||
dest: /etc/pam.d/
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0644"
|
||||
when: ansible_os_family == "Archlinux"
|
||||
|
||||
- name: 'Deploy local-users common PAM files'
|
||||
ansible.builtin.copy:
|
||||
src: 'common-{{ item }}'
|
||||
dest: '/etc/pam.d/'
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0644"
|
||||
when: user_source == "local"
|
||||
with_items:
|
||||
- password
|
||||
- session
|
||||
- account
|
||||
11
playbooks/roles/2fa/templates/second-factor.j2
Normal file
11
playbooks/roles/2fa/templates/second-factor.j2
Normal file
@ -0,0 +1,11 @@
|
||||
#%PAM-1.0 -*- mode: conf-space; tab-width: 8 -*-
|
||||
|
||||
# Only prompt for security key if this is a local session.
|
||||
auth [success=ignore default=2] pam_access.so accessfile=/etc/security/remote-switch.access.conf
|
||||
auth [success=2 default=ignore] pam_u2f.so cue origin=pam://{{ ansible_nodename }} appid=pam://{{ ansible_nodename }} userpresence=1
|
||||
# This is a moderate security risk due to the nullok, but the alternative is locking ourselves out of remote machines.
|
||||
# This turns 2FA into an opt-in system.
|
||||
auth [success=1 default=ignore] pam_google_authenticator.so nullok
|
||||
# We could change this to 'pam_faillock.so authfail', but idk that that's worth it.
|
||||
auth [default=die] pam_deny.so
|
||||
auth optional pam_permit.so
|
||||
42
playbooks/roles/aur/tasks/main.yml
Normal file
42
playbooks/roles/aur/tasks/main.yml
Normal file
@ -0,0 +1,42 @@
|
||||
---
|
||||
|
||||
- name: Install devel packages
|
||||
community.general.pacman:
|
||||
name:
|
||||
- 'base-devel'
|
||||
- 'git'
|
||||
when: ansible_pkg_mgr == "pacman"
|
||||
|
||||
- name: Disable package compression
|
||||
ansible.builtin.replace:
|
||||
path: '/etc/makepkg.conf'
|
||||
regexp: "^PKGEXT=.*$"
|
||||
replace: "PKGEXT='.pkg.tar'"
|
||||
|
||||
- name: Create AUR build user
|
||||
ansible.builtin.user:
|
||||
name: aur_builder
|
||||
system: yes
|
||||
home: /var/lib/pacman/aur/
|
||||
password_lock: yes
|
||||
shell: /usr/bin/false
|
||||
when: ansible_pkg_mgr == "pacman"
|
||||
|
||||
- name: Allow AUR build user to run Pacman as root
|
||||
ansible.builtin.lineinfile:
|
||||
path: /etc/sudoers.d/aur_builder-allow-to-sudo-pacman
|
||||
state: present
|
||||
line: "aur_builder ALL=(ALL) NOPASSWD: /usr/bin/pacman"
|
||||
validate: /usr/sbin/visudo -cf %s
|
||||
create: yes
|
||||
when: ansible_pkg_mgr == "pacman"
|
||||
|
||||
- name: Install AUR helper using makepkg
|
||||
kewlfft.aur.aur:
|
||||
name: paru-bin
|
||||
use: makepkg
|
||||
state: present
|
||||
become: yes
|
||||
become_user: aur_builder
|
||||
when: ansible_pkg_mgr == "pacman"
|
||||
|
||||
12
playbooks/roles/kanidm_native/files/common-account
Normal file
12
playbooks/roles/kanidm_native/files/common-account
Normal file
@ -0,0 +1,12 @@
|
||||
#%PAM-1.0 -*- mode: conf-space; tab-width: 10 -*-
|
||||
|
||||
# Local users don't authenticate with Kanidm
|
||||
account [success=1 default=ignore] pam_localuser.so
|
||||
# When Kanidm fails, jump straight to the deny line. We already know we're not a local user, so this is fine.
|
||||
account [success=3 default=2] pam_kanidm.so
|
||||
-account [success=2 default=ignore] pam_systemd_home.so
|
||||
account [success=1 default=ignore] pam_unix.so
|
||||
# If any of the above account lines fail, they'll jump here, which kills the authorization attempt.
|
||||
account [default=die] pam_deny.so
|
||||
account optional pam_permit.so
|
||||
account required pam_time.so
|
||||
8
playbooks/roles/kanidm_native/files/common-password
Normal file
8
playbooks/roles/kanidm_native/files/common-password
Normal file
@ -0,0 +1,8 @@
|
||||
#%PAM-1.0 -*- mode: conf-space; tab-width: 10 -*-
|
||||
|
||||
password [success=1 default=ignore] pam_localuser.so
|
||||
password [success=3 default=2] pam_kanidm.so
|
||||
-password [success=2 default=ignore] pam_systemd_home.so
|
||||
password [success=1 default=ignore] pam_unix.so try_first_pass nullok shadow sha512
|
||||
password [default=die] pam_deny.so
|
||||
password optional pam_permit.so
|
||||
7
playbooks/roles/kanidm_native/files/common-session
Normal file
7
playbooks/roles/kanidm_native/files/common-session
Normal file
@ -0,0 +1,7 @@
|
||||
#%PAM-1.0 -*- mode: conf-space; tab-width: 10 -*-
|
||||
|
||||
session required pam_limits.so
|
||||
session optional pam_unix.so
|
||||
session optional pam_umask.so
|
||||
session optional pam_kanidm.so
|
||||
session optional pam_env.so
|
||||
11
playbooks/roles/kanidm_native/files/first-factor
Normal file
11
playbooks/roles/kanidm_native/files/first-factor
Normal file
@ -0,0 +1,11 @@
|
||||
#%PAM-1.0 -*- mode: conf-space; tab-width: 8 -*-
|
||||
|
||||
# First authentication factor for Kanidm-native systems
|
||||
|
||||
auth requisite pam_faillock.so preauth
|
||||
auth [success=1 default=ignore] pam_localuser.so
|
||||
auth [success=3 default=2] pam_kanidm.so
|
||||
auth [sucesss=2 default=ignore] pam_unix.so try_first_pass nullok
|
||||
-auth [success=1 default=ignore] pam_systemd_home.so
|
||||
auth [default=die] pam_faillock.so authfail
|
||||
auth optional pam_permit.so
|
||||
10
playbooks/roles/kanidm_native/files/kanidm-hack.sh
Normal file
10
playbooks/roles/kanidm_native/files/kanidm-hack.sh
Normal file
@ -0,0 +1,10 @@
|
||||
#!/bin/bash
|
||||
|
||||
# This script is called by systemd-sleep, and is used to prevent the
|
||||
# daemon from getting stuck when resuming from sleep.
|
||||
# Only noticed so far on resume from hibernate, but it's possible that
|
||||
# it could happen on suspend as well.
|
||||
|
||||
if [[ $1 == "post" ]]; then
|
||||
systemctl restart kanidm-unixd.service
|
||||
fi
|
||||
6
playbooks/roles/kanidm_native/handlers/main.yml
Normal file
6
playbooks/roles/kanidm_native/handlers/main.yml
Normal file
@ -0,0 +1,6 @@
|
||||
---
|
||||
|
||||
- name: Restart SSH
|
||||
ansible.builtin.systemd:
|
||||
unit: "sshd.service"
|
||||
state: "restarted"
|
||||
109
playbooks/roles/kanidm_native/tasks/main.yml
Normal file
109
playbooks/roles/kanidm_native/tasks/main.yml
Normal file
@ -0,0 +1,109 @@
|
||||
---
|
||||
|
||||
- name: 'Install kanidm clients with pacman'
|
||||
kewlfft.aur.aur:
|
||||
use: paru
|
||||
aur_only: yes
|
||||
name: kanidm-unixd-clients
|
||||
become: yes
|
||||
become_user: aur_builder
|
||||
when: ansible_pkg_mgr == "pacman"
|
||||
|
||||
- name: 'Fetch kanidm PPA key'
|
||||
ansible.builtin.apt_key:
|
||||
url: >-
|
||||
https://kanidm.github.io/kanidm_ppa/KEY.gpg
|
||||
state: present
|
||||
id: 'EA20E95D68A65191FE8CE79576CC814060B23E66'
|
||||
when: ansible_pkg_mgr == "apt"
|
||||
|
||||
- name: 'Create kanidm PPA'
|
||||
ansible.builtin.apt_repository:
|
||||
repo: >-
|
||||
deb https://kanidm.github.io/kanidm_ppa/{{ ansible_distribution | lower }} ./
|
||||
state: present
|
||||
when: ansible_pkg_mgr == "apt"
|
||||
|
||||
- name: 'Install kanidm with apt'
|
||||
ansible.builtin.apt:
|
||||
name: kanidm-unixd-clients
|
||||
state: present
|
||||
update_cache: yes
|
||||
when: ansible_pkg_mgr == "apt"
|
||||
|
||||
- name: 'Ensure kanidm config directory exists'
|
||||
ansible.builtin.file:
|
||||
path: /etc/kanidm
|
||||
state: directory
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0755"
|
||||
|
||||
- name: 'Install kanidm config files'
|
||||
ansible.builtin.template:
|
||||
src: '{{ item }}.j2'
|
||||
dest: '/etc/kanidm/{{ item }}'
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0644"
|
||||
with_items:
|
||||
- unixd
|
||||
- config
|
||||
|
||||
- name: 'Enable kanidm daemons'
|
||||
ansible.builtin.systemd_service:
|
||||
state: started
|
||||
enabled: yes
|
||||
name: "{{ item }}"
|
||||
daemon_reload: yes
|
||||
with_items:
|
||||
- kanidm-unixd
|
||||
- kanidm-unixd-tasks
|
||||
|
||||
|
||||
- name: 'Enable kanidm as a passwd db'
|
||||
ansible.builtin.replace:
|
||||
path: '/etc/nsswitch.conf'
|
||||
regexp: "^{{ item }}:.*$"
|
||||
replace: "{{ item }}: files {{ (item == 'group') | ternary('[SUCCESS=merge]', '') }} systemd compat kanidm"
|
||||
# This is a critical system file that could brick the OS. Back it up!
|
||||
backup: yes
|
||||
with_items:
|
||||
- passwd
|
||||
- group
|
||||
|
||||
- name: 'Deploy first-factor PAM configuration'
|
||||
ansible.builtin.copy:
|
||||
src: first-factor
|
||||
dest: /etc/pam.d/first-factor
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0644"
|
||||
|
||||
- name: 'Deploy common PAM modules for kanidm'
|
||||
ansible.builtin.copy:
|
||||
src: '{{ item }}'
|
||||
dest: /etc/pam.d/
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0644"
|
||||
with_fileglob:
|
||||
- "../files/common-*"
|
||||
|
||||
- name: 'Deploy SSH key handling'
|
||||
ansible.builtin.template:
|
||||
src: 10-kanidm-keys.conf.j2
|
||||
dest: /etc/ssh/sshd_config.d/
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0644"
|
||||
notify: Restart SSH
|
||||
|
||||
- name: 'Deploy sleep fix hack'
|
||||
ansible.builtin.copy:
|
||||
src: kanidm-hack.sh
|
||||
dest: /usr/lib/systemd/system-sleep/
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0755"
|
||||
|
||||
@ -0,0 +1,6 @@
|
||||
PubkeyAuthentication yes
|
||||
UsePAM yes
|
||||
|
||||
Match Group {{ allowed_groups | join(',') }}
|
||||
AuthorizedKeysCommand /usr/sbin/kanidm_ssh_authorizedkeys %u
|
||||
AuthorizedKeysCommandUser nobody
|
||||
8
playbooks/roles/kanidm_native/templates/config.j2
Normal file
8
playbooks/roles/kanidm_native/templates/config.j2
Normal file
@ -0,0 +1,8 @@
|
||||
uri = "{{ kanidm_uri }}"
|
||||
verify_ca = true
|
||||
verify_hostnames = true
|
||||
|
||||
{% for name, uri in kanidm_supplemental %}
|
||||
[{{ name }}]
|
||||
uri = "{{ uri }}"
|
||||
{% endfor %}
|
||||
11
playbooks/roles/kanidm_native/templates/unixd.j2
Normal file
11
playbooks/roles/kanidm_native/templates/unixd.j2
Normal file
@ -0,0 +1,11 @@
|
||||
# -*-conf-unix-*-
|
||||
|
||||
pam_allowed_login_groups = {{ allowed_groups }}
|
||||
default_shell = "/bin/bash"
|
||||
home_attr = "uuid"
|
||||
home_alias = "name"
|
||||
use_etc_skel = true
|
||||
# Just use name for usernames, it shouldn't be too hard to keep track of
|
||||
uid_attr_map = "name"
|
||||
# Use the SPN for groups, so we can easily tell which are local and which are remote
|
||||
gid_attr_map = "spn"
|
||||
6
requirements.yml
Normal file
6
requirements.yml
Normal file
@ -0,0 +1,6 @@
|
||||
---
|
||||
collections:
|
||||
- name: >-
|
||||
kewlfft.aur
|
||||
- name: >-
|
||||
community.general
|
||||
Loading…
x
Reference in New Issue
Block a user