diff --git a/_tests/pillar/core/test_users.py b/_tests/pillar/core/test_users.py index ffe6c25..883e5f3 100644 --- a/_tests/pillar/core/test_users.py +++ b/_tests/pillar/core/test_users.py @@ -1,37 +1,38 @@ import unittest import yaml PILLAR_FILE = '../pillar/core/users.sls' USER_PROPERTIES_MANDATORY = set(["fullname", "ssh_keys", "uid"]) USER_PROPERTIES_OPTIONAL = set([ + "class", "shell", "yubico_keys", "deploy_dotfiles_to_devserver" ]) class Testinstance(unittest.TestCase): def setUp(self): with open(PILLAR_FILE, 'r') as fd: self.pillar = yaml.safe_load(fd) # users must have an username, an UID and SSH keys def test_users_properties(self): is_valid = True errors = [] for user, properties in self.pillar["shellusers"].items(): missing_properties = USER_PROPERTIES_MANDATORY - set(properties) if missing_properties: errors.append(f" Missing properties for {user}: {missing_properties}") is_valid = False invalid_properties = set(properties) - USER_PROPERTIES_MANDATORY - USER_PROPERTIES_OPTIONAL if invalid_properties: errors.append(f" Invalid properties for {user}: {invalid_properties}") is_valid = False self.assertTrue(is_valid, "\n" + "\n".join(errors)) diff --git a/roles/core/init.sls b/roles/core/init.sls index ec5b0d6..94b8871 100644 --- a/roles/core/init.sls +++ b/roles/core/init.sls @@ -1,20 +1,21 @@ # ------------------------------------------------------------- # Salt — Core units # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # Project: Nasqueron # License: Trivial work, not eligible to copyright # ------------------------------------------------------------- include: - .rc - .hostname + - .login - .network - .motd - .rsyslog - .salt - .sshd - .sudo - .sysctl - .timezone - .userland-software - .users diff --git a/roles/core/login/files/login.conf b/roles/core/login/files/login.conf new file mode 100644 index 0000000..8bf30c8 --- /dev/null +++ b/roles/core/login/files/login.conf @@ -0,0 +1,97 @@ +# ------------------------------------------------------------- +# Login class capabilities database +# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +# Project: Nasqueron +# Created: 2020-01-20 +# License: Trivial work, not eligible to copyright +# Based on: FreeBSD releng/12.1/usr.bin/login/login.conf +# VCS info: 338399 2018-08-30 15:52:03Z brd +# Source file: roles/core/login/files/login.conf +# ------------------------------------------------------------- +# +# <auto-generated> +# This file is managed by our rOPS SaltStack repository. +# +# Changes to this file may cause incorrect behavior +# and will be lost if the state is redeployed. +# </auto-generated> + +# ------------------------------------------------------------- +# Default settings +# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +default:\ + :passwd_format=sha512:\ + :copyright=/etc/COPYRIGHT:\ + :welcome=/etc/motd:\ + :setenv=MAIL=/var/mail/$,BLOCKSIZE=K:\ + :path=/sbin /bin /usr/sbin /usr/bin /usr/local/sbin /usr/local/bin ~/bin:\ + :nologin=/var/run/nologin:\ + :cputime=unlimited:\ + :datasize=unlimited:\ + :stacksize=unlimited:\ + :memorylocked=64K:\ + :memoryuse=unlimited:\ + :filesize=unlimited:\ + :coredumpsize=unlimited:\ + :openfiles=unlimited:\ + :maxproc=unlimited:\ + :sbsize=unlimited:\ + :vmemoryuse=unlimited:\ + :swapuse=unlimited:\ + :pseudoterminals=unlimited:\ + :kqueues=unlimited:\ + :umtxp=unlimited:\ + :priority=0:\ + :ignoretime@:\ + :umask=022: + +# ------------------------------------------------------------- +# Common class names to forward to 'default' +# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +standard:\ + :tc=default: +xuser:\ + :tc=default: +staff:\ + :tc=default: +daemon:\ + :memorylocked=128M:\ + :tc=default: +news:\ + :tc=default: +dialer:\ + :tc=default: + +# ------------------------------------------------------------- +# Root class +# +# Root can always login. +# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +root:\ + :ignorenologin:\ + :memorylocked=unlimited:\ + :tc=default: + +# ------------------------------------------------------------- +# Users classes +# +# Provide proper UTF-8 environment +# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +english|English Users Accounts:\ + :charset=UTF-8:\ + :lang=en_US.UTF-8:\ + :tc=default: + +french|French Users Accounts:\ + :charset=UTF-8:\ + :lang=fr_FR.UTF-8:\ + :tc=default: + +russian|Russian Users Accounts:\ + :charset=UTF-8:\ + :lang=ru_RU.UTF-8:\ + :tc=default: diff --git a/roles/core/login/init.sls b/roles/core/login/init.sls new file mode 100644 index 0000000..af874fb --- /dev/null +++ b/roles/core/login/init.sls @@ -0,0 +1,22 @@ +# ------------------------------------------------------------- +# Set login capabilities +# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +# Project: Nasqueron +# Created: 2020-01-20 +# License: Trivial work, not eligible to copyright +# ------------------------------------------------------------- + +{% if grains['os'] == 'FreeBSD' %} + +/etc/login.conf: + file.managed: + - source: salt://roles/core/login/files/login.conf + - mode: 644 + +compile_login_db: + cmd.run: + - name: cap_mkdb /etc/login.conf + - onchanges: + - file: /etc/login.conf + +{% endif %} diff --git a/roles/core/users/init.sls b/roles/core/users/init.sls index 12a828d..28ab5e1 100644 --- a/roles/core/users/init.sls +++ b/roles/core/users/init.sls @@ -1,126 +1,127 @@ # ------------------------------------------------------------- # Salt — Provision users accounts # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # Project: Nasqueron # Created: 2017-11-09 # Description: Adds and revokes user accounts, in the relevant # groups and with their stable SSH keys. # License: Trivial work, not eligible to copyright # ------------------------------------------------------------- # ------------------------------------------------------------- # Table of contents # ------------------------------------------------------------- # # :: Disabled accounts # :: ZFS (before user account creation) # :: Active accounts # :: ZFS (after user account creation) # :: Groups # :: SSH keys # # ------------------------------------------------------------- {% from "map.jinja" import dirs, shells with context %} {% set users = salt['forest.get_users']() %} {% set zfs_tank = salt['node.get']("zfs:pool") %} # ------------------------------------------------------------- # Disabled accounts # ------------------------------------------------------------- {% for username in pillar.get('revokedusers') %} {{ username }}: user.absent {% endfor %} # ------------------------------------------------------------- # ZFS datasets # # Where ZFS is available, home directories are created as separate # datasets. That has several benefits, like allowing users to create # snapshots or manage backups. # ------------------------------------------------------------- {% if zfs_tank %} zfs_home_permissions_sets: cmd.run: - name: | zfs allow -s @local allow,clone,create,diff,hold,mount,promote,receive,release,rollback,snapshot,send {{ zfs_tank }}{{ dirs.home }} zfs allow -s @descendent allow,clone,create,diff,destroy,hold,mount,promote,receive,release,rename,rollback,snapshot,send {{ zfs_tank }}{{ dirs.home }} touch {{ dirs.home }}/.zfs-permissions-set - creates: {{ dirs.home }}/.zfs-permissions-set {% for username in users %} {% set home_directory = zfs_tank + dirs['home'] + '/' + username %} {{ home_directory }}: zfs.filesystem_present zfs_permissions_home_local_{{ username }}: cmd.run: - name: zfs allow -lu {{ username }} @local {{ home_directory }} - require: - user: {{ username }} - onchanges: - zfs: {{ home_directory }} zfs_permissions_home_descendant_{{ username }}: cmd.run: - name: zfs allow -du {{ username }} @descendent {{ home_directory }} - require: - user: {{ username }} - onchanges: - zfs: {{ home_directory }} {% endfor %} {% endif %} # ------------------------------------------------------------- # Active accounts # ------------------------------------------------------------- {% for username, user in users.items() %} {{ username }}: user.present: - fullname: {{ user['fullname'] }} - shell: {{ shells[user['shell']|default('bash')] }} - uid: {{ user['uid'] }} + - loginclass: {{ user['class']|default('english') }} {% endfor %} # ------------------------------------------------------------- # Groups # ------------------------------------------------------------- {% for groupname, group in salt['forest.get_groups']().items() %} group_{{ groupname }}: group.present: - name: {{ groupname }} - gid: {{ group['gid'] }} - members: {{ group['members'] }} {% endfor %} # ------------------------------------------------------------- # SSH keys # ------------------------------------------------------------- {% for username, user in users.items() %} /home/{{ username }}/.ssh: file.directory: - user: {{ username }} - group: {{ username }} - dir_mode: 700 /home/{{ username}}/.ssh/authorized_keys: file.managed: - source: salt://roles/core/users/files/authorized_keys - user: {{ username }} - group: {{ username }} - mode: 600 - template: jinja - context: keys: {{ user['ssh_keys']|default([]) }} {% endfor %}