Bulk update for roles for homelab

This commit is contained in:
Ezri Brimhall 2024-10-01 18:54:14 -06:00
parent db2918ef1b
commit dd803b2d1d
Signed by: ezri
GPG Key ID: 3DA1675C4E9B9216
27 changed files with 388 additions and 34 deletions

View File

@ -12,6 +12,7 @@
path: '/etc/makepkg.conf' path: '/etc/makepkg.conf'
regexp: "^PKGEXT=.*$" regexp: "^PKGEXT=.*$"
replace: "PKGEXT='.pkg.tar'" replace: "PKGEXT='.pkg.tar'"
when: ansible_pkg_mgr == "pacman"
- name: Create AUR build user - name: Create AUR build user
ansible.builtin.user: ansible.builtin.user:

View File

@ -0,0 +1,14 @@
---
- name: Update packages
community.general.pacman:
update_cache: yes
upgrade: yes
- name: Install packages
ansible.builtin.pacman:
name:
- ufw
- base-devel
- wget
state: present

View File

@ -1,5 +1,11 @@
--- ---
- name: Create wheel group
ansible.builtin.group:
name: wheel
state: present
system: yes
- name: Create local administrator - name: Create local administrator
ansible.builtin.user: ansible.builtin.user:
state: present state: present
@ -9,7 +15,7 @@
- wheel - wheel
create_home: yes create_home: yes
# Salt the password with the inventory name, this should be static between runs # Salt the password with the inventory name, this should be static between runs
password: '{{ admin_password|password_hash("sha512", inventory_hostname) }}' password: '{{ admin_password|password_hash("sha512", "thisisabadsalt") }}'
- name: Load Arch tasks - name: Load Arch tasks
import_tasks: arch.yml import_tasks: arch.yml
@ -28,10 +34,8 @@
from: "{{ item }}" from: "{{ item }}"
- name: Start UFW - name: Start UFW
ansible.builtin.systemd_service: community.general.ufw:
name: ufw state: enabled
state: started
enabled: true
- name: Allow wheel to use sudo - name: Allow wheel to use sudo
ansible.builtin.copy: ansible.builtin.copy:

View File

