diff --git a/linux_os/guide/system/accounts/accounts-session/file_groupownership_home_directories/ansible/shared.yml b/linux_os/guide/system/accounts/accounts-session/file_groupownership_home_directories/ansible/shared.yml
index 14ebb3662f27..a9c23013c91b 100644
--- a/linux_os/guide/system/accounts/accounts-session/file_groupownership_home_directories/ansible/shared.yml
+++ b/linux_os/guide/system/accounts/accounts-session/file_groupownership_home_directories/ansible/shared.yml
@@ -4,32 +4,32 @@
# complexity = low
# disruption = low
-- name: Get all local users from /etc/passwd
+- name: Get all users from getent to support remote users (LDAP, SSSD, etc.)
ansible.builtin.getent:
database: passwd
split: ':'
-- name: Create local_users variable from the getent output
+- name: Create interactive_users variable filtering out non-interactive shells
ansible.builtin.set_fact:
- local_users: '{{ ansible_facts.getent_passwd|dict2items }}'
- # Creates a dictionary where the key is the first field of the /etc/passwd file, the username.
- # The list of values are the next 6 fields from /etc/passwd. Example for the root entry:
- # The "root" key would have these values: ["x", "0", "0", "root", "/root", "/bin/bash"]
+ interactive_users: '{{ ansible_facts.getent_passwd|dict2items|rejectattr("value.5", "match", ".*/sbin/nologin$")|rejectattr("value.5", "match", ".*/usr/sbin/nologin$")|rejectattr("value.5", "match", ".*/bin/false$")|rejectattr("value.5", "match", ".*/usr/bin/false$")|list }}'
+ # Creates a dictionary where the key is the username and values are fields from getent passwd.
+ # Filters out users with non-interactive shells: nologin and false.
+ # Example for the admin entry: ["x", "1000", "1000", "", "/home/admin", "/bin/bash"]
- name: Test for existence of home directories to avoid creating them, but only fixing group ownership
ansible.builtin.stat:
path: '{{ item.value[4] }}'
register: path_exists
- loop: '{{ local_users }}'
+ loop: '{{ interactive_users }}'
when:
- item.value[1]|int >= {{{ uid_min }}}
- item.value[1]|int != {{{ nobody_uid }}}
- item.value[4] != "/"
-- name: Ensure interactive local users are the group-owners of their respective home directories
+- name: Ensure interactive users are the group-owners of their respective home directories
ansible.builtin.file:
path: '{{ item.0.value[4] }}'
group: '{{ item.0.value[2] }}'
- loop: '{{ local_users|zip(path_exists.results)|list }}'
+ loop: '{{ interactive_users|zip(path_exists.results)|list }}'
when:
- item.1.stat is defined and item.1.stat.exists
diff --git a/linux_os/guide/system/accounts/accounts-session/file_groupownership_home_directories/bash/shared.sh b/linux_os/guide/system/accounts/accounts-session/file_groupownership_home_directories/bash/shared.sh
index a6c7b07bd586..4f8d83d7ca5e 100644
--- a/linux_os/guide/system/accounts/accounts-session/file_groupownership_home_directories/bash/shared.sh
+++ b/linux_os/guide/system/accounts/accounts-session/file_groupownership_home_directories/bash/shared.sh
@@ -4,4 +4,14 @@
# complexity = low
# disruption = low
-awk -F':' '{ if ($3 >= {{{ uid_min }}} && $3 != {{{ nobody_uid }}} && $6 != "/") system("chgrp -f " $4" "$6) }' /etc/passwd
+# Get interactive users using getent to support remote users (LDAP, SSSD, etc.)
+while IFS=: read -r _ _ uid gid _ home shell; do
+ # Filter interactive users: UID >= {{{ uid_min }}}, not nobody, has valid home dir, not nologin/false shell
+ if [ "$uid" -ge {{{ uid_min }}} ] && [ "$uid" -ne {{{ nobody_uid }}} ] && \
+ [ "$home" != "/" ] && \
+ [ "$shell" != "/sbin/nologin" ] && [ "$shell" != "/usr/sbin/nologin" ] && \
+ [ "$shell" != "/bin/false" ] && [ "$shell" != "/usr/bin/false" ]; then
+ # Arguments are properly quoted to prevent command injection
+ chgrp -f -- "$gid" "$home"
+ fi
+done < <(getent passwd)
diff --git a/linux_os/guide/system/accounts/accounts-session/file_groupownership_home_directories/oval/shared.xml b/linux_os/guide/system/accounts/accounts-session/file_groupownership_home_directories/oval/shared.xml
index 79a5f7dec0d3..2dbf49b051c1 100644
--- a/linux_os/guide/system/accounts/accounts-session/file_groupownership_home_directories/oval/shared.xml
+++ b/linux_os/guide/system/accounts/accounts-session/file_groupownership_home_directories/oval/shared.xml
@@ -7,21 +7,20 @@
- {{%- set interactive_users_home_dirs_object = "object_" ~ rule_id ~ "_home_dirs" -%}}
- {{{ create_local_interactive_users_home_dirs_list_object(interactive_users_home_dirs_object) }}}
- {{%- set interactive_users_gids_object = "object_" ~ rule_id ~ "_gids" -%}}
- {{{ create_local_interactive_users_gids_list_object(interactive_users_gids_object) }}}
+ {{%- set interactive_users_object = "object_" ~ rule_id ~ "_interactive_users" -%}}
+ {{{ create_interactive_users_list_object(interactive_users_object, rule_id=rule_id) }}}
-
+
$ sudo chgrp USER_GROUP /home/USERThis rule ensures every home directory related to an interactive user is - group-owned by an interactive user. It also ensures that interactive users + group-owned by that user's primary group. It also ensures that interactive users are group-owners of one and only one home directory. + Interactive users are those with a UID greater than or equal to {{{ uid_min }}} + and a valid interactive shell (not /sbin/nologin, /usr/sbin/nologin, + /bin/false, or /usr/bin/false). + rationale: |- If the Group Identifier (GID) of a local interactive users home directory is not the same as the primary GID of the user, this would allow unauthorized @@ -43,15 +47,27 @@ ocil_clause: 'the group ownership is incorrect' ocil: |- To verify the assigned home directory of all interactive users is group- - owned by that users primary GID, run the following command: -
# ls -ld $(awk -F: '($3>={{{ uid_min }}})&&($7 !~ /nologin/){print $6}' /etc/passwd)
+ owned by that user's primary GID, run the following command:
+ # ls -ld $(getent passwd | awk -F: '($3>={{{ uid_min }}})&&($7 !~ /nologin/)&&($7 !~ /\/false$/){print $6}')
+
+ This should return a list of home directories with group ownership matching each user's primary group.
+ Using getent passwd instead of reading /etc/passwd directly ensures that remote users
+ (LDAP, SSSD, NIS, etc.) are also checked.
fixtext: |-
- Change the group owner of a local interactive user’s home directory to the group found in "/etc/passwd". To change the group owner of a local interactive user’s home directory, use the following command:
+ Change the group owner of an interactive user’s home directory to the group found in the system user database.
+
+ Identify the user’s primary group:
+ $ getent passwd smithj + smithj:x:1000:1000:John Smith:/home/smithj:/bin/bash+ + The fourth field (1000) is the primary group ID (GID). Change the home directory group ownership: +
$ sudo chgrp 1000 /home/smithj- Note: The example will be for the user "smithj", who has a home directory of "/home/smithj", and has a primary group of users. + Or use the group name: +
$ sudo chgrp users /home/smithj- $ sudo chgrp users /home/smithj + Note: This applies to all interactive users, including those in remote directories (LDAP, SSSD, NIS, etc.). srg_requirement: 'All {{{ full_name }}} local interactive user home directories must be group-owned by the home directory owner’s primary group.' diff --git a/shared/macros/10-oval.jinja b/shared/macros/10-oval.jinja index 22082d69d395..3f69afb6f012 100644 --- a/shared/macros/10-oval.jinja +++ b/shared/macros/10-oval.jinja @@ -1276,7 +1276,7 @@ Generates the :code:`