diff --git a/docs-chef-io/content/inspec/resources/selinux.md b/docs-chef-io/content/inspec/resources/selinux.md index 50ee3b977..50f9f34c7 100644 --- a/docs-chef-io/content/inspec/resources/selinux.md +++ b/docs-chef-io/content/inspec/resources/selinux.md @@ -11,9 +11,9 @@ platform = "linux" parent = "inspec/resources/os" +++ -Use the `selinux` Chef InSpec audit resource to test the state and mode of SELinux policy. +Use the `selinux` Chef Inspec audit resource to test the configuration data of the SELinux policy, SELinux modules and SELinux booleans. -The `selinux` resource extracts and exposes data reported by the `sestatus` command. +The `selinux` resource extracts and exposes data reported by the `sestatus`, `semodule -lfull`and `semanage boolean -l -n` command. ## Availability @@ -34,6 +34,41 @@ The `selinux` Chef InSpec resource block tests the state and mode of SELinux pol it { should_not be_permissive } end +The `selinux` resource block also declares allows you to write test for many modules: + + describe selinux.modules.where("zebra") do + it { should exist } + it { should be_installed } + it { should be_enabled } + end + +or: + describe selinux.modules.where(status: "installed") do + it { should exist } + its('count') { should cmp 404 } + end + +where + +- `.where()` may specify a specific item and value, to which the resource parameters are compared +- `name`, `status`, `state`, `priority` are valid parameters for `modules` + +The `selinux` resource block also declares allows you to write test for many booleans: + + describe selinux.booleans.where(name: "httpd_enable_homedirs") do + it { should_not be_on } + end + +or: + + describe selinux.booleans.where(name: "xend_run_blktap", state: "on") do + it { should exist } + its('defaults') { should cmp "on" } + end + +- `.where()` may specify a specific item and value, to which the resource parameters are compared +- `name`, `state`, `default` are valid parameters for `booleans` + ## Examples The following examples show how to use this Chef InSpec selinux resource. @@ -52,13 +87,18 @@ describe selinux do it { should be_enforcing } end +### Test if selinux policy type +describe selinux do + its('policy') { should eq "targeted"} +end + ## Matchers For a full list of available matchers, please visit our [matchers page](/inspec/matchers/). ### be_installed -The `be_installed` matcher tests if the SELinux is installed on the system: +The `be_installed` matcher tests if the SElinux policy or SElinux modules is installed on the system: it { should be_installed } @@ -79,3 +119,42 @@ The `be_enforcing` matcher tests if the SELinux mode is set to enforcing: The `be_permissive` matcher tests if the SELinux mode is set to permissive: it { should be_permissive } + +### be_on +The `be_on` matcher tests if the selinux boolean is on. + +### be_enabled +The `be_enabled` matcher tests if the selinux module is enabled + +## Resource Parameters + +- `names`, `status`, `states`, `priorities`, are valid parameters for `modules` + +- `names`, `status`, `states`, `defaults`, are valid parameters for `booleans` + +## Resource Parameter Examples + +### modules + +`modules` returns the information about modules as returned by [semodule -lfull](https://man7.org/linux/man-pages/man8/semodule.8.html). + +Note: semodule -l command does not provide version information in newer versions of linux based systems like RHEL8 and Centos8 so we are not supporting that option [REF](https://access.redhat.com/solutions/2760071). + +describe selinux.modules do + its("names") { should include "zebra" } + its("status") { should include "installed" } + its("states") { should include "enabled" } + its("priorities") { should include "100" } +end + +### booleans + +`booleans` returns the information about boolean as returned by [semanage boolean -l -n](https://man7.org/linux/man-pages/man8/semanage-boolean.8.html) + +describe selinux.booleans do + its("names") { should include "httpd_enable_homedirs" } + its("states") { should include "on" } + its("states") { should include "off" } + its("defaults") { should include "on" } + its("defaults") { should include "off" } +end diff --git a/lib/inspec/resources/selinux.rb b/lib/inspec/resources/selinux.rb index 36d84bcdb..876039a66 100644 --- a/lib/inspec/resources/selinux.rb +++ b/lib/inspec/resources/selinux.rb @@ -48,7 +48,7 @@ module Inspec::Resources name "selinux" supports platform: "linux" - desc "Use selinux Inspec resource to test state/mode of the selinux policy." + desc "Use selinux Chef Inspec resource to test the configuration data of the selinux policy, selinux modules and selinux booleans." example <<~EXAMPLE describe selinux do @@ -57,6 +57,29 @@ module Inspec::Resources it { should be_permissive } it { should be_enforcing } end + + describe selinux do + its('policy') { should eq "targeted"} + end + + describe selinux.modules.where("zebra") do + it { should exist } + it { should be_installed } + it { should be_enabled } + end + + describe selinux.modules.where(status: "installed") do + it { should exist } + its('count') { should cmp 404 } + end + + describe selinux.booleans.where(name: "xend_run_blktap") do + it { should be_on } + end + + describe selinux.booleans.where { name == "xend_run_blktap" && state == "on" } do + it { should exist } + end EXAMPLE def initialize(selinux_path = "/etc/selinux/config") @@ -89,6 +112,10 @@ module Inspec::Resources @data["currentmode"] == "permissive" end + def policy + @data["loadedpolicyname"] + end + def modules SelinuxModuleFilter.new(parse_modules) end diff --git a/test/fixtures/cmd/semanage-boolean b/test/fixtures/cmd/semanage-boolean new file mode 100644 index 000000000..74dda0792 --- /dev/null +++ b/test/fixtures/cmd/semanage-boolean @@ -0,0 +1,3 @@ +xen_use_nfs (off , off) Allow xen to use nfs +xend_run_blktap (on , on) Allow xend to run blktap +zebra_write_config (off , off) Allow zebra to write config \ No newline at end of file diff --git a/test/fixtures/cmd/semodule-lfull b/test/fixtures/cmd/semodule-lfull new file mode 100644 index 000000000..743ab07cf --- /dev/null +++ b/test/fixtures/cmd/semodule-lfull @@ -0,0 +1,3 @@ +100 foo pp +100 bar pp disabled +100 baz pp \ No newline at end of file diff --git a/test/helpers/mock_loader.rb b/test/helpers/mock_loader.rb index b46a288a7..df4386489 100644 --- a/test/helpers/mock_loader.rb +++ b/test/helpers/mock_loader.rb @@ -558,11 +558,15 @@ class MockLoader # filesystem command "2e7e0d4546342cee799748ec7e2b1c87ca00afbe590fa422a7c27371eefa88f0" => cmd.call("get-wmiobject-filesystem"), "sestatus" => cmd.call("sestatus"), + "semodule -lfull" => cmd.call("semodule-lfull"), + "semanage boolean -l -n" => cmd.call("semanage-boolean"), } if @platform && (@platform[:name] == "windows" || @platform[:name] == "freebsd") mock_cmds.merge!( - "sestatus" => empty.call + "sestatus" => empty.call, + "semodule -lfull" => empty.call, + "semanage boolean -l -n" => empty.call, ) end diff --git a/test/unit/resources/selinux_test.rb b/test/unit/resources/selinux_test.rb index 74376b6c1..8225da6f4 100644 --- a/test/unit/resources/selinux_test.rb +++ b/test/unit/resources/selinux_test.rb @@ -3,26 +3,29 @@ require "inspec/resource" require "inspec/resources/selinux" describe "Inspec::Resources::Selinux" do + let(:resource) { load_resource("selinux") } + it "verify selinux is installed" do resource = load_resource("selinux", "/etc/selinux/selinux_conf") _(resource.installed?).must_equal true end it "verify selinux state - enforcing" do - resource = load_resource("selinux") _(resource.enforcing?).must_equal true end it "verify selinux state - permissive" do - resource = load_resource("selinux") _(resource.permissive?).must_equal false end - it "verify selinux disabled " do - resource = load_resource("selinux") + it "verify selinux disabled" do _(resource.disabled?).must_equal false end + it "verify selinux policy type is targeted" do + _(resource.policy).must_equal "targeted" + end + it "verify selinux on linux" do resource = MockLoader.new(:linux).load_resource("selinux") _(resource.enforcing?).must_equal true @@ -41,4 +44,25 @@ describe "Inspec::Resources::Selinux" do _(resource.installed?).must_equal false _(resource.enforcing?).must_equal false end + + it "verify selinux.modules is exist" do + _(resource.modules.exist?).must_equal true + end + + it "verify selinux.modules parsing" do + _(resource.modules.names).must_equal %w{foo bar baz} + _(resource.modules.states).must_equal %w{enabled disabled enabled} + _(resource.modules.status).must_equal %w{installed installed installed} + _(resource.modules.priorities).must_equal %w{100 100 100} + end + + it "verify selinux.booleans is exist" do + _(resource.booleans.exist?).must_equal true + end + + it "verify selinux.booleans parsing" do + _(resource.booleans.names).must_equal %w{xen_use_nfs xend_run_blktap zebra_write_config} + _(resource.booleans.states).must_equal %w{off on off} + _(resource.booleans.defaults).must_equal %w{off on off} + end end