[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:12 UTC 2009


The following commit has been merged in the master branch:
commit 772e9b217aafb22da3a7572085f631da54274937
Author: Sean E. Millichamp <sean at bruenor.org>
Date:   Tue Sep 30 14:18:14 2008 -0400

    Refactor SELinux commands to utility module

diff --git a/lib/puppet/type/file/selcontext.rb b/lib/puppet/type/file/selcontext.rb
index f366950..6e36a02 100644
--- a/lib/puppet/type/file/selcontext.rb
+++ b/lib/puppet/type/file/selcontext.rb
@@ -20,27 +20,26 @@
 # See http://www.nsa.gov/selinux/ for complete docs on SELinux.
 
 module Puppet
+    require 'puppet/util/selinux'
+
     class SELFileContext < Puppet::Property
+        include Puppet::Util::SELinux
 
         def retrieve
             unless @resource.stat(false)
                 return :absent
             end
-            context = `stat -c %C #{@resource[:path]}`
-            context.chomp!
-            if context == "unlabeled"
+            context = self.get_selinux_current_context(@resource[:path])
+            return parse_selinux_context(name, context)
+        end
+
+        def retrieve_default_context(property)
+            unless context = self.get_selinux_default_context(@resource[:path])
                 return nil
             end
-            unless context =~ /^[a-z0-9_]+:[a-z0-9_]+:[a-z0-9_]+/
-                raise Puppet::Error, "Invalid output from stat: #{context}"
-            end
-            bits = context.split(':')
-            ret = {
-                :seluser => bits[0],
-                :selrole => bits[1],
-                :seltype => bits[2]
-            }
-            return ret[name]
+            property_default = self.parse_selinux_context(property, context)
+            self.debug "Found #{property} default '#{property_default}' for #{@resource[:path]}"
+            return property_default
         end
 
         def sync
@@ -51,25 +50,7 @@ module Puppet
                 end
             end
 
-            flag = ''
-
-            case name
-            when :seluser
-                flag = "-u"
-            when :selrole
-                flag = "-r"
-            when :seltype
-                flag = "-t"
-            else
-                raise Puppet::Error, "Invalid SELinux file context component: #{name}"
-            end
-
-            self.debug "Running chcon #{flag} #{@should} #{@resource[:path]}"
-            retval = system("chcon #{flag} #{@should} #{@resource[:path]}")
-            unless retval
-                error = Puppet::Error.new("failed to chcon %s" % [@resource[:path]])
-                raise error
-            end
+            self.set_selinux_context(@resource[:path], @should, name)
             return :file_changed
         end
     end
diff --git a/lib/puppet/util/selinux.rb b/lib/puppet/util/selinux.rb
new file mode 100644
index 0000000..6a9bcaf
--- /dev/null
+++ b/lib/puppet/util/selinux.rb
@@ -0,0 +1,113 @@
+# Provides utility functions to help interfaces Puppet to SELinux.
+#
+# Currently this is implemented via the command line tools.  At some
+# point support should be added to use the new SELinux ruby bindings
+# as that will be faster and more reliable then shelling out when they
+# are available.  At this time (2008-09-26) these bindings aren't bundled on
+# any SELinux-using distribution I know of.
+
+module Puppet::Util::SELinux
+
+    def selinux_support?
+        FileTest.exists?("/selinux/enforce")
+    end
+
+    # Retrieve and return the full context of the file.  If we don't have
+    # SELinux support or if the stat call fails then return nil.
+    def get_selinux_current_context(file)
+        unless selinux_support?
+            return nil
+        end
+        context = `stat -c %C #{file}`
+        if ($?.to_i >> 8) > 0
+            return nil
+        end
+        context.chomp!
+        return context
+    end
+
+    # Use the matchpathcon command, if present, to return the SELinux context
+    # which the SELinux policy on the system expects the file to have.  We can
+    # use this to obtain a good default context.  If the command does not
+    # exist or the call fails return nil.
+    #
+    # Note: For this command to work a full, non-relative, filesystem path
+    # should be given.
+    def get_selinux_default_context(file)
+        unless FileTest.executable?("/usr/sbin/matchpathcon")
+            return nil
+        end
+        context = %x{/usr/sbin/matchpathcon #{file} 2>&1}
+        if ($?.to_i >> 8) > 0
+            return nil
+        end
+        # For a successful match, matchpathcon returns two fields separated by
+        # a variable amount of whitespace.  The second field is the full context.
+        context = context.split(/\s/)[1]
+        return context
+    end
+
+    # Take the full SELinux context returned from the tools and parse it
+    # out to the three (or four) component parts.  Supports :seluser, :selrole,
+    # :seltype, and on systems with range support, :selrange.
+    def parse_selinux_context(component, context)
+        if context == "unlabeled"
+            return nil
+        end
+        unless context =~ /^[a-z0-9_]+:[a-z0-9_]+:[a-z0-9_]+(:[a-z0-9_])?/
+            raise Puppet::Error, "Invalid context to parse: #{context}"
+        end
+        bits = context.split(':')
+        ret = {
+            :seluser => bits[0],
+            :selrole => bits[1],
+            :seltype => bits[2]
+        }
+        if bits.length == 4
+            ret[:selrange] = bits[3]
+        end
+        return ret[component]
+    end
+
+    # This updates the actual SELinux label on the file.  You can update
+    # only a single component or update the entire context.  It is just a
+    # wrapper around the chcon command.
+    def set_selinux_context(file, value, component = false)
+        case component
+            when :seluser
+                flag = "-u"
+            when :selrole
+                flag = "-r"
+            when :seltype
+                flag = "-t"
+            when :selrange
+                flag = "-l"
+            else
+                flag = ""
+        end
+
+        Puppet.debug "Running chcon #{flag} #{value} #{file}"
+        retval = system("chcon #{flag} #{value} #{file}")
+        unless retval
+            error = Puppet::Error.new("failed to chcon %s" % [@resource[:path]])
+            raise error
+        end
+    end
+
+    # Since this call relies on get_selinux_default_context it also needs a
+    # full non-relative path to the file.  Fortunately, that seems to be all
+    # Puppet uses.  This will set the file's SELinux context to the policy's
+    # default context (if any) if it differs from the context currently on
+    # the file.
+    def set_selinux_default_context(file)
+        new_context = get_selinux_default_context(file)
+        unless new_context
+            return nil
+        end
+        cur_context = get_selinux_current_context(file)
+        if new_context != cur_context
+            set_selinux_context(file, new_context)
+        end
+        return new_context
+    end
+end

-- 
Puppet packaging for Debian



More information about the Pkg-puppet-devel mailing list