-
Notifications
You must be signed in to change notification settings - Fork 50
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
docs: Add example playbook and "readme" for confined users #184
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||
---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,61 @@ | ||||||||
# Confined users | ||||||||
|
||||||||
By default linux users are mapped to SELinux user `unconfined_u`, which is subject to minimal restrictions. You can greatly improve security of your systems by confining users, that is by mapping them to SELinux users with less privilege. | ||||||||
`confined_users-playbook.yml` contains an example configuration for confining existing users and creating new ones with varying levels of access. | ||||||||
|
||||||||
## Expected functionality | ||||||||
|
||||||||
* Set default user mapping | ||||||||
* Confine existing users accounts | ||||||||
* Set booleans to customize access | ||||||||
|
||||||||
## Variables | ||||||||
|
||||||||
### selinux_booleans | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed, thank you. |
||||||||
|
||||||||
SELinux policy provides several booleans for customizing access of confined users. | ||||||||
|
||||||||
`selinux_booleans` is expected to hold a list of booleans together with their intended value and persistence setting. | ||||||||
Formally it is a `list` of `dict`, where each `dict` is in the same format as used by the | ||||||||
[seboolean](https://docs.ansible.com/ansible/latest/collections/ansible/posix/seboolean_module.html#ansible-collections-ansible-posix-seboolean-module) | ||||||||
module. | ||||||||
|
||||||||
```yaml | ||||||||
selinux_booleans: | ||||||||
- {name: 'ssh_sysadm_login', state: 'on', persistent: 'yes'} | ||||||||
- {name: 'user_exec_content', state: 'off', persistent: 'yes'} | ||||||||
``` | ||||||||
|
||||||||
See | ||||||||
[confined users documentation](https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/9/html-single/using_selinux/index#managing-confined-and-unconfined-users_using-selinux) | ||||||||
for a list of relevant booleans. | ||||||||
|
||||||||
### existing_privileged_users | ||||||||
|
||||||||
Specify a list of existing users to be mapped to `staff_u` and allowed to use `sudo` to perform administrative tasks. | ||||||||
|
||||||||
```yaml | ||||||||
existing_privileged_users: | ||||||||
- "Mark" | ||||||||
- "Roger" | ||||||||
``` | ||||||||
|
||||||||
### selinux_logins | ||||||||
|
||||||||
Manage the linux user to SELinux user mapping. This is a `list` of `dict`, | ||||||||
where each `dict` is in the same format as used by the | ||||||||
[selogin](https://docs.ansible.com/ansible/latest/collections/community/general/selogin_module.html) | ||||||||
module. | ||||||||
|
||||||||
```yaml | ||||||||
selinux_logins: | ||||||||
- {login: 'plautrba', seuser: 'staff_u', state: 'absent'} | ||||||||
- {login: '__default__', seuser: 'staff_u', serange: 's0-s0:c0.c1023', state: 'present'} | ||||||||
``` | ||||||||
|
||||||||
`__default__` is the value assigned to a new user when no login mapping is specified for them. All other lines must correspond to existing user accounts. Note that changing a login mapping changes the file context definitions of the user's home directory. This change is applied using `restorecon` at the end of the playbook. | ||||||||
|
||||||||
## Examples | ||||||||
|
||||||||
Confining users is demonstrated in | ||||||||
[confined_users-playbook.yml](examples/confined_users-playbook.yml) playbook. |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,126 @@ | ||||||
--- | ||||||
- name: Manage SELinux policy example | ||||||
hosts: all | ||||||
become: true | ||||||
vars: | ||||||
# Use "targeted" SELinux policy type | ||||||
selinux_policy: targeted | ||||||
# Set "enforcing" mode | ||||||
selinux_state: enforcing | ||||||
# Set SELinux booleans | ||||||
selinux_booleans: | ||||||
# Allow ssh logins as sysadm_r:sysadm_t | ||||||
# - {name: 'ssh_sysadm_login', state: 'on', persistent: 'yes'} | ||||||
# Allow sysadm_u/staff_u to execute applications in their | ||||||
# home directories and /tmp | ||||||
- {name: 'sysadm_exec_content', state: 'on', persistent: 'yes'} | ||||||
- {name: 'staff_exec_content', state: 'on', persistent: 'yes'} | ||||||
# But block normal users from the same | ||||||
- {name: 'user_exec_content', state: 'off', persistent: 'yes'} | ||||||
# Allow staff user to create and transition to svirt domains | ||||||
# - {name: 'staff_use_svirt', state: 'on', persistent: 'yes'} | ||||||
# Allow confined users the ability to execute the ping and traceroute | ||||||
# - {name: 'selinuxuser_ping', state: 'on', persistent: 'yes'} | ||||||
# Allow users to connect to the local mysql server | ||||||
# - {name: 'selinuxuser_mysql_connect_enabled', state: 'on', | ||||||
# persistent: 'yes'} | ||||||
# Allow samba and winbind-rpcd to share users home directories | ||||||
# - {name: 'samba_enable_home_dirs', state: 'on', persistent: 'yes'} | ||||||
# Disallow programs, such as newrole, from transitioning to administrative | ||||||
# user domains | ||||||
# - {name: 'secure_mode', state: 'on', persistent: 'yes'} | ||||||
|
||||||
# List of existing users to be mapped to staff_u and allowed to use sudo | ||||||
existing_privileged_users: | ||||||
- "Lizzy" | ||||||
- "Tarja" | ||||||
|
||||||
# The following section specifies mapping of EXISTING system users | ||||||
# to SELinux users | ||||||
selinux_logins: | ||||||
# Map all new users to SElinux user "user_u" (instead of "unconfined_u") | ||||||
- {login: '__default__', seuser: 'user_u', serange: 's0', | ||||||
state: 'present'} | ||||||
# Alternatively map all new users to SElinux user "staff_u" (instead of | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I skipped this one since it would indent the comment from the surrounding lines. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ok - what do you suggest we do to make yamllint happy? |
||||||
# "unconfined_u") | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
# - {login: '__default__', seuser: 'staff_u', serange: 's0-s0:c0.c1023', | ||||||
# state: 'present'} | ||||||
# Map admin users to SElinux user "staff_u" | ||||||
# Map select non-admin privileged users to SELinux user "staff_u" | ||||||
# - {login: '<existing_user>', seuser: 'staff_u', serange: 's0', | ||||||
# state: 'present'} | ||||||
# - {login: 'Lizzy', seuser: 'staff_u', serange: 's0', | ||||||
# state: 'present'} | ||||||
|
||||||
# Prepare the prerequisites required for this playbook | ||||||
tasks: | ||||||
# Enable kiosk mode -- add extremely limited users "guest" and "xguest" | ||||||
# - name: Install xguest package | ||||||
# yum: | ||||||
# name: xguest | ||||||
# state: present | ||||||
|
||||||
# Create login mappings for "existing_privileged_users" | ||||||
- name: Build list of selinux logins | ||||||
set_fact: | ||||||
selinux_logins: "{{ selinux_logins + login_helper | list }}" | ||||||
with_items: "{{ existing_privileged_users }}" | ||||||
vars: | ||||||
login_helper: | ||||||
- {login: "{{ item }}", seuser: 'staff_u', serange: 's0', | ||||||
state: 'present'} | ||||||
|
||||||
# Users that get assigned a new SELinux user need to have their homedirs | ||||||
# relabeled. | ||||||
# Gather homedirs of each user with a new login mapping | ||||||
- name: Gather homedirs of users with new login mapping | ||||||
shell: >- | ||||||
# exit in case of errors in the following command ("-o pipefail" | ||||||
# cannot be used since "getent passwd __default__" is expected to fail) | ||||||
set -eu; | ||||||
getent passwd "{{ item.login }}" | awk -F: '{ print $6 }' | ||||||
register: __login_homedirs | ||||||
with_items: "{{ selinux_logins }}" | ||||||
changed_when: false | ||||||
|
||||||
# Relabel the gathered homedirs using "selinux_restore_dirs" variable | ||||||
- name: Relabel homedirs of users with new login mapping | ||||||
set_fact: | ||||||
selinux_restore_dirs: "{{ selinux_restore_dirs | default([]) | ||||||
+ [item.stdout] }}" | ||||||
when: item.stdout != "" | ||||||
with_items: "{{ __login_homedirs.results if __login_homedirs.results is | ||||||
iterable else [] }}" | ||||||
|
||||||
# Allow existing_privileged_users to use sudo | ||||||
- name: Allow privileged users to use sudo | ||||||
copy: | ||||||
dest: /etc/sudoers.d/{{ item }} | ||||||
content: "{{ item }} ALL=(ALL) TYPE=sysadm_t ROLE=sysadm_r ALL" | ||||||
mode: "0640" | ||||||
loop: "{{ existing_privileged_users | list }}" | ||||||
|
||||||
# Run selinux role to apply changes described in "vars" section | ||||||
- name: Execute the role and catch errors | ||||||
block: | ||||||
- name: Include selinux role | ||||||
include_role: | ||||||
name: linux-system-roles.selinux | ||||||
rescue: | ||||||
# Fail if failed for a different reason than selinux_reboot_required. | ||||||
- name: Handle errors | ||||||
fail: | ||||||
msg: "role failed" | ||||||
when: not selinux_reboot_required | ||||||
|
||||||
- name: Restart managed host | ||||||
reboot: | ||||||
|
||||||
- name: Wait for managed host to come back | ||||||
wait_for_connection: | ||||||
delay: 10 | ||||||
timeout: 300 | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why so long? Is this because selinux has to do some sort of filesystem-wide restorecon? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is just copied from the first example. |
||||||
|
||||||
- name: Reapply the role | ||||||
include_role: | ||||||
name: linux-system-roles.selinux |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed, thank you.