From 317364b0e5086335a51d6db649689c129d1017b8 Mon Sep 17 00:00:00 2001 From: Bas Zoetekouw Date: Wed, 6 May 2026 17:47:30 +0200 Subject: [PATCH 01/25] syslog: generate ruleset and template from simple(r) yaml config --- .ansible-lint | 3 + roles/rsyslog/defaults/main.yml | 56 +++++++++++++++ roles/rsyslog/templates/sc_ruleset.conf.j2 | 78 ++++++--------------- roles/rsyslog/templates/sc_template.conf.j2 | 59 +++------------- 4 files changed, 91 insertions(+), 105 deletions(-) diff --git a/.ansible-lint b/.ansible-lint index 5ab59f61d..065a01693 100644 --- a/.ansible-lint +++ b/.ansible-lint @@ -1,3 +1,6 @@ --- profile: "production" offline: false + +skip_list: + - yaml[colons] diff --git a/roles/rsyslog/defaults/main.yml b/roles/rsyslog/defaults/main.yml index 755c27773..aa3c2be6c 100644 --- a/roles/rsyslog/defaults/main.yml +++ b/roles/rsyslog/defaults/main.yml @@ -1,3 +1,4 @@ +--- rsyslog_ca: /etc/pki/rsyslog/rsyslog_ca.pem rsyslog_dir: /opt/openconext/logs rsyslog_read_group: adm @@ -40,3 +41,58 @@ rsyslog_checkemptylogs_cron_minute: "0" rsyslog_checkemptylogs_cron_hour: "9" rsyslog_checkemptylogs_cron_weekdays: "1-5" rsyslog_checkemptylogs_dir: "/usr/local/bin" + +# "program" matches the syslog identifier +# "contains" and "startswith" match the syslog message +rsyslog_central_apps: + haproxy: { program: "haproxy", target: "haproxy/haproxy.log" } + keepalived: { program: "Keepalived_vrrp", target: "keepalived/keepalived.log" } + galera: { program: "mariadb", target: "galera/galera.log" } + galera_garb: { program: "garb-systemd", target: "galera/galera_garb.log" } + mongo: { program: "mongod", target: "mongo/mongo.log" } + traefik: { program: "loadbalancer", target: "traefik/traefik.log" } + eb_auth: { program: "engineblock", contains: '"channel":"authentication"', + dir: "log_logins", target: "eb-authentication.log" } + stepup_auth1: { program: "gateway", contains: '"message":"Second Factor Authenticated"', + dir: "log_logins", target: "stepup-authentication.log" } + stepup_auth2: { program: "gateway", contains: '"message":"Intrinsic Loa Requested"', + dir: "log_logins", target: "stepup-authentication.log" } + stepup_auth3: { program: "stepup-authentication", + dir: "log_logins", target: "stepup-authentication.log" } + eb_apache: { program: "engineblock", startswith: "engine", + target: "eb/apache.log" } + eb: { program: "engineblock", target: "eb/eb.log" } + eb_log: { program: "EBLOG", target: "eb/eb.log" } + eb_apache2: { program: "Apache-EB", target: "eb/apache.log" } # probabaly ununsed + eb_api: { program: "Apache-EBAPI", target: "eb-api/apache.log" } # probabaly ununsed + oidcng_server: { program: "oidcngserver", target: "oidcng/oidcng.log" } + oidcng_json: { program: "oicdngjson", target: "oidcng/oidcngjson.log" } + oidc_play_server: { program: "oidcplaygroundserver", target: "oidc-playground/oidc-playground.log" } + oidc_play_gui: { program: "oidcplaygroundgui", target: "oidc-playground/oidc-playground-apache.log" } + manage_server: { program: "manageserver", target: "manage/manage.log" } + manage_gui: { program: "managegui", target: "manage/apache.log" } + aa_server: { program: "aaserver", target: "aa/aa.log" } + aa_gui: { program: "aagui", target: "aa/apache.log" } + aa_link: { program: "aalink", target: "aa/apache.log" } + pdp: { program: "pdp", target: "pdp/pdp.log" } + voot: { program: "vootserver", target: "voot/voot.log" } + eduid_server: { program: "myconextserver", target: "eduid/myconext.log" } + eduid_json: { program: "myconextjson", target: "eduid/myconextjson.log" } + eduid_gui: { program: "myconextgui", target: "eduid/myconext-apache.log" } + eduid_account: { program: "accountgui", target: "eduid/account-apache.log" } + eduid_servicedesk: { program: "servicedeskgui", target: "eduid/servicedesk-apache.log" } + invite_client: { program: "inviteclient", target: "invite/inviteclient.log" } + invite_welcome: { program: "invitewelcome", target: "invite/invitewelcome.log" } + invite_server: { program: "inviteserver", target: "invite/inviteserver.log" } + invite_json: { program: "invitejson", target: "invite/invitejson.log" } + invite_provmock: { program: "inviteprovisioningmock", target: "invite/inviteprovisioningmock.log" } + profile: { program: "profile", startswith: "{", + target: "profile/profile.log" } + profile_apache: { program: "profile", target: "profile/apache.log" } + spdashboard: { program: "spdashboard", startswith: "spdashboard", + target: "spdashboard/spdashboard.log" } + spdashboard_apache: { program: "spdashboard", target: "spdashboard/apache.log" } + dashboard_server: { program: "dashboardserver", target: "dashboard/dashboard.log" } + dashboard_gui: { program: "dashboardgui", target: "dashboard/apache.log" } + static: { program: "Apache-STATIC", target: "static/apache.log" } + metadata: { program: "Apache-METADATA", target: "metadata/apache.log" } diff --git a/roles/rsyslog/templates/sc_ruleset.conf.j2 b/roles/rsyslog/templates/sc_ruleset.conf.j2 index 34d5392dd..afb8c1dea 100644 --- a/roles/rsyslog/templates/sc_ruleset.conf.j2 +++ b/roles/rsyslog/templates/sc_ruleset.conf.j2 @@ -1,66 +1,30 @@ +global({{ rsyslog_dir_file_modes }}) + $RuleSet {{ item.name }} {% if item.name != "mgnt_sc" %} -if $programname == "engineblock" and $msg startswith " engine" then { action(type="omfile" DynaFile="apache-eb-{{ item.name }}" {{ rsyslog_dir_file_modes }} ) stop } -if $programname == "engineblock" and $msg startswith "engine" then { action(type="omfile" DynaFile="apache-eb-{{ item.name }}" {{ rsyslog_dir_file_modes }} ) stop } -if $programname == "engineblock" and $msg contains '{"channel":"authentication"' then { action(type="omfile" DynaFile="ebauth-{{ item.name }}" {{ rsyslog_dir_file_modes }} ) stop } -:programname, isequal, "engineblock" { action(type="omfile" DynaFile="eblog-{{ item.name }}" {{ rsyslog_dir_file_modes }} ) stop } -:programname, isequal, "EBLOG" { action(type="omfile" DynaFile="eblog-{{ item.name }}" {{ rsyslog_dir_file_modes }} ) stop } -:programname, isequal, "Apache-EB" { action(type="omfile" DynaFile="apache-eb-{{ item.name }}" {{ rsyslog_dir_file_modes }} ) stop } -:programname, isequal, "EBAUTH" { action(type="omfile" DynaFile="ebauth-{{ item.name }}" {{ rsyslog_dir_file_modes }} ) stop } -:programname, isequal, "haproxy" { action(type="omfile" DynaFile="haproxy-{{ item.name }}" {{ rsyslog_dir_file_modes }} ) stop } -:programname, isequal, "aaserver" { action(type="omfile" DynaFile="aa-{{ item.name }}" {{ rsyslog_dir_file_modes }} ) stop } -:programname, isequal, "aagui" { action(type="omfile" DynaFile="apache-aa-{{ item.name }}" {{ rsyslog_dir_file_modes }} ) stop } -:programname, isequal, "aalink" { action(type="omfile" DynaFile="apache-aa-{{ item.name }}" {{ rsyslog_dir_file_modes }} ) stop } -:programname, isequal, "dashboardgui" { action(type="omfile" DynaFile="apache-dashboard-{{ item.name }}" {{ rsyslog_dir_file_modes }} ) stop } -:programname, isequal, "dashboardserver" { action(type="omfile" DynaFile="dashboard-{{ item.name }}" {{ rsyslog_dir_file_modes }} ) stop } -:programname, isequal, "Apache-EBAPI" { action(type="omfile" DynaFile="apache-eb-api-{{ item.name }}" {{ rsyslog_dir_file_modes }} ) stop } -:programname, isequal, "manageserver" { action(type="omfile" DynaFile="manage-{{ item.name }}" {{ rsyslog_dir_file_modes }} ) stop } -:programname, isequal, "managegui" { action(type="omfile" DynaFile="apache-manage-{{ item.name }}" {{ rsyslog_dir_file_modes }} ) stop } -:programname, isequal, "pdp" { action(type="omfile" DynaFile="pdp-{{ item.name }}" {{ rsyslog_dir_file_modes }} ) stop } -if $programname == "profile" and $msg startswith "{" then { action(type="omfile" DynaFile="profile-{{ item.name }}" {{ rsyslog_dir_file_modes }} ) stop } -:programname, isequal, "profile" { action(type="omfile" DynaFile="apache-profile-{{ item.name }}" {{ rsyslog_dir_file_modes }} ) stop } -:programname, isequal, "vootserver" { action(type="omfile" DynaFile="voot-{{ item.name }}" {{ rsyslog_dir_file_modes }} ) stop } -:programname, isequal, "mariadbd" { action(type="omfile" DynaFile="galera-{{ item.name }}" {{ rsyslog_dir_file_modes }} ) stop } -:programname, isequal, "garb-systemd" { action(type="omfile" DynaFile="haproxy-{{ item.name }}" {{ rsyslog_dir_file_modes }} ) stop } -:programname, isequal, "Keepalived_vrrp" { action(type="omfile" DynaFile="keepalived-{{ item.name }}" {{ rsyslog_dir_file_modes }} ) stop } -:programname, startswith, "mongo" { action(type="omfile" DynaFile="mongo-{{ item.name }}" {{ rsyslog_dir_file_modes }} ) stop } -:programname, isequal, "Apache-STATIC" { action(type="omfile" DynaFile="apache-static-{{ item.name }}" {{ rsyslog_dir_file_modes }} ) stop } -:programname, isequal, "Apache-METADATA" { action(type="omfile" DynaFile="apache-metadata-{{ item.name }}" {{ rsyslog_dir_file_modes }} ) stop } -:programname, isequal, "oidcngserver" { action(type="omfile" DynaFile="oidcng-{{ item.name }}" {{ rsyslog_dir_file_modes }} ) stop } -:programname, isequal, "oidcngjson" { action(type="omfile" DynaFile="oidcngjson-{{ item.name }}" {{ rsyslog_dir_file_modes }} ) stop } -:programname, isequal, "oidcplaygroundserver" { action(type="omfile" DynaFile="oidc-playground-{{ item.name }}" {{ rsyslog_dir_file_modes }} ) stop } -:programname, isequal, "oidcplaygroundgui" { action(type="omfile" DynaFile="apache-oidcplayground-{{item.name }}" {{ rsyslog_dir_file_modes }} ) stop } -:programname, isequal, "myconextserver" { action(type="omfile" DynaFile="myconext-{{ item.name }}" {{ rsyslog_dir_file_modes }} ) stop } -:programname, isequal, "myconextjson" { action(type="omfile" DynaFile="myconextjson-{{ item.name }}" {{ rsyslog_dir_file_modes }} ) stop } -:programname, isequal, "myconextgui" { action(type="omfile" DynaFile="apache-myconext-{{item.name }}" {{ rsyslog_dir_file_modes }} ) stop } -:programname, isequal, "accountgui" { action(type="omfile" DynaFile="apache-account-{{item.name }}" {{ rsyslog_dir_file_modes }} ) stop } -:programname, isequal, "servicedeskgui" { action(type="omfile" DynaFile="apache-servicedesk-{{item.name }}" {{ rsyslog_dir_file_modes }} ) stop } -:programname, startswith, "inviteclient" { action(type="omfile" DynaFile="inviteclient-{{ item.name }}" {{ rsyslog_dir_file_modes }} ) stop } -:programname, startswith, "invitewelcome" { action(type="omfile" DynaFile="invitewelcome-{{ item.name }}" {{ rsyslog_dir_file_modes }} ) stop } -:programname, startswith, "inviteserver" { action(type="omfile" DynaFile="inviteserver-{{ item.name }}" {{ rsyslog_dir_file_modes }} ) stop } -:programname, isequal, "invitejson" { action(type="omfile" DynaFile="invitejson-{{ item.name }}" {{ rsyslog_dir_file_modes }} ) stop } -:programname, startswith, "inviteprovisioningmock" { action(type="omfile" DynaFile="inviteprovisioningmock-{{ item.name }}" {{ rsyslog_dir_file_modes }} ) stop } -:programname, startswith, "loadbalancer" { action(type="omfile" DynaFile="loadbalancer-{{ item.name }}" {{ rsyslog_dir_file_modes }} ) stop } -if $programname == "gateway" and $msg contains '{"message":"Second Factor Authenticated"' then { action(type="omfile" DynaFile="stepup-authentication-{{ item.name }}" {{ rsyslog_dir_file_modes }} ) stop } -if $programname == "gateway" and $msg contains '{"message":"Intrinsic Loa Requested"' then { action(type="omfile" DynaFile="stepup-authentication-{{ item.name }}" {{ rsyslog_dir_file_modes }} ) stop } +{% for app, config in rsyslog_central_apps.items() %} +if $programname == "{{ config.program }}" + {%- if 'contains' in config %} and $msg contains '{{ config.contains }}' {% endif -%} + {%- if 'startswith' in config %} and $msg startswith '{{ config.startswith }}' {% endif %} + then { action(type="omfile" DynaFile="{{ app }}-{{ item.name }}") stop }} +{% endfor %} {% for stepupapp in stepupapps %} -:programname, isequal, "stepup-{{ stepupapp }}" { action(type="omfile" DynaFile="stepup-{{ stepupapp }}-{{item.name }}" {{ rsyslog_dir_file_modes }} ) stop } -if $programname == "{{ stepupapp }}" and $msg startswith "{{ stepupapp }}" then { action(type="omfile" DynaFile="apache-{{ stepupapp }}-{{item.name }}" {{ rsyslog_dir_file_modes }} ) stop } -:programname, isequal, "{{ stepupapp }}" { action(type="omfile" DynaFile="stepup-{{ stepupapp }}-{{item.name }}" {{ rsyslog_dir_file_modes }} ) stop } -:programname, isequal, "Apache-{{ stepupapp }}" { action(type="omfile" DynaFile="apache-{{ stepupapp }}-{{item.name }}" {{ rsyslog_dir_file_modes }} ) stop } +if $programname == "stepup-{{ stepupapp }}" then { action(type="omfile" DynaFile="stepup-{{ stepupapp }}-{{item.name }}") stop } +if $programname == "{{ stepupapp }}" and $msg startswith "{{ stepupapp }}" then { action(type="omfile" DynaFile="apache-{{ stepupapp }}-{{item.name }}") stop } +if $programname == "{{ stepupapp }}" then { action(type="omfile" DynaFile="stepup-{{ stepupapp }}-{{item.name }}") stop } +if $programname == "Apache-{{ stepupapp }}" then { action(type="omfile" DynaFile="apache-{{ stepupapp }}-{{item.name }}") stop } {% endfor %} -:programname, isequal, "Apache-azuremfa" { action(type="omfile" DynaFile="apache-azure-mfa-{{ item.name }}" {{ rsyslog_dir_file_modes }} ) stop } -if $programname == "spdashboard" and $msg startswith "spdashboard" then { action(type="omfile" DynaFile="apache-spdashboard-{{item.name }}" {{ rsyslog_dir_file_modes }} ) stop } -:programname, isequal, "spdashboard" { action(type="omfile" DynaFile="spdashboard-{{item.name }}" {{ rsyslog_dir_file_modes }} ) stop } +if $programname == "Apache-azuremfa" then { action(type="omfile" DynaFile="apache-azure-mfa-{{ item.name }}") stop } + -:programname, isequal, "stepup-authentication" { action(type="omfile" DynaFile="stepup-authentication-{{ item.name }}" {{ rsyslog_dir_file_modes }} ) stop } {% endif %} -:programname, isequal, "audispd" { action(type="omfile" DynaFile="auditd-{{ item.name }}" {{ rsyslog_dir_file_modes }} ) stop } -:programname, isequal, "audit" { action(type="omfile" DynaFile="auditd-{{ item.name }}" {{ rsyslog_dir_file_modes }} ) stop } -:programname, isequal, "audisp-syslog" { action(type="omfile" DynaFile="auditd-{{ item.name }}" {{ rsyslog_dir_file_modes }} ) stop } -:programname, isequal, "-bash" { action(type="omfile" DynaFile="bash-{{ item.name }}" {{ rsyslog_dir_file_modes }} ) stop } -:syslogfacility-text, isequal, "authpriv" { action(type="omfile" dynafile="secure-{{ item.name }}" {{ rsyslog_dir_file_modes }} ) stop } -:msg, contains, "-- MARK --" { action(type="omfile" DynaFile="MARK-{{ item.name }}" {{ rsyslog_dir_file_modes }} ) stop } +if $programname == "audispd" then { action(type="omfile" DynaFile="auditd-{{ item.name }}") stop } +if $programname == "audit" then { action(type="omfile" DynaFile="auditd-{{ item.name }}") stop } +if $programname == "audisp-syslog" then { action(type="omfile" DynaFile="auditd-{{ item.name }}") stop } +if $programname == "-bash" then { action(type="omfile" DynaFile="bash-{{ item.name }}") stop } +if $programname == "authpriv" then { action(type="omfile" dynafile="secure-{{ item.name }}") stop } +if $msg contains "-- MARK --" then { action(type="omfile" DynaFile="MARK-{{ item.name }}") stop } + *.* ?hostleft-{{ item.name }} diff --git a/roles/rsyslog/templates/sc_template.conf.j2 b/roles/rsyslog/templates/sc_template.conf.j2 index 3a47df0a6..c4d27c9e6 100644 --- a/roles/rsyslog/templates/sc_template.conf.j2 +++ b/roles/rsyslog/templates/sc_template.conf.j2 @@ -1,57 +1,20 @@ {% if item.name != "mgnt_sc" %} -$template haproxy-{{ item.name }}, "{{ rsyslog_dir }}/apps/{{ item.name }}/haproxy/haproxy.log" -$template aa-{{ item.name }}, "{{ rsyslog_dir }}/apps/{{ item.name }}/aa/aa.log" -$template apache-aa-{{ item.name }}, "{{ rsyslog_dir }}/apps/{{ item.name }}/aa/apache.log" -$template apache-aalink-{{ item.name }}, "{{ rsyslog_dir }}/apps/{{ item.name }}/link/apache.log" -$template dashboard-{{ item.name }}, "{{ rsyslog_dir }}/apps/{{ item.name }}/dashboard/dashboard.log" -$template apache-dashboard-{{ item.name }}, "{{ rsyslog_dir }}/apps/{{ item.name }}/dashboard/apache.log" -$template eb-api-{{ item.name }}, "{{ rsyslog_dir }}/apps/{{ item.name }}/eb-api/eb-api.log" -$template apache-eb-api-{{ item.name }}, "{{ rsyslog_dir }}/apps/{{ item.name }}/eb-api/apache.log" -$template manage-{{ item.name }}, "{{ rsyslog_dir }}/apps/{{ item.name }}/manage/manage.log" -$template apache-manage-{{ item.name }}, "{{ rsyslog_dir }}/apps/{{ item.name }}/manage/apache.log" -$template pdp-{{ item.name }}, "{{ rsyslog_dir }}/apps/{{ item.name }}/pdp/pdp.log" -$template pdpanalytics-{{ item.name }}, "{{ rsyslog_dir }}/apps/{{ item.name }}/pdp/pdpanalytics.log" -$template apache-pdp-{{ item.name }}, "{{ rsyslog_dir }}/apps/{{ item.name }}/pdp/apache.log" -$template profile-{{ item.name }}, "{{ rsyslog_dir }}/apps/{{ item.name }}/profile/profile.log" -$template apache-profile-{{ item.name }}, "{{ rsyslog_dir }}/apps/{{ item.name }}/profile/apache.log" -$template voot-{{ item.name }}, "{{ rsyslog_dir }}/apps/{{ item.name }}/voot/voot.log" -$template apache-voot-{{ item.name }}, "{{ rsyslog_dir }}/apps/{{ item.name }}/voot/apache.log" -$template galera-{{ item.name }}, "{{ rsyslog_dir }}/apps/{{ item.name }}/galera/galera.log" -$template garb-{{ item.name }}, "{{ rsyslog_dir }}/apps/{{ item.name }}/galera/galera_garb.log" -$template keepalived-{{ item.name }}, "{{ rsyslog_dir }}/apps/{{ item.name }}/keepalived/keepalived.log" -$template mongo-{{ item.name }}, "{{ rsyslog_dir }}/apps/{{ item.name }}/mongo/mongo.log" -$template apache-static-{{ item.name }}, "{{ rsyslog_dir }}/apps/{{ item.name }}/static/apache.log" -$template apache-eb-{{ item.name }}, "{{ rsyslog_dir }}/apps/{{ item.name }}/eb/apache.log" -$template eblog-{{ item.name }}, "{{ rsyslog_dir }}/apps/{{ item.name }}/eb/eb.log" -$template apache-metadata-{{ item.name }}, "{{ rsyslog_dir }}/apps/{{ item.name }}/metadata/apache.log" -$template ebauth-{{ item.name }}, "{{ rsyslog_dir }}/log_logins/{{ item.name }}/eb-authentication.log" -$template oidcng-{{ item.name }}, "{{ rsyslog_dir }}/apps/{{ item.name }}/oidcng/oidcng.log" -$template oidcngjson-{{ item.name }}, "{{ rsyslog_dir }}/apps/{{ item.name }}/oidcng/oidcngjson.log" -$template apache-oidcng-{{ item.name }}, "{{ rsyslog_dir }}/apps/{{ item.name }}/oidcng/apache.log" -$template oidc-playground-{{ item.name }}, "{{ rsyslog_dir }}/apps/{{ item.name }}/oidc-playground/oidc-playground.log" -$template apache-oidcplayground-{{ item.name }}, "{{ rsyslog_dir }}/apps/{{ item.name }}/oidc-playground/oidc-playground-apache.log" -$template myconext-{{ item.name }}, "{{ rsyslog_dir }}/apps/{{ item.name }}/eduid/myconext.log" -$template myconextjson-{{ item.name }}, "{{ rsyslog_dir }}/apps/{{ item.name }}/eduid/myconextjson.log" -$template apache-myconext-{{ item.name }}, "{{ rsyslog_dir }}/apps/{{ item.name }}/eduid/myconext-apache.log" -$template apache-account-{{ item.name }}, "{{ rsyslog_dir }}/apps/{{ item.name }}/eduid/account-apache.log" -$template apache-servicedesk-{{ item.name }}, "{{ rsyslog_dir }}/apps/{{ item.name }}/servicedeskgui/servicedesk-apache.log -$template apache-eduid-{{ item.name }}, "{{ rsyslog_dir }}/apps/{{ item.name }}/eduid/eduid-apache.log" -$template spdashboard-{{ item.name }}, "{{ rsyslog_dir }}/apps/{{ item.name }}/spdashboard/spdashboard.log" -$template apache-spdashboard-{{ item.name }}, "{{ rsyslog_dir }}/apps/{{ item.name }}/spdashboard/apache.log" -$template inviteclient-{{ item.name }}, "{{ rsyslog_dir }}/apps/{{ item.name }}/invite//inviteclient.log" -$template invitewelcome-{{ item.name }}, "{{ rsyslog_dir }}/apps/{{ item.name }}/invite//invitewelcome.log" -$template inviteserver-{{ item.name }}, "{{ rsyslog_dir }}/apps/{{ item.name }}/invite//inviteserver.log" -$template invitejson-{{ item.name }}, "{{ rsyslog_dir }}/apps/{{ item.name }}/invite/invitejson.log" -$template inviteprovisioningmock-{{ item.name }}, "{{ rsyslog_dir }}/apps/{{ item.name }}/invite//inviteprovisioningmock.log" -$template loadbalancer-{{ item.name }}, "{{ rsyslog_dir }}/apps/{{ item.name }}/traefik/traefik.log" + +{% for app, config in rsyslog_central_apps.items() %} +{% set dir = config.dir if 'dir' in config else 'apps' %} +$template {{ app }}-{{ item.name }}, "{{ rsyslog_dir }}/{{ dir }}/{{ item.name }}/{{ config.target }}" +{% endfor %} + {% for stepupapp in stepupapps %} $template stepup-{{ stepupapp }}-{{ item.name }}, "{{ rsyslog_dir }}/apps/{{ item.name }}/{{ stepupapp }}/{{ stepupapp }}.log $template apache-{{ stepupapp }}-{{ item.name }}, "{{ rsyslog_dir }}/apps/{{ item.name }}/{{ stepupapp }}/{{ stepupapp }}-apache.log {% endfor %} -$template stepup-authentication-{{ item.name }}, "{{ rsyslog_dir }}/log_logins/{{ item.name }}/stepup-authentication.log" + {% endif %} + $template auditd-{{ item.name }}, "{{ rsyslog_dir }}/apps/{{ item.name }}/auditd/%HOSTNAME%/auditd.log" -$template bash-{{ item.name }}, "{{ rsyslog_dir }}/apps/{{ item.name }}/bash/%HOSTNAME%/bash.log" +$template bash-{{ item.name }}, "{{ rsyslog_dir }}/apps/{{ item.name }}/bash/%HOSTNAME%/bash.log" $template secure-{{ item.name }}, "{{ rsyslog_dir }}/apps/{{ item.name }}/secure/%HOSTNAME%/secure.log" -$template MARK-{{ item.name }}, "{{ rsyslog_dir }}/monitoring/%HOSTNAME%" +$template MARK-{{ item.name }}, "{{ rsyslog_dir }}/monitoring/%HOSTNAME%" + $template hostleft-{{ item.name }}, "{{ rsyslog_dir }}/hosts/{{ item.name }}/%HOSTNAME%/%SYSLOGFACILITY-TEXT%" From dbab8d393a836bdc1b38f02a24bc964eec2ce1bb Mon Sep 17 00:00:00 2001 From: Bas Zoetekouw Date: Thu, 7 May 2026 14:52:51 +0200 Subject: [PATCH 02/25] rsyslog_dir_file_modes options are not allowed in global() --- roles/rsyslog/templates/sc_ruleset.conf.j2 | 26 ++++++++++------------ 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/roles/rsyslog/templates/sc_ruleset.conf.j2 b/roles/rsyslog/templates/sc_ruleset.conf.j2 index afb8c1dea..c5a5ae0d2 100644 --- a/roles/rsyslog/templates/sc_ruleset.conf.j2 +++ b/roles/rsyslog/templates/sc_ruleset.conf.j2 @@ -1,5 +1,3 @@ -global({{ rsyslog_dir_file_modes }}) - $RuleSet {{ item.name }} {% if item.name != "mgnt_sc" %} @@ -7,24 +5,24 @@ $RuleSet {{ item.name }} if $programname == "{{ config.program }}" {%- if 'contains' in config %} and $msg contains '{{ config.contains }}' {% endif -%} {%- if 'startswith' in config %} and $msg startswith '{{ config.startswith }}' {% endif %} - then { action(type="omfile" DynaFile="{{ app }}-{{ item.name }}") stop }} + then { action(type="omfile" DynaFile="{{ app }}-{{ item.name }}" {{ rsyslog_dir_file_modes }}) stop } {% endfor %} {% for stepupapp in stepupapps %} -if $programname == "stepup-{{ stepupapp }}" then { action(type="omfile" DynaFile="stepup-{{ stepupapp }}-{{item.name }}") stop } -if $programname == "{{ stepupapp }}" and $msg startswith "{{ stepupapp }}" then { action(type="omfile" DynaFile="apache-{{ stepupapp }}-{{item.name }}") stop } -if $programname == "{{ stepupapp }}" then { action(type="omfile" DynaFile="stepup-{{ stepupapp }}-{{item.name }}") stop } -if $programname == "Apache-{{ stepupapp }}" then { action(type="omfile" DynaFile="apache-{{ stepupapp }}-{{item.name }}") stop } +if $programname == "stepup-{{ stepupapp }}" then { action(type="omfile" DynaFile="stepup-{{ stepupapp }}-{{item.name }}" {{ rsyslog_dir_file_modes }}) stop } +if $programname == "{{ stepupapp }}" and $msg startswith "{{ stepupapp }}" then { action(type="omfile" DynaFile="apache-{{ stepupapp }}-{{item.name }}" {{ rsyslog_dir_file_modes }}) stop } +if $programname == "{{ stepupapp }}" then { action(type="omfile" DynaFile="stepup-{{ stepupapp }}-{{item.name }}" {{ rsyslog_dir_file_modes }}) stop } +if $programname == "Apache-{{ stepupapp }}" then { action(type="omfile" DynaFile="apache-{{ stepupapp }}-{{item.name }}" {{ rsyslog_dir_file_modes }}) stop } {% endfor %} -if $programname == "Apache-azuremfa" then { action(type="omfile" DynaFile="apache-azure-mfa-{{ item.name }}") stop } +if $programname == "Apache-azuremfa" then { action(type="omfile" DynaFile="apache-azure-mfa-{{ item.name }}" {{ rsyslog_dir_file_modes }}) stop } {% endif %} -if $programname == "audispd" then { action(type="omfile" DynaFile="auditd-{{ item.name }}") stop } -if $programname == "audit" then { action(type="omfile" DynaFile="auditd-{{ item.name }}") stop } -if $programname == "audisp-syslog" then { action(type="omfile" DynaFile="auditd-{{ item.name }}") stop } -if $programname == "-bash" then { action(type="omfile" DynaFile="bash-{{ item.name }}") stop } -if $programname == "authpriv" then { action(type="omfile" dynafile="secure-{{ item.name }}") stop } -if $msg contains "-- MARK --" then { action(type="omfile" DynaFile="MARK-{{ item.name }}") stop } +if $programname == "audispd" then { action(type="omfile" DynaFile="auditd-{{ item.name }}" {{ rsyslog_dir_file_modes }}) stop } +if $programname == "audit" then { action(type="omfile" DynaFile="auditd-{{ item.name }}" {{ rsyslog_dir_file_modes }}) stop } +if $programname == "audisp-syslog" then { action(type="omfile" DynaFile="auditd-{{ item.name }}" {{ rsyslog_dir_file_modes }}) stop } +if $programname == "-bash" then { action(type="omfile" DynaFile="bash-{{ item.name }}" {{ rsyslog_dir_file_modes }}) stop } +if $programname == "authpriv" then { action(type="omfile" Dynafile="secure-{{ item.name }}" {{ rsyslog_dir_file_modes }}) stop } +if $msg contains "-- MARK --" then { action(type="omfile" DynaFile="MARK-{{ item.name }}" {{ rsyslog_dir_file_modes }}) stop } *.* ?hostleft-{{ item.name }} From 4a2d0254492f77648bb8a76ff7b0cf686cea6452 Mon Sep 17 00:00:00 2001 From: Bas Zoetekouw Date: Mon, 17 Aug 2026 15:36:01 +0200 Subject: [PATCH 03/25] add acme log --- roles/rsyslog/defaults/main.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/rsyslog/defaults/main.yml b/roles/rsyslog/defaults/main.yml index aa3c2be6c..c9ba8074f 100644 --- a/roles/rsyslog/defaults/main.yml +++ b/roles/rsyslog/defaults/main.yml @@ -96,3 +96,4 @@ rsyslog_central_apps: dashboard_gui: { program: "dashboardgui", target: "dashboard/apache.log" } static: { program: "Apache-STATIC", target: "static/apache.log" } metadata: { program: "Apache-METADATA", target: "metadata/apache.log" } + acme: { program: "acme.sh", target: "haproxy/acme.log" } From cf23c830669562c6bb95d111c679debc8c5a0018 Mon Sep 17 00:00:00 2001 From: Bas Zoetekouw Date: Thu, 20 Aug 2026 21:03:39 +0200 Subject: [PATCH 04/25] Consolidate rsyslog_ca files. rsyslog_ca.pem and rsyslogclientca.crt where the same file. Now just use a single source file and put it in a single location. --- roles/rsyslog/tasks/main.yml | 20 +++++++++++++------ roles/rsyslog/tasks/rsyslog_central.yml | 8 +------- roles/rsyslog/templates/rsyslog.conf.j2 | 2 +- .../templates/rsyslog_onlyforward.conf.j2 | 2 +- 4 files changed, 17 insertions(+), 15 deletions(-) diff --git a/roles/rsyslog/tasks/main.yml b/roles/rsyslog/tasks/main.yml index e4fc916b2..39e4408d9 100644 --- a/roles/rsyslog/tasks/main.yml +++ b/roles/rsyslog/tasks/main.yml @@ -1,3 +1,12 @@ +- name: remove old files: + ansible.builtin.file: + path: "/etc/pki/rsyslog/{{ item }}" + state: "absent" + loop: + - "rsyslogclientca.crt" + - "rsyslogclientcaprd.crt" + - "rsyslogclientprd.crt" + - name: Install rsyslog and python modules ansible.builtin.package: name: @@ -23,7 +32,6 @@ enabled: true - name: Forwarding journalctl to rsyslog forward syslog to central logserver - when: "'centrallog_servers' not in group_names" block: # journald forwards logs to rsyslog @@ -74,17 +82,17 @@ ansible.builtin.copy: src: "{{ inventory_dir }}/files/certs/rsyslog/rsyslogclient.crt" dest: "{{ rsyslog_certifcate_dir }}/rsyslogclient.crt" - mode: "0744" + mode: "0644" owner: root group: adm notify: - "restart rsyslog" - - name: Put rsyslog CA file (new location) + - name: Put rsyslog CA file ansible.builtin.copy: - src: "{{ inventory_dir }}/files/certs/rsyslog/rsyslogclientca.crt" - dest: "{{ rsyslog_certifcate_dir }}/rsyslogclientca.crt" - mode: "0744" + src: "{{ inventory_dir }}/files/certs/rsyslog/rsyslog_ca.crt" + dest: "{{ rsyslog_ca }}" + mode: "0644" owner: root group: adm diff --git a/roles/rsyslog/tasks/rsyslog_central.yml b/roles/rsyslog/tasks/rsyslog_central.yml index 1efa858f8..3bf9605bc 100644 --- a/roles/rsyslog/tasks/rsyslog_central.yml +++ b/roles/rsyslog/tasks/rsyslog_central.yml @@ -20,7 +20,7 @@ mode: "0750" # recurse: true # this makes everything very slow and not sure if it is necessary -- name: Put rsyslog client certificate +- name: Put rsyslog server certificate ansible.builtin.copy: src: "{{ inventory_dir }}/files/certs/rsyslog/rsyslogserver.crt" dest: "/etc/pki/rsyslog/rsyslogserver.crt" @@ -28,12 +28,6 @@ owner: root group: adm -- name: Place rsyslog CA file - ansible.builtin.copy: - src: "{{ inventory_dir }}/files/certs/rsyslog_ca.pem" - dest: "{{ rsyslog_ca }}" - mode: "0644" - - name: Create directories to keep configuration file ansible.builtin.file: path: "/etc/rsyslog.d/{{ item }}" diff --git a/roles/rsyslog/templates/rsyslog.conf.j2 b/roles/rsyslog/templates/rsyslog.conf.j2 index f77ef1068..0f9caa69f 100644 --- a/roles/rsyslog/templates/rsyslog.conf.j2 +++ b/roles/rsyslog/templates/rsyslog.conf.j2 @@ -108,7 +108,7 @@ action(type="omrelp" target="{{ rsyslog_remote_server_relp }}" port="{{ rsyslog_remote_relp_port }}" tls="on" -tls.caCert="/etc/pki/rsyslog/rsyslogclientca.crt" +tls.caCert="{{ rsyslog_ca }}" tls.MyCert="/etc/pki/rsyslog/rsyslogclient.crt" tls.MyPrivKey="/etc/pki/rsyslog/rsyslogclient.key" tls.authmode="name" diff --git a/roles/rsyslog/templates/rsyslog_onlyforward.conf.j2 b/roles/rsyslog/templates/rsyslog_onlyforward.conf.j2 index bd612f534..5cd6fb976 100644 --- a/roles/rsyslog/templates/rsyslog_onlyforward.conf.j2 +++ b/roles/rsyslog/templates/rsyslog_onlyforward.conf.j2 @@ -34,7 +34,7 @@ action(type="omrelp" target="{{ relp_host.host }}" port="{{ relp_host.port }}" tls="on" -tls.caCert="/etc/pki/rsyslog/rsyslogclientca.crt" +tls.caCert="{{ rsyslog_ca }}" tls.MyCert="/etc/pki/rsyslog/rsyslogclient.crt" tls.MyPrivKey="/etc/pki/rsyslog/rsyslogclient.key" tls.authmode="name" From 183c6cf59aea87c4bdd76b5e3f7e33581447e819 Mon Sep 17 00:00:00 2001 From: Bas Zoetekouw Date: Thu, 27 Aug 2026 10:49:47 +0200 Subject: [PATCH 05/25] Consolidate two different rsyslog config files --- roles/rsyslog/defaults/main.yml | 13 +- roles/rsyslog/tasks/main.yml | 24 +- roles/rsyslog/tasks/rsyslog_central.yml | 12 - roles/rsyslog/templates/rsyslog.conf.j2 | 210 +++++++++--------- .../templates/rsyslog_onlyforward.conf.j2 | 52 ----- 5 files changed, 132 insertions(+), 179 deletions(-) delete mode 100644 roles/rsyslog/templates/rsyslog_onlyforward.conf.j2 diff --git a/roles/rsyslog/defaults/main.yml b/roles/rsyslog/defaults/main.yml index c9ba8074f..a39efaae7 100644 --- a/roles/rsyslog/defaults/main.yml +++ b/roles/rsyslog/defaults/main.yml @@ -12,7 +12,15 @@ stepupapps: - tiqr - azure-mfa - azuremfa -rsyslog_dir_file_modes: 'dirCreateMode="0755" fileCreateMode="0640" FileGroup="surfsudo"' + +rsyslog_dir_file_modes: > + dirCreateMode="0755" + DirOwner="root" + DirGroup="root" + fileCreateMode="0640" + FileOwner="root" + FileGroup="{{ rsyslog_read_group }}" + # Define relp_remote in group vars for rsyslog remote logging # relp_remote: # - name: '' # name of the central syslog server @@ -42,6 +50,9 @@ rsyslog_checkemptylogs_cron_hour: "9" rsyslog_checkemptylogs_cron_weekdays: "1-5" rsyslog_checkemptylogs_dir: "/usr/local/bin" +# messages can become quote large; e.g., Engineblock sometimes dumps large SAMLResponses +rsyslog_maxmessagesize: "32k" + # "program" matches the syslog identifier # "contains" and "startswith" match the syslog message rsyslog_central_apps: diff --git a/roles/rsyslog/tasks/main.yml b/roles/rsyslog/tasks/main.yml index 39e4408d9..901dfec26 100644 --- a/roles/rsyslog/tasks/main.yml +++ b/roles/rsyslog/tasks/main.yml @@ -31,6 +31,22 @@ name: rsyslog enabled: true +- name: Create the group that is allowed to read the logs + ansible.builtin.group: + name: "{{ rsyslog_read_group }}" + state: present + +# note: this config file supports both local-log-only and central syslog hosts +- name: Put rsyslog config file + ansible.builtin.template: + src: "rsyslog.conf.j2" + dest: "/etc/rsyslog.conf" + owner: root + group: root + mode: "0644" + notify: + - "restart rsyslog" + - name: Forwarding journalctl to rsyslog forward syslog to central logserver block: @@ -95,14 +111,6 @@ mode: "0644" owner: root group: adm - - - name: Put rsyslog config file for logforwarding - ansible.builtin.template: - src: "rsyslog_onlyforward.conf.j2" - dest: "/etc/rsyslog.conf" - mode: "0644" - owner: root - group: root notify: - "restart rsyslog" diff --git a/roles/rsyslog/tasks/rsyslog_central.yml b/roles/rsyslog/tasks/rsyslog_central.yml index 3bf9605bc..8c701d6ab 100644 --- a/roles/rsyslog/tasks/rsyslog_central.yml +++ b/roles/rsyslog/tasks/rsyslog_central.yml @@ -7,11 +7,6 @@ mode: "0400" owner: root -- name: Create the group that is allowed to read the logs - ansible.builtin.group: - name: "{{ rsyslog_read_group }}" - state: present - - name: Create directory to save the logs ansible.builtin.file: path: "{{ rsyslog_dir }}" @@ -78,13 +73,6 @@ src: centralsyslog.j2 dest: /etc/logrotate.d/centralsyslog -- name: Put rsyslog config file - ansible.builtin.template: - src: "rsyslog.conf.j2" - dest: "/etc/rsyslog.conf" - notify: - - "restart rsyslog" - - name: Put log empty warn script and cronjob when: rsyslog_enable_warn_empty_script block: diff --git a/roles/rsyslog/templates/rsyslog.conf.j2 b/roles/rsyslog/templates/rsyslog.conf.j2 index 0f9caa69f..336700292 100644 --- a/roles/rsyslog/templates/rsyslog.conf.j2 +++ b/roles/rsyslog/templates/rsyslog.conf.j2 @@ -1,122 +1,120 @@ -# rsyslog configuration file - -# For more information see /usr/share/doc/rsyslog-*/rsyslog_conf.html -# If you experience problems, see http://www.rsyslog.com/doc/troubleshoot.html - #### MODULES #### -$MaxMessageSize 32k -# The imjournal module below is now used as a message source instead of imuxsock. -$ModLoad imuxsock # provides support for local system logging (e.g. via logger command) -$ModLoad imjournal # provides access to the systemd journal -#$ModLoad imklog # reads kernel messages (the same are read from journald) -$ModLoad immark # provides --MARK-- message capability - -## Adjust Ratelimit -$imjournalRatelimitInterval 30 -$imjournalRatelimitBurst 20000 - -#### GLOBAL DIRECTIVES #### - -# Where to place auxiliary files -$WorkDirectory /var/lib/rsyslog - -# Use default timestamp format -$ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat - -# File syncing capability is disabled by default. This feature is usually not required, -# not useful and an extreme performance hit -#$ActionFileEnableSync on - -# Turn off message reception via local log socket; -# local messages are retrieved through imjournal now. -$OmitLocalLogging on - -# File to store the position in the journal -$IMJournalStateFile imjournal.state -# MARK messages -$ActionWriteAllMarkMessages on -$MarkMessagePeriod 600 -$PreserveFQDN on -# Order is important here: First the templates, then rules, then listerers, then forwarders -{% if 'centrallog_servers' in group_names %} -# This directory contains templates for a central syslog host -$IncludeConfig /etc/rsyslog.d/templates/*.conf +## input modules +# This module provides the ability to accept syslog messages from applications running on the local system via Unix sockets +module(load="imuxsock" + syssock.use="off" # Turn off message reception via local log socket; local messages are retrieved through imjournal now. +) + +{% if 'docker' in group_names %} +# for docker hosts, we support logging directly from inside the docker host to a TCP socket on the container host +# Provides the ability to receive syslog messages via TCP +module(load="imptcp") +input(type="imptcp" port="514") {% endif %} -#### RULES #### -# The rules below make sure all local logging is also logged on local machines -# Log all kernel messages to the console. -# Logging much else clutters up the screen. -#kern.* /dev/console - -# Log anything (except mail) of level info or higher. -# Don't log private authentication messages! -*.info;mail.none;authpriv.none;cron.none;local6.none /var/log/messages +# Provides the ability to import structured log messages from systemd journal to syslog. +module(load="imjournal" + UsePid="system" # PID number is retrieved as the ID of the process the journal entry originates from + StateFile="{{ rsyslog_imjournal_statefile | default('imjournal.state') }}" + ratelimit.interval="{{ rsyslog_imjournal_ratelimitinterval | default('60') }}" + ratelimit.burst="{{ rsyslog_imjournal_ratelimitburst | default('20000') }}" +) + +# Reads messages from the kernel log and submits them to the syslog engine. +module(load="imklog") + +# This module provides the ability to inject periodic “mark” messages to the input of rsyslog. +module(load="immark" + interval="300" + writeallmarkmessages="on" +) + +## output modules +# This module supports sending syslog messages over the reliable RELP protocol +module(load="omrelp") -# The authpriv file has restricted access. -authpriv.* /var/log/secure +# The omfile plug-in provides the core functionality of writing messages to files residing inside the local file system +module(load="builtin:omfile" + template="RSYSLOG_TraditionalFileFormat" # Use default timestamp format + {{ rsyslog_dir_file_modes}} # Set default file permission +) -# Log all the mail messages in one place. -mail.* -/var/log/maillog -# Log cron stuff -cron.* /var/log/cron -# Everybody gets emergency messages -*.emerg :omusrmsg:* -# Save news errors of level crit and higher in a special file. -uucp,news.crit /var/log/spooler +#### GLOBAL DIRECTIVES #### +# where to place aux file (spool, etc) +global(workDirectory="/var/lib/rsyslog") + +# Support large messages +global(maxMessageSize="{{ rsyslog_maxmessagesize }}") + +# Keep fully qualified hostnames instead of stripping the local domain. +global(preserveFQDN="on") + + +#### LOCAL TEMPLATES AND RULES #### +## templates +template(name="CustomRelpFormat" + type="string" + string="<%PRI%>%TIMESTAMP% {{ ansible_fqdn }} %syslogtag%%msg%\n" +) + +## rules +## this is the default ruleset, used for local messages + +# emergency messages to the console +if prifilt("*.emerg") then { + action(type="omusrmsg" users="*") +} + +{% for relp_host in relp_remote %} +# all other local logs are forwarded to {{ relp_host.name }} +action(type="omrelp" + target="{{ relp_host.host }}" + port="{{ relp_host.port }}" + tls="on" + tls.caCert="{{ rsyslog_ca }}" + tls.MyCert="/etc/pki/rsyslog/rsyslogclient.crt" + tls.MyPrivKey="/etc/pki/rsyslog/rsyslogclient.key" + tls.authmode="name" + tls.permittedpeer=["{{ relp_host.peer }}"] + queue.type="LinkedList" + queue.filename="{{ relp_host.name }}" + queue.spoolDirectory="{{ rsyslog_queue_dir }}" + queue.maxdiskspace="1G" + queue.saveonshutdown="on" + action.resumeRetryCount="-1" + action.resumeInterval="5" + action.writeAllMarkMessages="on" + template="CustomRelpFormat" +) +{% else %} +{# default if relp_remote is empty #} +# No relp hosts are available, write everything to /var/log/syslog} +action(type="omfile" file="/var/log/syslog") +{% endfor %} + +# stop processing local messages +stop -# Save boot messages also to boot.log -local7.* /var/log/boot.log {% if 'centrallog_servers' in group_names %} -# Make the logs readable -$DirCreateMode 0775 -$FileCreateMode 0640 -$FileOwner root -$FileGroup {{ rsyslog_read_group }} -$DirOwner root -$DirGroup root - -# This directory contains all rulesets on the central syslog host -$IncludeConfig /etc/rsyslog.d/rulesets/*.conf -{% endif %} -# Default listener for localhost -module(load="imudp") -input(type="imudp" port="514") +#### TEMPLATE, RULES AND LISTENERS FOR REMOTE MESSAGES +# Each listener (on a specific port) binds to a specific ruleset for a specific environment. +# Only the rules from that specific ruleset are applied. The default ruleset defined above +# for local messages is not used here +# Provides the ability to receive syslog messages via the reliable RELP protocol. +module(load="imrelp") -{% if 'centrallog_servers' in group_names %} -# Now we include all the listeners -module(load="imrelp" ) -$IncludeConfig /etc/rsyslog.d/listeners/*.conf -{% endif %} +# Templates +include(file="/etc/rsyslog.d/templates/*.conf") -# ### begin forwarding rule ### -# The statement between the begin ... end define a SINGLE forwarding -# rule. They belong together, do NOT split them. If you create multiple -# forwarding rules, duplicate the whole block! -# Remote Logging (we use TCP for reliable delivery) -# +# Rulesets +include(file="/etc/rsyslog.d/rulesets/*.conf") + +# Listeners +include(file="/etc/rsyslog.d/listeners/*.conf") -{% if rsyslog_remote_server_relp is defined and 'centrallog_servers' not in group_names %} -# Forward all logs to the central logging server using relp -module(load="omrelp") -action(type="omrelp" -target="{{ rsyslog_remote_server_relp }}" -port="{{ rsyslog_remote_relp_port }}" -tls="on" -tls.caCert="{{ rsyslog_ca }}" -tls.MyCert="/etc/pki/rsyslog/rsyslogclient.crt" -tls.MyPrivKey="/etc/pki/rsyslog/rsyslogclient.key" -tls.authmode="name" -tls.permittedpeer=["{{ rsyslog_remote_server_relp }}"] -queue.type="LinkedList" -queue.filename="rsyslog_relp_q" -queue.maxdiskspace="1G" -queue.saveonshutdown="on" -action.resumeRetryCount="-1" -action.resumeInterval="5") {% endif %} diff --git a/roles/rsyslog/templates/rsyslog_onlyforward.conf.j2 b/roles/rsyslog/templates/rsyslog_onlyforward.conf.j2 deleted file mode 100644 index 5cd6fb976..000000000 --- a/roles/rsyslog/templates/rsyslog_onlyforward.conf.j2 +++ /dev/null @@ -1,52 +0,0 @@ -# Where to place auxiliary files -global(workDirectory="{{ rsyslog_workdirectory | default('/var/spool/rsyslog') }}") - -{% if 'docker' in group_names %} -module(load="imptcp") -input(type="imptcp" port="514") -{% endif %} -{% if ansible_os_family == "RedHat" %} -module(load="imuxsock") -{% endif %} -module(load="imjournal" # provides access to the systemd journal - UsePid="system" # PID number is retrieved as the ID of the process the journal entry originates from - StateFile="{{ rsyslog_imjournal_statefile | default('imjournal.state') }}" - ratelimit.interval="{{ rsyslog_imjournal_ratelimitinterval | default('60') }}" - ratelimit.burst="{{ rsyslog_imjournal_ratelimitburst | default('20000') }}") # Reads journald logs -module(load="imklog") # provides kernel logging support -module(load="immark" interval="300" ) # provides --MARK-- message capability -module(load="omrelp") - -template(name="CustomRelpFormat" type="string" - string="<%PRI%>%TIMESTAMP% {{ ansible_fqdn }} %syslogtag%%msg%\n") - -$PreserveFQDN on - -*.emerg :omusrmsg:* -{% if rsyslog_maxmessagesize is defined %} -$MaxMessageSize {{ rsyslog_maxmessagesize }} -{% endif %} - -{% if 'centrallog_servers' not in group_names %} -{% for relp_host in relp_remote %} -# Logs are forwarded to {{ relp_host.name }} -action(type="omrelp" -target="{{ relp_host.host }}" -port="{{ relp_host.port }}" -tls="on" -tls.caCert="{{ rsyslog_ca }}" -tls.MyCert="/etc/pki/rsyslog/rsyslogclient.crt" -tls.MyPrivKey="/etc/pki/rsyslog/rsyslogclient.key" -tls.authmode="name" -tls.permittedpeer=["{{ relp_host.peer }}"] -queue.type="LinkedList" -queue.filename="{{ relp_host.name }}" -queue.spoolDirectory="{{ rsyslog_queue_dir }}" -queue.maxdiskspace="1G" -queue.saveonshutdown="on" -action.resumeRetryCount="-1" -action.resumeInterval="5" -action.writeAllMarkMessages="on" -template="CustomRelpFormat") -{% endfor %} -{% endif %} From 4ed374e491ba6ea6e24e1b2aa482c655c78ad1aa Mon Sep 17 00:00:00 2001 From: Bas Zoetekouw Date: Thu, 27 Aug 2026 11:49:08 +0200 Subject: [PATCH 06/25] Fix rsyslog start/restart --- roles/rsyslog/tasks/main.yml | 14 ++++++++------ roles/rsyslog/tasks/rsyslog_central.yml | 2 ++ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/roles/rsyslog/tasks/main.yml b/roles/rsyslog/tasks/main.yml index 901dfec26..928f0feb3 100644 --- a/roles/rsyslog/tasks/main.yml +++ b/roles/rsyslog/tasks/main.yml @@ -26,11 +26,6 @@ notify: - "restart rsyslog" -- name: Enable rsyslog - ansible.builtin.service: - name: rsyslog - enabled: true - - name: Create the group that is allowed to read the logs ansible.builtin.group: name: "{{ rsyslog_read_group }}" @@ -63,7 +58,9 @@ ansible.builtin.file: path: "{{ rsyslog_service_dropindir }}/logging.conf" state: absent - notify: "Reload systemd" + notify: + - "Reload systemd" + - "restart rsyslog" # Since we specify queue.spoolDirectory, lets make sure it exists - name: Create queue dir @@ -135,3 +132,8 @@ - name: Include tasks for authentication log processing ansible.builtin.include_tasks: process_auth_logs.yml when: "'auth_processor' in group_names" + +- name: Enable rsyslog + ansible.builtin.service: + name: rsyslog + enabled: true diff --git a/roles/rsyslog/tasks/rsyslog_central.yml b/roles/rsyslog/tasks/rsyslog_central.yml index 8c701d6ab..f7dc2198c 100644 --- a/roles/rsyslog/tasks/rsyslog_central.yml +++ b/roles/rsyslog/tasks/rsyslog_central.yml @@ -22,6 +22,8 @@ mode: "0644" owner: root group: adm + notify: + - "restart rsyslog" - name: Create directories to keep configuration file ansible.builtin.file: From 2e7a46a3cbdca878b6ff8aa476a3385193796246 Mon Sep 17 00:00:00 2001 From: Bas Zoetekouw Date: Thu, 27 Aug 2026 11:49:46 +0200 Subject: [PATCH 07/25] clean up --- roles/rsyslog/defaults/main.yml | 2 +- roles/rsyslog/tasks/main.yml | 4 +++- roles/rsyslog/tasks/rsyslog_central.yml | 6 +++--- roles/rsyslog/templates/listener.conf.j2 | 17 +++++++++-------- 4 files changed, 16 insertions(+), 13 deletions(-) diff --git a/roles/rsyslog/defaults/main.yml b/roles/rsyslog/defaults/main.yml index a39efaae7..6d6883955 100644 --- a/roles/rsyslog/defaults/main.yml +++ b/roles/rsyslog/defaults/main.yml @@ -65,7 +65,7 @@ rsyslog_central_apps: eb_auth: { program: "engineblock", contains: '"channel":"authentication"', dir: "log_logins", target: "eb-authentication.log" } stepup_auth1: { program: "gateway", contains: '"message":"Second Factor Authenticated"', - dir: "log_logins", target: "stepup-authentication.log" } + dir: "log_logins", target: "stepup-authentication.log" } stepup_auth2: { program: "gateway", contains: '"message":"Intrinsic Loa Requested"', dir: "log_logins", target: "stepup-authentication.log" } stepup_auth3: { program: "stepup-authentication", diff --git a/roles/rsyslog/tasks/main.yml b/roles/rsyslog/tasks/main.yml index 928f0feb3..85dd2ef80 100644 --- a/roles/rsyslog/tasks/main.yml +++ b/roles/rsyslog/tasks/main.yml @@ -1,3 +1,5 @@ +--- + - name: remove old files: ansible.builtin.file: path: "/etc/pki/rsyslog/{{ item }}" @@ -50,7 +52,7 @@ ansible.builtin.lineinfile: path: /etc/systemd/journald.conf search_string: 'ForwardToSyslog=' - line: 'ForwardToSyslog=no' # commenting out ForwardToSyslog=yes still results in enabling the option on debian + line: 'ForwardToSyslog=no' notify: - "Restart journald" diff --git a/roles/rsyslog/tasks/rsyslog_central.yml b/roles/rsyslog/tasks/rsyslog_central.yml index f7dc2198c..9440c23f1 100644 --- a/roles/rsyslog/tasks/rsyslog_central.yml +++ b/roles/rsyslog/tasks/rsyslog_central.yml @@ -44,7 +44,6 @@ with_items: "{{ rsyslog_environments }}" loop_control: label: "{{ item.name }}" - notify: - "restart rsyslog" @@ -83,10 +82,11 @@ src: warn-empty-log.sh.j2 dest: "{{ rsyslog_checkemptylogs_dir }}/warn-empty-log.sh" backup: True + - name: Create cronjob ansible.builtin.cron: name: "check empty logs" - minute: "{{ rsyslog_checkemptylogs_cron_minute }}" - hour: "{{ rsyslog_checkemptylogs_cron_hour }}" + minute: "{{ rsyslog_checkemptylogs_cron_minute | str }}" + hour: "{{ rsyslog_checkemptylogs_cron_hour| str }}" weekday: "{{ rsyslog_checkemptylogs_cron_weekdays }}" job: "{{ rsyslog_checkemptylogs_dir }}/warn-empty-log.sh -m" diff --git a/roles/rsyslog/templates/listener.conf.j2 b/roles/rsyslog/templates/listener.conf.j2 index 1e1a667fe..59ac4d29d 100644 --- a/roles/rsyslog/templates/listener.conf.j2 +++ b/roles/rsyslog/templates/listener.conf.j2 @@ -1,9 +1,10 @@ +# define rsyslog listener for environment {{ item.name }} input(type="imrelp" port="{{ item.port }}" -ruleset="{{ item.name }}" -tls="on" -tls.mycert="/etc/pki/rsyslog/rsyslogserver.crt" -tls.myprivkey="/etc/pki/rsyslog/rsyslogserver.key" -tls.caCert="{{ rsyslog_ca }}" -tls.authmode="name" -tls.permittedpeer="{{ item.permittedpeer }}") - + ruleset="{{ item.name }}" + tls="on" + tls.mycert="/etc/pki/rsyslog/rsyslogserver.crt" + tls.myprivkey="/etc/pki/rsyslog/rsyslogserver.key" + tls.caCert="{{ rsyslog_ca }}" + tls.authmode="name" + tls.permittedpeer="{{ item.permittedpeer }}" +) From 06c10baf75125c923a77ac6a57b05fbb6b7c2351 Mon Sep 17 00:00:00 2001 From: Bas Zoetekouw Date: Thu, 27 Aug 2026 11:50:27 +0200 Subject: [PATCH 08/25] Simplify ruleset and templates for central syslog --- roles/rsyslog/templates/sc_ruleset.conf.j2 | 57 ++++++++++++--------- roles/rsyslog/templates/sc_template.conf.j2 | 14 ----- 2 files changed, 34 insertions(+), 37 deletions(-) diff --git a/roles/rsyslog/templates/sc_ruleset.conf.j2 b/roles/rsyslog/templates/sc_ruleset.conf.j2 index c5a5ae0d2..dda4bc5ce 100644 --- a/roles/rsyslog/templates/sc_ruleset.conf.j2 +++ b/roles/rsyslog/templates/sc_ruleset.conf.j2 @@ -1,28 +1,39 @@ -$RuleSet {{ item.name }} -{% if item.name != "mgnt_sc" %} +ruleset(name="{{ item.name }}") { -{% for app, config in rsyslog_central_apps.items() %} -if $programname == "{{ config.program }}" - {%- if 'contains' in config %} and $msg contains '{{ config.contains }}' {% endif -%} - {%- if 'startswith' in config %} and $msg startswith '{{ config.startswith }}' {% endif %} - then { action(type="omfile" DynaFile="{{ app }}-{{ item.name }}" {{ rsyslog_dir_file_modes }}) stop } -{% endfor %} + {% if item.name != "mgnt_sc" %} -{% for stepupapp in stepupapps %} -if $programname == "stepup-{{ stepupapp }}" then { action(type="omfile" DynaFile="stepup-{{ stepupapp }}-{{item.name }}" {{ rsyslog_dir_file_modes }}) stop } -if $programname == "{{ stepupapp }}" and $msg startswith "{{ stepupapp }}" then { action(type="omfile" DynaFile="apache-{{ stepupapp }}-{{item.name }}" {{ rsyslog_dir_file_modes }}) stop } -if $programname == "{{ stepupapp }}" then { action(type="omfile" DynaFile="stepup-{{ stepupapp }}-{{item.name }}" {{ rsyslog_dir_file_modes }}) stop } -if $programname == "Apache-{{ stepupapp }}" then { action(type="omfile" DynaFile="apache-{{ stepupapp }}-{{item.name }}" {{ rsyslog_dir_file_modes }}) stop } -{% endfor %} -if $programname == "Apache-azuremfa" then { action(type="omfile" DynaFile="apache-azure-mfa-{{ item.name }}" {{ rsyslog_dir_file_modes }}) stop } + {% for app, config in rsyslog_central_apps.items() %} + {% set dir = config.dir if 'dir' in config else 'apps' %} + if $programname == "{{ config.program }}" + {%- if 'contains' in config %} and $msg contains '{{ config.contains }}' {% endif -%} + {%- if 'startswith' in config %} and $msg startswith '{{ config.startswith }}' {% endif %} + then { action(type="omfile" File="{{ rsyslog_dir }}/{{ dir }}/{{ item.name }}/{{ config.target }}") stop } + {% endfor %} + ## stepup + {% for stepupapp in stepupapps %} + # {{ stepupapp }} + if $programname == "stepup-{{ stepupapp }}" + then { action(type="omfile" File="{{ rsyslog_dir }}/apps/{{ item.name }}/{{ stepupapp }}/{{ stepupapp }}.log") stop } + if $programname == "{{ stepupapp }}" and $msg startswith "{{ stepupapp }}" + then { action(type="omfile" File="{{ rsyslog_dir }}/apps/{{ item.name }}/{{ stepupapp }}/{{ stepupapp }}-apache.log") stop } + if $programname == "{{ stepupapp }}" + then { action(type="omfile" File="{{ rsyslog_dir }}/apps/{{ item.name }}/{{ stepupapp }}/{{ stepupapp }}.log") stop } + if $programname == "Apache-{{ stepupapp }}" + then { action(type="omfile" File="{{ rsyslog_dir }}/apps/{{ item.name }}/{{ stepupapp }}/{{ stepupapp }}-apache.log") stop } + {% endfor %} -{% endif %} -if $programname == "audispd" then { action(type="omfile" DynaFile="auditd-{{ item.name }}" {{ rsyslog_dir_file_modes }}) stop } -if $programname == "audit" then { action(type="omfile" DynaFile="auditd-{{ item.name }}" {{ rsyslog_dir_file_modes }}) stop } -if $programname == "audisp-syslog" then { action(type="omfile" DynaFile="auditd-{{ item.name }}" {{ rsyslog_dir_file_modes }}) stop } -if $programname == "-bash" then { action(type="omfile" DynaFile="bash-{{ item.name }}" {{ rsyslog_dir_file_modes }}) stop } -if $programname == "authpriv" then { action(type="omfile" Dynafile="secure-{{ item.name }}" {{ rsyslog_dir_file_modes }}) stop } -if $msg contains "-- MARK --" then { action(type="omfile" DynaFile="MARK-{{ item.name }}" {{ rsyslog_dir_file_modes }}) stop } + {% endif %} -*.* ?hostleft-{{ item.name }} + # per-host specials + if $programname == "audispd" then { action(type="omfile" DynaFile="auditd-{{ item.name }}") stop } + if $programname == "audit" then { action(type="omfile" DynaFile="auditd-{{ item.name }}") stop } + if $programname == "audisp-syslog" then { action(type="omfile" DynaFile="auditd-{{ item.name }}") stop } + if $programname == "-bash" then { action(type="omfile" DynaFile="bash-{{ item.name }}") stop } + if $programname == "authpriv" then { action(type="omfile" Dynafile="secure-{{ item.name }}") stop } + if $msg contains "-- MARK --" then { action(type="omfile" DynaFile="MARK-{{ item.name }}") stop } + + # default action + action(type="omfile" dynaFile="hostleft-{{ item.name }}") + +} diff --git a/roles/rsyslog/templates/sc_template.conf.j2 b/roles/rsyslog/templates/sc_template.conf.j2 index c4d27c9e6..adb709016 100644 --- a/roles/rsyslog/templates/sc_template.conf.j2 +++ b/roles/rsyslog/templates/sc_template.conf.j2 @@ -1,17 +1,3 @@ -{% if item.name != "mgnt_sc" %} - -{% for app, config in rsyslog_central_apps.items() %} -{% set dir = config.dir if 'dir' in config else 'apps' %} -$template {{ app }}-{{ item.name }}, "{{ rsyslog_dir }}/{{ dir }}/{{ item.name }}/{{ config.target }}" -{% endfor %} - -{% for stepupapp in stepupapps %} -$template stepup-{{ stepupapp }}-{{ item.name }}, "{{ rsyslog_dir }}/apps/{{ item.name }}/{{ stepupapp }}/{{ stepupapp }}.log -$template apache-{{ stepupapp }}-{{ item.name }}, "{{ rsyslog_dir }}/apps/{{ item.name }}/{{ stepupapp }}/{{ stepupapp }}-apache.log -{% endfor %} - -{% endif %} - $template auditd-{{ item.name }}, "{{ rsyslog_dir }}/apps/{{ item.name }}/auditd/%HOSTNAME%/auditd.log" $template bash-{{ item.name }}, "{{ rsyslog_dir }}/apps/{{ item.name }}/bash/%HOSTNAME%/bash.log" $template secure-{{ item.name }}, "{{ rsyslog_dir }}/apps/{{ item.name }}/secure/%HOSTNAME%/secure.log" From 8fa85faa42af7c65f4a62775463022f193aa7fc4 Mon Sep 17 00:00:00 2001 From: Bas Zoetekouw Date: Thu, 27 Aug 2026 14:01:04 +0200 Subject: [PATCH 09/25] Clean uo rule generation --- roles/rsyslog/defaults/main.yml | 98 ++++++++++----------- roles/rsyslog/tasks/rsyslog_central.yml | 14 ++- roles/rsyslog/templates/listener.conf.j2 | 8 +- roles/rsyslog/templates/sc_ruleset.conf.j2 | 30 +++---- roles/rsyslog/templates/sc_template.conf.j2 | 10 +-- 5 files changed, 81 insertions(+), 79 deletions(-) diff --git a/roles/rsyslog/defaults/main.yml b/roles/rsyslog/defaults/main.yml index 6d6883955..3a63d2cc7 100644 --- a/roles/rsyslog/defaults/main.yml +++ b/roles/rsyslog/defaults/main.yml @@ -55,56 +55,50 @@ rsyslog_maxmessagesize: "32k" # "program" matches the syslog identifier # "contains" and "startswith" match the syslog message +# order is important! First matching rule wins. rsyslog_central_apps: - haproxy: { program: "haproxy", target: "haproxy/haproxy.log" } - keepalived: { program: "Keepalived_vrrp", target: "keepalived/keepalived.log" } - galera: { program: "mariadb", target: "galera/galera.log" } - galera_garb: { program: "garb-systemd", target: "galera/galera_garb.log" } - mongo: { program: "mongod", target: "mongo/mongo.log" } - traefik: { program: "loadbalancer", target: "traefik/traefik.log" } - eb_auth: { program: "engineblock", contains: '"channel":"authentication"', - dir: "log_logins", target: "eb-authentication.log" } - stepup_auth1: { program: "gateway", contains: '"message":"Second Factor Authenticated"', - dir: "log_logins", target: "stepup-authentication.log" } - stepup_auth2: { program: "gateway", contains: '"message":"Intrinsic Loa Requested"', - dir: "log_logins", target: "stepup-authentication.log" } - stepup_auth3: { program: "stepup-authentication", - dir: "log_logins", target: "stepup-authentication.log" } - eb_apache: { program: "engineblock", startswith: "engine", - target: "eb/apache.log" } - eb: { program: "engineblock", target: "eb/eb.log" } - eb_log: { program: "EBLOG", target: "eb/eb.log" } - eb_apache2: { program: "Apache-EB", target: "eb/apache.log" } # probabaly ununsed - eb_api: { program: "Apache-EBAPI", target: "eb-api/apache.log" } # probabaly ununsed - oidcng_server: { program: "oidcngserver", target: "oidcng/oidcng.log" } - oidcng_json: { program: "oicdngjson", target: "oidcng/oidcngjson.log" } - oidc_play_server: { program: "oidcplaygroundserver", target: "oidc-playground/oidc-playground.log" } - oidc_play_gui: { program: "oidcplaygroundgui", target: "oidc-playground/oidc-playground-apache.log" } - manage_server: { program: "manageserver", target: "manage/manage.log" } - manage_gui: { program: "managegui", target: "manage/apache.log" } - aa_server: { program: "aaserver", target: "aa/aa.log" } - aa_gui: { program: "aagui", target: "aa/apache.log" } - aa_link: { program: "aalink", target: "aa/apache.log" } - pdp: { program: "pdp", target: "pdp/pdp.log" } - voot: { program: "vootserver", target: "voot/voot.log" } - eduid_server: { program: "myconextserver", target: "eduid/myconext.log" } - eduid_json: { program: "myconextjson", target: "eduid/myconextjson.log" } - eduid_gui: { program: "myconextgui", target: "eduid/myconext-apache.log" } - eduid_account: { program: "accountgui", target: "eduid/account-apache.log" } - eduid_servicedesk: { program: "servicedeskgui", target: "eduid/servicedesk-apache.log" } - invite_client: { program: "inviteclient", target: "invite/inviteclient.log" } - invite_welcome: { program: "invitewelcome", target: "invite/invitewelcome.log" } - invite_server: { program: "inviteserver", target: "invite/inviteserver.log" } - invite_json: { program: "invitejson", target: "invite/invitejson.log" } - invite_provmock: { program: "inviteprovisioningmock", target: "invite/inviteprovisioningmock.log" } - profile: { program: "profile", startswith: "{", - target: "profile/profile.log" } - profile_apache: { program: "profile", target: "profile/apache.log" } - spdashboard: { program: "spdashboard", startswith: "spdashboard", - target: "spdashboard/spdashboard.log" } - spdashboard_apache: { program: "spdashboard", target: "spdashboard/apache.log" } - dashboard_server: { program: "dashboardserver", target: "dashboard/dashboard.log" } - dashboard_gui: { program: "dashboardgui", target: "dashboard/apache.log" } - static: { program: "Apache-STATIC", target: "static/apache.log" } - metadata: { program: "Apache-METADATA", target: "metadata/apache.log" } - acme: { program: "acme.sh", target: "haproxy/acme.log" } + - { program: "haproxy", target: "haproxy/haproxy.log" } + - { program: "Keepalived_vrrp", target: "keepalived/keepalived.log" } + - { program: "mariadb", target: "galera/galera.log" } + - { program: "garb-systemd", target: "galera/galera_garb.log" } + - { program: "mongod", target: "mongo/mongo.log" } + - { program: "loadbalancer", target: "traefik/traefik.log" } + - { program: "engineblock", contains: '"channel":"authentication"', dir: "log_logins", target: "eb-authentication.log" } + - { program: "gateway", contains: '"message":"Second Factor Authenticated"', dir: "log_logins", target: "stepup-authentication.log" } + - { program: "gateway", contains: '"message":"Intrinsic Loa Requested"', dir: "log_logins", target: "stepup-authentication.log" } + - { program: "stepup-authentication", dir: "log_logins", target: "stepup-authentication.log" } + - { program: "engineblock", startswith: "engine", target: "eb/apache.log" } + - { program: "engineblock", target: "eb/eb.log" } + - { program: "EBLOG", target: "eb/eb.log" } + - { program: "Apache-EB", target: "eb/apache.log" } # probably ununsed + - { program: "Apache-EBAPI", target: "eb-api/apache.log" } # probably ununsed + - { program: "oidcngserver", target: "oidcng/oidcng.log" } + - { program: "oicdngjson", target: "oidcng/oidcngjson.log" } + - { program: "oidcplaygroundserver", target: "oidc-playground/oidc-playground.log" } + - { program: "oidcplaygroundgui", target: "oidc-playground/oidc-playground-apache.log" } + - { program: "manageserver", target: "manage/manage.log" } + - { program: "managegui", target: "manage/apache.log" } + - { program: "aaserver", target: "aa/aa.log" } + - { program: "aagui", target: "aa/apache.log" } + - { program: "aalink", target: "aa/apache.log" } + - { program: "pdp", target: "pdp/pdp.log" } + - { program: "vootserver", target: "voot/voot.log" } + - { program: "myconextserver", target: "eduid/myconext.log" } + - { program: "myconextjson", target: "eduid/myconextjson.log" } + - { program: "myconextgui", target: "eduid/myconext-apache.log" } + - { program: "accountgui", target: "eduid/account-apache.log" } + - { program: "servicedeskgui", target: "eduid/servicedesk-apache.log" } + - { program: "inviteclient", target: "invite/inviteclient.log" } + - { program: "invitewelcome", target: "invite/invitewelcome.log" } + - { program: "inviteserver", target: "invite/inviteserver.log" } + - { program: "invitejson", target: "invite/invitejson.log" } + - { program: "inviteprovisioningmock", target: "invite/inviteprovisioningmock.log" } + - { program: "profile", startswith: "{", target: "profile/profile.log" } + - { program: "profile", target: "profile/apache.log" } + - { program: "spdashboard", startswith: "spdashboard", target: "spdashboard/spdashboard.log" } + - { program: "spdashboard", target: "spdashboard/apache.log" } + - { program: "dashboardserver", target: "dashboard/dashboard.log" } + - { program: "dashboardgui", target: "dashboard/apache.log" } + - { program: "Apache-STATIC", target: "static/apache.log" } + - { program: "Apache-METADATA", target: "metadata/apache.log" } + - { program: "acme.sh", target: "haproxy/acme.log" } diff --git a/roles/rsyslog/tasks/rsyslog_central.yml b/roles/rsyslog/tasks/rsyslog_central.yml index 9440c23f1..1ad8c37ce 100644 --- a/roles/rsyslog/tasks/rsyslog_central.yml +++ b/roles/rsyslog/tasks/rsyslog_central.yml @@ -41,7 +41,9 @@ src: sc_template.conf.j2 dest: /etc/rsyslog.d/templates/{{ item.name }}.conf backup: true - with_items: "{{ rsyslog_environments }}" + vars: # use a semantic name in the template + env_name: "{{ item.name }}" + loop: "{{ rsyslog_environments }}" loop_control: label: "{{ item.name }}" notify: @@ -52,7 +54,9 @@ src: sc_ruleset.conf.j2 dest: /etc/rsyslog.d/rulesets/{{ item.name }}.conf backup: true - with_items: "{{ rsyslog_environments }}" + vars: # use a semantic name in the template + env_name: "{{ item.name }}" + loop: "{{ rsyslog_environments }}" loop_control: label: "{{ item.name }}" notify: @@ -63,7 +67,11 @@ src: listener.conf.j2 dest: /etc/rsyslog.d/listeners/{{ item.name }}.conf backup: true - with_items: "{{ rsyslog_environments }}" + vars: # use a semantic name in the template + env_name: "{{ item.name }}" + port: "{{ item.port }}" + peer: "{{ item.permittedpeer }}" + loop: "{{ rsyslog_environments }}" loop_control: label: "{{ item.name }}" notify: diff --git a/roles/rsyslog/templates/listener.conf.j2 b/roles/rsyslog/templates/listener.conf.j2 index 59ac4d29d..ff8e188b0 100644 --- a/roles/rsyslog/templates/listener.conf.j2 +++ b/roles/rsyslog/templates/listener.conf.j2 @@ -1,10 +1,10 @@ -# define rsyslog listener for environment {{ item.name }} -input(type="imrelp" port="{{ item.port }}" - ruleset="{{ item.name }}" +# define rsyslog listener for environment {{ env_name }} +input(type="imrelp" port="{{ port }}" + ruleset="{{ env_name }}" tls="on" tls.mycert="/etc/pki/rsyslog/rsyslogserver.crt" tls.myprivkey="/etc/pki/rsyslog/rsyslogserver.key" tls.caCert="{{ rsyslog_ca }}" tls.authmode="name" - tls.permittedpeer="{{ item.permittedpeer }}" + tls.permittedpeer="{{ peer }}" ) diff --git a/roles/rsyslog/templates/sc_ruleset.conf.j2 b/roles/rsyslog/templates/sc_ruleset.conf.j2 index dda4bc5ce..224e111d1 100644 --- a/roles/rsyslog/templates/sc_ruleset.conf.j2 +++ b/roles/rsyslog/templates/sc_ruleset.conf.j2 @@ -1,39 +1,39 @@ -ruleset(name="{{ item.name }}") { +ruleset(name="{{ env_name }}") { - {% if item.name != "mgnt_sc" %} + {% if env_name != "mgnt_sc" %} - {% for app, config in rsyslog_central_apps.items() %} + {% for config in rsyslog_central_apps %} {% set dir = config.dir if 'dir' in config else 'apps' %} if $programname == "{{ config.program }}" {%- if 'contains' in config %} and $msg contains '{{ config.contains }}' {% endif -%} {%- if 'startswith' in config %} and $msg startswith '{{ config.startswith }}' {% endif %} - then { action(type="omfile" File="{{ rsyslog_dir }}/{{ dir }}/{{ item.name }}/{{ config.target }}") stop } + then { action(type="omfile" File="{{ rsyslog_dir }}/{{ dir }}/{{ env_name }}/{{ config.target }}") stop } {% endfor %} ## stepup {% for stepupapp in stepupapps %} # {{ stepupapp }} if $programname == "stepup-{{ stepupapp }}" - then { action(type="omfile" File="{{ rsyslog_dir }}/apps/{{ item.name }}/{{ stepupapp }}/{{ stepupapp }}.log") stop } + then { action(type="omfile" File="{{ rsyslog_dir }}/apps/{{ env_name }}/{{ stepupapp }}/{{ stepupapp }}.log") stop } if $programname == "{{ stepupapp }}" and $msg startswith "{{ stepupapp }}" - then { action(type="omfile" File="{{ rsyslog_dir }}/apps/{{ item.name }}/{{ stepupapp }}/{{ stepupapp }}-apache.log") stop } + then { action(type="omfile" File="{{ rsyslog_dir }}/apps/{{ env_name }}/{{ stepupapp }}/{{ stepupapp }}-apache.log") stop } if $programname == "{{ stepupapp }}" - then { action(type="omfile" File="{{ rsyslog_dir }}/apps/{{ item.name }}/{{ stepupapp }}/{{ stepupapp }}.log") stop } + then { action(type="omfile" File="{{ rsyslog_dir }}/apps/{{ env_name }}/{{ stepupapp }}/{{ stepupapp }}.log") stop } if $programname == "Apache-{{ stepupapp }}" - then { action(type="omfile" File="{{ rsyslog_dir }}/apps/{{ item.name }}/{{ stepupapp }}/{{ stepupapp }}-apache.log") stop } + then { action(type="omfile" File="{{ rsyslog_dir }}/apps/{{ env_name }}/{{ stepupapp }}/{{ stepupapp }}-apache.log") stop } {% endfor %} {% endif %} # per-host specials - if $programname == "audispd" then { action(type="omfile" DynaFile="auditd-{{ item.name }}") stop } - if $programname == "audit" then { action(type="omfile" DynaFile="auditd-{{ item.name }}") stop } - if $programname == "audisp-syslog" then { action(type="omfile" DynaFile="auditd-{{ item.name }}") stop } - if $programname == "-bash" then { action(type="omfile" DynaFile="bash-{{ item.name }}") stop } - if $programname == "authpriv" then { action(type="omfile" Dynafile="secure-{{ item.name }}") stop } - if $msg contains "-- MARK --" then { action(type="omfile" DynaFile="MARK-{{ item.name }}") stop } + if $programname == "audispd" then { action(type="omfile" DynaFile="auditd-{{ env_name }}") stop } + if $programname == "audit" then { action(type="omfile" DynaFile="auditd-{{ env_name }}") stop } + if $programname == "audisp-syslog" then { action(type="omfile" DynaFile="auditd-{{ env_name }}") stop } + if $programname == "-bash" then { action(type="omfile" DynaFile="bash-{{ env_name }}") stop } + if $programname == "authpriv" then { action(type="omfile" Dynafile="secure-{{ env_name }}") stop } + if $msg contains "-- MARK --" then { action(type="omfile" DynaFile="MARK-{{ env_name }}") stop } # default action - action(type="omfile" dynaFile="hostleft-{{ item.name }}") + action(type="omfile" dynaFile="hostleft-{{ env_name }}") } diff --git a/roles/rsyslog/templates/sc_template.conf.j2 b/roles/rsyslog/templates/sc_template.conf.j2 index adb709016..6e5306894 100644 --- a/roles/rsyslog/templates/sc_template.conf.j2 +++ b/roles/rsyslog/templates/sc_template.conf.j2 @@ -1,6 +1,6 @@ -$template auditd-{{ item.name }}, "{{ rsyslog_dir }}/apps/{{ item.name }}/auditd/%HOSTNAME%/auditd.log" -$template bash-{{ item.name }}, "{{ rsyslog_dir }}/apps/{{ item.name }}/bash/%HOSTNAME%/bash.log" -$template secure-{{ item.name }}, "{{ rsyslog_dir }}/apps/{{ item.name }}/secure/%HOSTNAME%/secure.log" -$template MARK-{{ item.name }}, "{{ rsyslog_dir }}/monitoring/%HOSTNAME%" +$template auditd-{{ env_name }}, "{{ rsyslog_dir }}/apps/{{ env_name }}/auditd/%HOSTNAME%/auditd.log" +$template bash-{{ env_name }}, "{{ rsyslog_dir }}/apps/{{ env_name }}/bash/%HOSTNAME%/bash.log" +$template secure-{{ env_name }}, "{{ rsyslog_dir }}/apps/{{ env_name }}/secure/%HOSTNAME%/secure.log" +$template MARK-{{ env_name }}, "{{ rsyslog_dir }}/monitoring/%HOSTNAME%" -$template hostleft-{{ item.name }}, "{{ rsyslog_dir }}/hosts/{{ item.name }}/%HOSTNAME%/%SYSLOGFACILITY-TEXT%" +$template hostleft-{{ env_name }}, "{{ rsyslog_dir }}/hosts/{{ env_name }}/%HOSTNAME%/%SYSLOGFACILITY-TEXT%" From a44df3e38778e2ae59e20f63b1d342f86105e478 Mon Sep 17 00:00:00 2001 From: Bas Zoetekouw Date: Thu, 27 Aug 2026 14:03:55 +0200 Subject: [PATCH 10/25] remove unused block --- roles/rsyslog/tasks/main.yml | 159 +++++++++++++++++------------------ 1 file changed, 79 insertions(+), 80 deletions(-) diff --git a/roles/rsyslog/tasks/main.yml b/roles/rsyslog/tasks/main.yml index 85dd2ef80..41719508e 100644 --- a/roles/rsyslog/tasks/main.yml +++ b/roles/rsyslog/tasks/main.yml @@ -1,6 +1,6 @@ --- -- name: remove old files: +- name: remove old files ansible.builtin.file: path: "/etc/pki/rsyslog/{{ item }}" state: "absent" @@ -44,86 +44,83 @@ notify: - "restart rsyslog" -- name: Forwarding journalctl to rsyslog forward syslog to central logserver - block: +# journald forwards logs to rsyslog +- name: When using imjournal no forwarding necessary + ansible.builtin.lineinfile: + path: /etc/systemd/journald.conf + search_string: 'ForwardToSyslog=' + line: 'ForwardToSyslog=no' + notify: + - "Restart journald" + +- name: Remove logging dropin + ansible.builtin.file: + path: "{{ rsyslog_service_dropindir }}/logging.conf" + state: absent + notify: + - "Reload systemd" + - "restart rsyslog" + +# Since we specify queue.spoolDirectory, lets make sure it exists +- name: Create queue dir + ansible.builtin.file: + path: "{{ rsyslog_queue_dir }}" + state: directory + owner: root + group: root + mode: "0700" + +# rsyslog certificates for relp +- name: Create the pki directory if it does not exist + ansible.builtin.file: + path: "{{ rsyslog_certifcate_dir }}" + state: directory + owner: root + group: root + mode: "0700" + +# We need a key and client certificate to when using RELP +- name: Put rsyslog client key + ansible.builtin.copy: + content: "{{ rsyslogclientkey }}" + dest: "{{ rsyslog_certifcate_dir }}/rsyslogclient.key" + mode: "0400" + owner: root + no_log: true + notify: + - "restart rsyslog" - # journald forwards logs to rsyslog - - name: When using imjournal no forwarding necessary - ansible.builtin.lineinfile: - path: /etc/systemd/journald.conf - search_string: 'ForwardToSyslog=' - line: 'ForwardToSyslog=no' - notify: - - "Restart journald" - - - name: Remove logging dropin - ansible.builtin.file: - path: "{{ rsyslog_service_dropindir }}/logging.conf" - state: absent - notify: - - "Reload systemd" - - "restart rsyslog" - - # Since we specify queue.spoolDirectory, lets make sure it exists - - name: Create queue dir - ansible.builtin.file: - path: "{{ rsyslog_queue_dir }}" - state: directory - owner: root - group: root - mode: "0700" - - # rsyslog certificates for relp - - name: Create the pki directory if it does not exist - ansible.builtin.file: - path: "{{ rsyslog_certifcate_dir }}" - state: directory - owner: root - group: root - mode: "0700" - - # We need a key and client certificate to when using RELP - - name: Put rsyslog client key - ansible.builtin.copy: - content: "{{ rsyslogclientkey }}" - dest: "{{ rsyslog_certifcate_dir }}/rsyslogclient.key" - mode: "0400" - owner: root - no_log: true - notify: - - "restart rsyslog" - - - name: Put rsyslog client certificate - ansible.builtin.copy: - src: "{{ inventory_dir }}/files/certs/rsyslog/rsyslogclient.crt" - dest: "{{ rsyslog_certifcate_dir }}/rsyslogclient.crt" - mode: "0644" - owner: root - group: adm - notify: - - "restart rsyslog" - - - name: Put rsyslog CA file - ansible.builtin.copy: - src: "{{ inventory_dir }}/files/certs/rsyslog/rsyslog_ca.crt" - dest: "{{ rsyslog_ca }}" - mode: "0644" - owner: root - group: adm - notify: - - "restart rsyslog" - - # Not sure why this is necessary on the forwarding server - # but seems to work - - name: Allow extra port rsyslog_tls_port_t - community.general.seport: - ports: "{{ rsyslog_remote_relp_port }}" - proto: tcp - setype: syslog_tls_port_t - state: present - when: ansible_selinux.mode is defined and ansible_selinux.mode == "enforcing" - -# central logserver +- name: Put rsyslog client certificate + ansible.builtin.copy: + src: "{{ inventory_dir }}/files/certs/rsyslog/rsyslogclient.crt" + dest: "{{ rsyslog_certifcate_dir }}/rsyslogclient.crt" + mode: "0644" + owner: root + group: adm + notify: + - "restart rsyslog" + +- name: Put rsyslog CA file + ansible.builtin.copy: + src: "{{ inventory_dir }}/files/certs/rsyslog/rsyslog_ca.crt" + dest: "{{ rsyslog_ca }}" + mode: "0644" + owner: root + group: adm + notify: + - "restart rsyslog" + +# Not sure why this is necessary on the forwarding server +# but seems to work +- name: Allow extra port rsyslog_tls_port_t + community.general.seport: + ports: "{{ rsyslog_remote_relp_port }}" + proto: tcp + setype: syslog_tls_port_t + state: present + when: ansible_selinux.mode is defined and ansible_selinux.mode == "enforcing" + +#### central logserver - name: Include tasks for configuring the central log server when: "'centrallog_servers' in group_names" @@ -135,6 +132,8 @@ ansible.builtin.include_tasks: process_auth_logs.yml when: "'auth_processor' in group_names" +### and enable + - name: Enable rsyslog ansible.builtin.service: name: rsyslog From 502d50f63aec776ba65e6e2b8ae757654e8ff381 Mon Sep 17 00:00:00 2001 From: Bas Zoetekouw Date: Thu, 27 Aug 2026 15:25:31 +0200 Subject: [PATCH 11/25] task bugs --- roles/rsyslog/tasks/main.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/roles/rsyslog/tasks/main.yml b/roles/rsyslog/tasks/main.yml index 41719508e..6d3fd8ce5 100644 --- a/roles/rsyslog/tasks/main.yml +++ b/roles/rsyslog/tasks/main.yml @@ -77,7 +77,7 @@ state: directory owner: root group: root - mode: "0700" + mode: "0755" # We need a key and client certificate to when using RELP - name: Put rsyslog client key @@ -106,7 +106,7 @@ dest: "{{ rsyslog_ca }}" mode: "0644" owner: root - group: adm + group: root notify: - "restart rsyslog" From c1fad94731dd6a5e3e5b9c274cd822ac3f10f058 Mon Sep 17 00:00:00 2001 From: Bas Zoetekouw Date: Thu, 27 Aug 2026 15:25:52 +0200 Subject: [PATCH 12/25] fix spaces --- roles/rsyslog/templates/sc_ruleset.conf.j2 | 22 ++++++++++----------- roles/rsyslog/templates/sc_template.conf.j2 | 4 ++-- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/roles/rsyslog/templates/sc_ruleset.conf.j2 b/roles/rsyslog/templates/sc_ruleset.conf.j2 index 224e111d1..f8e12c0b5 100644 --- a/roles/rsyslog/templates/sc_ruleset.conf.j2 +++ b/roles/rsyslog/templates/sc_ruleset.conf.j2 @@ -2,24 +2,24 @@ ruleset(name="{{ env_name }}") { {% if env_name != "mgnt_sc" %} - {% for config in rsyslog_central_apps %} - {% set dir = config.dir if 'dir' in config else 'apps' %} + {% for config in rsyslog_central_apps -%} + {%- set dir = config.dir if 'dir' in config else 'apps' -%} if $programname == "{{ config.program }}" - {%- if 'contains' in config %} and $msg contains '{{ config.contains }}' {% endif -%} - {%- if 'startswith' in config %} and $msg startswith '{{ config.startswith }}' {% endif %} - then { action(type="omfile" File="{{ rsyslog_dir }}/{{ dir }}/{{ env_name }}/{{ config.target }}") stop } + {%- if 'contains' in config %} and $msg contains '{{ config.contains }}'{% endif %} + {%- if 'startswith' in config %} and $msg startswith '{{ config.startswith }}'{% endif -%} + {# #} then { action(type="omfile" File="{{ rsyslog_dir }}/{{ dir }}/{{ env_name }}/{{ config.target }}") stop } {% endfor %} ## stepup - {% for stepupapp in stepupapps %} + {%- for stepupapp in stepupapps -%} # {{ stepupapp }} - if $programname == "stepup-{{ stepupapp }}" + if $programname == "stepup-{{ stepupapp }}" {# -#} then { action(type="omfile" File="{{ rsyslog_dir }}/apps/{{ env_name }}/{{ stepupapp }}/{{ stepupapp }}.log") stop } - if $programname == "{{ stepupapp }}" and $msg startswith "{{ stepupapp }}" + if $programname == "{{ stepupapp }}" and $msg startswith "{{ stepupapp }}" {# -#} then { action(type="omfile" File="{{ rsyslog_dir }}/apps/{{ env_name }}/{{ stepupapp }}/{{ stepupapp }}-apache.log") stop } - if $programname == "{{ stepupapp }}" + if $programname == "{{ stepupapp }}" {# -#} then { action(type="omfile" File="{{ rsyslog_dir }}/apps/{{ env_name }}/{{ stepupapp }}/{{ stepupapp }}.log") stop } - if $programname == "Apache-{{ stepupapp }}" + if $programname == "Apache-{{ stepupapp }}" {# -#} then { action(type="omfile" File="{{ rsyslog_dir }}/apps/{{ env_name }}/{{ stepupapp }}/{{ stepupapp }}-apache.log") stop } {% endfor %} @@ -35,5 +35,5 @@ ruleset(name="{{ env_name }}") { # default action action(type="omfile" dynaFile="hostleft-{{ env_name }}") - + stop } diff --git a/roles/rsyslog/templates/sc_template.conf.j2 b/roles/rsyslog/templates/sc_template.conf.j2 index 6e5306894..fa425ae3f 100644 --- a/roles/rsyslog/templates/sc_template.conf.j2 +++ b/roles/rsyslog/templates/sc_template.conf.j2 @@ -1,6 +1,6 @@ $template auditd-{{ env_name }}, "{{ rsyslog_dir }}/apps/{{ env_name }}/auditd/%HOSTNAME%/auditd.log" -$template bash-{{ env_name }}, "{{ rsyslog_dir }}/apps/{{ env_name }}/bash/%HOSTNAME%/bash.log" +$template bash-{{ env_name }}, "{{ rsyslog_dir }}/apps/{{ env_name }}/bash/%HOSTNAME%/bash.log" $template secure-{{ env_name }}, "{{ rsyslog_dir }}/apps/{{ env_name }}/secure/%HOSTNAME%/secure.log" -$template MARK-{{ env_name }}, "{{ rsyslog_dir }}/monitoring/%HOSTNAME%" +$template MARK-{{ env_name }}, "{{ rsyslog_dir }}/monitoring/%HOSTNAME%" $template hostleft-{{ env_name }}, "{{ rsyslog_dir }}/hosts/{{ env_name }}/%HOSTNAME%/%SYSLOGFACILITY-TEXT%" From 22f4f7a4193ee59bbb1a5370a4664ba5a9697275 Mon Sep 17 00:00:00 2001 From: Bas Zoetekouw Date: Thu, 27 Aug 2026 15:26:06 +0200 Subject: [PATCH 13/25] fix inconsistent defaults --- roles/rsyslog/defaults/main.yml | 7 ++----- roles/rsyslog/templates/rsyslog.conf.j2 | 4 ++-- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/roles/rsyslog/defaults/main.yml b/roles/rsyslog/defaults/main.yml index 3a63d2cc7..f1d2d0e46 100644 --- a/roles/rsyslog/defaults/main.yml +++ b/roles/rsyslog/defaults/main.yml @@ -32,11 +32,8 @@ rsyslog_service_dropindir: "/etc/systemd/system/rsyslog.service.d" rsyslog_certifcate_dir: "/etc/pki/rsyslog" rsyslog_queue_dir: "/var/spool/rsyslog" -# these already have appropriate defaults in the template or rsyslog but you can -# change them if necessary, for example on docker hosts they have to be a little higher -# rsyslog_imjournal_ratelimitburst: 2000 -# rsyslog_imjournal_ratelimitinterval: 600 -# rsyslog_maxmessagesize: 8000 +rsyslog_imjournal_ratelimitburst: 20000 +rsyslog_imjournal_ratelimitinterval: 60 # rsyslog_imjournal_statefile # default is imjournal.state which means imjournal.state relative to the rsyslog workdir # rsyslog_workdirectory # default /var/spool/rsyslog diff --git a/roles/rsyslog/templates/rsyslog.conf.j2 b/roles/rsyslog/templates/rsyslog.conf.j2 index 336700292..2578a9e2a 100644 --- a/roles/rsyslog/templates/rsyslog.conf.j2 +++ b/roles/rsyslog/templates/rsyslog.conf.j2 @@ -17,8 +17,8 @@ input(type="imptcp" port="514") module(load="imjournal" UsePid="system" # PID number is retrieved as the ID of the process the journal entry originates from StateFile="{{ rsyslog_imjournal_statefile | default('imjournal.state') }}" - ratelimit.interval="{{ rsyslog_imjournal_ratelimitinterval | default('60') }}" - ratelimit.burst="{{ rsyslog_imjournal_ratelimitburst | default('20000') }}" + ratelimit.interval="{{ rsyslog_imjournal_ratelimitinterval }}" + ratelimit.burst="{{ rsyslog_imjournal_ratelimitburst }}" ) # Reads messages from the kernel log and submits them to the syslog engine. From 37d0b20d5da3347cbcdfc5a0b6aef338e2495fa4 Mon Sep 17 00:00:00 2001 From: Bas Zoetekouw Date: Thu, 27 Aug 2026 15:26:18 +0200 Subject: [PATCH 14/25] Fix order of rules --- roles/rsyslog/defaults/main.yml | 47 ++++++++++++++++++++++----------- 1 file changed, 31 insertions(+), 16 deletions(-) diff --git a/roles/rsyslog/defaults/main.yml b/roles/rsyslog/defaults/main.yml index f1d2d0e46..fd21b0cd2 100644 --- a/roles/rsyslog/defaults/main.yml +++ b/roles/rsyslog/defaults/main.yml @@ -54,20 +54,24 @@ rsyslog_maxmessagesize: "32k" # "contains" and "startswith" match the syslog message # order is important! First matching rule wins. rsyslog_central_apps: + # infra - { program: "haproxy", target: "haproxy/haproxy.log" } - - { program: "Keepalived_vrrp", target: "keepalived/keepalived.log" } + - { program: "acme.sh", target: "haproxy/acme.log" } - { program: "mariadb", target: "galera/galera.log" } - - { program: "garb-systemd", target: "galera/galera_garb.log" } - { program: "mongod", target: "mongo/mongo.log" } + - { program: "garb-systemd", target: "galera/galera_garb.log" } + - { program: "Keepalived_vrrp", target: "keepalived/keepalived.log" } - { program: "loadbalancer", target: "traefik/traefik.log" } + + # core - { program: "engineblock", contains: '"channel":"authentication"', dir: "log_logins", target: "eb-authentication.log" } - - { program: "gateway", contains: '"message":"Second Factor Authenticated"', dir: "log_logins", target: "stepup-authentication.log" } - - { program: "gateway", contains: '"message":"Intrinsic Loa Requested"', dir: "log_logins", target: "stepup-authentication.log" } - { program: "stepup-authentication", dir: "log_logins", target: "stepup-authentication.log" } + - { program: "engineblock", startswith: "engine", target: "eb/apache.log" } + - { program: "Apache-EB", target: "eb/apache.log" } # probably ununsed + - { program: "engineblock", target: "eb/eb.log" } - { program: "EBLOG", target: "eb/eb.log" } - - { program: "Apache-EB", target: "eb/apache.log" } # probably ununsed - { program: "Apache-EBAPI", target: "eb-api/apache.log" } # probably ununsed - { program: "oidcngserver", target: "oidcng/oidcng.log" } - { program: "oicdngjson", target: "oidcng/oidcngjson.log" } @@ -75,27 +79,38 @@ rsyslog_central_apps: - { program: "oidcplaygroundgui", target: "oidc-playground/oidc-playground-apache.log" } - { program: "manageserver", target: "manage/manage.log" } - { program: "managegui", target: "manage/apache.log" } + + # core-supporting - { program: "aaserver", target: "aa/aa.log" } - { program: "aagui", target: "aa/apache.log" } - { program: "aalink", target: "aa/apache.log" } - - { program: "pdp", target: "pdp/pdp.log" } - { program: "vootserver", target: "voot/voot.log" } - - { program: "myconextserver", target: "eduid/myconext.log" } - - { program: "myconextjson", target: "eduid/myconextjson.log" } - - { program: "myconextgui", target: "eduid/myconext-apache.log" } - - { program: "accountgui", target: "eduid/account-apache.log" } - - { program: "servicedeskgui", target: "eduid/servicedesk-apache.log" } + - { program: "pdp", target: "pdp/pdp.log" } + + # Invite - { program: "inviteclient", target: "invite/inviteclient.log" } - { program: "invitewelcome", target: "invite/invitewelcome.log" } - { program: "inviteserver", target: "invite/inviteserver.log" } - { program: "invitejson", target: "invite/invitejson.log" } - { program: "inviteprovisioningmock", target: "invite/inviteprovisioningmock.log" } + + # dashboards + - { program: "dashboardgui", target: "dashboard/apache.log" } + - { program: "dashboardserver", target: "dashboard/dashboard.log" } - { program: "profile", startswith: "{", target: "profile/profile.log" } - { program: "profile", target: "profile/apache.log" } - - { program: "spdashboard", startswith: "spdashboard", target: "spdashboard/spdashboard.log" } - - { program: "spdashboard", target: "spdashboard/apache.log" } - - { program: "dashboardserver", target: "dashboard/dashboard.log" } - - { program: "dashboardgui", target: "dashboard/apache.log" } + + # static - { program: "Apache-STATIC", target: "static/apache.log" } - { program: "Apache-METADATA", target: "metadata/apache.log" } - - { program: "acme.sh", target: "haproxy/acme.log" } + + # MyConext + - { program: "myconextserver", target: "eduid/myconext.log" } + - { program: "myconextjson", target: "eduid/myconextjson.log" } + - { program: "myconextgui", target: "eduid/myconext-apache.log" } + - { program: "accountgui", target: "eduid/account-apache.log" } + - { program: "servicedeskgui", target: "eduid/servicedesk-apache.log" } + - { program: "gateway", contains: '"message":"Second Factor Authenticated"', dir: "log_logins", target: "stepup-authentication.log" } + - { program: "gateway", contains: '"message":"Intrinsic Loa Requested"', dir: "log_logins", target: "stepup-authentication.log" } + - { program: "spdashboard", startswith: "spdashboard", target: "spdashboard/spdashboard.log" } + - { program: "spdashboard", target: "spdashboard/apache.log" } From b18355450af462680acb62ff8e7dd9bf59f2d6dd Mon Sep 17 00:00:00 2001 From: Bas Zoetekouw Date: Fri, 28 Aug 2026 14:24:57 +0200 Subject: [PATCH 15/25] imuxsock module is obsolete; handled by systemd socket in decent Linxu distros --- roles/rsyslog/templates/rsyslog.conf.j2 | 5 ----- 1 file changed, 5 deletions(-) diff --git a/roles/rsyslog/templates/rsyslog.conf.j2 b/roles/rsyslog/templates/rsyslog.conf.j2 index 2578a9e2a..4ade3730f 100644 --- a/roles/rsyslog/templates/rsyslog.conf.j2 +++ b/roles/rsyslog/templates/rsyslog.conf.j2 @@ -1,11 +1,6 @@ #### MODULES #### ## input modules -# This module provides the ability to accept syslog messages from applications running on the local system via Unix sockets -module(load="imuxsock" - syssock.use="off" # Turn off message reception via local log socket; local messages are retrieved through imjournal now. -) - {% if 'docker' in group_names %} # for docker hosts, we support logging directly from inside the docker host to a TCP socket on the container host # Provides the ability to receive syslog messages via TCP From 65346a9cb4fb30ca67fa3fcdc5124484c191b832 Mon Sep 17 00:00:00 2001 From: Bas Zoetekouw Date: Fri, 28 Aug 2026 14:45:23 +0200 Subject: [PATCH 16/25] fix cnfig error. `writeallmarkmessages` is already default in recent rsyslog versions --- roles/rsyslog/templates/rsyslog.conf.j2 | 1 - 1 file changed, 1 deletion(-) diff --git a/roles/rsyslog/templates/rsyslog.conf.j2 b/roles/rsyslog/templates/rsyslog.conf.j2 index 4ade3730f..e83a5af35 100644 --- a/roles/rsyslog/templates/rsyslog.conf.j2 +++ b/roles/rsyslog/templates/rsyslog.conf.j2 @@ -22,7 +22,6 @@ module(load="imklog") # This module provides the ability to inject periodic “mark” messages to the input of rsyslog. module(load="immark" interval="300" - writeallmarkmessages="on" ) ## output modules From 86867fc7b914ce2726dd7ce9f2ede0ca663bd67d Mon Sep 17 00:00:00 2001 From: Bas Zoetekouw Date: Fri, 28 Aug 2026 14:07:57 +0200 Subject: [PATCH 17/25] yamllint and ansible-lint --- .yamllint.yaml | 7 +- roles/rsyslog/defaults/main.yml | 132 ++++++++++-------- roles/rsyslog/handlers/main.yml | 19 +-- roles/rsyslog/tasks/main.yml | 95 ++++++------- .../process_auth_log_for_environment.yml | 83 +++++------ roles/rsyslog/tasks/process_auth_logs.yml | 32 ++--- roles/rsyslog/tasks/rsyslog_central.yml | 78 ++++++----- roles/rsyslog/templates/clean_loglogins.j2 | 2 +- roles/rsyslog/templates/sc_ruleset.conf.j2 | 2 +- 9 files changed, 224 insertions(+), 226 deletions(-) diff --git a/.yamllint.yaml b/.yamllint.yaml index 8824391dc..916644d96 100644 --- a/.yamllint.yaml +++ b/.yamllint.yaml @@ -13,7 +13,7 @@ rules: allow-quoted-quotes: false check-keys: false -# ansible-lint compatibility: + # ansible-lint compatibility: comments: min-spaces-from-content: 1 @@ -25,3 +25,8 @@ rules: octal-values: forbid-implicit-octal: true forbid-explicit-octal: true + + commas: + ignore: | + # uses spaces for outlining + /roles/rsyslog/defaults/main.yml diff --git a/roles/rsyslog/defaults/main.yml b/roles/rsyslog/defaults/main.yml index fd21b0cd2..8f4859b2b 100644 --- a/roles/rsyslog/defaults/main.yml +++ b/roles/rsyslog/defaults/main.yml @@ -1,17 +1,17 @@ --- -rsyslog_ca: /etc/pki/rsyslog/rsyslog_ca.pem -rsyslog_dir: /opt/openconext/logs -rsyslog_read_group: adm -loglogins_max_age: 6 -stepupapps: - - gateway - - selfservice - - ra - - middleware - - webauthn - - tiqr - - azure-mfa - - azuremfa +rsyslog_ca: "/etc/pki/rsyslog/rsyslog_ca.pem" +rsyslog_dir: "/opt/openconext/logs" +rsyslog_read_group: "adm" +rsyslog_loglogins_max_age: 6 +rsyslog_stepupapps: + - "gateway" + - "selfservice" + - "ra" + - "middleware" + - "webauthn" + - "tiqr" + - "azure-mfa" + - "azuremfa" rsyslog_dir_file_modes: > dirCreateMode="0755" @@ -40,7 +40,7 @@ rsyslog_imjournal_ratelimitinterval: 60 # Empty log check script, optional rsyslog_enable_warn_empty_script: false -rsyslog_warn_empty_log_recipient: admin@example.com +rsyslog_warn_empty_log_recipient: "admin@example.com" rsyslog_monitor_for_emptylogs_path: "{{ rsyslog_dir }}/apps/prod_sc" rsyslog_checkemptylogs_cron_minute: "0" rsyslog_checkemptylogs_cron_hour: "9" @@ -50,67 +50,75 @@ rsyslog_checkemptylogs_dir: "/usr/local/bin" # messages can become quote large; e.g., Engineblock sometimes dumps large SAMLResponses rsyslog_maxmessagesize: "32k" + +# matching rules for distributing logs on central loghost +# order is important! First matching rule wins. +# # "program" matches the syslog identifier # "contains" and "startswith" match the syslog message -# order is important! First matching rule wins. +# "dir" defaults to `apps` +# +# final path of the log file is `{{ rsyslog_dir }}/{{ dir }}/{{ env_name }}/{{ target }}` rsyslog_central_apps: # infra - - { program: "haproxy", target: "haproxy/haproxy.log" } - - { program: "acme.sh", target: "haproxy/acme.log" } - - { program: "mariadb", target: "galera/galera.log" } - - { program: "mongod", target: "mongo/mongo.log" } - - { program: "garb-systemd", target: "galera/galera_garb.log" } - - { program: "Keepalived_vrrp", target: "keepalived/keepalived.log" } - - { program: "loadbalancer", target: "traefik/traefik.log" } + - { program: "haproxy", target: "haproxy/haproxy.log" } + - { program: "acme.sh", target: "haproxy/acme.log" } + - { program: "mariadb", target: "galera/galera.log" } + - { program: "mongod", target: "mongo/mongo.log" } + - { program: "garb-systemd", target: "galera/galera_garb.log" } + - { program: "Keepalived_vrrp", target: "keepalived/keepalived.log" } + - { program: "loadbalancer", target: "traefik/traefik.log" } # core - - { program: "engineblock", contains: '"channel":"authentication"', dir: "log_logins", target: "eb-authentication.log" } - - { program: "stepup-authentication", dir: "log_logins", target: "stepup-authentication.log" } - - - { program: "engineblock", startswith: "engine", target: "eb/apache.log" } - - { program: "Apache-EB", target: "eb/apache.log" } # probably ununsed - - - { program: "engineblock", target: "eb/eb.log" } - - { program: "EBLOG", target: "eb/eb.log" } - - { program: "Apache-EBAPI", target: "eb-api/apache.log" } # probably ununsed - - { program: "oidcngserver", target: "oidcng/oidcng.log" } - - { program: "oicdngjson", target: "oidcng/oidcngjson.log" } - - { program: "oidcplaygroundserver", target: "oidc-playground/oidc-playground.log" } - - { program: "oidcplaygroundgui", target: "oidc-playground/oidc-playground-apache.log" } - - { program: "manageserver", target: "manage/manage.log" } - - { program: "managegui", target: "manage/apache.log" } + - { program: "engineblock", contains: '"channel":"authentication"', dir: "log_logins", target: "eb-authentication.log" } + - { program: "stepup-authentication", dir: "log_logins", target: "stepup-authentication.log" } + + - { program: "engineblock", startswith: "engine", target: "eb/apache.log" } + - { program: "Apache-EB", target: "eb/apache.log" } # probably ununsed + + - { program: "engineblock", target: "eb/eb.log" } + - { program: "EBLOG", target: "eb/eb.log" } + - { program: "Apache-EBAPI", target: "eb-api/apache.log" } # probably ununsed + - { program: "oidcngserver", target: "oidcng/oidcng.log" } + - { program: "oicdngjson", target: "oidcng/oidcngjson.log" } + - { program: "oidcplaygroundserver", target: "oidc-playground/oidc-playground.log" } + - { program: "oidcplaygroundgui", target: "oidc-playground/oidc-playground-apache.log" } + - { program: "manageserver", target: "manage/manage.log" } + - { program: "managegui", target: "manage/apache.log" } # core-supporting - - { program: "aaserver", target: "aa/aa.log" } - - { program: "aagui", target: "aa/apache.log" } - - { program: "aalink", target: "aa/apache.log" } - - { program: "vootserver", target: "voot/voot.log" } - - { program: "pdp", target: "pdp/pdp.log" } + - { program: "aaserver", target: "aa/aa.log" } + - { program: "aagui", target: "aa/apache.log" } + - { program: "aalink", target: "aa/apache.log" } + - { program: "vootserver", target: "voot/voot.log" } + - { program: "pdp", target: "pdp/pdp.log" } # Invite - - { program: "inviteclient", target: "invite/inviteclient.log" } - - { program: "invitewelcome", target: "invite/invitewelcome.log" } - - { program: "inviteserver", target: "invite/inviteserver.log" } - - { program: "invitejson", target: "invite/invitejson.log" } - - { program: "inviteprovisioningmock", target: "invite/inviteprovisioningmock.log" } + - { program: "inviteclient", target: "invite/inviteclient.log" } + - { program: "invitewelcome", target: "invite/invitewelcome.log" } + - { program: "inviteserver", target: "invite/inviteserver.log" } + - { program: "invitejson", target: "invite/invitejson.log" } + - { program: "inviteprovisioningmock", target: "invite/inviteprovisioningmock.log" } # dashboards - - { program: "dashboardgui", target: "dashboard/apache.log" } - - { program: "dashboardserver", target: "dashboard/dashboard.log" } - - { program: "profile", startswith: "{", target: "profile/profile.log" } - - { program: "profile", target: "profile/apache.log" } + - { program: "dashboardgui", target: "dashboard/apache.log" } + - { program: "dashboardserver", target: "dashboard/dashboard.log" } + - { program: "spdashboard", startswith: "spdashboard", target: "spdashboard/spdashboard.log" } + - { program: "spdashboard", target: "spdashboard/apache.log" } + - { program: "profile", startswith: "{", target: "profile/profile.log" } + - { program: "profile", target: "profile/apache.log" } # static - - { program: "Apache-STATIC", target: "static/apache.log" } - - { program: "Apache-METADATA", target: "metadata/apache.log" } + - { program: "Apache-STATIC", target: "static/apache.log" } + - { program: "Apache-METADATA", target: "metadata/apache.log" } # MyConext - - { program: "myconextserver", target: "eduid/myconext.log" } - - { program: "myconextjson", target: "eduid/myconextjson.log" } - - { program: "myconextgui", target: "eduid/myconext-apache.log" } - - { program: "accountgui", target: "eduid/account-apache.log" } - - { program: "servicedeskgui", target: "eduid/servicedesk-apache.log" } - - { program: "gateway", contains: '"message":"Second Factor Authenticated"', dir: "log_logins", target: "stepup-authentication.log" } - - { program: "gateway", contains: '"message":"Intrinsic Loa Requested"', dir: "log_logins", target: "stepup-authentication.log" } - - { program: "spdashboard", startswith: "spdashboard", target: "spdashboard/spdashboard.log" } - - { program: "spdashboard", target: "spdashboard/apache.log" } + - { program: "myconextserver", target: "eduid/myconext.log" } + - { program: "myconextjson", target: "eduid/myconextjson.log" } + - { program: "myconextgui", target: "eduid/myconext-apache.log" } + - { program: "accountgui", target: "eduid/account-apache.log" } + - { program: "servicedeskgui", target: "eduid/servicedesk-apache.log" } + + # SSID log_logins + - { program: "gateway", contains: '"message":"Second Factor Authenticated"', dir: "log_logins", target: "stepup-authentication.log" } + - { program: "gateway", contains: '"message":"Intrinsic Loa Requested"', dir: "log_logins", target: "stepup-authentication.log" } diff --git a/roles/rsyslog/handlers/main.yml b/roles/rsyslog/handlers/main.yml index 532abdffe..24d7e48c4 100644 --- a/roles/rsyslog/handlers/main.yml +++ b/roles/rsyslog/handlers/main.yml @@ -1,13 +1,14 @@ --- -- name: restart rsyslog - service: - name: rsyslog - state: restarted +- name: "Restart rsyslog" + ansible.builtin.systemd_service: + name: "rsyslog" + state: "restarted" -- name: Restart journald +- name: "Restart journald" ansible.builtin.systemd_service: - name: systemd-journald - state: restarted + name: "systemd-journald" + state: "restarted" -- name: Reload systemd - ansible.builtin.command: "systemctl daemon-reload" # noqa command-instead-of-module +- name: "Reload systemd" + ansible.builtin.systemd_service: + daemon_reload: true diff --git a/roles/rsyslog/tasks/main.yml b/roles/rsyslog/tasks/main.yml index 6d3fd8ce5..e57a22c85 100644 --- a/roles/rsyslog/tasks/main.yml +++ b/roles/rsyslog/tasks/main.yml @@ -1,6 +1,6 @@ --- -- name: remove old files +- name: "Remove old files" ansible.builtin.file: path: "/etc/pki/rsyslog/{{ item }}" state: "absent" @@ -9,15 +9,15 @@ - "rsyslogclientcaprd.crt" - "rsyslogclientprd.crt" -- name: Install rsyslog and python modules +- name: "Install rsyslog and python modules" ansible.builtin.package: name: - - rsyslog - - rsyslog-gnutls - - rsyslog-relp - state: present + - "rsyslog" + - "rsyslog-gnutls" + - "rsyslog-relp" + state: "present" notify: - - "restart rsyslog" + - "Restart rsyslog" - name: Install rsyslog and python modules ansible.builtin.package: @@ -28,113 +28,106 @@ notify: - "restart rsyslog" -- name: Create the group that is allowed to read the logs +- name: "Create the group that is allowed to read the logs" ansible.builtin.group: name: "{{ rsyslog_read_group }}" - state: present + state: "present" # note: this config file supports both local-log-only and central syslog hosts -- name: Put rsyslog config file +- name: "Put rsyslog config file" ansible.builtin.template: src: "rsyslog.conf.j2" dest: "/etc/rsyslog.conf" - owner: root - group: root mode: "0644" notify: - - "restart rsyslog" + - "Restart rsyslog" # journald forwards logs to rsyslog -- name: When using imjournal no forwarding necessary +- name: "When using imjournal no forwarding necessary" ansible.builtin.lineinfile: - path: /etc/systemd/journald.conf - search_string: 'ForwardToSyslog=' - line: 'ForwardToSyslog=no' + path: "/etc/systemd/journald.conf" + search_string: "ForwardToSyslog=" + line: "ForwardToSyslog=no" notify: - "Restart journald" -- name: Remove logging dropin +- name: "Remove logging dropin" ansible.builtin.file: path: "{{ rsyslog_service_dropindir }}/logging.conf" - state: absent + state: "absent" notify: - "Reload systemd" - - "restart rsyslog" + - "Restart rsyslog" # Since we specify queue.spoolDirectory, lets make sure it exists -- name: Create queue dir +- name: "Create queue dir" ansible.builtin.file: path: "{{ rsyslog_queue_dir }}" - state: directory - owner: root - group: root + state: "directory" mode: "0700" # rsyslog certificates for relp -- name: Create the pki directory if it does not exist +- name: "Create the pki directory if it does not exist" ansible.builtin.file: path: "{{ rsyslog_certifcate_dir }}" - state: directory - owner: root - group: root + state: "directory" mode: "0755" # We need a key and client certificate to when using RELP -- name: Put rsyslog client key +- name: "Put rsyslog client key" ansible.builtin.copy: content: "{{ rsyslogclientkey }}" dest: "{{ rsyslog_certifcate_dir }}/rsyslogclient.key" mode: "0400" - owner: root no_log: true notify: - - "restart rsyslog" + - "Restart rsyslog" -- name: Put rsyslog client certificate +- name: "Put rsyslog client certificate" ansible.builtin.copy: src: "{{ inventory_dir }}/files/certs/rsyslog/rsyslogclient.crt" dest: "{{ rsyslog_certifcate_dir }}/rsyslogclient.crt" mode: "0644" - owner: root - group: adm + owner: "root" + group: "adm" notify: - - "restart rsyslog" + - "Restart rsyslog" -- name: Put rsyslog CA file +- name: "Put rsyslog CA file" ansible.builtin.copy: src: "{{ inventory_dir }}/files/certs/rsyslog/rsyslog_ca.crt" dest: "{{ rsyslog_ca }}" mode: "0644" - owner: root - group: root notify: - - "restart rsyslog" + - "Restart rsyslog" # Not sure why this is necessary on the forwarding server # but seems to work -- name: Allow extra port rsyslog_tls_port_t +- name: "Allow extra port rsyslog_tls_port_t" community.general.seport: ports: "{{ rsyslog_remote_relp_port }}" - proto: tcp - setype: syslog_tls_port_t - state: present - when: ansible_selinux.mode is defined and ansible_selinux.mode == "enforcing" + proto: "tcp" + setype: "syslog_tls_port_t" + state: "present" + when: "ansible_selinux.mode is defined and ansible_selinux.mode == 'enforcing'" #### central logserver -- name: Include tasks for configuring the central log server +- name: "Include tasks for configuring the central log server" when: "'centrallog_servers' in group_names" block: - - name: Include tasks for central syslog server - ansible.builtin.include_tasks: rsyslog_central.yml + - name: "Include tasks for central syslog server" + ansible.builtin.include_tasks: + file: "rsyslog_central.yml" - - name: Include tasks for authentication log processing - ansible.builtin.include_tasks: process_auth_logs.yml + - name: "Include tasks for authentication log processing" + ansible.builtin.include_tasks: + file: "process_auth_logs.yml" when: "'auth_processor' in group_names" ### and enable -- name: Enable rsyslog +- name: "Enable rsyslog" ansible.builtin.service: - name: rsyslog + name: "rsyslog" enabled: true diff --git a/roles/rsyslog/tasks/process_auth_log_for_environment.yml b/roles/rsyslog/tasks/process_auth_log_for_environment.yml index de97e1af5..ce0705f61 100644 --- a/roles/rsyslog/tasks/process_auth_log_for_environment.yml +++ b/roles/rsyslog/tasks/process_auth_log_for_environment.yml @@ -1,78 +1,67 @@ --- - -- name: Create log_logins table for each log_login environment +- name: "Create log_logins table for each log_login environment" community.mysql.mysql_db: name: "{{ rsyslog_environment.db_loglogins_name }}" login_user: "{{ rsyslog_environment.db_loglogins_user }}" login_password: "{{ rsyslog_environment.db_loglogins_password }}" login_host: "{{ rsyslog_environment.db_loglogins_host }}" - state: import - target: /var/tmp/log_logins.sql - changed_when: false + state: "import" + target: "/var/tmp/log_logins.sql" + changed_when: false # TODO -- name: Create lastseen table for each log_login environment +- name: "Create lastseen table for each log_login environment" community.mysql.mysql_db: name: "{{ rsyslog_environment.db_lastseen_name }}" login_user: "{{ rsyslog_environment.db_lastseen_user }}" login_password: "{{ rsyslog_environment.db_lastseen_password }}" login_host: "{{ rsyslog_environment.db_lastseen_host }}" - state: import - target: /var/tmp/lastseen.sql - changed_when: false + state: "import" + target: "/var/tmp/lastseen.sql" + changed_when: false # TODO -- name: Create a python script that parses eb log_logins per environment +- name: "Create a python script that parses eb log_logins per environment" ansible.builtin.template: - src: parse_ebauth_to_mysql.py.j2 - dest: /usr/local/sbin/parse_ebauth_to_mysql_{{ rsyslog_environment.name }}.py - mode: 0740 - owner: root - group: root + src: "parse_ebauth_to_mysql.py.j2" + dest: "/usr/local/sbin/parse_ebauth_to_mysql_{{ rsyslog_environment.name }}.py" + mode: "0740" -- name: Create a python script that parses stepup log_logins per environment +- name: "Create a python script that parses stepup log_logins per environment" ansible.builtin.template: - src: parse_stepupauth_to_mysql.py.j2 - dest: /usr/local/sbin/parse_stepupauth_to_mysql_{{ rsyslog_environment.name }}.py - mode: 0740 - owner: root - group: root + src: "parse_stepupauth_to_mysql.py.j2" + dest: "/usr/local/sbin/parse_stepupauth_to_mysql_{{ rsyslog_environment.name }}.py" + mode: "0740" -- name: Put log_logins logrotate scripts for eb +- name: "Put log_logins logrotate scripts for eb" ansible.builtin.template: - src: logrotate_ebauth.j2 - dest: /etc/logrotate.d/logrotate_ebauth_{{ rsyslog_environment.name }} - mode: 0644 - owner: root - group: root + src: "logrotate_ebauth.j2" + dest: "/etc/logrotate.d/logrotate_ebauth_{{ rsyslog_environment.name }}" + mode: "0644" -- name: Put log_logins logrotate scripts for stepup +- name: "Put log_logins logrotate scripts for stepup" ansible.builtin.template: - src: logrotate_stepupauth.j2 - dest: /etc/logrotate.d/logrotate_stepupauth_{{ rsyslog_environment.name }} - mode: 0644 - owner: root - group: root + src: "logrotate_stepupauth.j2" + dest: "/etc/logrotate.d/logrotate_stepupauth_{{ rsyslog_environment.name }}" + mode: "0644" -- name: Create logdirectory for log_logins cleanup script +- name: "Create logdirectory for log_logins cleanup script" ansible.builtin.file: path: "{{ rsyslog_dir }}/apps/{{ rsyslog_environment.name }}/loglogins_cleanup/" - state: directory - owner: root + state: "directory" + mode: "0750" + owner: "root" group: "{{ rsyslog_read_group }}" - mode: 0750 -- name: Put log_logins cleanup script +- name: "Put log_logins cleanup script" ansible.builtin.template: - src: clean_loglogins.j2 - dest: /usr/local/sbin/clean_loglogins_{{ rsyslog_environment.name }} - owner: root - group: root - mode: 0700 + src: "clean_loglogins.j2" + dest: "/usr/local/sbin/clean_loglogins_{{ rsyslog_environment.name }}" + mode: "0700" -- name: Create cronjobs to run the log_logins script +- name: "Create cronjobs to run the log_logins script" ansible.builtin.cron: - name: Delete old {{ rsyslog_environment.name }} log_login data - user: root + name: "Delete old {{ rsyslog_environment.name }} log_login data" + cron_file: "loglogins_cleanup_{{ rsyslog_environment.name }}" + user: "root" minute: "20" hour: "02" job: "/usr/local/sbin/clean_loglogins_{{ rsyslog_environment.name }}" - cron_file: loglogins_cleanup_{{ rsyslog_environment.name }} diff --git a/roles/rsyslog/tasks/process_auth_logs.yml b/roles/rsyslog/tasks/process_auth_logs.yml index e1cb22365..d428bf390 100644 --- a/roles/rsyslog/tasks/process_auth_logs.yml +++ b/roles/rsyslog/tasks/process_auth_logs.yml @@ -1,24 +1,24 @@ --- -- name: Copy the log_logins and lastseen database table definitions - copy: +- name: "Copy the log_logins and lastseen database table definitions" + ansible.builtin.copy: src: "{{ item }}" - dest: /var/tmp/{{ item }} - owner: root - mode: 0744 + dest: "/var/tmp/{{ item }}" + mode: "0744" with_items: - - log_logins.sql - - lastseen.sql + - "log_logins.sql" + - "lastseen.sql" -- name: add python mysql module for parse_ebauth_to_mysql script - apt: - name: python3-mysqldb - state: present - when: ansible_os_family == "Debian" +- name: "Add python mysql module for parse_ebauth_to_mysql script" + ansible.builtin.apt: + name: "python3-mysqldb" + state: "present" + when: "ansible_os_family == 'Debian'" -- name: Process auth logs for each rsyslog environment - ansible.builtin.include_tasks: process_auth_log_for_environment.yml +- name: "Process auth logs for each rsyslog environment" + ansible.builtin.include_tasks: + file: "process_auth_log_for_environment.yml" loop: "{{ rsyslog_environments }}" loop_control: - loop_var: rsyslog_environment + loop_var: "rsyslog_environment" label: "{{ rsyslog_environment.name }}" - when: rsyslog_environment.db_loglogins_name is defined + when: "rsyslog_environment.db_loglogins_name is defined" diff --git a/roles/rsyslog/tasks/rsyslog_central.yml b/roles/rsyslog/tasks/rsyslog_central.yml index 1ad8c37ce..91829597f 100644 --- a/roles/rsyslog/tasks/rsyslog_central.yml +++ b/roles/rsyslog/tasks/rsyslog_central.yml @@ -1,72 +1,72 @@ --- -# The server uses a different set of keys as the client -- name: Put rsyslog server key +# The server uses a different set of keys than the client +- name: "Put rsyslog server key" ansible.builtin.copy: content: "{{ rsyslogserverkey }}" dest: "/etc/pki/rsyslog/rsyslogserver.key" mode: "0400" - owner: root -- name: Create directory to save the logs +- name: "Create directory to save the logs" ansible.builtin.file: path: "{{ rsyslog_dir }}" - owner: root + owner: "root" group: "{{ rsyslog_read_group }}" mode: "0750" - # recurse: true # this makes everything very slow and not sure if it is necessary -- name: Put rsyslog server certificate +- name: "Put rsyslog server certificate" ansible.builtin.copy: src: "{{ inventory_dir }}/files/certs/rsyslog/rsyslogserver.crt" dest: "/etc/pki/rsyslog/rsyslogserver.crt" mode: "0644" - owner: root - group: adm + owner: "root" + group: "adm" notify: - - "restart rsyslog" + - "Restart rsyslog" -- name: Create directories to keep configuration file +- name: "Create directories to keep configuration file" ansible.builtin.file: path: "/etc/rsyslog.d/{{ item }}" - owner: root mode: "0755" - state: directory + state: "directory" with_items: - - listeners - - rulesets - - templates + - "listeners" + - "rulesets" + - "templates" -- name: Create template configurations +- name: "Create template configurations" ansible.builtin.template: - src: sc_template.conf.j2 - dest: /etc/rsyslog.d/templates/{{ item.name }}.conf + src: "sc_template.conf.j2" + dest: "/etc/rsyslog.d/templates/{{ item.name }}.conf" backup: true + mode: "0644" vars: # use a semantic name in the template env_name: "{{ item.name }}" loop: "{{ rsyslog_environments }}" loop_control: label: "{{ item.name }}" notify: - - "restart rsyslog" + - "Restart rsyslog" -- name: Create ruleset configurations +- name: "Create ruleset configurations" ansible.builtin.template: - src: sc_ruleset.conf.j2 - dest: /etc/rsyslog.d/rulesets/{{ item.name }}.conf + src: "sc_ruleset.conf.j2" + dest: "/etc/rsyslog.d/rulesets/{{ item.name }}.conf" backup: true + mode: "0644" vars: # use a semantic name in the template env_name: "{{ item.name }}" loop: "{{ rsyslog_environments }}" loop_control: label: "{{ item.name }}" notify: - - "restart rsyslog" + - "Restart rsyslog" -- name: Create sc listener configurations +- name: "Create sc listener configurations" ansible.builtin.template: - src: listener.conf.j2 - dest: /etc/rsyslog.d/listeners/{{ item.name }}.conf + src: "listener.conf.j2" + dest: "/etc/rsyslog.d/listeners/{{ item.name }}.conf" backup: true + mode: "0644" vars: # use a semantic name in the template env_name: "{{ item.name }}" port: "{{ item.port }}" @@ -75,26 +75,28 @@ loop_control: label: "{{ item.name }}" notify: - - "restart rsyslog" + - "Restart rsyslog" -- name: Create logrotate file for apps and host logs +- name: "Create logrotate file for apps and host logs" ansible.builtin.template: - src: centralsyslog.j2 - dest: /etc/logrotate.d/centralsyslog + src: "centralsyslog.j2" + dest: "/etc/logrotate.d/centralsyslog" + mode: "0644" -- name: Put log empty warn script and cronjob - when: rsyslog_enable_warn_empty_script +- name: "Put log empty warn script and cronjob" + when: "rsyslog_enable_warn_empty_script" block: - - name: Put log empty script + - name: "Put log empty script" ansible.builtin.template: - src: warn-empty-log.sh.j2 + src: "warn-empty-log.sh.j2" dest: "{{ rsyslog_checkemptylogs_dir }}/warn-empty-log.sh" - backup: True + backup: true + mode: "0644" - - name: Create cronjob + - name: "Create cronjob" ansible.builtin.cron: name: "check empty logs" minute: "{{ rsyslog_checkemptylogs_cron_minute | str }}" - hour: "{{ rsyslog_checkemptylogs_cron_hour| str }}" + hour: "{{ rsyslog_checkemptylogs_cron_hour | str }}" weekday: "{{ rsyslog_checkemptylogs_cron_weekdays }}" job: "{{ rsyslog_checkemptylogs_dir }}/warn-empty-log.sh -m" diff --git a/roles/rsyslog/templates/clean_loglogins.j2 b/roles/rsyslog/templates/clean_loglogins.j2 index 7296b01ff..112025094 100644 --- a/roles/rsyslog/templates/clean_loglogins.j2 +++ b/roles/rsyslog/templates/clean_loglogins.j2 @@ -6,7 +6,7 @@ # The script is intended to be run daily from a cron job. MAX_DELETE_DAYS=5 -LOG_LOGINS_MAX_AGE="{{ loglogins_max_age }}" # Number of MONTHS of logins to keep +LOG_LOGINS_MAX_AGE="{{ rsyslog_loglogins_max_age }}" # Number of MONTHS of logins to keep RSYSLOG_DIR="{{ rsyslog_dir }}" RSYSLOG_ENVIRONMENT_NAME="{{ rsyslog_environment.name }}" DB_LOG_LOGINS_NAME="{{ rsyslog_environment.db_loglogins_name }}" diff --git a/roles/rsyslog/templates/sc_ruleset.conf.j2 b/roles/rsyslog/templates/sc_ruleset.conf.j2 index f8e12c0b5..357f76700 100644 --- a/roles/rsyslog/templates/sc_ruleset.conf.j2 +++ b/roles/rsyslog/templates/sc_ruleset.conf.j2 @@ -11,7 +11,7 @@ ruleset(name="{{ env_name }}") { {% endfor %} ## stepup - {%- for stepupapp in stepupapps -%} + {%- for stepupapp in rsyslog_stepupapps -%} # {{ stepupapp }} if $programname == "stepup-{{ stepupapp }}" {# -#} then { action(type="omfile" File="{{ rsyslog_dir }}/apps/{{ env_name }}/{{ stepupapp }}/{{ stepupapp }}.log") stop } From 1e01698261ce4e19f39b0dcd9aa5dbada342312b Mon Sep 17 00:00:00 2001 From: Bas Zoetekouw Date: Fri, 28 Aug 2026 14:08:22 +0200 Subject: [PATCH 18/25] Fix weird defaults handling --- roles/rsyslog/defaults/main.yml | 4 ++-- roles/rsyslog/templates/rsyslog.conf.j2 | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/roles/rsyslog/defaults/main.yml b/roles/rsyslog/defaults/main.yml index 8f4859b2b..ed669da64 100644 --- a/roles/rsyslog/defaults/main.yml +++ b/roles/rsyslog/defaults/main.yml @@ -35,8 +35,8 @@ rsyslog_queue_dir: "/var/spool/rsyslog" rsyslog_imjournal_ratelimitburst: 20000 rsyslog_imjournal_ratelimitinterval: 60 -# rsyslog_imjournal_statefile # default is imjournal.state which means imjournal.state relative to the rsyslog workdir -# rsyslog_workdirectory # default /var/spool/rsyslog +rsyslog_imjournal_statefile: "imjournal.state" +rsyslog_workdirectory: "/var/spool/rsyslog" # Empty log check script, optional rsyslog_enable_warn_empty_script: false diff --git a/roles/rsyslog/templates/rsyslog.conf.j2 b/roles/rsyslog/templates/rsyslog.conf.j2 index e83a5af35..ae050d586 100644 --- a/roles/rsyslog/templates/rsyslog.conf.j2 +++ b/roles/rsyslog/templates/rsyslog.conf.j2 @@ -11,7 +11,7 @@ input(type="imptcp" port="514") # Provides the ability to import structured log messages from systemd journal to syslog. module(load="imjournal" UsePid="system" # PID number is retrieved as the ID of the process the journal entry originates from - StateFile="{{ rsyslog_imjournal_statefile | default('imjournal.state') }}" + StateFile="{{ rsyslog_imjournal_statefile }}" ratelimit.interval="{{ rsyslog_imjournal_ratelimitinterval }}" ratelimit.burst="{{ rsyslog_imjournal_ratelimitburst }}" ) @@ -38,7 +38,7 @@ module(load="builtin:omfile" #### GLOBAL DIRECTIVES #### # where to place aux file (spool, etc) -global(workDirectory="/var/lib/rsyslog") +global(workDirectory="{{ rsyslog_workdirectory }}") # Support large messages global(maxMessageSize="{{ rsyslog_maxmessagesize }}") From 2828314b9a634d6455567ac2633107836f328151 Mon Sep 17 00:00:00 2001 From: Bas Zoetekouw Date: Fri, 28 Aug 2026 14:08:42 +0200 Subject: [PATCH 19/25] Install python module in correct task --- roles/rsyslog/tasks/main.yml | 9 --------- roles/rsyslog/tasks/rsyslog_central.yml | 8 ++++++++ 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/roles/rsyslog/tasks/main.yml b/roles/rsyslog/tasks/main.yml index e57a22c85..e0367e33e 100644 --- a/roles/rsyslog/tasks/main.yml +++ b/roles/rsyslog/tasks/main.yml @@ -19,15 +19,6 @@ notify: - "Restart rsyslog" -- name: Install rsyslog and python modules - ansible.builtin.package: - name: - - python3-dateutil - state: present - when: "'centrallog_servers' in group_names and ansible_distribution_major_version > '7'" - notify: - - "restart rsyslog" - - name: "Create the group that is allowed to read the logs" ansible.builtin.group: name: "{{ rsyslog_read_group }}" diff --git a/roles/rsyslog/tasks/rsyslog_central.yml b/roles/rsyslog/tasks/rsyslog_central.yml index 91829597f..8838ff786 100644 --- a/roles/rsyslog/tasks/rsyslog_central.yml +++ b/roles/rsyslog/tasks/rsyslog_central.yml @@ -1,4 +1,12 @@ --- +- name: "Install python modules" + ansible.builtin.package: + name: + - "python3-dateutil" + state: "present" + notify: + - "Restart rsyslog" + # The server uses a different set of keys than the client - name: "Put rsyslog server key" ansible.builtin.copy: From f9ffb9ad98852b005afb44b5ed1af17bc1df4081 Mon Sep 17 00:00:00 2001 From: Bas Zoetekouw Date: Fri, 28 Aug 2026 14:09:06 +0200 Subject: [PATCH 20/25] fix vars --- roles/rsyslog/tasks/rsyslog_central.yml | 4 ++-- roles/rsyslog/templates/listener.conf.j2 | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/roles/rsyslog/tasks/rsyslog_central.yml b/roles/rsyslog/tasks/rsyslog_central.yml index 8838ff786..6ac7fdceb 100644 --- a/roles/rsyslog/tasks/rsyslog_central.yml +++ b/roles/rsyslog/tasks/rsyslog_central.yml @@ -77,8 +77,8 @@ mode: "0644" vars: # use a semantic name in the template env_name: "{{ item.name }}" - port: "{{ item.port }}" - peer: "{{ item.permittedpeer }}" + listener_port: "{{ item.port }}" + listener_peer: "{{ item.permittedpeer }}" loop: "{{ rsyslog_environments }}" loop_control: label: "{{ item.name }}" diff --git a/roles/rsyslog/templates/listener.conf.j2 b/roles/rsyslog/templates/listener.conf.j2 index ff8e188b0..29e9e76f0 100644 --- a/roles/rsyslog/templates/listener.conf.j2 +++ b/roles/rsyslog/templates/listener.conf.j2 @@ -1,10 +1,10 @@ # define rsyslog listener for environment {{ env_name }} -input(type="imrelp" port="{{ port }}" +input(type="imrelp" port="{{ listener_port }}" ruleset="{{ env_name }}" tls="on" tls.mycert="/etc/pki/rsyslog/rsyslogserver.crt" tls.myprivkey="/etc/pki/rsyslog/rsyslogserver.key" tls.caCert="{{ rsyslog_ca }}" tls.authmode="name" - tls.permittedpeer="{{ peer }}" + tls.permittedpeer="{{ listener_peer }}" ) From 2dbf3937fbb457b4a40d39df5b4092d8c540ea99 Mon Sep 17 00:00:00 2001 From: Bas Zoetekouw Date: Fri, 28 Aug 2026 14:09:16 +0200 Subject: [PATCH 21/25] use semantic variable name --- roles/rsyslog/tasks/rsyslog_central.yml | 5 +++++ roles/rsyslog/templates/rsyslog.conf.j2 | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/roles/rsyslog/tasks/rsyslog_central.yml b/roles/rsyslog/tasks/rsyslog_central.yml index 6ac7fdceb..5012cbb62 100644 --- a/roles/rsyslog/tasks/rsyslog_central.yml +++ b/roles/rsyslog/tasks/rsyslog_central.yml @@ -1,4 +1,9 @@ --- + +- name: "Set variable to note centrallog server" + ansible.builtin.set_fact: + rsyslog_is_centrallog_server: true + - name: "Install python modules" ansible.builtin.package: name: diff --git a/roles/rsyslog/templates/rsyslog.conf.j2 b/roles/rsyslog/templates/rsyslog.conf.j2 index ae050d586..227ca8f00 100644 --- a/roles/rsyslog/templates/rsyslog.conf.j2 +++ b/roles/rsyslog/templates/rsyslog.conf.j2 @@ -93,7 +93,7 @@ action(type="omfile" file="/var/log/syslog") stop -{% if 'centrallog_servers' in group_names %} +{% if rsyslog_is_centrallog_server %} #### TEMPLATE, RULES AND LISTENERS FOR REMOTE MESSAGES # Each listener (on a specific port) binds to a specific ruleset for a specific environment. # Only the rules from that specific ruleset are applied. The default ruleset defined above From fdd3f781e31c89c7edb375ece547e183a4bf8754 Mon Sep 17 00:00:00 2001 From: Bas Zoetekouw Date: Fri, 28 Aug 2026 18:40:44 +0200 Subject: [PATCH 22/25] camelCase and put all gobal deirectives together --- roles/rsyslog/templates/listener.conf.j2 | 10 ++++++---- roles/rsyslog/templates/rsyslog.conf.j2 | 22 ++++++++++++---------- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/roles/rsyslog/templates/listener.conf.j2 b/roles/rsyslog/templates/listener.conf.j2 index 29e9e76f0..f11dd3b22 100644 --- a/roles/rsyslog/templates/listener.conf.j2 +++ b/roles/rsyslog/templates/listener.conf.j2 @@ -2,9 +2,11 @@ input(type="imrelp" port="{{ listener_port }}" ruleset="{{ env_name }}" tls="on" - tls.mycert="/etc/pki/rsyslog/rsyslogserver.crt" - tls.myprivkey="/etc/pki/rsyslog/rsyslogserver.key" + tls.myCert="/etc/pki/rsyslog/rsyslogserver.crt" + tls.myPrivKey="/etc/pki/rsyslog/rsyslogserver.key" tls.caCert="{{ rsyslog_ca }}" - tls.authmode="name" - tls.permittedpeer="{{ listener_peer }}" + tls.authMode="name" + {# CN of certificate of clients that are allowed to connect. + # All clients use the same cert and thus the same "peer name" #} + tls.permittedPeer=["{{ listener_peer }}"] ) diff --git a/roles/rsyslog/templates/rsyslog.conf.j2 b/roles/rsyslog/templates/rsyslog.conf.j2 index 227ca8f00..673f36bb1 100644 --- a/roles/rsyslog/templates/rsyslog.conf.j2 +++ b/roles/rsyslog/templates/rsyslog.conf.j2 @@ -37,14 +37,16 @@ module(load="builtin:omfile" #### GLOBAL DIRECTIVES #### -# where to place aux file (spool, etc) -global(workDirectory="{{ rsyslog_workdirectory }}") +global( + # where to place aux file (spool, etc) + workDirectory="{{ rsyslog_workdirectory }}" -# Support large messages -global(maxMessageSize="{{ rsyslog_maxmessagesize }}") + # Support large messages + maxMessageSize="{{ rsyslog_maxmessagesize }}" -# Keep fully qualified hostnames instead of stripping the local domain. -global(preserveFQDN="on") + # Keep fully qualified hostnames instead of stripping the local domain. + preserveFQDN="on" +) #### LOCAL TEMPLATES AND RULES #### @@ -71,13 +73,13 @@ action(type="omrelp" tls.caCert="{{ rsyslog_ca }}" tls.MyCert="/etc/pki/rsyslog/rsyslogclient.crt" tls.MyPrivKey="/etc/pki/rsyslog/rsyslogclient.key" - tls.authmode="name" - tls.permittedpeer=["{{ relp_host.peer }}"] + tls.authMode="name" + tls.permittedPeer=["{{ relp_host.peer }}"] {#- CN of the certificate of the server #} queue.type="LinkedList" queue.filename="{{ relp_host.name }}" queue.spoolDirectory="{{ rsyslog_queue_dir }}" - queue.maxdiskspace="1G" - queue.saveonshutdown="on" + queue.maxDiskSpace="1G" + queue.saveOnShutdown="on" action.resumeRetryCount="-1" action.resumeInterval="5" action.writeAllMarkMessages="on" From 06a1e2e59f7ec8e954919092e61f0032afbf3af8 Mon Sep 17 00:00:00 2001 From: Bas Zoetekouw Date: Fri, 28 Aug 2026 18:40:53 +0200 Subject: [PATCH 23/25] minor --- roles/rsyslog/tasks/main.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/roles/rsyslog/tasks/main.yml b/roles/rsyslog/tasks/main.yml index e0367e33e..0934c9d34 100644 --- a/roles/rsyslog/tasks/main.yml +++ b/roles/rsyslog/tasks/main.yml @@ -79,8 +79,6 @@ src: "{{ inventory_dir }}/files/certs/rsyslog/rsyslogclient.crt" dest: "{{ rsyslog_certifcate_dir }}/rsyslogclient.crt" mode: "0644" - owner: "root" - group: "adm" notify: - "Restart rsyslog" From d37578dc3055dda93c034c589163a17ab8b322f0 Mon Sep 17 00:00:00 2001 From: Bas Zoetekouw Date: Fri, 28 Aug 2026 19:06:25 +0200 Subject: [PATCH 24/25] FIx SE Linux rule: correctly iterate over used ports --- roles/rsyslog/tasks/main.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/roles/rsyslog/tasks/main.yml b/roles/rsyslog/tasks/main.yml index 0934c9d34..be1c7578f 100644 --- a/roles/rsyslog/tasks/main.yml +++ b/roles/rsyslog/tasks/main.yml @@ -94,10 +94,11 @@ # but seems to work - name: "Allow extra port rsyslog_tls_port_t" community.general.seport: - ports: "{{ rsyslog_remote_relp_port }}" + ports: "{{ item }}" proto: "tcp" setype: "syslog_tls_port_t" state: "present" + loop: "{{ relp_remote | map(attribute='port') | unique }}" when: "ansible_selinux.mode is defined and ansible_selinux.mode == 'enforcing'" #### central logserver From ddfa23d50be28946ace55551b704ab430e387aa9 Mon Sep 17 00:00:00 2001 From: Bas Zoetekouw Date: Fri, 28 Aug 2026 19:06:44 +0200 Subject: [PATCH 25/25] Add timeout to relp formwarder --- roles/rsyslog/templates/listener.conf.j2 | 3 ++- roles/rsyslog/templates/rsyslog.conf.j2 | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/roles/rsyslog/templates/listener.conf.j2 b/roles/rsyslog/templates/listener.conf.j2 index f11dd3b22..af6086cb9 100644 --- a/roles/rsyslog/templates/listener.conf.j2 +++ b/roles/rsyslog/templates/listener.conf.j2 @@ -1,5 +1,6 @@ # define rsyslog listener for environment {{ env_name }} -input(type="imrelp" port="{{ listener_port }}" +input(type="imrelp" + port="{{ listener_port }}" ruleset="{{ env_name }}" tls="on" tls.myCert="/etc/pki/rsyslog/rsyslogserver.crt" diff --git a/roles/rsyslog/templates/rsyslog.conf.j2 b/roles/rsyslog/templates/rsyslog.conf.j2 index 673f36bb1..4a7875e6b 100644 --- a/roles/rsyslog/templates/rsyslog.conf.j2 +++ b/roles/rsyslog/templates/rsyslog.conf.j2 @@ -69,6 +69,7 @@ if prifilt("*.emerg") then { action(type="omrelp" target="{{ relp_host.host }}" port="{{ relp_host.port }}" + timeout="10" {#- needed because otherwise exiting rsyslogd will take the default 90 second timeout #} tls="on" tls.caCert="{{ rsyslog_ca }}" tls.MyCert="/etc/pki/rsyslog/rsyslogclient.crt"