Configure /etc/default/useradd through 'defaults'
Add linux:system:defaults:user section that aims two things:
* configure /etc/default/useradd file as this file contains
INACTIVE parameter that should be configured according to
CIS 5.4.1.4
We have to manage entire file so a template was added.
* Configure three parameters that are related to user
account management but configured in /etc/login.defs file.
These are PASS_MAX_DAYS, PASS_MIN_DAYS, PASS_WARN_AGE.
More details in README.rst
Related-Prod: PROD-23600
Change-Id: Idc502af3b0f31b3fe84dc9a42e3e9ec2ead7fe3c
diff --git a/.gitreview b/.gitreview
new file mode 100644
index 0000000..443a01c
--- /dev/null
+++ b/.gitreview
@@ -0,0 +1,3 @@
+[gerrit]
+host=gerrit.mcp.mirantis.com
+project=salt-formulas/linux.git
diff --git a/README.rst b/README.rst
index 9655d5e..9c66374 100644
--- a/README.rst
+++ b/README.rst
@@ -76,6 +76,50 @@
home: '/home/elizabeth'
password: "$6$nUI7QEz3$dFYjzQqK5cJ6HQ38KqG4gTWA9eJu3aKx6TRVDFh6BVJxJgFWg2akfAA7f1fCxcSUeOJ2arCO6EEI6XXnHXxG10"
+Setting user defaults
+---------------------
+Default parameters that will be used by `useradd` command could be configured
+the following way:
+
+.. code-block:: yaml
+
+ linux:
+ system:
+ ...
+ defaults:
+ user:
+ shell: <SHELL>
+ gid: <GROUP>
+ home: <HOME>
+ inactdays: <INACTIVE>
+ expire: <EXPIRE>
+ skeleton: <SKEL>
+ create_mail_spool: <CREATE_MAIL_SPOOL>
+
+Other parameters that are used when creating user profile could be configured
+as well, acting as global defaults:
+
+.. code-block:: yaml
+
+ linux:
+ system:
+ ...
+ defaults:
+ user:
+ ...
+ maxdays: <PASS_MAX_DAYS>
+ mindays: <PASS_MIN_DAYS>
+ warndays: <PASS_WARN_AGE>
+
+.. note::
+
+ The three options above ('maxdays', 'mindays', 'warndays') could be
+ overriden in linux:system:login_defs using their 'real' names.
+ The reason they could be defined here is that it's quite logical to
+ have these parameters related to configuration of user account
+ behaviour in one place.
+
+
Configure password expiration parameters
----------------------------------------
The following login.defs parameters can be overridden per-user:
@@ -83,7 +127,6 @@
* PASS_MAX_DAYS
* PASS_MIN_DAYS
* PASS_WARN_DAYS
-* INACTIVE
.. code-block:: yaml
@@ -97,8 +140,7 @@
...
maxdays: <PASS_MAX_DAYS>
mindays: <PASS_MIN_DAYS>
- warndays: <PASS_WARN_DAYS>
- inactdays: <INACTIVE>
+ warndays: <PASS_WARN_AGE>
Configure sudo for users and groups under ``/etc/sudoers.d/``.
This ways ``linux.system.sudo`` pillar map to actual sudo attributes:
diff --git a/linux/files/etc_default_useradd.jinja b/linux/files/etc_default_useradd.jinja
new file mode 100644
index 0000000..076cfeb
--- /dev/null
+++ b/linux/files/etc_default_useradd.jinja
@@ -0,0 +1,50 @@
+# This file is managed by Salt, do not edit
+{%- macro define_option(option_name, option_key, default=None) %}
+ {%- set value = defaults.get(option_key, default) %}
+ {%- if value != None %}
+{{ option_name }}={{ value }}
+ {%- endif %}
+{%- endmacro %}
+# Default values for useradd(8)
+#
+# The SHELL variable specifies the default login shell on your
+# system.
+# Similar to DHSELL in adduser. However, we use "sh" here because
+# useradd is a low level utility and should be as general
+# as possible
+# SHELL=/bin/sh
+{{- define_option('SHELL', 'shell', default='/bin/sh') }}
+#
+# The default group for users
+# 100=users on Debian systems
+# Same as USERS_GID in adduser
+# This argument is used when the -n flag is specified.
+# The default behavior (when -n and -g are not specified) is to create a
+# primary user group with the same name as the user being added to the
+# system.
+# GROUP=100
+{{- define_option('GROUP', 'gid') }}
+#
+# The default home directory. Same as DHOME for adduser
+# HOME=/home
+{{- define_option('HOME', 'home') }}
+#
+# The number of days after a password expires until the account
+# is permanently disabled
+# INACTIVE=-1
+{{- define_option('INACTIVE', 'inactdays') }}
+#
+# The default expire date
+# EXPIRE=
+{{- define_option('EXPIRE', 'expire') }}
+#
+# The SKEL variable specifies the directory containing "skeletal" user
+# files; in other words, files such as a sample .profile that will be
+# copied to the new user's home directory when it is created.
+# SKEL=/etc/skel
+{{- define_option('SKEL', 'skeleton') }}
+#
+# Defines whether the mail spool should be created while
+# creating the account
+# CREATE_MAIL_SPOOL=yes
+{{- define_option('CREATE_MAIN_SPOOL', 'create_mail_spool')}}
\ No newline at end of file
diff --git a/linux/files/login.defs.jinja b/linux/files/login.defs.jinja
index 572c558..ad4d6d3 100644
--- a/linux/files/login.defs.jinja
+++ b/linux/files/login.defs.jinja
@@ -52,11 +52,30 @@
'USERDEL_CMD',
'USERGROUPS_ENAB'
] %}
+{#
+ 'defaults' could be passed externally, in this case it should be dictionary
+#}
+{%- if defaults is not defined %}
+ {%- set defaults = {} %}
+{%- endif %}
+{#
+ Override values in 'defaults' with those defined in system:login_defs as they
+ are of highest priority.
+#}
{%- for opt_name in allowed_options %}
{%- if opt_name in login_defs %}
{%- set opt_params = login_defs.get(opt_name) %}
{%- if opt_params.get('enabled', true) %}
-{{ opt_name.ljust(20) }} {{ opt_params.value }}
+ {%- do defaults.update({opt_name: opt_params.value}) %}
{%- endif %}
{%- endif %}
{%- endfor %}
+{#
+ Now we can write merged data to file, keeping order of items as in the list above
+#}
+{%- for opt_name in allowed_options %}
+ {%- set value = defaults.get(opt_name, None) %}
+ {%- if value != None %}
+{{ opt_name.ljust(20) }} {{ value }}
+ {%- endif %}
+{%- endfor %}
diff --git a/linux/system/login_defs.sls b/linux/system/login_defs.sls
index f94348a..914e6eb 100644
--- a/linux/system/login_defs.sls
+++ b/linux/system/login_defs.sls
@@ -1,6 +1,16 @@
{%- from "linux/map.jinja" import system with context %}
{%- if system.enabled %}
- {%- if system.login_defs is defined %}
+ {%- set defaults = {} %}
+ {%- set user_defaults = system.get('defaults', {}).get('user', {}) %}
+ {%- for option_name, login_defs_name in [('maxdays', 'PASS_MAX_DAYS'),
+ ('mindays', 'PASS_MIN_DAYS'),
+ ('warndays', 'PASS_WARN_AGE')] %}
+ {%- set value = user_defaults.get(option_name, None) %}
+ {%- if value != None %}
+ {%- do defaults.update({login_defs_name: value}) %}
+ {%- endif %}
+ {%- endfor %}
+ {%- if system.login_defs is defined or defaults %}
login_defs:
file.managed:
- name: /etc/login.defs
@@ -9,5 +19,7 @@
- user: root
- group: root
- mode: 644
+ - defaults:
+ defaults: {{ defaults|yaml }}
{%- endif %}
{%- endif %}
diff --git a/linux/system/user.sls b/linux/system/user.sls
index 64636f3..ca95c34 100644
--- a/linux/system/user.sls
+++ b/linux/system/user.sls
@@ -4,74 +4,86 @@
include:
- linux.system.group
-{%- for name, user in system.user.items() %}
-
-{%- if user.enabled %}
-
-{%- set requires = [] %}
-{%- for group in user.get('groups', []) %}
- {%- if group in system.get('group', {}).keys() %}
- {%- do requires.append({'group': 'system_group_'+group}) %}
+ {%- set defaults = system.get('defaults', {}).get('user', {}) %}
+ {%- if defaults %}
+etc_default_useradd:
+ file.managed:
+ - name: /etc/default/useradd
+ - source: salt://linux/files/etc_default_useradd.jinja
+ - template: jinja
+ - user: root
+ - group: root
+ - mode: 644
+ - defaults:
+ defaults: {{ defaults|yaml }}
{%- endif %}
-{%- endfor %}
-{%- if user.gid is not defined %}
+ {%- for name, user in system.user.items() %}
+ {%- if user.enabled %}
+ {%- set requires = [] %}
+ {%- for group in user.get('groups', []) %}
+ {%- if group in system.get('group', {}).keys() %}
+ {%- do requires.append({'group': 'system_group_'+group}) %}
+ {%- endif %}
+ {%- endfor %}
+
+ {%- if user.gid is not defined %}
system_group_{{ name }}:
group.present:
- name: {{ name }}
- require_in:
- user: system_user_{{ name }}
-{%- endif %}
+ {%- endif %}
system_user_{{ name }}:
user.present:
- name: {{ name }}
- home: {{ user.home }}
- {% if user.get('password') == False %}
+ {% if user.get('password') == False %}
- enforce_password: false
- {% elif user.get('password') == None %}
+ {% elif user.get('password') == None %}
- enforce_password: true
- password: '*'
- {% elif user.get('password') %}
+ {% elif user.get('password') %}
- enforce_password: true
- password: {{ user.password }}
- hash_password: {{ user.get('hash_password', False) }}
- {% endif %}
- {%- if user.gid is defined and user.gid %}
+ {% endif %}
+ {%- if user.gid is defined and user.gid %}
- gid: {{ user.gid }}
- {%- else %}
+ {%- else %}
- gid_from_name: true
- {%- endif %}
- {%- if user.groups is defined %}
+ {%- endif %}
+ {%- if user.groups is defined %}
- groups: {{ user.groups }}
- {%- endif %}
- {%- if user.optional_groups is defined %}
+ {%- endif %}
+ {%- if user.optional_groups is defined %}
- optional_groups: {{ user.optional_groups }}
- {%- endif %}
- {%- if user.system is defined and user.system %}
+ {%- endif %}
+ {%- if user.system is defined and user.system %}
- system: True
- shell: {{ user.get('shell', '/bin/false') }}
- {%- else %}
+ {%- else %}
- shell: {{ user.get('shell', '/bin/bash') }}
- {%- endif %}
- {%- if user.uid is defined and user.uid %}
+ {%- endif %}
+ {%- if user.uid is defined and user.uid %}
- uid: {{ user.uid }}
- {%- endif %}
- {%- if user.unique is defined %}
+ {%- endif %}
+ {%- if user.unique is defined %}
- unique: {{ user.unique }}
- {%- endif %}
- {%- if user.maxdays is defined %}
+ {%- endif %}
+ {%- if user.maxdays is defined %}
- maxdays: {{ user.maxdays }}
- {%- endif %}
- {%- if user.mindays is defined %}
+ {%- endif %}
+ {%- if user.mindays is defined %}
- mindays: {{ user.mindays }}
- {%- endif %}
- {%- if user.warndays is defined %}
+ {%- endif %}
+ {%- if user.warndays is defined %}
- warndays: {{ user.warndays }}
- {%- endif %}
- {%- if user.inactdays is defined %}
+ {%- endif %}
+ {%- if user.inactdays is defined %}
- inactdays: {{ user.inactdays }}
- {%- endif %}
+ {%- endif %}
- require: {{ requires|yaml }}
system_user_home_{{ user.home }}:
@@ -83,7 +95,7 @@
- require:
- user: system_user_{{ name }}
-{%- if user.get('sudo', False) %}
+ {%- if user.get('sudo', False) %}
/etc/sudoers.d/90-salt-user-{{ name|replace('.', '-') }}:
file.managed:
@@ -98,14 +110,13 @@
- user: system_user_{{ name }}
- check_cmd: /usr/sbin/visudo -c -f
-{%- else %}
+ {%- else %}
/etc/sudoers.d/90-salt-user-{{ name|replace('.', '-') }}:
file.absent
-{%- endif %}
-
-{%- else %}
+ {%- endif %}
+ {%- else %}
system_user_{{ name }}:
user.absent:
@@ -118,8 +129,6 @@
/etc/sudoers.d/90-salt-user-{{ name|replace('.', '-') }}:
file.absent
-{%- endif %}
-
-{%- endfor %}
-
+ {%- endif %}
+ {%- endfor %}
{%- endif %}