Skip to content

Commit

Permalink
[issue #119] Update fcontext to allow override of built-in types (#120)
Browse files Browse the repository at this point in the history
* [issue #119] Update fcontext to allow override of built-in types

---------

Signed-off-by: Yansheng Wei <[email protected]>
  • Loading branch information
ywei2017 authored Jul 15, 2024
1 parent f6b0707 commit 3f06103
Show file tree
Hide file tree
Showing 15 changed files with 113 additions and 40 deletions.
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
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

0 comments on commit 3f06103

Please sign in to comment.