# Common syslog configuration
#
# === Global variables:
#
#   $syslog_type:
#       Syslog type to use. Valid values are syslogd and rsyslog.
#       Default depends on operating system.
#
#   $syslog_group:
#       Group name which has permissions to read logs. Defaults to
#       wheel or root depending on operating system.
#
class syslog::common {

    if !$syslog_type {
        case $::operatingsystem {
            "centos","redhat": {
                $syslog_type = $::operatingsystemrelease ? {
                    /^6/    => "rsyslog",
                    default => "syslogd",
                }
            }
            "fedora": { $syslog_type = "rsyslog" }
            "openbsd": { $syslog_type = "syslogd" }
            "ubuntu": { $syslog_type = "rsyslog" }
        }
    }

    if $syslog_group {
        $group = $syslog_group
    } else {
        if $::operatingsystem == "OpenBSD" {
            $group = "wheel"
        } else {
            $group = "root"
        }
    }

    case $kernel {
        "linux": {
            file { "/etc/logrotate.d/syslog.all":
                ensure  => present,
                mode    => "0644",
                owner   => "root",
                group   => "root",
                content => template("syslog/logrotate.erb"),
            }
        }
        "openbsd": {
            exec { "add-newsyslog-all":
                path    => "/bin:/usr/bin:/sbin:/usr/sbin",
                command => "echo '/var/log/all.log	root:${group}	640  7     *    \$D0   Z' >> /etc/newsyslog.conf",
                unless  => "grep -q '^/var/log/all.log' /etc/newsyslog.conf",
            }
        }
    }

    file { "/var/log/all.log":
        ensure => present,
        mode   => "0640",
        owner  => "root",
        group  => $group,
    }

}

# Install syslog client
#
# === Global variables:
#
#   $syslog_server:
#       Address of remote syslog server where to send logs.
#
#   $syslog_tlsserver:
#       Address of remote syslog server where to send logs over TCP/TLS.
#
class syslog::client inherits syslog::common {

    case $syslog_type {
        "syslogd": { include syslog::client::syslogd }
        "rsyslog": { include syslog::client::rsyslog }
        default: { fail("Unknown \$syslog_type '$syslog_type'") }
    }

}


# Install syslog client using syslogd
#
class syslog::client::syslogd {

    if $::operatingsystem != "OpenBSD" {
        package { "syslogd":
            ensure => installed,
            name   => "sysklogd",
            before => File["/etc/syslog.conf"],
        }
    }

    file { "/etc/syslog.conf":
        ensure  => present,
        content => template("syslog/syslog.conf.$operatingsystem.erb",
                            "syslog/syslog.conf.client.erb"),
        mode    => "0644",
        owner   => "root",
        group   => $::operatingsystem ? {
            "openbsd" => "wheel",
            default   => "root",
        },
        notify  => Service["syslogd"],
    }

    service { "syslogd":
        name    => $::operatingsystem ? {
            "openbsd" => "syslogd",
            default   => "syslog",
        },
        ensure  => running,
        enable  => true,
        start   => $::operatingsystem ? {
            "openbsd" => "syslogd -a /var/www/dev/log -a /var/named/dev/log -a /var/empty/dev/log",
            default   => undef,
        },
        restart => $::operatingsystem ? {
            "openbsd" => "pkill -HUP -u _syslogd",
            default   => undef,
        },
        require => File["/var/log/all.log"],
    }

}


# Install syslog client using rsyslog.
#
class syslog::client::rsyslog {

    package { "rsyslog":
        ensure => installed,
    }

    if $::operatingsystem != "OpenBSD" and $syslog_tlsserver {
        package { "rsyslog-gnutls":
            ensure => installed,
            before => Service["rsyslog"],
        }
    }

    file { "/etc/rsyslog.conf":
        ensure  => present,
        content => template("syslog/rsyslog.conf.erb",
                            "syslog/syslog.conf.$operatingsystem.erb",
                            "syslog/syslog.conf.client.erb"),
        mode    => "0644",
        owner   => "root",
        group   => $::operatingsystem ? {
            "openbsd" => "wheel",
            default   => "root",
        },
        require => Package["rsyslog"],
        notify  => Service["rsyslog"],
    }

    if $syslog_tlsserver {
        file { "/var/spool/rsyslog":
            ensure => directory,
            mode   => "0700",
            owner  => "root",
            group  => $::operatingsystem ? {
                "openbsd" => "wheel",
                default   => "root",
            },
            before => Service["rsyslog"],
        }
    }

    service { "rsyslog":
        ensure     => running,
        enable     => true,
        start      => $::operatingsystem ? {
            "openbsd" => $::operatingsystemrelease ? {
                /4\.[1-8]/ => "pkill syslogd; /usr/local/sbin/rsyslogd -c 4 -x -i /var/run/syslog.pid",
                default    => undef,
            },
            default   => undef,
        },
        hasrestart => $::operatingsystem ? {
            "fedora" => true,
            default  => false,
        },
        require    => File["/var/log/all.log"],
    }

    if $::operatingsystem == "OpenBSD" and $::operatingsystemrelease !~ /4\.[1-8]/ {
        file { "/etc/rc.d/syslogd":
            ensure => present,
            mode   => "0555",
            owner  => "root",
            group  => "wheel",
            source => "puppet:///modules/syslog/rsyslogd.rc",
            backup => ".orig",
            before => Service["rsyslog"],
        }
        Service["rsyslog"] {
            name => "syslogd",
        }
    }

}


