
# 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-targeted", "setroubleshoot" ]:
        ensure => installed,
    }
    
    file { "/etc/selinux/config":
        ensure  => present,
        content => template("selinux/config.erb"),
        mode    => 0644,
        owner   => root,
        group   => root,
        require => Package["selinux-policy-targeted"],
        notify  => Exec["set-selinux-mode"],
    }

    if $operatingsystem == "CentOS" and $operatingsystemrelease =~ /^[1-5]\./ {
        service { "setroubleshoot":
            ensure    => $selinux_type ? {
                disabled => stopped,
                default  => running,
            },
            enable    => $selinux_type ? {
                disabled => false,
                default  => true,
            },
            hasstatus => true,
            require   => Package["setroubleshoot"],
        }
    }

    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"],
    }
    
}

# 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) {

    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) {

    exec { "semanage fcontext -a -t '${type}' '${name}'":
        path   => "/bin:/usr/bin:/sbin:/usr/sbin",
        unless => "matchpathcon `echo '${name}' | sed -e 's/(.*$//'` | egrep -q ':${type}(:s[0-9]*)?$'",
        notify => Exec["restorecon ${name}"],
    }

    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) {

    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}(,.*)?\$'",
    }

}
