Showing with 93 additions and 29 deletions.
  1. +16 −0 CHANGELOG.md
  2. +1 −1 lib/facter/selinux_semanage_is_python3.rb
  3. +19 −12 lib/puppet/provider/selinux_fcontext/semanage.rb
  4. +1 −3 metadata.json
  5. +56 −13 spec/unit/puppet/provider/selinux_fcontext/semanage_spec.rb
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,22 @@ All notable changes to this project will be documented in this file.
Each new release typically also includes the latest modulesync defaults.
These should not affect the functionality of the module.

## [v3.0.0](https://github.com/voxpupuli/puppet-selinux/tree/v3.0.0) (2019-06-17)

[Full Changelog](https://github.com/voxpupuli/puppet-selinux/compare/v2.0.0...v3.0.0)

**Breaking changes:**

- Python 3 semanage is named python3-libsemanage; Drop Fedora 26/27 support [\#287](https://github.com/voxpupuli/puppet-selinux/pull/287) ([ehelms](https://github.com/ehelms))

**Fixed bugs:**

- Load system policy contexts [\#290](https://github.com/voxpupuli/puppet-selinux/pull/290) ([ekohl](https://github.com/ekohl))

**Closed issues:**

- Fcontext fails on re-run on newer platforms [\#288](https://github.com/voxpupuli/puppet-selinux/issues/288)

## [v2.0.0](https://github.com/voxpupuli/puppet-selinux/tree/v2.0.0) (2019-05-15)

[Full Changelog](https://github.com/voxpupuli/puppet-selinux/compare/v1.6.1...v2.0.0)
Expand Down
2 changes: 1 addition & 1 deletion lib/facter/selinux_semanage_is_python3.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Facter.add(:selinux_semanage_is_python3) do
confine osfamily: 'RedHat'
setcode do
Facter::Core::Execution.execute('rpm -q libsemanage-python3') !~ %r{not installed}
Facter::Core::Execution.execute('rpm -q python3-libsemanage') !~ %r{not installed}
end
end
31 changes: 19 additions & 12 deletions lib/puppet/provider/selinux_fcontext/semanage.rb
Original file line number Diff line number Diff line change
Expand Up @@ -66,22 +66,29 @@ def self.parse_fcontext_lines(lines)
ret
end

def self.parse_fcontext_file(path)
return [] unless File.exist?(path)
parse_fcontext_lines(File.readlines(path))
end

def self.instances
# With fcontext, we only need to care about local customisations as they
# should never conflict with system policy
# Old semanage fails with --locallist, use -C
local_fcs = Selinux.selinux_file_context_local_path
if File.exist? local_fcs
parse_fcontext_lines(File.readlines(local_fcs))
else
# no file, no local contexts
[]
end
parse_fcontext_file(Selinux.selinux_file_context_local_path)
end

def self.system_policy_instances
parse_fcontext_file(Selinux.selinux_file_context_path)
end

def self.prefetch(resources)
# is there a better way to do this? map port/protocol pairs to the provider regardless of the title
# and make sure all system resources have ensure => :present so that we don't try to remove them
# This loads resources from built in instances. These are part of the
# system policy. That means we can't modify them, but we should still be
# aware of them.
system_policy_instances.each do |provider|
resource = resources[provider.name]
resource.provider = provider if resource
end

# These are the local overrides. We prefer them over the system policy.
instances.each do |provider|
resource = resources[provider.name]
resource.provider = provider if resource
Expand Down
4 changes: 1 addition & 3 deletions metadata.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "puppet-selinux",
"version": "2.0.0",
"version": "3.0.0",
"author": "Vox Pupuli",
"summary": "This class manages SELinux on RHEL based systems",
"license": "Apache-2.0",
Expand All @@ -25,8 +25,6 @@
{
"operatingsystem": "Fedora",
"operatingsystemrelease": [
"26",
"27",
"28",
"29"
]
Expand Down
69 changes: 56 additions & 13 deletions spec/unit/puppet/provider/selinux_fcontext/semanage_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ module Selinux
def selinux_file_context_local_path
'spec_dummy'
end

def selinux_file_context_path
'spec_policy_dummy'
end
end

semanage_provider = Puppet::Type.type(:selinux_fcontext).provider(:semanage)
Expand All @@ -19,6 +23,12 @@ def selinux_file_context_local_path
/something/else -s <<none>>
EOS

fcontexts_system = <<-EOS
# This file is auto-generated by libsemanage
# Do not edit directly.
/var/log system_u:object_r:var_log_t:s0
EOS

describe semanage_provider do
on_supported_os.each do |os, facts|
context "on #{os}" do
Expand Down Expand Up @@ -93,26 +103,35 @@ def selinux_file_context_local_path
end
context 'With resources differing from the catalog' do
let(:resources) do
return { '/var/lib/mydir_s' => fcontext.new(
name: '/var/lib/mydir_s',
pathspec: '/var/lib/mydir',
file_type: 's',
seltype: 'some_type_t'
),
'/foobar_a' => fcontext.new(
name: '/foobar_a',
file_type: 'a',
pathspec: '/foobar',
seltype: 'mytype_t',
seluser: 'myuser_u'
) }
return {
# This one should be loaded from the system policy
'/var/log_a' => fcontext.new(
name: '/var/log_a'
),
'/var/lib/mydir_s' => fcontext.new(
name: '/var/lib/mydir_s',
pathspec: '/var/lib/mydir',
file_type: 's',
seltype: 'some_type_t'
),
'/foobar_a' => fcontext.new(
name: '/foobar_a',
file_type: 'a',
pathspec: '/foobar',
seltype: 'mytype_t',
seluser: 'myuser_u'
)
}
end

before do
# prefetch should find the provider parsed from this:
Selinux.expects(:selinux_file_context_local_path).returns('spec_dummy')
File.expects(:exist?).with('spec_dummy').returns(true)
File.expects(:readlines).with('spec_dummy').returns(fcontexts_local.split("\n"))
Selinux.expects(:selinux_file_context_path).returns('spec_policy_dummy')
File.expects(:exist?).with('spec_policy_dummy').returns(true)
File.expects(:readlines).with('spec_policy_dummy').returns(fcontexts_system.split("\n"))
semanage_provider.prefetch(resources)
end
it 'finds provider for /foobar' do
Expand All @@ -138,6 +157,30 @@ def selinux_file_context_local_path
described_class.expects(:semanage).with('fcontext', '-m', '-s', 'unconfined_u', '-t', 'bin_t', '-f', 'a', '/foobar')
p.seluser = 'unconfined_u'
end

it 'finds provider for /var/log' do
p = resources['/var/log_a'].provider
expect(p).not_to eq(nil)
end
context 'has the correct attributes from the system policy' do
let(:p) { resources['/var/log_a'].provider }

it { expect(p.name).to eq('/var/log_a') }
it { expect(p.file_type).to eq('a') }
it { expect(p.seltype).to eq('var_log_t') }
it { expect(p.selrole).to eq('object_r') }
it { expect(p.seluser).to eq('system_u') }
end
it 'can change seltype' do
p = resources['/var/log_a'].provider
described_class.expects(:semanage).with('fcontext', '-m', '-t', 'new_type_t', '-f', 'a', '/var/log')
p.seltype = 'new_type_t'
end
it 'can change seluser' do
p = resources['/var/log_a'].provider
described_class.expects(:semanage).with('fcontext', '-m', '-s', 'unconfined_u', '-t', 'var_log_t', '-f', 'a', '/var/log')
p.seluser = 'unconfined_u'
end
end
end
end
Expand Down