# Common configuration for standalone syslog client and server
#
# === Global variables:
#
#   $syslog_datadir:
#       Directory where to store logs. Defaults to /srv/log.
#
#   $syslog_rotate:
#       Array of log files to rotate. Defaults to 'all.log'.
#
class syslog::common::standalone inherits syslog::common {

    require ssl::openssl

    if !$syslog_rotate {
        $syslog_rotate = [ "all.log" ]
    }

    if $syslog_datadir {
        file { $syslog_datadir:
            ensure  => directory,
            mode    => "2750",
            owner   => "root",
            group   => $group,
            seltype => "var_log_t",
        }
        file { "/srv/log":
            ensure  => link,
            target  => $syslog_datadir,
            owner   => "root",
            group   => $group,
            require => File[$syslog_datadir],
            seltype => "var_log_t",
        }
    } else {
        file { "/srv/log":
            ensure  => directory,
            mode    => "2750",
            owner   => "root",
            group   => $group,
            seltype => "var_log_t",
        }
    }

    file { "/srv/log/archive":
        ensure  => directory,
        mode    => "2750",
        owner   => "root",
        group   => $group,
        require => File["/srv/log"],
    }

    File["/var/log/all.log"] {
        ensure => link,
        target => "/srv/log/all.log",
    }

    case $kernel {
        "linux": {
            File["/etc/logrotate.d/syslog.all"] {
                ensure => absent,
            }
        }
        "openbsd": {
            Exec["add-newsyslog-all"] {
                # never run this
                unless => "true",
            }
        }
    }

    file { "/usr/local/sbin/logarchiver.sh":
        ensure => present,
        source => "puppet:///modules/syslog/logarchiver.sh",
        mode   => "0755",
        owner  => "root",
        group  => $::operatingsystem ? {
            "openbsd" => "wheel",
            default   => "root",
        },
    }
    $syslog_rotate_files = inline_template('<%= syslog_rotate.join(" ") -%>')
    cron { "logarchiver.sh":
        command => "/usr/local/sbin/logarchiver.sh ${syslog_rotate_files} >/dev/null",
        user    => "root",
        hour    => 0,
        minute  => 0,
        require => File["/usr/local/sbin/logarchiver.sh"],
    }

    if "${selinux}" == "true" {
        selinux::manage_fcontext { "/srv/log(/all\\.log)?":
            type   => "var_log_t",
            before => File["/srv/log"],
        }
        if $syslog_datadir {
            selinux::manage_fcontext { "${syslog_datadir}(/all\\.log)?":
                type   => "var_log_t",
                before => File[$syslog_datadir],
            }
        }
    }

}


# Install standalone syslog host.
#
class syslog::standalone inherits syslog::common::standalone {

    case $syslog_type {
        "syslogd": { include syslog::standalone::syslogd }
        "rsyslog": { include syslog::standalone::rsyslog }
        default: { fail("Unknown \$syslog_type '$syslog_type'") }
    }

}


# Install standalone syslog host using syslogd.
#
class syslog::standalone::syslogd inherits syslog::client::syslogd {

    File["/etc/syslog.conf"] {
        content => template("syslog/syslog.conf.server.erb",
                            "syslog/syslog.conf.$operatingsystem.erb"),
        require => [ File["/srv/log"],
                     File["/var/log/all.log"], ],
    }

}


# Install standalone syslog host using rsyslog.
#
class syslog::standalone::rsyslog inherits syslog::client::rsyslog {

    File["/etc/rsyslog.conf"] {
        content => template("syslog/rsyslog.conf.erb",
                            "syslog/syslog.conf.server.erb",
                            "syslog/syslog.conf.$operatingsystem.erb"),
        require => [ File["/srv/log"],
                     File["/var/log/all.log"], ],
    }

}


# Install syslog server.
#
class syslog::server inherits syslog::common::standalone {

    case $syslog_type {
        "syslogd": { fail("Server for \$syslog_type '$syslog_type' not yet supported.") }
        "rsyslog": { include syslog::server::rsyslog }
        default: { fail("Unknown \$syslog_type '$syslog_type'") }
    }

}


# Install syslog server using rsyslog.
#
class syslog::server::rsyslog inherits syslog::client::rsyslog {

    File["/etc/rsyslog.conf"] {
        content => template("syslog/rsyslog.conf.erb",
                            "syslog/rsyslog.conf.server.erb",
                            "syslog/syslog.conf.server.erb",
                            "syslog/syslog.conf.$operatingsystem.erb"),
        require => [ File["/srv/log"],
                     File["/var/log/all.log"], ],
    }

}


# Install syslog server with custom configuration.
#
class syslog::custom inherits syslog::common::standalone {

    case $syslog_type {
        "syslogd": { fail("Server for \$syslog_type '$syslog_type' not yet supported.") }
        "rsyslog": { include syslog::custom::rsyslog }
        default: { fail("Unknown \$syslog_type '$syslog_type'") }
    }

}


# Install syslog server using rsyslog with custom configuration.
#
class syslog::custom::rsyslog inherits syslog::client::rsyslog {

    File["/etc/rsyslog.conf"] {
        content => undef,
        source  => [ "puppet:///files/syslog/rsyslog.conf.${homename}",
                     "puppet:///files/syslog/rsyslog.conf", ],
        require => [ File["/srv/log"],
                     File["/var/log/all.log"], ],
    }

}
