[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 e77ddc16570fd15b161db416e7dd35f95e7fb0ac
Author: Brett Lentz <wakko666 at gmail.com>
Date:   Thu Jul 24 18:13:14 2008 -0700

    Merged fsweetser's selinux patch against HEAD

diff --git a/lib/puppet/provider/selboolean/getsetsebool.rb b/lib/puppet/provider/selboolean/getsetsebool.rb
new file mode 100644
index 0000000..4614c6c
--- /dev/null
+++ b/lib/puppet/provider/selboolean/getsetsebool.rb
@@ -0,0 +1,47 @@
+Puppet::Type.type(:selboolean).provide(:getsetsebool) do
+    desc "Manage SELinux booleans using the getsebool and setsebool binaries."
+
+    commands :getsebool => "/usr/sbin/getsebool"
+    commands :setsebool => "/usr/sbin/setsebool"
+
+    def value
+        self.debug "Retrieving value of selboolean #{@resource[:name]}"
+
+        status = getsebool(@resource[:name])
+
+        if status =~ / off$/ then
+            return :off
+        elsif status =~ / on$/ then
+            return :on
+        else
+            status.chomp!
+            raise Puppet::Error, "Invalid response '%s' returned from getsebool" % [status]
+        end
+    end
+
+    def value=(new)
+        persist = ""
+        if @resource[:persistent] == :true
+            self.debug "Enabling persistence"
+            persist = "-P"
+        end
+        execoutput("#{command(:setsebool)} #{persist} #{@resource[:name]} #{new}")
+        return :file_changed
+    end
+
+    # Required workaround, since SELinux policy prevents setsebool
+    # from writing to any files, even tmp, preventing the standard
+    # 'setsebool("...")' construct from working.
+
+    def execoutput (cmd)
+      output = ''
+      begin
+        execpipe(cmd) do |out|
+          output = out.readlines.join('').chomp!
+        end
+      rescue Puppet::ExecutionFailure
+        raise Puppet::ExecutionFailure, output.split("\n")[0]
+      end
+      return output
+    end
+end
diff --git a/lib/puppet/provider/selmodule/semodule.rb b/lib/puppet/provider/selmodule/semodule.rb
new file mode 100644
index 0000000..4981366
--- /dev/null
+++ b/lib/puppet/provider/selmodule/semodule.rb
@@ -0,0 +1,143 @@
+Puppet::Type.type(:selmodule).provide(:semodule) do
+    desc "Manage SELinux policy modules using the semodule binary."
+
+    commands :semodule => "/usr/sbin/semodule"
+
+    def create
+        begin
+            execoutput("#{command(:semodule)} --install #{selmod_name_to_filename}")
+        rescue Puppet::ExecutionFailure => detail
+            raise Puppet::Error, "Could not load policy module: %s" % [detail];
+        end
+        return :true
+    end
+
+    def destroy
+        begin
+            execoutput("#{command(:semodule)} --remove #{@resource[:name]}")
+        rescue Puppet::ExecutionFailure => detail
+            raise Puppet::Error, "Could not remove policy module: %s" % [detail];
+        end
+    end
+
+    def exists?
+        self.debug "Checking for module #{@resource[:name]}"
+        execpipe("#{command(:semodule)} --list") do |out|
+            out.each do |line|
+                if line =~ /#{@resource[:name]}\b/
+                        return :true
+                end
+            end
+        end
+        return nil
+    end
+
+    def syncversion
+        self.debug "Checking syncversion on #{@resource[:name]}"
+
+        loadver = selmodversion_loaded
+
+        if(loadver) then
+            filever = selmodversion_file
+            if (filever == loadver) then
+                return :true
+            end
+        end
+        return :false
+    end
+    
+    def syncversion= (dosync)
+        begin
+            execoutput("#{command(:semodule)} --upgrade #{selmod_name_to_filename}")
+        rescue Puppet::ExecutionFailure => detail
+            raise Puppet::Error, "Could not upgrade policy module: %s" % [detail];
+        end
+    end
+
+    # Helper functions
+
+    def execoutput (cmd)
+      output = ''
+      begin
+        execpipe(cmd) do |out|
+          output = out.readlines.join('').chomp!
+        end
+      rescue Puppet::ExecutionFailure
+        raise Puppet::ExecutionFailure, output.split("\n")[0]
+      end
+      return output
+    end
+
+    def selmod_name_to_filename
+        if @resource[:selmodulepath]
+            return @resource[:selmodulepath]
+        else
+            return "#{@resource[:selmoduledir]}/#{@resource[:name]}.pp"
+        end
+    end
+
+    def selmod_readnext (handle)
+        len = handle.read(4).unpack('L')[0]
+        return handle.read(len)
+    end
+
+    def selmodversion_file
+        magic = 0xF97CFF8F
+
+        filename = selmod_name_to_filename
+        mod = File.new(filename, "r")
+
+        (hdr, ver, numsec) = mod.read(12).unpack('LLL')
+
+        if hdr != magic
+            raise Puppet::Error, "Found #{hdr} instead of magic #{magic} in #{filename}"
+        end
+
+        if ver != 1
+            raise Puppet::Error, "Unknown policy file version #{ver} in #{filename}"
+        end
+
+        # Read through (and throw away) the file section offsets, and also
+        # the magic header for the first section.
+
+        mod.read((numsec + 1) * 4)
+
+        ## Section 1 should be "SE Linux Module"
+
+        selmod_readnext(mod)
+        selmod_readnext(mod)
+
+        # Skip past the section headers
+        mod.read(14)
+
+        # Module name
+        selmod_readnext(mod)
+
+        # At last!  the version
+
+        v = selmod_readnext(mod) 
+
+        self.debug "file version #{v}"
+        return v
+    end
+
+    def selmodversion_loaded 
+        lines = ()
+        begin
+            execpipe("#{command(:semodule)} --list") do |output|
+                lines = output.readlines
+                lines.each do |line|
+                    line.chomp!
+                    bits = line.split
+                    if bits[0] == @resource[:name] then
+                        self.debug "load version #{bits[1]}"
+                        return bits[1]
+                    end
+                end
+            end
+        rescue Puppet::ExecutionFailure
+            raise Puppet::ExecutionFailure, "Could not list policy modules: %s" % [lines.join(' ').chomp!]
+        end
+        return nil
+    end
+end
diff --git a/lib/puppet/type/file.rb b/lib/puppet/type/file.rb
index 2a5e61d..371571f 100644
--- a/lib/puppet/type/file.rb
+++ b/lib/puppet/type/file.rb
@@ -1157,4 +1157,5 @@ module Puppet
     require 'puppet/type/file/group'
     require 'puppet/type/file/mode'
     require 'puppet/type/file/type'
+    require 'puppet/type/file/selcontext'  # SELinux file context
 end
diff --git a/lib/puppet/type/file/selcontext.rb b/lib/puppet/type/file/selcontext.rb
new file mode 100644
index 0000000..f366950
--- /dev/null
+++ b/lib/puppet/type/file/selcontext.rb
@@ -0,0 +1,96 @@
+# Manage SELinux context of files.
+#
+# This code actually manages three pieces of data in the context.
+#
+# [root at delenn files]# ls -dZ /
+# drwxr-xr-x  root root system_u:object_r:root_t         /
+#
+# The context of '/' here is 'system_u:object_r:root_t'.  This is
+# three seperate fields:
+#
+# system_u is the user context
+# object_r is the role context
+# root_t is the type context
+#
+# All three of these fields are returned in a single string by the
+# output of the stat command, but set individually with the chcon
+# command.  This allows the user to specify a subset of the three
+# values while leaving the others alone.
+#
+# See http://www.nsa.gov/selinux/ for complete docs on SELinux.
+
+module Puppet
+    class SELFileContext < Puppet::Property
+
+        def retrieve
+            unless @resource.stat(false)
+                return :absent
+            end
+            context = `stat -c %C #{@resource[:path]}`
+            context.chomp!
+            if context == "unlabeled"
+                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]
+        end
+
+        def sync
+            unless @resource.stat(false)
+                stat = @resource.stat(true)
+                unless stat
+                    return nil
+                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
+            return :file_changed
+        end
+    end
+
+    Puppet.type(:file).newproperty(:seluser, :parent => Puppet::SELFileContext) do
+        desc "What the SELinux User context of the file should be."
+
+        @event = :file_changed
+    end
+
+    Puppet.type(:file).newproperty(:selrole, :parent => Puppet::SELFileContext) do
+        desc "What the SELinux Role context of the file should be."
+
+        @event = :file_changed
+    end
+
+    Puppet.type(:file).newproperty(:seltype, :parent => Puppet::SELFileContext) do
+        desc "What the SELinux Type context of the file should be."
+
+        @event = :file_changed
+    end
+
+end
+
diff --git a/lib/puppet/type/selboolean.rb b/lib/puppet/type/selboolean.rb
new file mode 100644
index 0000000..d12dd3b
--- /dev/null
+++ b/lib/puppet/type/selboolean.rb
@@ -0,0 +1,29 @@
+#
+# Simple module for manageing SELinux booleans
+#
+
+module Puppet
+    newtype(:selboolean) do
+        @doc = "Enable or disable SELinux booleans."
+
+        newparam(:name) do
+            desc "The name of the SELinux boolean to be managed."
+            isnamevar
+        end
+
+        newproperty(:value) do
+            desc "Whether the the SELinux boolean should be enabled or disabled.  Possible values are ``on`` or ``off``."
+            newvalue(:on)
+            newvalue(:off)
+        end
+
+        newparam(:persistent) do
+            desc "If set true, SELinux booleans will be written to disk and persist accross reboots."
+
+            defaultto :false
+            newvalues(:true, :false)
+        end
+
+    end
+end
+
diff --git a/lib/puppet/type/selmodule.rb b/lib/puppet/type/selmodule.rb
new file mode 100644
index 0000000..1f02912
--- /dev/null
+++ b/lib/puppet/type/selmodule.rb
@@ -0,0 +1,50 @@
+#
+# Simple module for manageing SELinux policy modules
+#
+
+Puppet::Type.newtype(:selmodule) do
+    @doc = "Enable or disable SELinux policy modules."
+
+    ensurable
+
+    newparam(:name) do
+        desc "The name of the SELinux policy to be managed."
+        isnamevar
+    end
+
+    newparam(:selmoduledir) do
+
+        desc "The directory to look for the compiled pp module file in.
+        Currently defaults to /usr/share/selinux/targeted"
+
+        defaultto "/usr/share/selinux/targeted"
+    end
+
+    newparam(:selmodulepath) do
+
+        desc "The full path in which to look for the compiled pp
+        module file in.  You only need to use this if the module file
+        is not in the directory pointed at by selmoduledir."
+
+    end
+
+    newproperty(:syncversion) do
+
+        desc "If set to 'true', the policy will be reloaded if the
+        version found in the on-disk file differs from the loaded
+        version.  If set to 'false' (the default) the the only check
+        that will be made is if the policy is loaded at all or not."
+
+        newvalue(:true)
+        newvalue(:false)
+    end
+
+    autorequire(:file) do
+        if self[:selmodulepath]
+            [self[:selmodulepath]]
+        else
+            ["#{self[:selmoduledir]}/#{self[:name]}.pp"]
+        end       
+    end
+end
+
diff --git a/spec/unit/other/selinux.rb b/spec/unit/other/selinux.rb
new file mode 100644
index 0000000..3a07e09
--- /dev/null
+++ b/spec/unit/other/selinux.rb
@@ -0,0 +1,79 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+require 'puppet/type/selboolean'
+require 'puppet/type/selmodule'
+
+describe Puppet.type(:file), " when manipulating file contexts" do
+	before :each do
+	        @file = Puppet::Type::File.create(
+			:name => "/tmp/foo",
+			:ensure => "file",
+			:seluser => "user_u",
+			:selrole => "role_r",
+			:seltype => "type_t" )
+	end
+	it "should use :seluser to get/set an SELinux user file context attribute" do
+		@file.property(:seluser).should == "user_u"
+	end
+	it "should use :selrole to get/set an SELinux role file context attribute" do
+		@file.property(:selrole).should == "role_r"
+	end
+	it "should use :seltype to get/set an SELinux user file context attribute" do
+		@file.property(:seltype).should == "type_t"
+	end
+end
+
+describe Puppet.type(:selboolean), " when manipulating booleans" do
+	before :each do
+		@bool = Puppet::Type::Selboolean.create(
+			:name => "foo",
+			:value => "on",
+			:persistent => true )
+	end
+	it "should be able to access :name" do
+		@bool[:name].should == "foo"
+	end
+	it "should be able to access :value" do
+		@bool.property(:value).should == :on
+	end
+	it "should set :value to off" do
+		@bool[:value] = :off
+		@bool.property(:value).should == :off
+	end
+	it "should be able to access :persistent" do
+		@bool[:persistent].should == :true
+	end
+	it "should set :persistent to false" do
+		@bool[:persistent] = false
+		@bool[:persistent].should == :false
+	end
+end
+
+describe Puppet.type(:selmodule), " when checking policy modules" do
+	before :each do
+		@module = Puppet::Type::Selmodule.create(
+			:name => "foo",
+			:selmoduledir => "/some/path",
+			:selmodulepath => "/some/path/foo.pp",
+			:syncversion => true)
+	end
+	it "should be able to access :name" do
+		@module[:name].should == "foo"
+	end
+	it "should be able to access :selmoduledir" do
+		@module[:selmoduledir].should == "/some/path"
+	end
+	it "should be able to access :selmodulepath" do
+		@module[:selmodulepath].should == "/some/path/foo.pp"
+	end
+	it "should be able to access :syncversion" do
+		@module.property(:syncversion).should == :true
+	end
+	it "should set the syncversion value to false" do
+		@module[:syncversion] = :false
+		@module.property(:syncversion).should == :false
+	end
+end
+

-- 
Puppet packaging for Debian



More information about the Pkg-puppet-devel mailing list