Puppet: System Administration Automated

Support

Ticket #1155: puppet-selinux.diff

File puppet-selinux.diff, 11.7 kB (added by fs, 8 months ago)
  • /dev/null

    old new  
     1Puppet::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 
     47end 
  • /dev/null

    old new  
     1Puppet::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 
     143end 
  • a/lib/puppet/type/file.rb

    old new  
    11391139    require 'puppet/type/file/group' 
    11401140    require 'puppet/type/file/mode' 
    11411141    require 'puppet/type/file/type' 
     1142    require 'puppet/type/file/selcontext'  # SELinux file context 
    11421143end 
  • /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 
     22module 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 
     95end 
     96 
  • /dev/null

    old new  
     1# 
     2# Simple module for manageing SELinux booleans 
     3# 
     4 
     5module 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 
     28end 
     29 
  • /dev/null

    old new  
     1# 
     2# Simple module for manageing SELinux policy modules 
     3# 
     4 
     5Puppet::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 
     48end 
     49