Dear Maintainer,
Since 3.20.0-1, the barman package creates the "barman" system account
as a *locked* account, via the new /usr/lib/sysusers.d/barman.conf:
u! barman - "Backup and Recovery Manager for PostgreSQL" /var/lib/barman
/bin/bash
systemd implements the "!" modifier by writing 1 into the shadow expiry
field, so the account is expired since 1970-01-02:
# getent shadow barman
barman:!*:20700:::::1:
# chage -l barman | grep -i 'Account expires'
Account expires : Jan 02, 1970
pam_unix's account module then refuses *every* PAM session for the
account, not only interactive logins. That includes cron. On a stock
install, with no local configuration at all, cron therefore logs this
once a minute, caused by the package's own /etc/cron.d/barman:
CRON[2255]: pam_unix(cron:account): account barman has expired (account
expired)
CRON[2257]: pam_unix(cron:account): account barman has expired (account
expired)
and su(1) to the account no longer works:
# su -s /bin/bash barman -c id
Your account has expired; please contact your system administrator.
su: Authentication failure
I believe this is not what "u!" is meant to achieve here.
sysusers.d(5) documents the modifier as being about *login*:
"may be suffixed with an exclamation mark ("u!") to create a fully
locked account. This is recommended, since logins should typically
not be allowed for system users. With or without the exclamation
mark an invalid password is set. For "u!", the account is also
locked, which makes a difference for non-password forms of
authentication, such as SSH or similar."
Blocking logins and SSH is reasonable for barman. Blocking cron is not,
because scheduling barman through cron as the barman user is both the
documented way to use barman and what this very package ships in
/etc/cron.d/barman.
Impact
------
Two effects, one cosmetic and one not:
1. Every trixie/sid system with barman installed logs an authentication
failure once a minute. The package's own cron.d entry is a no-op
under systemd (it defers to barman.timer), but cron still runs the
PAM account check before evaluating the command, so the refusal is
logged regardless.
2. Any cron job that runs as the barman user is silently refused. This
is the part that actually breaks things. I hit it through a
third-party tool that schedules "barman cron" from /etc/cron.d as
the barman user: "barman archive-wal" never ran, so no WAL segment
was ever moved from streaming/ into wals/, and the tool's
provisioning timed out waiting for the first archived segment. The
only symptom is the PAM line above, which makes it quite hard to
diagnose.
I did not test a non-systemd installation, so I cannot say what
happens there. It is worth checking, though, since the body of the
package's own /etc/cron.d/barman entry is guarded to run only when
systemd is *not* the init system, and that entry also runs as the
barman user.
Steps to reproduce
------------------
Reproduced in a Docker container booted with systemd from the official
debian:sid image, so the kernel named in the system information below
is the container host's kernel rather than a Debian one. Nothing in
what follows depends on the kernel.
On a stock Debian unstable system with systemd:
# apt-get install barman cron
# chage -l barman | grep -i 'Account expires'
Account expires : Jan 02, 1970
# systemctl start cron
# sleep 120
# journalctl -u cron | grep barman
CRON[2255]: pam_unix(cron:account): account barman has expired (account
expired)
Clearing the expiry is enough to make cron work again, which confirms
the chain:
# chage -E -1 barman
# sleep 70
# journalctl -u cron | grep barman
CRON[2431]: pam_unix(cron:session): session opened for user barman(uid=993)
CRON[2433]: (barman) CMD (test -d /run/systemd/system || { ... barman -q
cron; })
Affected versions
-----------------
Only 3.20.0-1 (unstable), which introduced the sysusers.d file.
3.19.1-3 (testing) and 3.13.3-1 (trixie) ship no sysusers.d file and
create the account without an expiry, so they are unaffected. As it
stands, the problem would reach testing with 3.20.0-1.
Note the apt.postgresql.org rebuilds carry the same change, so the
issue is also present on trixie via barman 3.20.0-1.pgdg13+1. That is
where I first saw it; I then reproduced it on unstable with the
official package, which is what is reported above.
Possible fix
------------
Use plain "u" rather than "u!" in debian/barman.sysusers. An invalid
password is set either way, so password logins remain impossible, and
the shell could be changed to /usr/sbin/nologin if interactive logins
should be prevented outright. That keeps cron and su working for the
service account.
--- a/debian/barman.sysusers
+++ b/debian/barman.sysusers
@@ -1 +1 @@
-u! barman - "Backup and Recovery Manager for PostgreSQL" /var/lib/barman
/bin/bash
+u barman - "Backup and Recovery Manager for PostgreSQL" /var/lib/barman
/bin/bash
Note that this will not repair systems that already installed
3.20.0-1. I checked: once the expiry is cleared, neither re-running
"systemd-sysusers barman.conf" nor reinstalling the package sets it
again, because systemd-sysusers leaves the shadow fields of an
existing account alone. Conversely, that means an already-installed
system keeps the expired account after the fix, so it may be worth
clearing the expiry in postinst for the affected version.
Alternatively, if the locked account is deliberate, then the package
should stop relying on cron running as the barman user, and
/etc/cron.d/barman should be dropped or reworked, since it cannot work
on the non-systemd systems it exists to serve.
Thanks for maintaining barman.