[Pkg-puppet-devel] [SCM] Puppet packaging for Debian branch, master, updated. debian/0.24.6-1-356-g5718585
James Turnbull
james at lovedthanlost.net
Fri Jan 23 14:21:21 UTC 2009
The following commit has been merged in the master branch:
commit a562ce5f7c6737280b92ee05b0609bd4b8088450
Author: Sean E. Millichamp <sean at bruenor.org>
Date: Wed Oct 8 11:39:10 2008 -0400
Add unit test coverage for Puppet::Util::SELinux and fix problems found by tests
diff --git a/lib/puppet/util/selinux.rb b/lib/puppet/util/selinux.rb
index e99ee30..8c1aecf 100644
--- a/lib/puppet/util/selinux.rb
+++ b/lib/puppet/util/selinux.rb
@@ -18,11 +18,22 @@ module Puppet::Util::SELinux
unless selinux_support?
return nil
end
- context = `stat -c %C #{file}`
- if ($?.to_i >> 8) > 0
+ context = ""
+ begin
+ execpipe("stat -c %C #{file}") do |out|
+ out.each do |line|
+ context << line
+ end
+ end
+ rescue Puppet::ExecutionFailure
return nil
end
context.chomp!
+ # Handle the case that the system seems to have SELinux support but
+ # stat finds unlabled files.
+ if context == "(null)"
+ return nil
+ end
return context
end
@@ -40,8 +51,14 @@ module Puppet::Util::SELinux
unless FileTest.executable?("/usr/sbin/matchpathcon")
return nil
end
- context = %x{/usr/sbin/matchpathcon #{file} 2>&1}
- if ($?.to_i >> 8) > 0
+ context = ""
+ begin
+ execpipe("/usr/sbin/matchpathcon #{file}") do |out|
+ out.each do |line|
+ context << line
+ end
+ end
+ rescue Puppet::ExecutionFailure
return nil
end
# For a successful match, matchpathcon returns two fields separated by
@@ -57,18 +74,15 @@ module Puppet::Util::SELinux
if context.nil? or context == "unlabeled"
return nil
end
- unless context =~ /^[a-z0-9_]+:[a-z0-9_]+:[a-z0-9_]+(:[a-z0-9_])?/
+ unless context =~ /^([a-z0-9_]+):([a-z0-9_]+):([a-z0-9_]+)(?::([a-zA-Z0-9:,._-]+))?/
raise Puppet::Error, "Invalid context to parse: #{context}"
end
- bits = context.split(':')
ret = {
- :seluser => bits[0],
- :selrole => bits[1],
- :seltype => bits[2]
+ :seluser => $1,
+ :selrole => $2,
+ :seltype => $3,
+ :selrange => $4,
}
- if bits.length == 4
- ret[:selrange] = bits[3]
- end
return ret[component]
end
@@ -97,7 +111,9 @@ module Puppet::Util::SELinux
unless retval
error = Puppet::Error.new("failed to chcon %s" % [@resource[:path]])
raise error
+ return false
end
+ return true
end
# Since this call relies on get_selinux_default_context it also needs a
@@ -113,7 +129,8 @@ module Puppet::Util::SELinux
cur_context = get_selinux_current_context(file)
if new_context != cur_context
set_selinux_context(file, new_context)
+ return new_context
end
- return new_context
+ return nil
end
end
diff --git a/spec/unit/util/selinux.rb b/spec/unit/util/selinux.rb
new file mode 100644
index 0000000..1718404
--- /dev/null
+++ b/spec/unit/util/selinux.rb
@@ -0,0 +1,174 @@
+#!/usr/bin/env ruby
+
+Dir.chdir(File.dirname(__FILE__)) { (s = lambda { |f| File.exist?(f) ? require(f) : Dir.chdir("..") { s.call(f) } }).call("spec/spec_helper.rb") }
+
+require 'puppet/util/selinux'
+include Puppet::Util::SELinux
+
+describe Puppet::Util::SELinux do
+
+ describe "selinux_support?" do
+ it "should return :true if this system has SELinux enabled" do
+ FileTest.expects(:exists?).with("/selinux/enforce").returns true
+ selinux_support?.should be_true
+ end
+
+ it "should return :false if this system lacks SELinux" do
+ FileTest.expects(:exists?).with("/selinux/enforce").returns false
+ selinux_support?.should be_false
+ end
+ end
+
+ describe "get_selinux_current_context" do
+ it "should return nil if no SELinux support" do
+ self.expects(:selinux_support?).returns false
+ get_selinux_current_context("/foo").should be_nil
+ end
+
+ it "should return a context" do
+ self.expects(:selinux_support?).returns true
+ self.expects(:execpipe).with("stat -c %C /foo").yields ["user_u:role_r:type_t:s0\n"]
+ get_selinux_current_context("/foo").should == "user_u:role_r:type_t:s0"
+ end
+
+ it "should return nil if an exception is raised calling stat" do
+ self.expects(:selinux_support?).returns true
+ self.expects(:execpipe).with("stat -c %C /foo").raises(Puppet::ExecutionFailure, 'error')
+ get_selinux_current_context("/foo").should be_nil
+ end
+
+ it "should return nil if stat finds an unlabeled file" do
+ self.expects(:selinux_support?).returns true
+ self.expects(:execpipe).with("stat -c %C /foo").yields ["(null)\n"]
+ get_selinux_current_context("/foo").should be_nil
+ end
+ end
+
+ describe "get_selinux_default_context" do
+ it "should return nil if no SELinux support" do
+ self.expects(:selinux_support?).returns false
+ get_selinux_default_context("/foo").should be_nil
+ end
+
+ it "should return nil if matchpathcon is not executable" do
+ self.expects(:selinux_support?).returns true
+ FileTest.expects(:executable?).with("/usr/sbin/matchpathcon").returns false
+ get_selinux_default_context("/foo").should be_nil
+ end
+
+ it "should return a context if a default context exists" do
+ self.expects(:selinux_support?).returns true
+ FileTest.expects(:executable?).with("/usr/sbin/matchpathcon").returns true
+ self.expects(:execpipe).with("/usr/sbin/matchpathcon /foo").yields ["/foo\tuser_u:role_r:type_t:s0\n"]
+ get_selinux_default_context("/foo").should == "user_u:role_r:type_t:s0"
+ end
+
+ it "should return nil if an exception is raised calling matchpathcon" do
+ self.expects(:selinux_support?).returns true
+ FileTest.expects(:executable?).with("/usr/sbin/matchpathcon").returns true
+ self.expects(:execpipe).with("/usr/sbin/matchpathcon /foo").raises(Puppet::ExecutionFailure, 'error')
+ get_selinux_default_context("/foo").should be_nil
+ end
+ end
+
+ describe "parse_selinux_context" do
+ it "should return nil if no context is passed" do
+ parse_selinux_context(:seluser, nil).should be_nil
+ end
+
+ it "should return nil if the context is 'unlabeled'" do
+ parse_selinux_context(:seluser, "unlabeled").should be_nil
+ end
+
+ it "should return the user type when called with :seluser" do
+ parse_selinux_context(:seluser, "user_u:role_r:type_t:s0").should == "user_u"
+ end
+
+ it "should return the role type when called with :selrole" do
+ parse_selinux_context(:selrole, "user_u:role_r:type_t:s0").should == "role_r"
+ end
+
+ it "should return the type type when called with :seltype" do
+ parse_selinux_context(:seltype, "user_u:role_r:type_t:s0").should == "type_t"
+ end
+
+ it "should return nil for :selrange when no range is returned" do
+ parse_selinux_context(:selrange, "user_u:role_r:type_t").should be_nil
+ end
+
+ it "should return the range type when called with :selrange" do
+ parse_selinux_context(:selrange, "user_u:role_r:type_t:s0").should == "s0"
+ end
+
+ describe "with a variety of SELinux range formats" do
+ ['s0', 's0:c3', 's0:c3.c123', 's0:c3,c5,c8', 'TopSecret', 'TopSecret,Classified', 'Patient_Record'].each do |range|
+ it "should parse range '#{range}'" do
+ parse_selinux_context(:selrange, "user_u:role_r:type_t:#{range}").should == range
+ end
+ end
+ end
+ end
+
+ describe "set_selinux_context" do
+ it "should return nil if there is no SELinux support" do
+ self.expects(:selinux_support?).returns false
+ set_selinux_context("/foo", "user_u:role_r:type_t:s0").should be_nil
+ end
+
+ it "should use chcon to set a context" do
+ self.expects(:selinux_support?).returns true
+ self.expects(:system).with("chcon user_u:role_r:type_t:s0 /foo").returns 0
+ set_selinux_context("/foo", "user_u:role_r:type_t:s0").should be_true
+ end
+
+ it "should use chcon to set user_u user context" do
+ self.expects(:selinux_support?).returns true
+ self.expects(:system).with("chcon -u user_u /foo").returns 0
+ set_selinux_context("/foo", "user_u", :seluser).should be_true
+ end
+
+ it "should use chcon to set role_r role context" do
+ self.expects(:selinux_support?).returns true
+ self.expects(:system).with("chcon -r role_r /foo").returns 0
+ set_selinux_context("/foo", "role_r", :selrole).should be_true
+ end
+
+ it "should use chcon to set type_t type context" do
+ self.expects(:selinux_support?).returns true
+ self.expects(:system).with("chcon -t type_t /foo").returns 0
+ set_selinux_context("/foo", "type_t", :seltype).should be_true
+ end
+
+ it "should use chcon to set s0:c3,c5 range context" do
+ self.expects(:selinux_support?).returns true
+ self.expects(:system).with("chcon -l s0:c3,c5 /foo").returns 0
+ set_selinux_context("/foo", "s0:c3,c5", :selrange).should be_true
+ end
+ end
+
+ describe "set_selinux_default_context" do
+ it "should return nil if there is no SELinux support" do
+ self.expects(:selinux_support?).returns false
+ set_selinux_default_context("/foo").should be_nil
+ end
+
+ it "should return nil if no default context exists" do
+ self.expects(:get_selinux_default_context).with("/foo").returns nil
+ set_selinux_default_context("/foo").should be_nil
+ end
+
+ it "should do nothing and return nil if the current context matches the default context" do
+ self.expects(:get_selinux_default_context).with("/foo").returns "user_u:role_r:type_t"
+ self.expects(:get_selinux_current_context).with("/foo").returns "user_u:role_r:type_t"
+ set_selinux_default_context("/foo").should be_nil
+ end
+
+ it "should set and return the default context if current and default do not match" do
+ self.expects(:get_selinux_default_context).with("/foo").returns "user_u:role_r:type_t"
+ self.expects(:get_selinux_current_context).with("/foo").returns "olduser_u:role_r:type_t"
+ self.expects(:set_selinux_context).with("/foo", "user_u:role_r:type_t").returns true
+ set_selinux_default_context("/foo").should == "user_u:role_r:type_t"
+ end
+ end
+
+end
--
Puppet packaging for Debian
More information about the Pkg-puppet-devel
mailing list