Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
2f6e060
Enable SLE15 support for login.defs drop-in configuration
teacup-on-rockingchair Jul 24, 2026
c26b75a
Add support for drop-in login.defs configuration in SLE
teacup-on-rockingchair Jul 24, 2026
10900d3
Add drop-in support for login.defs configuration in accounts_umask_et…
teacup-on-rockingchair Jul 24, 2026
4a7b28f
For SLE platforms support drop-in login.defs when looking for UIDs
teacup-on-rockingchair Jul 24, 2026
50cc450
Adapt accounts_have_homedir_login_defs to use correctly drop-in logic
teacup-on-rockingchair Jul 24, 2026
79f8473
Add support for slmicro6 of require_emergency_target_auth rule
teacup-on-rockingchair Jul 24, 2026
920b753
Fix ansible comment keys removed by mistake
teacup-on-rockingchair Jul 24, 2026
d4b3a09
Some additional fixes and tests for new drop-in behaviour
teacup-on-rockingchair Jul 27, 2026
385c1d6
Update linux_os/guide/system/accounts/accounts-pam/set_password_hashi…
teacup-on-rockingchair Jul 29, 2026
7b9fb06
Update linux_os/guide/system/accounts/accounts-pam/set_password_hashi…
teacup-on-rockingchair Jul 29, 2026
73ecbe4
Drop duplicate ansible field and unneeded criteria tag
teacup-on-rockingchair Jul 29, 2026
6825ee1
Use much more self-explanotory variable name in macro
teacup-on-rockingchair Jul 29, 2026
fa8171d
Use much more descriptive variables in ansible jinja macro
teacup-on-rockingchair Jul 29, 2026
1cd93be
Fix ambigiuos comments for criterions
teacup-on-rockingchair Jul 29, 2026
8ef16b8
Add empty newline at end of the file
teacup-on-rockingchair Jul 29, 2026
ac655df
Update linux_os/guide/system/accounts/accounts-restrictions/root_logi…
teacup-on-rockingchair Jul 30, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@

{{{ ansible_instantiate_variables("var_password_hashing_algorithm") }}}

