# Install SELinux prequisites # # === Global variables # # $selinux_type: # SELinux mode to use. Valid values are enforcing, permissive and # disabled. Defaults to permissive. # class selinux { if $::kernel != "Linux" { fail("SELinux supported only on Linux systems") } if ! $selinux_type { $selinux_type = "permissive" } case $selinux_type { "enforcing": {} "permissive": {} "disabled": {} default: { fail("Invalid SELinux mode ${selinux_type}") } } package { "selinux-policy": ensure => installed, } file { "/etc/selinux/config": ensure => present, content => template("selinux/config.erb"), mode => "0644", owner => "root", group => "root", require => Package["selinux-policy"], notify => Exec["set-selinux-mode"], } exec { "set-selinux-mode": command => $selinux_type ? { "enforcing" => "setenforce 1", "permissive" => "setenforce 0", "disabled" => "/bin/true", }, path => "/bin:/usr/bin:/sbin:/usr/sbin", unless => "getenforce | egrep -i '${selinux_type}'", require => File["/etc/selinux/config"], } if $selinux_type != "disabled" { include selinux::tools package { "selinux-policy-targeted": ensure => installed, } } } # Install setroubleshoot # # === Parameters # # $client_users: # Array of users allowed to access the setroubleshoot server. # Defaults to ["*"]. # # $mailto: # Array of email addresses where to send SELinux alerts. # Disabled by default. # class selinux::setroubleshoot($client_users=["*"], $mailto=undef) { if $::selinux == "true" { package { "setroubleshoot": ensure => installed, } if $::operatingsystem in ["CentOS","RedHat"] and $::operatingsystemrelease =~ /^[1-5]\./ { service { "setroubleshoot": ensure => running, enable => true, hasstatus => true, require => Package["setroubleshoot"], } $service = Service["setroubleshoot"] } else { $service = undef } $client_users_real = inline_template("<%= @client_users.join(',') %>") augeas { "set-setroubleshoot-client_users": changes => "set access/client_users '${client_users_real}'", incl => "/etc/setroubleshoot/setroubleshoot.conf", lens => "Puppet.lns", notify => $service, require => Package["setroubleshoot"], } if $mailto { if !$mail_server { $mail_server = "127.0.0.1" } augeas { "set-setroubleshoot-smtp_host": changes => "set email/smtp_host '${mail_server}'", incl => "/etc/setroubleshoot/setroubleshoot.conf", lens => "Puppet.lns", notify => $service, require => Package["setroubleshoot"], } file { "/var/lib/setroubleshoot/email_alert_recipients": ensure => present, mode => "0600", owner => "root", group => "root", content => template("selinux/email_alert_recipients.erb"), notify => $service, require => Augeas["set-setroubleshoot-smtp_host"], } } } } # Install tools for managing SELinux # class selinux::tools { tag("bootstrap") case $::operatingsystem { "fedora": { $package = "policycoreutils-python" } "centos","redhat": { case $::operatingsystemrelease { /^[1-5]/: { $package = "policycoreutils" } default: { $package = "policycoreutils-python" } } } default: { fail("selinux::tools not supported on ${::operatingsystem}") } } package { $package: ensure => installed, } } # Enable restorecond service. # class selinux::restorecond { if $::selinux == "true" { file { "/etc/selinux/restorecond.conf": ensure => present, mode => "0644", owner => "root", group => "root", seltype => "selinux_config_t", source => [ "puppet:///files/selinux/restorecond.conf.${::homename}", "puppet:///files/selinux/restorecond.conf", "puppet:///modules/selinux/restorecond.conf", ], notify => Service["restorecond"], } service { "restorecond": ensure => running, enable => true, } } } # Set SELinux boolean value # # === Parameters # # $name: # SELinux key to set # $value: # Value for given key (on or off) # # === Sample usage # # selinux::boolean { "use_nfs_home_dirs": # value => "on", # } # define selinux::boolean($value) { if $::selinux == "true" { selboolean { $name: value => $value, persistent => true, } } } # Configure SELinux file contexts # # === Parameters # # $name: # Regexp of path to configure # $type: # SELinux type for file # $recurse: # Recursively run restorecon on given path. Defaults to true. # # === Sample usage # # selinux::manage_fcontext { "/srv/www/http(/.*)?": # type => "httpd_sys_content_t", # } # define selinux::manage_fcontext($type, $recurse = true) { if $::selinux == "true" { include selinux::tools exec { "semanage fcontext -a -t '${type}' '${name}'": path => "/bin:/usr/bin:/sbin:/usr/sbin", unless => "matchpathcon `echo '${name}' | sed -e 's/(.*$//' -e 's/\\\\\\//g'` | egrep -q ':${type}(:s[0-9]*)?$'", notify => Exec["restorecon ${name}"], require => Class["selinux::tools"], } if $recurse { $restorecon_opts = "-R" } else { $restorecon_opts = "" } exec { "restorecon ${name}": command => "restorecon -i ${restorecon_opts} `echo '${name}' | sed -e 's/(.*$//'`", path => "/bin:/usr/bin:/sbin:/usr/sbin", refreshonly => true, } } } # Configure SELinux port authorizations # # === Parameters # # $name: # Port range to configure # $type: # SELinux type for port range # $proto: # Protocol for port (tcp or udp) # # === Sample usage # # selinux::manage_port { "18140-18143": # type => "http_port_t", # proto => "tcp", # } # define selinux::manage_port($type, $proto) { if $::selinux == "true" { include selinux::tools exec { "semanage port -a -t ${type} -p ${proto} ${name}": path => "/bin:/usr/bin:/sbin:/usr/sbin", unless => "semanage port -ln | egrep '^${type}[ ]*${proto}' | egrep ' ${name}(,.*)?\$'", require => Class["selinux::tools"], } } } # Install new SELinux module # # === Parameters # # $name: # Module name # $source: # Module source (.te) or compiled file (.pp). # # === Sample usage # # selinux::module { "munin-local": # source => "puppet:///files/common/selinux/munin-local.te", # } # define selinux::module($source) { if $::selinux == "true" { $ext = regsubst($source, '.*\.(te|pp)', '\1') case $ext { "te": { include selinux::module::devel file { "/usr/local/src/selinux/${name}.te": ensure => present, source => $source, mode => "0644", owner => "root", group => "root", require => File["/usr/local/src/selinux"], notify => Exec["selinux-module-compile"], } $module = "/usr/local/src/selinux/${name}.pp" } "pp": { $module = $source } default: { fail("Invalid source '${source}' for selinux::module") } } file { "/usr/share/selinux/targeted/${name}.pp": ensure => present, source => $module, mode => "0644", owner => "root", group => "root", require => $ext ? { "te" => Exec["selinux-module-compile"], default => undef, }, } selmodule { $name: ensure => present, require => File["/usr/share/selinux/targeted/${name}.pp"], syncversion => true, } } } # Prequisites for compiling SELinux modules # class selinux::module::devel { include selinux::tools if $::operatingsystem in ["CentOS","RedHat"] { if $::operatingsystemrelease =~ /^5\.[0-9]/ { package { "selinux-policy-devel": ensure => installed, before => File["/usr/local/src/selinux"], } } } file { "/usr/local/src/selinux": ensure => directory, mode => "0755", owner => "root", group => "root", require => Class["selinux::tools"], } exec { "selinux-module-compile": path => "/bin:/usr/bin:/sbin:/usr/sbin", command => "make -f /usr/share/selinux/devel/Makefile", cwd => "/usr/local/src/selinux", user => "root", refreshonly => true, require => Class["selinux::tools"], } }