@ -6,7 +6,7 @@ Include /etc/ssh/sshd_config.d/*.conf
Port {{ ssh_port|default(22) }} Port {{ ssh_port|default(22) }}
# If this is initial setup of a container (where we log in as root, so become is disabled), # If this is initial setup of a container (where we log in as root, so become is disabled),
# leave root login enabled so we can finish deploying everything. Otherwise, disable it. # leave root login enabled so we can finish deploying everything. Otherwise, disable it.
PermitRootLogin {{ ansible_become | ternary("yes", "no") }} PermitRootLogin {{ ansible_become|default(false) | ternary("yes", "no") }}
PubkeyAuthentication yes PubkeyAuthentication yes
PasswordAuthentication no PasswordAuthentication no

View File

@ -17,3 +17,9 @@
name: grafana name: grafana
state: present state: present
update_cache: yes update_cache: yes
- name: Build envfile
ansible.builtin.template:
src: grafana-server.j2
dest: /etc/default/grafana-server

View File

@ -25,4 +25,3 @@ PID_FILE_DIR=/run/grafana
GF_DEFAULT_INSTANCE_NAME={{ ansible_nodename }} GF_DEFAULT_INSTANCE_NAME={{ ansible_nodename }}

View File

@ -1,11 +1,10 @@
#%PAM-1.0 -*- mode: conf-space; tab-width: 8 -*- #%PAM-1.0 -*- mode: conf-space; tab-width: 8 -*-
# First authentication factor for Kanidm-native systems
auth requisite pam_faillock.so preauth auth requisite pam_faillock.so preauth
auth [success=1 default=ignore] pam_localuser.so auth [success=1 default=ignore] pam_localuser.so
auth [success=3 default=2] pam_kanidm.so auth [success=3 default=2] pam_kanidm.so
auth [sucesss=2 default=ignore] pam_unix.so try_first_pass nullok auth [sucesss=2 default=ignore] pam_unix.so try_first_pass nullok
-auth [success=1 default=ignore] pam_systemd_home.so -auth [success=1 default=ignore] pam_systemd_home.so
auth [default=die] pam_faillock.so authfail auth [default=die] pam_faillock.so authfail
auth optional pam_faillock.so authsucc
auth optional pam_permit.so auth optional pam_permit.so

View File

@ -62,38 +62,18 @@
- name: 'Enable kanidm as a passwd db' - name: 'Enable kanidm as a passwd db'
ansible.builtin.replace: ansible.builtin.lineinfile:
path: '/etc/nsswitch.conf' path: '/etc/nsswitch.conf'
regexp: "^{{ item }}:.*$" regexp: "^{{ item }}:.*$"
replace: "{{ item }}: files {{ (item == 'group') | ternary('[SUCCESS=merge]', '') }} systemd compat kanidm" line: "{{ item }}: files {{ (item == 'group') | ternary('[SUCCESS=merge]', '') }} kanidm"
# This is a critical system file that could brick the OS. Back it up!
backup: yes
with_items: with_items:
- passwd - passwd
- group - 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' - name: 'Deploy SSH key handling'
ansible.builtin.template: ansible.builtin.template:
src: 10-kanidm-keys.conf.j2 src: 10-kanidm-keys.conf.j2
dest: /etc/ssh/sshd_config.d/ dest: /etc/ssh/sshd_config.d/10-kanidm-keys.conf
owner: root owner: root
group: root group: root
mode: "0644" mode: "0644"

View File

@ -0,0 +1,57 @@
---
- name: 'Install sssd with pacman'
community.general.pacman:
name: sssd
state: present
when: ansible_pkg_mgr == "pacman"
- name: 'Install sssd with apt'
ansible.builtin.apt:
name: sssd
state: present
when: ansible_pkg_mgr == "apt"
- name: 'Build sssd config'
ansible.builtin.template:
src: sssd.conf.j2
dest: /etc/sssd/sssd.conf
owner: root
group: root
mode: "0600"
- name: 'Enable SSSD'
ansible.builtin.systemd_service:
name: sssd.service
state: started
enabled: yes
- name: 'Enable SSSD as a passwd db'
ansible.builtin.lineinfile:
path: '/etc/nsswitch.conf'
regexp: '^passwd:.*$'
line: 'passwd: files sss'
- name: 'Enable SSSD as a group db'
ansible.builtin.lineinfile:
path: '/etc/nsswitch.conf'
regexp: '^group:.*$'
line: 'group: files [SUCCESS=merge] sss'
- name: 'Deploy SSH key handling'
ansible.builtin.template:
src: 10-kanidm-keys.conf.j2
dest: /etc/ssh/sshd_config.d/10-kanidm-keys.conf
owner: root
group: root
mode: "0644"
notify: Restart SSH
- name: 'Allow sudo for authorized groups'
ansible.builtin.template:
src: sso_admins.conf.j2
dest: /etc/sudoers.d/10-sso
validate: /usr/sbin/visudo -cf %s
mode: "0440"
owner: root
group: root

View File

@ -0,0 +1,6 @@
PubkeyAuthentication yes
UsePAM yes
Match Group {{ allowed_groups | join(',') }}
AuthorizedKeysCommand /usr/local/bin/sss_ssh_authorizedkeys %u
AuthorizedKeysCommandUser nobody

View File

@ -0,0 +1,18 @@
#!/bin/bash
# This script retrieves SSH keys from LDAP for the passed username
# and prints them to stdout. Intended to be used as the
# AuthorizedKeysCommand in sshd_config.
# Usage: ldap-ssh-authorizedkeys.sh <username>
sshkey_attr="{{ sshkey_attr | default('ssh_publickey') }}"
# user_attr should probably be either 'cn' or 'spn' depending on which attribute
# is used for username mapping on the system.
user_attr="{{ user_attr | default('cn') }}"
ldap_base="{{ ldap_search_base }}"
ldap_uri="{{ ldap_uri }}"
ldap_filter="(&(objectClass=posixAccount)($user_attr=$1))"
ldapsearch -o ldif-wrap=no -x -LLL -H "$ldap_uri" -b "$ldap_base" "$ldap_filter" "$sshkey_attr" | grep "^$sshkey_attr:" | cut -d' ' -f2-

View File

@ -0,0 +1,20 @@
#
# NSLCD.CONF(5)
#
uri {{ ldap_uri }}
base {{ ldap_search_base }}
ssl on
binddn {{ ldap_bind_dn }}
bindpw {{ secrets.ldap_bind_password }}
scope sub
timelimit 10
bind_timelimit 10
pam_password_prohibit_message "Password changes are not permitted for externally-managed users. To change your password, please visit {{ kanidm_uri }}/ui/profile."
map passwd homeDirectory "${homeDirectory:-{{ homedir_base | default('/home') }}/$uuid}"
map group memberUid member
filter user {{ ldap_user_filter }}
filter group (|(objectClass=posixAccount)(objectClass=posixGroup))
nss_min_uid 65536
nss_initgroups_ignoreusers ALLLOCAL

View File

@ -0,0 +1,9 @@
# -*-etc-sudoers-*-
{% for group in sudo_groups|default([]) %}
%{{ group }} ALL=(ALL:ALL) ALL
{% endfor %}
{% for user in sudo_users|default([]) %}
{{ user }} ALL=(ALL:ALL) ALL
{% endfor %}

View File

@ -0,0 +1,31 @@
[sssd]
services = nss, pam, ssh
config_file_version = 2
domains = ldap
[nss]
homedir_substring = /home
[domain/ldap]
id_provider = ldap
auth_provider = ldap
access_provider = ldap
chpass_provider = ldap
ldap_schema = rfc2307bis
ldap_search_base = {{ ldap_user_search_base }}
ldap_uri = {{ ldap_uri }}
ldap_group_object_class = object
ldap_group_search_base = {{ ldap_group_search_base }}
ldap_access_filter = {{ ldap_access_filter }}
override_homedir = /home/%U
ignore_group_members = True
cache_credentials = True
ldap_tls_cipher_suite = NORMAL:!VERS-TLS1.3

View File

@ -5,6 +5,14 @@
name: nginx name: nginx
state: present state: present
- name: Allow ports 80 and 443
loop:
- 80
- 443
community.general.ufw:
rule: allow
to_port: '{{ item }}'
- name: Create config directories - name: Create config directories
loop: loop:
- /etc/nginx - /etc/nginx
@ -60,15 +68,21 @@
- name: Enable stream configurations - name: Enable stream configurations
loop: '{{ streams_available }}' loop: '{{ streams_available }}'
when: item.enabled
ansible.builtin.file: ansible.builtin.file:
src: ../streams-available/{{ item.fqdn }}.conf src: ../streams-available/{{ item.fqdn }}.conf
dest: /etc/nginx/streams-enabled/{{ item.fqdn }}.conf dest: /etc/nginx/streams-enabled/{{ item.fqdn }}.conf
state: link state: '{{ item.enabled|ternary("link", "absent") }}'
owner: root owner: root
group: root group: root
notify: Reload nginx notify: Reload nginx
- name: Allow connections to enabled streams
loop: '{{ streams_available }}'
community.general.ufw:
rule: allow
to_port: '{{ item.listen_port }}'
delete: '{{ not item.enabled }}'
- name: Enable nginx - name: Enable nginx
ansible.builtin.systemd_service: ansible.builtin.systemd_service:
name: nginx name: nginx

View File

@ -33,6 +33,9 @@ server {
client_max_body_size {{ item.max_upload|default("1M") }}; client_max_body_size {{ item.max_upload|default("1M") }};
location / { location / {
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $http_connection;
proxy_http_version 1.1;
add_header X-Served-By $host; add_header X-Served-By $host;
proxy_set_header Host $host; proxy_set_header Host $host;
proxy_set_header X-Forwarded-Scheme $scheme; proxy_set_header X-Forwarded-Scheme $scheme;

View File

@ -0,0 +1,7 @@
---
uses_passkey_auth: no
uses_passkey_2fa: no
uses_totp_2fa: no
sso_type: null
totp_2fa_nullok: false

View File

@ -0,0 +1,11 @@
#%PAM-1.0 -*- mode: conf-space; tab-width: 10 -*-
account [success=2 default=ignore] pam_localuser.so
-account [success=4 ignore=ignore default=3] pam_kanidm.so
-account [success=3 ignore=ignore default=2] pam_ldap.so
-account [success=2 default=ignore] pam_systemd_home.so
account [success=1 default=ignore] pam_unix.so
account [default=die] pam_deny.so
account optional pam_permit.so
account required pam_time.so

View File

@ -0,0 +1,9 @@
#%PAM-1.0 -*- mode: conf-space; tab-width: 10 -*-
password [success=2 default=ignore] pam_localuser.so
-password [success=4 default=3] pam_kanidm.so
-password [sucesss=3 default=2] pam_ldap.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

View File

@ -0,0 +1,8 @@
#%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_ldap.so
session optional pam_env.so

View File

@ -0,0 +1,8 @@
---
- name: 'Install 2FA plugins'
community.general.pacman:
name:
- libpam-google-authenticator
- pam-u2f
state: present

View File

@ -0,0 +1,9 @@
---
- name: 'Install 2FA plugins'
ansible.builtin.apt:
name:
- libpam-google-authenticator
- libpam-u2f
- pamu2fcfg
state: present

View File

@ -0,0 +1,58 @@
---
- name: 'Install 2FA plugins for Arch'
ansible.builtin.include_tasks:
file: arch.yaml
when: ansible_os_family | lower == "archlinux"
- name: 'Install 2FA plugins for Debian'
ansible.builtin.include_tasks:
file: debian.yml
when: ansible_os_family | lower == "debian"
- name: 'Configure Kanidm Native'
ansible.builtin.import_role:
name: kanidm_native
when: sso_type == "native"
- name: 'Configure Kanidm via SSSD'
ansible.builtin.import_role:
name: kanidm_sssd
when: sso_type == "ldap"
- name: 'Compile passkey switch'
ansible.builtin.template:
src: passkey-users.access.conf.j2
dest: /etc/security/passkey-users.access.conf
owner: root
group: root
mode: "0644"
- name: 'Copy remote session switch'
ansible.builtin.copy:
src: remote-switch.access.conf
dest: /etc/security/remote-sqitch.access.conf
owner: root
group: root
mode: "0644"
- name: 'Compile common-auth'
ansible.builtin.template:
src: common-auth.j2
dest: /etc/pam.d/common-auth
owner: root
group: root
mode: "0644"
- name: 'Copy common PAM configs'
ansible.builtin.copy:
src: common-{{ item }}
dest: /etc/pam.d/
owner: root
group: root
mode: "0644"
loop:
- account
- password
- session

View File

@ -0,0 +1,43 @@
#%PAM-1.0 -*- mode: conf-space; tab-width: 10 -*-
auth requisite pam_faillock.so preauth
{% if uses_passkey_auth %}
auth [success=ignore default=6] pam_access.so accessfile=/etc/security/passkey-users.access.conf
auth [success=5 default=ignore] pam_rootok.so
auth [success=1 default=ignore] pam_u2f.so cue origin=pam://{{ ansible_nodename }} appid=pam://{{ ansible_nodename }} userpresence=0 pinverification=1
auth requisite pam_faillock.so authfail
auth optional pam_permit.so
auth required pam_env.so
auth required pam_faillock.so authsucc
{% endif %}
{% if sso_type == "native" %}
auth [success=1 default=ignore] pam_localuser.so
auth [success=3 default=2] pam_kanidm.so
{% elif sso_type == "ldap" %}
auth [success=1 default=ignore] pam_localuser.so
auth [success=3 default=2] pam_ldap.so try_first_pass
{% endif %}
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
{% if uses_passkey_2fa %}
auth [success=ignore default=4] pam_access.so accessfile=/etc/security/remote-switch.access.conf
auth [success=ok default=3] pam_u2f.so cue origin=pam://{{ ansible_nodename }} appid=pam://{{ ansible_nodename }} userpresence=1
auth optional pam_permit.so
auth requisite pam_env.so
auth sufficient pam_faillock.so authsucc
{% endif %}
{% if uses_totp_2fa %}
auth [success=ok default=3] pam_google_authenticator.so {{ totp_2fa_nullok | ternary("nullok", "") }} echo_verification_code
auth optional pam_permit.so
auth requisite pam_env.so
auth sufficient pam_faillock.so authsucc
{% endif %}
{% if (uses_passkey_2fa) or (uses_totp_2fa) %}
auth [default=die] pam_deny.so
{% else %}
auth optional pam_permit.so
auth required pam_env.so
auth required pam_faillock.so authsucc
{% endif %}

View File

@ -0,0 +1,15 @@
# This file functions as a switch for passkey access. A user listed in the `passkey_users` variable will have an allow
# line in this file, which will require them to log in using a passkey. Note that THIS CAN LOCK YOU OUT if you do not
# have a passkey set up!!
#
# It only "allows" local connections, as currently there is no way to use a passkey over SSH.
{% for user in passkey_users | default([]) %}
+:{{ user }}:LOCAL
{% endfor %}
{% for group in passkey_groups | default([]) %}
+:({{ group }}):LOCAL
{% endfor %}
-:ALL:ALL

View File

@ -0,0 +1,25 @@
---
- name: 'Fetch repository keys'
loop:
- 'https://dl.ui.com/unifi/unifi-repo.gpg'
- 'https://www.mongodb.org/static/pgp/server-7.0.asc'
ansible.builtin.apt_key:
url: '{{ item }}'
state: present
- name: Add repositories
loop:
- 'deb [ arch=amd64,arm64 ] https://www.ui.com/downloads/unifi/debian stable ubiquiti'
- 'deb [ trusted=yes ] https://repo.mongodb.org/apt/debian bookworm/mongodb-org/7.0 main'
ansible.builtin.apt_repository:
repo: '{{ item }}'
state: present
- name: Install packages
ansible.builtin.apt:
name:
- mongodb-org
- unifi
state: present
update_cache: yes