{{% if product in [ 'slmicro6', 'sle16' ] %}}
{{% set cce_cce_identifier = cce_identifiers['cce'] %}}
{{% if product in [ 'slmicro6', 'sle15', 'sle16' ] %}}
{{% set password_hashing_algorithm_logindefs_cce_identifier = cce_identifiers['cce'] %}}
{{{
ansible_login_defs(
parameter='ENCRYPT_METHOD',
value='{{ var_password_hashing_algorithm.split("|")[0] }}',
rule_title=rule_title,
cce=cce_cce_identifier
cce=password_hashing_algorithm_logindefs_cce_identifier
)
}}}
{{% else %}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
#
var_password_hashing_algorithm="$(echo $var_password_hashing_algorithm | cut -d \| -f 1)"

{{% if product in [ 'slmicro6', 'sle16' ] %}}
{{% if product in [ 'slmicro6', 'sle15', 'sle16' ] %}}
{{{ bash_login_defs("ENCRYPT_METHOD", "$var_password_hashing_algorithm", cce_identifiers=cce_identifiers) }}}
{{% else %}}
{{{ bash_replace_or_append(login_defs_path, '^ENCRYPT_METHOD', "$var_password_hashing_algorithm", '%s %s', cce_identifiers=cce_identifiers) }}}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<def-group>
<definition class="compliance" id="{{{ rule_id }}}" version="2">
{{{ oval_metadata("The password hashing algorithm should be set correctly in " + login_defs_path + ".", rule_title=rule_title) }}}
{{% if product in [ 'slmicro6', 'sle16' ] %}}
{{% if product in [ 'slmicro6', 'sle15', 'sle16' ] %}}
<criteria operator="OR">
<criteria operator="AND">
<criterion comment="Check ENCRYPT_METHOD in {{{ login_defs_drop_in_path }}} is not set"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/bin/bash
# platform = SUSE Linux Enterprise 16
# platform = SUSE Linux Enterprise 15, SUSE Linux Enterprise 16
# variables = var_password_hashing_algorithm=SHA512

if [ -e {{{ login_defs_drop_in_path }}} ] ; then
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/bin/bash
# platform = SUSE Linux Enterprise 16
# platform = SUSE Linux Enterprise 15, SUSE Linux Enterprise 16
# variables = var_password_hashing_algorithm=SHA512

if [ -e {{{ login_defs_drop_in_path }}} ] ; then
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/bin/bash
# platform = SUSE Linux Enterprise 16
# platform = SUSE Linux Enterprise 15, SUSE Linux Enterprise 16
# variables = var_password_hashing_algorithm=SHA512

if [ -e {{{ login_defs_drop_in_path }}} ] ; then
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,22 @@

{{{ ansible_instantiate_variables("var_password_hashing_min_rounds_login_defs") }}}

{{% if product in [ 'sle16', 'slmicro6' ] %}}
{{% set cce_cce_identifier = cce_identifiers['cce'] %}}
{{% if product in [ 'sle15', 'sle16', 'slmicro6' ] %}}
{{% set password_hashing_min_rounds_logindefs_cce_identifier = cce_identifiers['cce'] %}}
{{{
ansible_login_defs(
parameter='SHA_CRYPT_MIN_ROUNDS',
value='{{ var_password_hashing_min_rounds_login_defs }}',
rule_title=rule_title,
cce=cce_cce_identifier
cce=password_hashing_min_rounds_logindefs_cce_identifier
)
}}}
{{{
ansible_login_defs(
parameter='SHA_CRYPT_MAX_ROUNDS',
value='{{ var_password_hashing_min_rounds_login_defs }}',
rule_title=rule_title,
cce=cce_cce_identifier
cce=password_hashing_min_rounds_logindefs_cce_identifier
)
}}}
{{% else %}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

{{{ bash_instantiate_variables("var_password_hashing_min_rounds_login_defs") }}}

{{% if product == [ 'sle16', 'slmicro6' ] %}}
{{% if product in [ 'sle15', 'sle16', 'slmicro6' ] %}}
{{% set login_defs_d_config_dir = "/".join(login_defs_drop_in_path.split("/")[:-1]) ~ "/*.defs" %}}

min_rounds_login_defs=$(grep -Po '^\s*SHA_CRYPT_MIN_ROUNDS\s+\K\d+' {{{ login_defs_d_config_dir }}})
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
<def-group>
<definition class="compliance" id="set_password_hashing_min_rounds_logindefs" version="3">
{{{ oval_metadata("The password hashing minimum rounds should be set correctly.", rule_title=rule_title) }}}
<criteria operator="OR">
<criteria operator="AND">
<criterion
comment="Check SHA_CRYPT_MIN_ROUNDS in {{{ login_defs_drop_in_path }}} is not set"
test_ref="test_sha_crypt_min_rounds_logindefs_drop_in_path_not_set"/>
<criterion
comment="Check SHA_CRYPT_MIN_ROUNDS should be set appropriately in {{{ login_defs_path }}}"
test_ref="test_sha_crypt_min_rounds_logindefs"/>

<criterion
comment="Check SHA_CRYPT_MAX_ROUNDS in {{{ login_defs_drop_in_path }}} is not set"
test_ref="test_sha_crypt_max_rounds_logindefs_drop_in_path_not_set"/>
<criterion
comment="Check SHA_CRYPT_MAX_ROUNDS should be set appropriately in {{{ login_defs_path }}}"
test_ref="test_sha_crypt_max_rounds_logindefs"/>
</criteria>
<criteria operator="AND">
<criterion comment="Check SHA_CRYPT_MIN_ROUNDS should be set appropriately in {{{ login_defs_drop_in_path }}}"
test_ref="test_sha_crypt_min_rounds_logindefs_drop_in_path"/>
<criterion comment="Check SHA_CRYPT_MAX_ROUNDS should be set appropriately in {{{ login_defs_drop_in_path }}}"
test_ref="test_sha_crypt_max_rounds_logindefs_drop_in_path"/>
</criteria>
</criteria>
</definition>

{{{
oval_param_in_file_variable_test(
filepath=login_defs_path,
parameter="SHA_CRYPT_MIN_ROUNDS",
pattern="^[\s]*(?i)(SHA_CRYPT_MIN_ROUNDS[\s]+\d+)[\s]*(?:#.*)?$",
regex_capture="SHA_CRYPT_MIN_ROUNDS\s+(\d+)",
operation="greater than or equal",
type="int",
variable="var_password_hashing_min_rounds_login_defs",
test_id="test_sha_crypt_min_rounds_logindefs"
)
}}}

{{{
oval_param_in_file_variable_test(
filepath=login_defs_path,
parameter="SHA_CRYPT_MAX_ROUNDS",
pattern="^[\s]*(?i)(SHA_CRYPT_MAX_ROUNDS[\s]+\d+)[\s]*(?:#.*)?$",
regex_capture="SHA_CRYPT_MAX_ROUNDS\s+(\d+)",
operation="greater than or equal",
type="int",
variable="var_password_hashing_min_rounds_login_defs",
test_id="test_sha_crypt_max_rounds_logindefs"
)
}}}

{{% set login_defs_drop_in_config_dir = "/".join(login_defs_drop_in_path.split("/")[:-1]) %}}
{{{
oval_param_in_file_variable_test(
filepath=login_defs_drop_in_config_dir,
filename_regex=".*\.defs$",
parameter="SHA_CRYPT_MIN_ROUNDS",
pattern="^[\s]*(?i)(SHA_CRYPT_MIN_ROUNDS[\s]+\d+)[\s]*(?:#.*)?$",
regex_capture="SHA_CRYPT_MIN_ROUNDS\s+(\d+)",
operation="greater than or equal",
type="int",
variable="var_password_hashing_min_rounds_login_defs",
test_id="test_sha_crypt_min_rounds_logindefs_drop_in_path"
)
}}}

{{{
oval_param_in_file_variable_test(
filepath=login_defs_drop_in_config_dir,
filename_regex=".*\.defs$",
parameter="SHA_CRYPT_MAX_ROUNDS",
pattern="^[\s]*(?i)(SHA_CRYPT_MAX_ROUNDS[\s]+\d+)[\s]*(?:#.*)?$",
regex_capture="SHA_CRYPT_MAX_ROUNDS\s+(\d+)",
operation="greater than or equal",
type="int",
variable="var_password_hashing_min_rounds_login_defs",
test_id="test_sha_crypt_max_rounds_logindefs_drop_in_path"
)
}}}

<ind:textfilecontent54_test check="all" check_existence="none_exist" version="1"
comment="Check SHA_CRYPT_MIN_ROUNDS in {{{ login_defs_drop_in_path }}} is not set"
id="test_sha_crypt_min_rounds_logindefs_drop_in_path_not_set">
<ind:object object_ref="object_sha_crypt_min_rounds_logindefs_drop_in_path_not_set" />
</ind:textfilecontent54_test>

<ind:textfilecontent54_object id="object_sha_crypt_min_rounds_logindefs_drop_in_path_not_set" version="1">
<ind:path>{{{ login_defs_drop_in_config_dir }}}</ind:path>
<ind:filename operation="pattern match">.*\.defs$</ind:filename>
<ind:pattern operation="pattern match">^\s*SHA_CRYPT_MIN_ROUNDS\s*</ind:pattern>
<ind:instance datatype="int">1</ind:instance>
</ind:textfilecontent54_object>

<ind:textfilecontent54_test check="all" check_existence="none_exist" version="1"
comment="Check SHA_CRYPT_MAX_ROUNDS in {{{ login_defs_drop_in_path }}} is not set"
id="test_sha_crypt_max_rounds_logindefs_drop_in_path_not_set">
<ind:object object_ref="object_sha_crypt_max_rounds_logindefs_drop_in_path_not_set" />
</ind:textfilecontent54_test>

<ind:textfilecontent54_object id="object_sha_crypt_max_rounds_logindefs_drop_in_path_not_set" version="1">
<ind:path>{{{ login_defs_drop_in_config_dir }}}</ind:path>
<ind:filename operation="pattern match">.*\.defs$</ind:filename>
<ind:pattern operation="pattern match">^\s*SHA_CRYPT_MAX_ROUNDS\s*</ind:pattern>
<ind:instance datatype="int">1</ind:instance>
</ind:textfilecontent54_object>
</def-group>
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/bin/bash
# platform = SUSE Linux Enterprise 16
# platform = SUSE Linux Enterprise 15, SUSE Linux Enterprise 16
# variables = var_password_hashing_min_rounds_login_defs=5000

if [ -e {{{ login_defs_drop_in_path }}} ] ; then
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/bin/bash
{{% if product == "sle16" %}}
{{% if product in ['sle15', 'sle16'] %}}
# platform = Not Applicable
{{% endif %}}
# variables = var_password_hashing_min_rounds_login_defs=5000
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/bin/bash
{{% if product == "sle16" %}}
{{% if product in ['sle15', 'sle16'] %}}
# platform = Not Applicable
{{% endif %}}
# variables = var_password_hashing_min_rounds_login_defs=5000
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/bin/bash
# platform = SUSE Linux Enterprise 16
# platform = SUSE Linux Enterprise 15, SUSE Linux Enterprise 16
# variables = var_password_hashing_min_rounds_login_defs=5000

if [ -e {{{ login_defs_drop_in_path }}} ] ; then
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/bin/bash
# platform = SUSE Linux Enterprise 16
# platform = SUSE Linux Enterprise 15, SUSE Linux Enterprise 16
# variables = var_password_hashing_min_rounds_login_defs=5000

if [ -e {{{ login_defs_drop_in_path }}} ] ; then
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
<ind:instance datatype="int">1</ind:instance>
</ind:textfilecontent54_object>

{{% if 'sle' in product or 'rhel' in product or product == 'fedora' or product == 'slmicro5' or 'ol' in families %}}
{{% if 'sle' in product or 'rhel' in product or product == 'fedora' or product.startswith('slmicro') or 'ol' in families %}}
<ind:textfilecontent54_test check="all" check_existence="all_exist"
comment="Tests that
/usr/lib/systemd/systemd-sulogin-shell
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,21 @@
# disruption = low
{{{ ansible_instantiate_variables("var_accounts_maximum_age_login_defs") }}}

{{% if product in [ 'slmicro6', 'sle15', 'sle16' ] %}}
{{% set accounts_maximum_age_login_defs_cce_identifier = cce_identifiers['cce'] %}}
{{{
ansible_login_defs(
parameter='PASS_MAX_DAYS',
value='{{ var_accounts_maximum_age_login_defs }}',
rule_title=rule_title,
cce=accounts_maximum_age_login_defs_cce_identifier
)
}}}
{{% else %}}
- name: Set Password Maximum Age
ansible.builtin.lineinfile:
create: yes
dest: {{{ login_defs_path }}}
regexp: ^#?PASS_MAX_DAYS
regexp: ^PASS_MAX_DAYS
line: "PASS_MAX_DAYS {{ var_accounts_maximum_age_login_defs }}"
{{% endif %}}
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
# platform = multi_platform_all

{{{ bash_instantiate_variables("var_accounts_maximum_age_login_defs") }}}

{{% if product in [ 'slmicro6', 'sle15', 'sle16' ] %}}
{{{ bash_login_defs("PASS_MAX_DAYS", "$var_accounts_maximum_age_login_defs", cce_identifiers=cce_identifiers) }}}
{{% else %}}
{{{ bash_replace_or_append(login_defs_path, '^PASS_MAX_DAYS', "$var_accounts_maximum_age_login_defs", '%s %s', cce_identifiers=cce_identifiers) }}}
{{% endif %}}
Original file line number Diff line number Diff line change
@@ -1,41 +1,64 @@
<def-group>
<definition class="compliance" id="accounts_maximum_age_login_defs" version="3">
{{{ oval_metadata("The maximum password age policy should meet minimum requirements.", rule_title=rule_title) }}}
{{% if product in [ 'slmicro6', 'sle15', 'sle16' ] %}}
<criteria operator="OR">
<criteria operator="AND">
<criterion comment="Check PASS_MAX_DAYS in {{{ login_defs_drop_in_path }}} is not set"
test_ref="test_pass_max_days_logindefs_drop_in_path_not_set"/>
<criterion comment="Check PASS_MAX_DAYS should be set appropriately in {{{ login_defs_path }}}"
test_ref="test_pass_max_days"/>
</criteria>
<criterion comment="Check PASS_MAX_DAYS should be set appropriately in {{{ login_defs_drop_in_path }}}"
test_ref="test_pass_max_days_logindefs_drop_in_path"/>
</criteria>
{{% else %}}
<criteria comment="The value PASS_MAX_DAYS should be set appropriately in {{{ login_defs_path }}}">
<criterion test_ref="test_pass_max_days" />
</criteria>
{{% endif %}}
</definition>

<ind:variable_test id="test_pass_max_days" check="all" comment="The value of PASS_MAX_DAYS should be set appropriately in {{{ login_defs_path }}}" version="1">
<ind:object object_ref="object_last_pass_max_days_instance_value" />
<ind:state state_ref="state_last_pass_max_days_instance_value" />
</ind:variable_test>

<ind:textfilecontent54_object id="object_last_pass_max_days_from_etc_login_defs" version="1">
<!-- Read whole /etc/login.defs as single line so we can retrieve last PASS_MAX_DAYS directive occurrence -->
<ind:filepath>{{{ login_defs_path }}}</ind:filepath>
<!-- Retrieve last (uncommented) occurrence of PASS_MAX_DAYS directive -->
<ind:pattern operation="pattern match">^(?:.*\n)*\s*[^#]*(PASS_MAX_DAYS\s+\d+)\s*\n</ind:pattern>
<ind:instance datatype="int" operation="greater than or equal">1</ind:instance>
</ind:textfilecontent54_object>
{{{
oval_param_in_file_variable_test(
filepath=login_defs_path,
parameter="PASS_MAX_DAYS",
pattern="^[\s]*(?i)(PASS_MAX_DAYS[\s]+\d+)",
regex_capture="PASS_MAX_DAYS\s+(\d+)",
operation="less than or equal",
type="int",
test_id="test_pass_max_days",
variable="var_accounts_maximum_age_login_defs"
)
}}}

<!-- Capture the actual PASS_MAX_DAYS integer value from the previously retrieved last instance -->
<local_variable id="variable_last_pass_max_days_instance_value" datatype="int" comment="The value of last PASS_MAX_DAYS directive in {{{ login_defs_path }}}" version="1">
<regex_capture pattern="PASS_MAX_DAYS\s+(\d+)">
<object_component item_field="subexpression" object_ref="object_last_pass_max_days_from_etc_login_defs" />
</regex_capture>
</local_variable>
{{% set login_defs_drop_in_config_dir = "/".join(login_defs_drop_in_path.split("/")[:-1]) %}}
{{{
oval_param_in_file_variable_test(
filepath=login_defs_drop_in_config_dir,
filename_regex=".*\.defs$",
parameter="PASS_MAX_DAYS",
pattern="^[\s]*(?i)(PASS_MAX_DAYS[\s]+\d+)",
regex_capture="PASS_MAX_DAYS\s+(\d+)",
operation="less than or equal",
type="int",
test_id="test_pass_max_days_logindefs_drop_in_path",
variable="var_accounts_maximum_age_login_defs"
)
}}}

<!-- Construct OVAL object from this local variable so we can use it in variable test above -->
<ind:variable_object id="object_last_pass_max_days_instance_value" version="1">
<ind:var_ref>variable_last_pass_max_days_instance_value</ind:var_ref>
</ind:variable_object>
<ind:textfilecontent54_test check="all" check_existence="none_exist" version="1"
comment="Check PASS_MAX_DAYS in drop-in files is not set"
id="test_pass_max_days_logindefs_drop_in_path_not_set">
<ind:object object_ref="object_pass_max_days_logindefs_drop_in_path_not_set" />
</ind:textfilecontent54_test>

<!-- Define corresponding variable state (the requirement) for the variable object -->
<!-- The check should PASS if retrieved last PASS_MAX_DAYS value is less than or equal to the requirement -->
<ind:variable_state id="state_last_pass_max_days_instance_value" version="1">
<ind:value operation="less than or equal" var_ref="var_accounts_maximum_age_login_defs" datatype="int" var_check="at least one" />
</ind:variable_state>
<ind:textfilecontent54_object id="object_pass_max_days_logindefs_drop_in_path_not_set" version="1">
<ind:path>{{{ login_defs_drop_in_config_dir }}}</ind:path>
<ind:filename operation="pattern match">.*\.defs$</ind:filename>
<ind:pattern operation="pattern match">^\s*PASS_MAX_DAYS\s*</ind:pattern>
<ind:instance datatype="int">1</ind:instance>
</ind:textfilecontent54_object>

<external_variable comment="Maximum password age" datatype="int" id="var_accounts_maximum_age_login_defs" version="1" />

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,21 @@
# disruption = low
{{{ ansible_instantiate_variables("var_accounts_minimum_age_login_defs") }}}

{{% if product in [ 'slmicro6', 'sle15', 'sle16' ] %}}
{{% set accounts_minimum_age_login_defs_cce_identifier = cce_identifiers['cce'] %}}
{{{
ansible_login_defs(
parameter='PASS_MIN_DAYS',
value='{{ var_accounts_minimum_age_login_defs }}',
rule_title=rule_title,
cce=accounts_minimum_age_login_defs_cce_identifier
)
}}}
{{% else %}}
- name: Set Password Minimum Age
ansible.builtin.lineinfile:
create: yes
dest: {{{ login_defs_path }}}
regexp: ^#?PASS_MIN_DAYS
line: "PASS_MIN_DAYS {{ var_accounts_minimum_age_login_defs }}"
dest: {{{ login_defs_path }}}
regexp: ^PASS_MIN_DAYS
line: "PASS_MIN_DAYS {{ var_accounts_minimum_age_login_defs }}"
create: yes
{{% endif %}}
Loading
Loading