# rsyslog and AppArmor

Starting with version 8.2210.0-3ubuntu2, on fresh installs and upgrades from
earlier versions, rsyslog will be confined by default with AppArmor in enforce
mode.

The AppArmor profile for rsyslog has a static component, and a dynamic one. It
all starts with the main profile in `/etc/apparmor.d/usr.sbin.rsyslogd`. That
profile has an include directive for the dynamic component in
`/etc/apparmor.d/rsyslog.d`:

    # apparmor snippets for rsyslog from other packages
    include if exists <rsyslog.d>

All files placed in `/etc/apparmor.d/rsyslog.d` will be included, with the
exception of standard backup files like files ending in `~`, or with a suffix
generated by `dpkg` when there was a config file prompt. The full list of
exclusions is not really documented, but can be inspected in the source code at
https://sources.debian.org/src/apparmor/3.0.8-2/libraries/libapparmor/src/private.c/#L65.
A `README` file is also ignored.

When `rsyslog` is started, it will reload the apparmor profile, including all
the snippets that may exist in the `rsyslog.d` include directory. This is done
via a `ExecStartPre` call in the systemd unit file:

    [Service]
    Type=notify
    ExecStartPre=/usr/lib/rsyslog/reload-apparmor-profile
    ExecStart=/usr/sbin/rsyslogd -n -iNONE
    ...

Packages (and users) can place apparmor profile config file snippets in
`/etc/apparmor.d/rsyslog.d/`. It is suggested that the filename be in the form
of `<pkg>.apparmor`.

For example, the `rsyslog-pgsql` debian package installs this file
`/etc/apparmor.d/rsyslog.d/rsyslog-pgsql.apparmor`:

    # PostgreSQL local access
    include <abstractions/openssl>
    include <abstractions/ssl_certs>
    /etc/gss/mech.d/ r,
    /etc/gss/mech.d/* r,
    /{,var/}run/postgresql/.s.PGSQL.*[0-9] rw,

When `rsyslog` starts, the `reload-apparmor-profile` will run and
reload the `rsyslogd` apparmor profile just before rsyslogd itself is
started. Note that the enforcement status of the profile (enforce, complain) is
not changed.


# Troubleshooting

When rsyslog gets something denied, particularly if it's in an output module,
it will retry a few times and eventually give up. It usually won´t crash, so
the only way to notice something is wrong is by inspecting the logs, or, well,
by noticing something isn't working, like logging to a database.

Here are the most useful troubleshooting tips.


## Watch the logs

Look for rsyslog errors in the logs, particularly `/var/log/syslog`, or via
`journalctl -u rsyslog.service -f`. For example, when it can't connect to a
local MySQL server, messages like these will appear:

    Jan 31 17:27:15 sender rsyslogd[82257]: ommysql: db error (2002): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (13)  [v8.2210.0]
    Jan 31 17:27:15 sender rsyslogd[82257]: action 'action-8-ommysql' suspended (module 'ommysql'), retry 0. There should be messages before this one giving the reason for suspe>


## Inspect dmesg/apparmor

If the rsyslog apparmor profile is interfering with rsyslog, there will be
messages about it in the `dmesg` output (or in the audit log, if `auditd` is
installed). For example, for the mysql case:

    [Tue Feb  7 12:35:28 2023] audit: type=1400 audit(1675773329.453:84): apparmor="DENIED" operation="connect" class="file" profile="rsyslogd" name="/run/mysqld/mysqld.sock" pid=15495 comm=72733A6D61696E20513A526567 requested_mask="wr" denied_mask="wr" fsuid=101 ouid=107

Since the rsyslog apparmor profile now may include multiple files from
`/etc/apparmor.d/rsyslog.d`, it helps to visualize the whole profile as one
file. The `apparmor_parser` command can be used for that with the `-p` option:

    # apparmor_parser -p /etc/apparmor.d/usr.sbin.rsyslogd
    ...
    ##included <rsyslog.d/rsyslog-mysql.apparmor>
    # MySQL local server access
    ...

This will show all included files, including abstractions.


# Example

Here is an example of what it would look like to adapt a package that ships a
rsyslog configuration that needs the rsyslog apparmor profile to be adjusted.

The `prometheus-postfix-exporter` adds an rsyslog config that has it write logs
to `/var/lib/prometheus/postfix-exporter/mail.log`, which is not allowed by the
base rsyslog apparmor profile.

This is what the fix for this package would look like:

```diff

diff --git a/debian/dirs b/debian/dirs
index 6d3533d..50d9ad8 100644
--- a/debian/dirs
+++ b/debian/dirs
@@ -1,3 +1,4 @@
 etc/rsyslog.d
+etc/apparmor.d/rsyslog.d
 var/lib/prometheus/postfix-exporter
 var/log/prometheus
diff --git a/debian/rsyslog-prometheus-postfix-exporter.apparmor b/debian/rsyslog-prometheus-postfix-exporter.apparmor
new file mode 100644
index 0000000..1b9f85f
--- /dev/null
+++ b/debian/rsyslog-prometheus-postfix-exporter.apparmor
@@ -0,0 +1 @@
+  /var/lib/prometheus/postfix-exporter/mail.log rw,
diff --git a/debian/rules b/debian/rules
index e8ce2f9..ffcf383 100755
--- a/debian/rules
+++ b/debian/rules
@@ -16,3 +16,5 @@ override_dh_auto_install:
 	dh_auto_install -- --no-source
 	install -m644 debian/rsyslog.conf \
             debian/$(BINNAME)/etc/rsyslog.d/$(BINNAME).conf
+	install -m644 debian/rsyslog-prometheus-postfix-exporter.apparmor \
+			debian/$(BINNAME)/etc/apparmor.d/rsyslog.d
```
