#!/bin/sh

set -eu

do_not_remove_list=''
hostname=$(hostname)

read puavo_domain < /etc/puavo/domain

puavo_hostprofile=$(puavo-conf puavo.profiles.list)

bootserver_for_logs=''
case "$puavo_hostprofile" in
  bootserver*)
    bootserver_for_logs=" <${hostname}>"
    ;;
esac

syslog_master_server=$(puavo-conf puavo.admin.logging.master)

do_not_remove() {
  do_not_remove_list="${do_not_remove_list} $@"
}

receive_as_bootserver() {
  do_not_remove /etc/logrotate.d/hosts \
                /etc/rsyslog.d/pass_to_smoke_test.conf \
                /etc/rsyslog.d/receive_messages_to_var_log_hosts.conf

  install -o root -g adm -m 750 -d /var/log/hosts

  cat <<'EOF' > /etc/logrotate.d/hosts
/var/log/hosts/*.log {
	compress
	copytruncate
	missingok
	nocreate
	notifempty
	rotate 8
	size 10M
}
EOF

  cat <<'EOF' > /etc/rsyslog.d/pass_to_smoke_test.conf
ruleset(name="pass_to_smoke_test") {
    action(type="omprog"
           binary="/usr/lib/puavo-ltsp-bootserver/smoke-test-cat")
}

if (
  $msg contains 'puavo-autopilot-login'
    or $msg contains 'puavo-autopilot-releasetest'
    or $msg contains 'puavo-autopilot-session-smoke'
) then call pass_to_smoke_test
EOF

  cat <<EOF > /etc/rsyslog.d/receive_messages_to_var_log_hosts.conf
# provides TCP syslog reception
module(load="imtcp")
input(type="imtcp" port="514")

module(load="imrelp")
input(type="imrelp" port="20514")

if (\$hostname != '${hostname}') then ?HostFile
EOF
}

send_everything_to_bootserver_with_cache() {
  do_not_remove /etc/rsyslog.d/send_everything_to_bootserver_with_cache.conf

  cat <<'EOF' > /etc/rsyslog.d/send_everything_to_bootserver_with_cache.conf
call cached_logging_to_bootserver
EOF
}

send_everything_to_logmaster_with_cache() {
  do_not_remove /etc/rsyslog.d/send_everything_to_logmaster_with_cache.conf

  cat <<EOF > /etc/rsyslog.d/send_everything_to_logmaster_with_cache.conf
if (\$hostname == "${hostname}") then {
  call cached_logging_to_logmaster
} else {
  call cached_logging_through_to_logmaster
}
EOF
}

send_as_laptop() {
  # if logmaster puavo-conf variable is set, send logs to logmaster only,
  # if not, we can use the bootserver
  if [ -n "$syslog_master_server" ]; then
    send_everything_to_logmaster_with_cache
  else
    send_everything_to_bootserver_with_cache
  fi
}

send_sessiondata_as_laptop() {
  # if logmaster puavo-conf variable is set, send logs to logmaster only,
  # if not, we can use the bootserver
  if [ -n "$syslog_master_server" ]; then
    send_sessiondata_to_logmaster_with_cache
  else
    send_sessiondata_to_bootserver_with_cache
  fi
}

send_sessiondata_to_bootserver_with_cache() {
  do_not_remove /etc/rsyslog.d/send_sessiondata_to_bootserver_with_cache.conf

  cat <<EOF > /etc/rsyslog.d/send_sessiondata_to_bootserver_with_cache.conf
if (
     (\$programname == 'puavo-login'
        and (   \$msg contains "opening login session"
             or \$msg contains "closing login session"))
  or (\$programname == 'sshd'
        and (   \$msg contains "session opened"
             or \$msg contains "session closed"))
  or (\$programname == 'systemd'
        and (   \$msg startswith " Started Session"
             or \$msg startswith " Stopped Session"))
  or \$programname == 'systemd-logind'
) then call cached_logging_to_bootserver
EOF
}

send_sessiondata_to_logmaster_with_cache() {
  do_not_remove /etc/rsyslog.d/send_sessiondata_to_logmaster_with_cache.conf

  cat <<EOF > /etc/rsyslog.d/send_sessiondata_to_logmaster_with_cache.conf
if (
     (\$programname == 'puavo-login'
        and (   \$msg contains "opening login session"
             or \$msg contains "closing login session"))
  or (\$programname == 'sshd'
        and (   \$msg contains "session opened"
             or \$msg contains "session closed"))
  or (\$programname == 'systemd'
        and (   \$msg startswith " Started Session"
             or \$msg startswith " Stopped Session"))
  or \$programname == 'systemd-logind'
) then call cached_logging_to_logmaster
EOF
}

#
# First make configuration that is common to all scenarios.
#

{
  cat <<EOF
#  /etc/rsyslog.conf	Configuration file for rsyslog.
#
#			For more information see
#			/usr/share/doc/rsyslog-doc/html/rsyslog_conf.html


#################
#### MODULES ####
#################

# Provides support for local system logging.
# Use rate limiting so that we do not fill up our /var
# or overwhelm others.
module(load="imuxsock" SysSock.RateLimit.Interval="5" SysSock.UseSpecialParser="off")

module(load="imklog")   # provides kernel logging support
#module(load="immark")  # provides --MARK-- message capability

# provides UDP syslog reception
#module(load="imudp")
#input(type="imudp" port="514")

# provides TCP syslog reception
#module(load="imtcp")
#input(type="imtcp" port="514")

module(load="builtin:omfile"
       fileCreateMode="0640"
       fileOwner="root"
       fileGroup="adm")

module(load="omprog")

###########################
#### GLOBAL DIRECTIVES ####
###########################

# this is like the "RSYSLOG_TraditionalFileFormat" but with a year included
\$template PuavoLogFormat,"%timegenerated:1:6:date-rfc3164% %timegenerated:1:4:date-rfc3339% %timegenerated:8:15:date-rfc3164% %HOSTNAME% %syslogtag:1:32%%msg:::sp-if-no-1st-sp%%msg%\n"
\$ActionFileDefaultTemplate PuavoLogFormat

#
# Set the default permissions for all log files.
#
\$FileOwner root
\$FileGroup adm
\$FileCreateMode 0640
\$DirCreateMode 0755
\$Umask 0022

#
# Where to place spool and state files
#
\$WorkDirectory /var/spool/rsyslog

\$template HostFile,"/var/log/hosts/%HOSTNAME%.log"
\$template PuavoBootserverForwardFormat,"<%PRI%>%TIMESTAMP% %HOSTNAME% [${puavo_hostprofile}] %syslogtag:1:32%%msg:::sp-if-no-1st-sp%%msg%\n"
\$template PuavoLogmasterForwardFormat,"<%PRI%>%TIMESTAMP% %HOSTNAME%.${puavo_domain} [${puavo_hostprofile}] %syslogtag:1:32%%msg:::sp-if-no-1st-sp%%msg%\n"
\$template PuavoLogmasterThroughForwardFormat,"<%PRI%>%TIMESTAMP% %HOSTNAME%.${puavo_domain}${bootserver_for_logs} %syslogtag:1:32%%msg:::sp-if-no-1st-sp%%msg%\n"

ruleset(name="cached_logging_to_bootserver") {
    action(type="omprog"
           binary="/usr/local/lib/puavo-caching-syslog-sender syslog.${puavo_domain} to_bootserver"
           template="PuavoBootserverForwardFormat")
}
EOF

  if [ -n "$syslog_master_server" ]; then
    cat <<EOF
ruleset(name="cached_logging_through_to_logmaster") {
  action(type="omprog"
         binary="/usr/local/lib/puavo-caching-syslog-sender ${syslog_master_server} through"
         template="PuavoLogmasterThroughForwardFormat")
}

ruleset(name="cached_logging_to_logmaster") {
  action(type="omprog"
         binary="/usr/local/lib/puavo-caching-syslog-sender ${syslog_master_server} host"
         template="PuavoLogmasterForwardFormat")
}
EOF
  fi

cat <<EOF
#
# Include all config files in /etc/rsyslog.d/
#
\$IncludeConfig /etc/rsyslog.d/*.conf


###############
#### RULES ####
###############

#
# filter some messages that we do not care about
#

# see https://forge.univention.org/bugzilla/show_bug.cgi?id=47639
:msg, contains, "slap_global_control: unrecognized control: 1.3.6.1.4.1.4203.666.5.16" stop

# XXX Do not log message about missing ldap attribute indexed.
# XXX We should perhaps look into this if we want to do add those indices...
:msg, regex, "<= mdb_equality_candidates: \(.*\) not indexed" stop

if (\$hostname == "${hostname}") then {
  # Put cron job runs to their own logfile.
  if (\$programname == "CRON") then {
    action(type="omfile" file="/var/log/cron.log")
    stop
  }

  # Put martians to their own logfile.  Duck Dodgers in the 24½th Century!
  if (\$programname == "kernel" and
       (\$msg contains "IPv4: martian source"
          or \$msg contains "ll header:")) then {
    action(type="omfile" file="/var/log/martians.log")
    stop
  }

  if \$programname == "hooktftp" then {
    action(type="omfile" file="/var/log/puavo/hooktftp.log")
    stop
  }

  if \$programname == "hooktftp" then {
    action(type="omfile" file="/var/log/puavo/hooktftp.log")
    stop
  }

  if \$programname == "puavo-bootserver-make-homedir" then {
    action(type="omfile" file="/var/log/puavo/puavo-bootserver-make-homedir.log")
    stop
  }

  if \$programname == "puavo-docker" then {
    action(type="omfile" file="/var/log/puavo/puavo-docker.log")
    stop
  }

  if \$programname == "puavo-ers-applet" then {
    # use two files, one that not include debug messages and one that does
    if \$syslogseverity < 7 then {
      action(type="omfile" file="/var/log/puavo/puavo-ers-applet.log")
    }
    action(type="omfile" file="/var/log/puavo/puavo-ers-applet-debug.log")
    stop
  }

  if \$programname == "puavo-pkg" or \$programname == "puavo-pkg-update" then {
    action(type="omfile" file="/var/log/puavo/puavo-pkg.log")
    stop
  }

  if \$programname == "puavo-rest" then {
    action(type="omfile" file="/var/log/puavo/puavo-rest.log")
    stop
  }

  if \$programname == "puavo-sharedir-manager" then {
    action(type="omfile" file="/var/log/puavo/puavo-sharedir-manager.log")
    stop
  }

  if \$programname == "puavo-torrent-updated" then {
    action(type="omfile" file="/var/log/puavo/puavo-torrent-updated.log")
    stop
  }

  if \$programname == "puavo-update-abitti2-image" then {
    action(type="omfile" file="/var/log/puavo/puavo-update-abitti2-image.log")
    stop
  }

  #
  # Some standard log files.  Log by facility.
  #
  auth,authpriv.*		/var/log/auth.log
  *.*;auth,authpriv.none	-/var/log/syslog
  #cron.*			/var/log/cron.log
  daemon.*			-/var/log/daemon.log
  kern.*			-/var/log/kern.log
  lpr.*				-/var/log/lpr.log
  mail.*			-/var/log/mail.log
  user.*			-/var/log/user.log

  #
  # Logging for the mail system.  Split it up so that
  # it is easy to write scripts to parse these files.
  #
  mail.info			-/var/log/mail.info
  mail.warn			-/var/log/mail.warn
  mail.err			/var/log/mail.err

  #
  # Some "catch-all" log files.
  #
  *.=debug;\\
          auth,authpriv.none;\\
          news.none;mail.none	-/var/log/debug
  *.=info;*.=notice;*.=warn;\\
          auth,authpriv.none;\\
          cron,daemon.none;\\
          mail,news.none	-/var/log/messages

  #
  # Emergencies are sent to everybody logged in.
  #
  *.emerg			:omusrmsg:*
}
EOF
} > /etc/rsyslog.conf

#
# Then continue with policy-specific configurations.
#

logging_policy="$(puavo-conf puavo.admin.logging.policy)"

case "$logging_policy" in
  local-only)
    ;;
  receive-as-bootserver)
    receive_as_bootserver
    send_everything_to_logmaster_with_cache
    ;;
  send-as-laptop)
    send_as_laptop
    ;;
  send-everything-to-bootserver)
    send_everything_to_bootserver_with_cache
    ;;
  send-sessiondata-as-laptop)
    send_sessiondata_as_laptop
    ;;
  *)
    echo "Unsupported logging policy: ${logging_policy}" >&2
    exit 1
    ;;
esac

all_configuration_files='
  /etc/logrotate.d/hosts
  /etc/rsyslog.d/receive_messages_to_var_log_hosts.conf
  /etc/rsyslog.d/send_everything_to_bootserver_with_cache.conf
  /etc/rsyslog.d/send_everything_to_logmaster_with_cache.conf
  /etc/rsyslog.d/send_sessiondata_to_bootserver_with_cache.conf
  /etc/rsyslog.d/send_sessiondata_to_logmaster_with_cache.conf
'

for conffile in $all_configuration_files; do
  found=false
  for do_not_remove in $do_not_remove_list; do
    [ "$do_not_remove" = "$conffile" ] && found=true
  done
  $found || rm -f "$conffile"
done

exit 0
