Ticket #1155: puppet-selinux.diff
| File puppet-selinux.diff, 11.7 kB (added by fs, 8 months ago) |
|---|
-
/dev/null
old new 1 Puppet::Type.type(:selboolean).provide(:getsetsebool) do 2 desc "Manage SELinux booleans using the getsebool and setsebool binaries." 3 4 commands :getsebool => "getsebool" 5 commands :setsebool => "setsebool" 6 7 def value 8 self.debug "Retrieving value of selboolean #{@resource[:name]}" 9 10 status = getsebool(@resource[:name]) 11 12 if status =~ / off$/ then 13 return :off 14 elsif status =~ / on$/ then 15 return :on 16 else 17 status.chomp! 18 raise Puppet::Error, "Invalid response '%s' returned from getsebool" % [status] 19 end 20 end 21 22 def value=(new) 23 persist = "" 24 if @resource[:persistent] == :true 25 self.debug "Enabling persistence" 26 persist = "-P" 27 end 28 execoutput("#{command(:setsebool)} #{persist} #{@resource[:name]} #{new}") 29 return :file_changed 30 end 31 32 # Required workaround, since SELinux policy prevents setsebool 33 # from writing to any files, even tmp, preventing the standard 34 # 'setsebool("...")' construct from working. 35 36 def execoutput (cmd) 37 output = '' 38 begin 39 execpipe(cmd) do |out| 40 output = out.readlines.join('').chomp! 41 end 42 rescue Puppet::ExecutionFailure 43 raise Puppet::ExecutionFailure, output.split("\n")[0] 44 end 45 return output 46 end 47 end -
/dev/null
old new 1 Puppet::Type.type(:selmodule).provide(:semodule) do 2 desc "Manage SELinux policy modules using the semodule binary." 3 4 commands :semodule => "/usr/sbin/semodule" 5 6 def create 7 begin 8 execoutput("#{command(:semodule)} --install #{selmod_name_to_filename}") 9 rescue Puppet::ExecutionFailure => detail 10 raise Puppet::Error, "Could not load policy module: %s" % [detail]; 11 end 12 return :true 13 end 14 15 def destroy 16 begin 17 execoutput("#{command(:semodule)} --remove #{@resource[:name]}") 18 rescue Puppet::ExecutionFailure => detail 19 raise Puppet::Error, "Could not remove policy module: %s" % [detail]; 20 end 21 end 22 23 def exists? 24 self.debug "Checking for module #{@resource[:name]}" 25 execpipe("#{command(:semodule)} --list") do |out| 26 out.each do |line| 27 if line =~ /#{@resource[:name]}\b/ 28 return :true 29 end 30 end 31 end 32 return nil 33 end 34 35 def syncversion 36 self.debug "Checking syncversion on #{@resource[:name]}" 37 38 loadver = selmodversion_loaded 39 40 if(loadver) then 41 filever = selmodversion_file 42 if (filever == loadver) then 43 return :true 44 end 45 end 46 return :false 47 end 48 49 def syncversion= (dosync) 50 begin 51 execoutput("#{command(:semodule)} --upgrade #{selmod_name_to_filename}") 52 rescue Puppet::ExecutionFailure => detail 53 raise Puppet::Error, "Could not upgrade policy module: %s" % [detail]; 54 end 55 end 56 57 # Helper functions 58 59 def execoutput (cmd) 60 output = '' 61 begin 62 execpipe(cmd) do |out| 63 output = out.readlines.join('').chomp! 64 end 65 rescue Puppet::ExecutionFailure 66 raise Puppet::ExecutionFailure, output.split("\n")[0] 67 end 68 return output 69 end 70 71 def selmod_name_to_filename 72 if @resource[:selmodulepath] 73 return @resource[:selmodulepath] 74 else 75 return "#{@resource[:selmoduledir]}/#{@resource[:name]}.pp" 76 end 77 end 78 79 def selmod_readnext (handle) 80 len = handle.read(4).unpack('L')[0] 81 return handle.read(len) 82 end 83 84 def selmodversion_file 85 magic = 0xF97CFF8F 86 87 filename = selmod_name_to_filename 88 mod = File.new(filename, "r") 89 90 (hdr, ver, numsec) = mod.read(12).unpack('LLL') 91 92 if hdr != magic 93 raise Puppet::Error, "Found #{hdr} instead of magic #{magic} in #{filename}" 94 end 95 96 if ver != 1 97 raise Puppet::Error, "Unknown policy file version #{ver} in #{filename}" 98 end 99 100 # Read through (and throw away) the file section offsets, and also 101 # the magic header for the first section. 102 103 mod.read((numsec + 1) * 4) 104 105 ## Section 1 should be "SE Linux Module" 106 107 selmod_readnext(mod) 108 selmod_readnext(mod) 109 110 # Skip past the section headers 111 mod.read(14) 112 113 # Module name 114 selmod_readnext(mod) 115 116 # At last! the version 117 118 v = selmod_readnext(mod) 119 120 self.debug "file version #{v}" 121 return v 122 end 123 124 def selmodversion_loaded 125 lines = () 126 begin 127 execpipe("#{command(:semodule)} --list") do |output| 128 lines = output.readlines 129 lines.each do |line| 130 line.chomp! 131 bits = line.split 132 if bits[0] == @resource[:name] then 133 self.debug "load version #{bits[1]}" 134 return bits[1] 135 end 136 end 137 end 138 rescue Puppet::ExecutionFailure 139 raise Puppet::ExecutionFailure, "Could not list policy modules: %s" % [lines.join(' ').chomp!] 140 end 141 return nil 142 end 143 end -
a/lib/puppet/type/file.rb
old new 1139 1139 require 'puppet/type/file/group' 1140 1140 require 'puppet/type/file/mode' 1141 1141 require 'puppet/type/file/type' 1142 require 'puppet/type/file/selcontext' # SELinux file context 1142 1143 end -
/dev/null
old new 1 # Manage SELinux context of files. 2 # 3 # This code actually manages three pieces of data in the context. 4 # 5 # [root@delenn files]# ls -dZ / 6 # drwxr-xr-x root root system_u:object_r:root_t / 7 # 8 # The context of '/' here is 'system_u:object_r:root_t'. This is 9 # three seperate fields: 10 # 11 # system_u is the user context 12 # object_r is the role context 13 # root_t is the type context 14 # 15 # All three of these fields are returned in a single string by the 16 # output of the stat command, but set individually with the chcon 17 # command. This allows the user to specify a subset of the three 18 # values while leaving the others alone. 19 # 20 # See http://www.nsa.gov/selinux/ for complete docs on SELinux. 21 22 module Puppet 23 class SELFileContext < Puppet::Property 24 25 def retrieve 26 unless @resource.stat(false) 27 return :absent 28 end 29 context = `stat -c %C #{@resource[:path]}` 30 context.chomp! 31 if context == "unlabeled" 32 return nil 33 end 34 unless context =~ /^[a-z0-9_]+:[a-z0-9_]+:[a-z0-9_]+/ 35 raise Puppet::Error, "Invalid output from stat: #{context}" 36 end 37 bits = context.split(':') 38 ret = { 39 :seluser => bits[0], 40 :selrole => bits[1], 41 :seltype => bits[2] 42 } 43 return ret[name] 44 end 45 46 def sync 47 unless @resource.stat(false) 48 stat = @resource.stat(true) 49 unless stat 50 return nil 51 end 52 end 53 54 flag = '' 55 56 case name 57 when :seluser 58 flag = "-u" 59 when :selrole 60 flag = "-r" 61 when :seltype 62 flag = "-t" 63 else 64 raise Puppet::Error, "Invalid SELinux file context component: #{name}" 65 end 66 67 self.debug "Running chcon #{flag} #{@should} #{@resource[:path]}" 68 retval = system("chcon #{flag} #{@should} #{@resource[:path]}") 69 unless retval 70 error = Puppet::Error.new("failed to chcon %s" % [@resource[:path]]) 71 raise error 72 end 73 return :file_changed 74 end 75 end 76 77 Puppet.type(:file).newproperty(:seluser, :parent => Puppet::SELFileContext) do 78 desc "What the SELinux User context of the file should be." 79 80 @event = :file_changed 81 end 82 83 Puppet.type(:file).newproperty(:selrole, :parent => Puppet::SELFileContext) do 84 desc "What the SELinux Role context of the file should be." 85 86 @event = :file_changed 87 end 88 89 Puppet.type(:file).newproperty(:seltype, :parent => Puppet::SELFileContext) do 90 desc "What the SELinux Type context of the file should be." 91 92 @event = :file_changed 93 end 94 95 end 96 -
/dev/null
old new 1 # 2 # Simple module for manageing SELinux booleans 3 # 4 5 module Puppet 6 newtype(:selboolean) do 7 @doc = "Enable or disable SELinux booleans." 8 9 newparam(:name) do 10 desc "The name of the SELinux boolean to be managed." 11 isnamevar 12 end 13 14 newproperty(:value) do 15 desc "Whether the the SELinux boolean should be enabled or disabled. Possible values are ``on`` or ``off``." 16 newvalue(:on) 17 newvalue(:off) 18 end 19 20 newparam(:persistent) do 21 desc "If set true, SELinux booleans will be written to disk and persist accross reboots." 22 23 defaultto :false 24 newvalues(:true, :false) 25 end 26 27 end 28 end 29 -
/dev/null
old new 1 # 2 # Simple module for manageing SELinux policy modules 3 # 4 5 Puppet::Type.newtype(:selmodule) do 6 @doc = "Enable or disable SELinux policy modules." 7 8 ensurable 9 10 newparam(:name) do 11 desc "The name of the SELinux policy to be managed." 12 isnamevar 13 end 14 15 newparam(:selmoduledir) do 16 17 desc "The directory to look for the compiled pp module file in. 18 Currently defaults to /usr/share/selinux/targeted" 19 20 defaultto "/usr/share/selinux/targeted" 21 end 22 23 newparam(:selmodulepath) do 24 25 desc "The full path in which to look for the compiled pp 26 module file in. You only need to use this if the module file 27 is not in the directory pointed at by selmoduledir." 28 29 end 30 31 newproperty(:syncversion) do 32 33 desc "If set to 'true', the policy will be reloaded if the 34 version found in the on-disk file differs from the loaded 35 version. If set to 'false' (the default) the the only check 36 that will be made is if the policy is loaded at all or not." 37 38 newvalue(:true) 39 end 40 41 autorequire(:file) do 42 if self[:selmodulepath] 43 [self[:selmodulepath]] 44 else 45 ["#{self[:selmoduledir]}/#{self[:name]}.pp"] 46 end 47 end 48 end 49