Skip to content
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

[issue #119] Update fcontext to allow override of built-in types #120

Merged
merged 12 commits into from
Jul 15, 2024
35 changes: 25 additions & 10 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,37 +10,52 @@ name: ci
jobs:
lint-unit:
uses: sous-chefs/.github/.github/workflows/[email protected]
permissions:
actions: write
checks: write
pull-requests: write
statuses: write
issues: write

integration:
needs: lint-unit
runs-on: macos-10.15
runs-on: ubuntu-latest
Stromweld marked this conversation as resolved.
Show resolved Hide resolved
strategy:
matrix:
os:
- almalinux-8
- almalinux-9
- amazonlinux-2
- centos-7
- centos-stream-8
- amazonlinux-2023
- centos-stream-9
- fedora-latest
- debian-10
- debian-11
- oracle-7
- debian-12
- oracle-8
- oracle-9
- rockylinux-8
- ubuntu-1804
- rockylinux-9
- ubuntu-2004
# Disabled due to image problems:
# https://github.com/chef/bento/issues/1405
# - ubuntu-2204
- ubuntu-2204
- ubuntu-2404
suite:
- enforcing
- permissive
- disabled
- port
- fcontext
fail-fast: false

steps:
- name: Install Vagrant VirtualBox
run: |
wget -O- https://apt.releases.hashicorp.com/gpg | gpg --dearmor | sudo tee /usr/share/keyrings/hashicorp-archive-keyring.gpg
wget -O- https://www.virtualbox.org/download/oracle_vbox_2016.asc | gpg --dearmor | sudo tee /usr/share/keyrings/oracle-virtualbox-2016.gpg
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
echo "deb [signed-by=/usr/share/keyrings/oracle-virtualbox-2016.gpg] https://download.virtualbox.org/virtualbox/debian $(lsb_release -cs) contrib" | sudo tee /etc/apt/sources.list.d/virtualbox.list
sudo apt-get update
sudo apt-get install -y software-properties-common vagrant virtualbox
vagrant --version
vboxmanage --version
- name: Check out code
uses: actions/checkout@v4
- name: Install Chef
Expand Down
4 changes: 2 additions & 2 deletions documentation/selinux_boolean.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[Back to resource list](../README.md#resources)

# selinux_boolean

[Back to resource list](../README.md#resources)

Set SELinux boolean values.

Introduced: v4.0.0
Expand Down
4 changes: 2 additions & 2 deletions documentation/selinux_fcontext.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[Back to resource list](../README.md#resources)

# selinux_fcontext

[Back to resource list](../README.md#resources)

Set the SELinux context of files with `semanage fcontext`.

## Actions
Expand Down
4 changes: 2 additions & 2 deletions documentation/selinux_install.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[Back to resource list](../README.md#resources)

# selinux_install

[Back to resource list](../README.md#resources)

The `selinux_install` resource is used to encapsulate the set of selinux packages to install in order to manage selinux. It also ensures the directory `/etc/selinux` is created.

Introduced: v4.0.0
Expand Down
4 changes: 2 additions & 2 deletions documentation/selinux_login.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[Back to resource list](../README.md#resources)

# selinux_login

[Back to resource list](../README.md#resources)

The `selinux_login` resource is used to manage Linux user to SELinux user mappings on the system.

## Actions
Expand Down
4 changes: 2 additions & 2 deletions documentation/selinux_module.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[Back to resource list](../README.md#resources)

# selinux_module

[Back to resource list](../README.md#resources)

Create an SELinux module from a cookfile file or content provided as a string.

Introduced: v4.0.0
Expand Down
4 changes: 2 additions & 2 deletions documentation/selinux_permissive.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[Back to resource list](../README.md#resources)

# selinux_permissive

[Back to resource list](../README.md#resources)

Allows some types to misbehave without stopping them. Not as good as specific policies, but better than disabling SELinux entirely.

> This does not set the SELinux state to permissive! Use [`selinux_state`](selinux_state.md) for that.
Expand Down
4 changes: 2 additions & 2 deletions documentation/selinux_port.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[Back to resource list](../README.md#resources)

# selinux_port

[Back to resource list](../README.md#resources)

Allows assigning a network port to a certain SELinux context, e.g. for running a webserver on a non-standard port.

## Actions
Expand Down
6 changes: 3 additions & 3 deletions documentation/selinux_state.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[Back to resource list](../README.md#resources)

# selinux_state

[Back to resource list](../README.md#resources)

The `selinux_state` resource is used to manage the SELinux state on the system. It does this by using the `setenforce` command and rendering the `/etc/selinux/config` file from a template.

Introduced: v4.0.0
Expand All @@ -13,7 +13,7 @@ Introduced: v4.0.0
| `:enforcing` | *(Default)* Set the SELinux state to enforcing |
| `:permissive` | Set the state to permissive |
| `:disabled` | Set the state to disabled |
`

> ⚠ Switching to or from `disabled` requires a reboot!

## Properties
Expand Down
4 changes: 2 additions & 2 deletions documentation/selinux_user.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[Back to resource list](../README.md#resources)

# selinux_user

[Back to resource list](../README.md#resources)

The `selinux_user` resource is used to manage SELinux users on the system.

## Actions
Expand Down
12 changes: 7 additions & 5 deletions kitchen.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,20 @@ verifier:

platforms:
- name: almalinux-8
- name: almalinux-9
- name: amazonlinux-2
- name: centos-7
- name: centos-stream-8
- name: debian-10
- name: amazonlinux-2023
- name: centos-stream-9
- name: debian-11
- name: debian-12
- name: fedora-latest
- name: oracle-7
- name: oracle-8
- name: oracle-9
- name: rockylinux-8
- name: ubuntu-18.04
- name: rockylinux-9
- name: ubuntu-20.04
- name: ubuntu-22.04
- name: ubuntu-24.04

suites:
- name: enforcing
Expand Down
9 changes: 8 additions & 1 deletion resources/fcontext.rb
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,14 @@ def relabel_files
return
end

unless current_file_context
# "add" is performed in two scenarios.
# 1: The local file_contexts.local has an entry for new_resource.file_spec, but secontext <> new_resource.secontext
# 2. The local file_contexts.local does NOT have an entry for new_resource.file_spec, AND
# either the system default (file_contexts) does not have an entry for new_resource.file_spec, or the secontext <> new_resource.secontext
# In both scenarios, file_contexts.local is created with a new entry, or the secontext is updated.

cfc = current_file_context
unless cfc && cfc == new_resource.secontext
converge_by "adding label #{new_resource.secontext} to #{new_resource.file_spec}" do
shell_out!("semanage fcontext -a -f #{new_resource.file_type} -t #{new_resource.secontext} '#{new_resource.file_spec}'")
relabel_files
Expand Down
15 changes: 10 additions & 5 deletions spec/unit/resources/fcontext_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@

context 'when not set' do
stubs_for_provider('selinux_fcontext[/test]') do |provider|
allow(provider).to receive_shell_out('semanage fcontext -l', stdout: <<~EOF)
allow(provider).to receive_shell_out('semanage fcontext -l', stdout: <<~EOF
/other/files all files user:role:type:level
EOF
)
end

# this is what actually checks that the fcontext was set correctly
Expand All @@ -38,15 +39,18 @@

context 'when set to incorrect value' do
stubs_for_provider('selinux_fcontext[/test]') do |provider|
allow(provider).to receive_shell_out('semanage fcontext -l', stdout: <<~EOF)
/test all files user:role:type:level
allow(provider).to receive_shell_out('semanage fcontext -l', stdout: <<~EOF
/test all files user:role:type:level'
EOF
)
end

# this is what actually checks that the fcontext was set correctly
# incorrect commands would not be stubbed and would throw error
stubs_for_provider('selinux_fcontext[/test]') do |provider|
# when set but incorrect, only modify calls (-m) and delete calls (-d) should happen
# when set but incorrect, the incorrect context is "deemed" as the built-in type, and
# attemp to perform the full cycle of activities
allow(provider).to receive_shell_out("semanage fcontext -a -f a -t foo '/test'")
allow(provider).to receive_shell_out("semanage fcontext -m -f a -t foo '/test'")
allow(provider).to receive_shell_out("semanage fcontext -d -f a '/test'")
end
Expand All @@ -60,9 +64,10 @@

context 'when set to correct value' do
stubs_for_provider('selinux_fcontext[/test]') do |provider|
allow(provider).to receive_shell_out('semanage fcontext -l', stdout: <<~EOF)
allow(provider).to receive_shell_out('semanage fcontext -l', stdout: <<~EOF
/test all files user:role:foo:level
EOF
)
end

# this is what actually checks that the fcontext was set correctly
Expand Down
35 changes: 35 additions & 0 deletions test/cookbooks/selinux_test/recipes/fcontext.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,38 @@
secontext 'etc_t'
file_type 'd'
end

# testing override of built-in context, using '/home/[^/]+/\.ssh(/.*)?'
# Use converge counter so we only do the fcontext manipulation in first round. Otherwise
# the "enforce_idempotency" will cause converge to fail.

node.run_state['chef_converge_counter'] = shell_out('cat /tmp/chef_converge_counter').stdout.to_i
node.run_state['chef_converge_counter'] += 1
file '/tmp/chef_converge_counter' do
content lazy { node.run_state['chef_converge_counter'].to_s }
mode '0644'
only_if { node.run_state['chef_converge_counter'] == 1 }
end

execute 'Check built-in fcontext' do
command 'matchpathcon /home/user1/.ssh | grep ssh_home_t'
only_if { node.run_state['chef_converge_counter'] == 1 }
end

# override with 'shadow_t'
selinux_fcontext '/home/[^/]+/\.ssh(/.*)?' do
secontext 'shadow_t'
action :add
only_if { node.run_state['chef_converge_counter'] == 1 }
end

execute 'Check fcontext override' do
command 'matchpathcon /home/user1/.ssh | grep shadow_t'
only_if { node.run_state['chef_converge_counter'] == 1 }
end

# remove the override
selinux_fcontext '/home/[^/]+/\.ssh(/.*)?' do
action :delete
only_if { node.run_state['chef_converge_counter'] == 1 }
end
9 changes: 9 additions & 0 deletions test/integration/fcontext/controls/fcontext_control.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,12 @@
its('selinux_label') { should match 'etc_t' }
end
end

control 'fcontext override' do
title 'Verify that built-in SELinux file contexts override works correctly'

describe command('matchpathcon /home/user1/.ssh') do
its('exit_status') { should eq 0 }
its('stdout') { should match /ssh_home_t/ }
end
end
Loading