Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 19 additions & 9 deletions lib/puppet/type/file/selcontext.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ module Puppet
class SELFileContext < Puppet::Property
include Puppet::Util::SELinux

def skip_property?
!Puppet::Util::SELinux.selinux_support? || @resource[:selinux_ignore_defaults] == :true
end

def retrieve
return :absent unless @resource.stat

Expand All @@ -40,11 +44,6 @@ def retrieve
end

def retrieve_default_context(property)
return nil if Puppet::Util::Platform.windows?
if @resource[:selinux_ignore_defaults] == :true
return nil
end

context = get_selinux_default_context_with_handle(@resource[:path], provider.class.selinux_handle, @resource[:ensure])
unless context
return nil
Expand All @@ -63,10 +62,21 @@ def insync?(value)
debug("SELinux not available for this filesystem. Ignoring parameter.")
true
else
@should = @should.collect { |v| v == :lookup ? retrieve_default_context(name) : v }
if @should.include?(nil)
return true
end

super
end
end

def validate(value)
unless value.is_a?(String) || value == :lookup
raise Puppet::Error, "The property #{name} must be either a string or :lookup"
end
end

def unsafe_munge(should)
unless selinux_support?
return should
Expand Down Expand Up @@ -104,7 +114,7 @@ def sync
enabled."

@event = :file_changed
defaultto { retrieve_default_context(:seluser) }
defaultto { skip_property? ? nil : :lookup }
end

Puppet::Type.type(:file).newproperty(:selrole, :parent => Puppet::SELFileContext) do
Expand All @@ -115,7 +125,7 @@ def sync
enabled."

@event = :file_changed
defaultto { retrieve_default_context(:selrole) }
defaultto { skip_property? ? nil : :lookup }
end

Puppet::Type.type(:file).newproperty(:seltype, :parent => Puppet::SELFileContext) do
Expand All @@ -126,7 +136,7 @@ def sync
enabled."

@event = :file_changed
defaultto { retrieve_default_context(:seltype) }
defaultto { skip_property? ? nil : :lookup }
end

Puppet::Type.type(:file).newproperty(:selrange, :parent => Puppet::SELFileContext) do
Expand All @@ -138,6 +148,6 @@ def sync
Security)."

@event = :file_changed
defaultto { retrieve_default_context(:selrange) }
defaultto { skip_property? ? nil : :lookup }
end
end
4 changes: 4 additions & 0 deletions lib/puppet/util/selinux.rb
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,10 @@ def selinux_category_to_label(category)
# We don't cache this, but there's already a ton of duplicate work
# in the selinux handling code.

if category == :lookup
return category
end

path = Selinux.selinux_translations_path
begin
File.open(path).each do |line|
Expand Down
5 changes: 5 additions & 0 deletions spec/unit/resource/catalog_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@
# audit only resources are unmanaged
# as are resources without properties with should values
it "should write its managed resources' types, namevars" do
if Puppet.features.selinux?
selinux = class_double('selinux', is_selinux_enabled: 0)
stub_const('Selinux', selinux)
end

catalog = Puppet::Resource::Catalog.new("host")

resourcefile = tmpfile('resourcefile')
Expand Down
5 changes: 5 additions & 0 deletions spec/unit/transaction/resource_harness_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@

describe "when evaluating a resource" do
it "produces a resource state that describes what happened with the resource" do
if Puppet.features.selinux?
selinux = class_double('selinux', is_selinux_enabled: 0)
stub_const('Selinux', selinux)
end

status = @harness.evaluate(@resource)

expect(status.resource).to eq(@resource.ref)
Expand Down
22 changes: 17 additions & 5 deletions spec/unit/transaction_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -760,14 +760,26 @@ def post_resource_eval

it "should call Selinux.selabel_close in case Selinux is enabled", :if => Puppet.features.posix? do
handle = double('selinux_handle')
selinux = class_double('selinux', is_selinux_enabled: 1, selabel_close: nil, selabel_open: handle, selabel_lookup: -1)
stub_const('Selinux', selinux)
stub_const('Selinux::SELABEL_CTX_FILE', 0)
resource = Puppet::Type.type(:file).new(:path => make_absolute("/tmp/foo"))
selinux = class_double('selinux',
is_selinux_enabled: 1,
lgetfilecon: [nil, "a:b:c:d"],
selabel_open: handle,
selabel_lookup: -1,
selinux_translations_path: "/dev/null",
selabel_close: nil,
)

if Puppet.features.selinux?
stub_const('Selinux', selinux, :transfer_nested_constants => [:SELABEL_CTX_FILE])
else
stub_const('Selinux', selinux)
stub_const('Selinux::SELABEL_CTX_FILE', 0)
end

resource = Puppet::Type.type(:file).new(:path => make_absolute("/tmp/foo"), :ensure => :file)
transaction = transaction_with_resource(resource)

expect(Selinux).to receive(:selabel_close).with(handle)

transaction.evaluate
end
end
Expand Down
41 changes: 24 additions & 17 deletions spec/unit/type/file/selinux_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -49,34 +49,41 @@
expect(@sel.retrieve).to eq(expectedresult)
end

it "should handle no default gracefully" do
skip if Puppet::Util::Platform.windows?
expect(@sel).to receive(:get_selinux_default_context_with_handle).with(@path, nil, :file).and_return(nil)
it "has a default value of :lookup if SELinux is supported" do
allow(Puppet::Util::SELinux).to receive(:selinux_support?).and_return(true)
expect(@sel.default).to eq(:lookup)
end

it "has a default value of nil if SELinux is not supported" do
allow(Puppet::Util::SELinux).to receive(:selinux_support?).and_return(false)
expect(@sel.default).to be_nil
end

it "should be able to detect default context on platforms other than Windows", unless: Puppet::Util::Platform.windows? do
allow(@sel).to receive(:debug)
it "has a default value of nil if selinux_ignore_defaults is true" do
@resource[:selinux_ignore_defaults] = :true
expect(@sel.default).to be_nil
end

it "looks up the default context when checking sync status", unless: Puppet::Util::Platform.windows? do
allow(@sel).to receive(:selinux_support?).and_return(true)
allow(@sel).to receive(:selinux_label_support?).with(@path).and_return(true)

if param == :selrange
expect(@sel).to receive(:selinux_category_to_label).with(:lookup).and_return(:lookup)
end
@sel.should = [:lookup]

hnd = double("SWIG::TYPE_p_selabel_handle")
allow(@sel.provider.class).to receive(:selinux_handle).and_return(hnd)
expect(@sel).to receive(:get_selinux_default_context_with_handle).with(@path, hnd, :file).and_return("user_u:role_r:type_t:s0")
expectedresult = case param

currentval = case param
when :seluser; "user_u"
when :selrole; "role_r"
when :seltype; "type_t"
when :selrange; "s0"
end
expect(@sel.default).to eq(expectedresult)
end

it "returns nil default context on Windows", if: Puppet::Util::Platform.windows? do
expect(@sel).to receive(:retrieve_default_context)
expect(@sel.default).to be_nil
end

it "should return nil for defaults if selinux_ignore_defaults is true" do
@resource[:selinux_ignore_defaults] = :true
expect(@sel.default).to be_nil
expect(@sel.insync?(currentval)).to be(true)
end

it "should be able to set a new context" do
Expand Down