Package: mailman3
Version: 3.2.1-1
Control: tags -1 + patch

When mailman3 is configured with a postgresql database, only the `list`
user has direct access to the database.

In this case, when logrotate tries to invoke "mailman reopen", it fails
with pretty verbose error messages (see below).

This is resolved by invoking the "reopen" subcommand via
mailman-wrapper, not mailman as root, as in the attached patch.

See also:

https://salsa.debian.org/mailman-team/mailman3/-/merge_requests/1

                 --dkg

From d4ddff58fa9b318c95c8938c7f3f556e5ae6abe3 Mon Sep 17 00:00:00 2001
From: Daniel Kahn Gillmor <d...@fifthhorseman.net>
Date: Sun, 26 Apr 2020 14:45:31 -0400
Subject: [PATCH] logrotate: invoke reopen as "list" user

logrotate's "reopen" invocation will fail if mailman is run as the
root user, and the backend database doesn't provide access to the
superuser.

For example, if mailman is connected to a postgresql database, the
credentials to connect to the database might not be immediately
available to the superuser, resulting in errors like:

    sqlalchemy.exc.OperationalError: (psycopg2.OperationalError) \
        FATAL:  role "root" does not exist
---
 debian/mailman3.logrotate | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/debian/mailman3.logrotate b/debian/mailman3.logrotate
index 0b048c8..d092400 100644
--- a/debian/mailman3.logrotate
+++ b/debian/mailman3.logrotate
@@ -8,7 +8,7 @@
 	create 640 list list
 	postrotate
 		if /etc/init.d/mailman3 status >/dev/null; then \
-		    /usr/bin/mailman reopen >/dev/null; \
+		    /usr/bin/mailman-wrapper reopen >/dev/null; \
 		fi;
 	endscript
 }
-- 
2.26.2

Apr 26 00:00:03 host systemd[1]: Starting Rotate log files...
Apr 26 00:00:06 host logrotate[12668]: Traceback (most recent call last):
Apr 26 00:00:06 host logrotate[12668]:   File 
"/usr/lib/python3/dist-packages/sqlalchemy/engine/base.py", line 2228, in 
_wrap_pool_connect
Apr 26 00:00:06 host logrotate[12668]:     return fn()
Apr 26 00:00:06 host logrotate[12668]:   File 
"/usr/lib/python3/dist-packages/sqlalchemy/pool.py", line 425, in connect
Apr 26 00:00:06 host logrotate[12668]:     return 
_ConnectionFairy._checkout(self)
Apr 26 00:00:06 host logrotate[12668]:   File 
"/usr/lib/python3/dist-packages/sqlalchemy/pool.py", line 822, in _checkout
Apr 26 00:00:06 host logrotate[12668]:     fairy = 
_ConnectionRecord.checkout(pool)
Apr 26 00:00:06 host logrotate[12668]:   File 
"/usr/lib/python3/dist-packages/sqlalchemy/pool.py", line 554, in checkout
Apr 26 00:00:06 host logrotate[12668]:     rec = pool._do_get()
Apr 26 00:00:06 host logrotate[12668]:   File 
"/usr/lib/python3/dist-packages/sqlalchemy/pool.py", line 1250, in _do_get
Apr 26 00:00:06 host logrotate[12668]:     self._dec_overflow()
Apr 26 00:00:06 host logrotate[12668]:   File 
"/usr/lib/python3/dist-packages/sqlalchemy/util/langhelpers.py", line 67, in 
__exit__
Apr 26 00:00:06 host logrotate[12668]:     compat.reraise(exc_type, exc_value, 
exc_tb)
Apr 26 00:00:06 host logrotate[12668]:   File 
"/usr/lib/python3/dist-packages/sqlalchemy/util/compat.py", line 277, in reraise
Apr 26 00:00:06 host logrotate[12668]:     raise value
Apr 26 00:00:06 host logrotate[12668]:   File 
"/usr/lib/python3/dist-packages/sqlalchemy/pool.py", line 1247, in _do_get
Apr 26 00:00:06 host logrotate[12668]:     return self._create_connection()
Apr 26 00:00:06 host logrotate[12668]:   File 
"/usr/lib/python3/dist-packages/sqlalchemy/pool.py", line 370, in 
_create_connection
Apr 26 00:00:06 host logrotate[12668]:     return _ConnectionRecord(self)
Apr 26 00:00:06 host logrotate[12668]:   File 
"/usr/lib/python3/dist-packages/sqlalchemy/pool.py", line 499, in __init__
Apr 26 00:00:06 host logrotate[12668]:     
self.__connect(first_connect_check=True)
Apr 26 00:00:06 host logrotate[12668]:   File 
"/usr/lib/python3/dist-packages/sqlalchemy/pool.py", line 701, in __connect
Apr 26 00:00:06 host logrotate[12668]:     connection = 
pool._invoke_creator(self)
Apr 26 00:00:06 host logrotate[12668]:   File 
"/usr/lib/python3/dist-packages/sqlalchemy/engine/strategies.py", line 114, in 
connect
Apr 26 00:00:06 host logrotate[12668]:     return dialect.connect(*cargs, 
**cparams)
Apr 26 00:00:06 host logrotate[12668]:   File 
"/usr/lib/python3/dist-packages/sqlalchemy/engine/default.py", line 437, in 
connect
Apr 26 00:00:06 host logrotate[12668]:     return self.dbapi.connect(*cargs, 
**cparams)
Apr 26 00:00:06 host logrotate[12668]:   File 
"/usr/lib/python3/dist-packages/psycopg2/__init__.py", line 130, in connect
Apr 26 00:00:06 host logrotate[12668]:     conn = _connect(dsn, 
connection_factory=connection_factory, **kwasync)
Apr 26 00:00:06 host logrotate[12668]: psycopg2.OperationalError: FATAL:  role 
"root" does not exist
Apr 26 00:00:06 host logrotate[12668]: The above exception was the direct cause 
of the following exception:
Apr 26 00:00:06 host logrotate[12668]: Traceback (most recent call last):
Apr 26 00:00:06 host logrotate[12668]:   File "/usr/bin/mailman", line 11, in 
<module>
Apr 26 00:00:06 host logrotate[12668]:     load_entry_point('mailman==3.2.1', 
'console_scripts', 'mailman')()
Apr 26 00:00:06 host logrotate[12668]:   File 
"/usr/lib/python3/dist-packages/click/core.py", line 764, in __call__
Apr 26 00:00:06 host logrotate[12668]:     return self.main(*args, **kwargs)
Apr 26 00:00:06 host logrotate[12668]:   File 
"/usr/lib/python3/dist-packages/click/core.py", line 716, in main
Apr 26 00:00:06 host logrotate[12668]:     with self.make_context(prog_name, 
args, **extra) as ctx:
Apr 26 00:00:06 host logrotate[12668]:   File 
"/usr/lib/python3/dist-packages/click/core.py", line 641, in make_context
Apr 26 00:00:06 host logrotate[12668]:     self.parse_args(ctx, args)
Apr 26 00:00:06 host logrotate[12668]:   File 
"/usr/lib/python3/dist-packages/click/core.py", line 1089, in parse_args
Apr 26 00:00:06 host logrotate[12668]:     rest = Command.parse_args(self, ctx, 
args)
Apr 26 00:00:06 host logrotate[12668]:   File 
"/usr/lib/python3/dist-packages/click/core.py", line 940, in parse_args
Apr 26 00:00:06 host logrotate[12668]:     value, args = 
param.handle_parse_result(ctx, opts, args)
Apr 26 00:00:06 host logrotate[12668]:   File 
"/usr/lib/python3/dist-packages/click/core.py", line 1477, in 
handle_parse_result
Apr 26 00:00:06 host logrotate[12668]:     self.callback, ctx, self, value)
Apr 26 00:00:06 host logrotate[12668]:   File 
"/usr/lib/python3/dist-packages/click/core.py", line 96, in 
invoke_param_callback
Apr 26 00:00:06 host logrotate[12668]:     return callback(ctx, param, value)
Apr 26 00:00:06 host logrotate[12668]:   File 
"/usr/lib/python3/dist-packages/mailman/bin/mailman.py", line 94, in 
initialize_config
Apr 26 00:00:06 host logrotate[12668]:     initialize(value)
Apr 26 00:00:06 host logrotate[12668]:   File 
"/usr/lib/python3/dist-packages/mailman/core/initialize.py", line 218, in 
initialize
Apr 26 00:00:06 host logrotate[12668]:     
initialize_2(propagate_logs=propagate_logs)
Apr 26 00:00:06 host logrotate[12668]:   File 
"/usr/lib/python3/dist-packages/mailman/core/initialize.py", line 177, in 
initialize_2
Apr 26 00:00:06 host logrotate[12668]:     config.db = 
getUtility(IDatabaseFactory, utility_name).create()
Apr 26 00:00:06 host logrotate[12668]:   File 
"/usr/lib/python3/dist-packages/mailman/database/factory.py", line 55, in create
Apr 26 00:00:06 host logrotate[12668]:     
SchemaManager(database).setup_database()
Apr 26 00:00:06 host logrotate[12668]:   File 
"/usr/lib/python3/dist-packages/mailman/database/factory.py", line 83, in 
setup_database
Apr 26 00:00:06 host logrotate[12668]:     context = 
MigrationContext.configure(self._database.store.connection())
Apr 26 00:00:06 host logrotate[12668]:   File 
"/usr/lib/python3/dist-packages/sqlalchemy/orm/session.py", line 1120, in 
connection
Apr 26 00:00:06 host logrotate[12668]:     execution_options=execution_options,
Apr 26 00:00:06 host logrotate[12668]:   File 
"/usr/lib/python3/dist-packages/sqlalchemy/orm/session.py", line 1126, in 
_connection_for_bind
Apr 26 00:00:06 host logrotate[12668]:     engine, execution_options
Apr 26 00:00:06 host logrotate[12668]:   File 
"/usr/lib/python3/dist-packages/sqlalchemy/orm/session.py", line 424, in 
_connection_for_bind
Apr 26 00:00:06 host logrotate[12668]:     conn = bind.contextual_connect()
Apr 26 00:00:06 host logrotate[12668]:   File 
"/usr/lib/python3/dist-packages/sqlalchemy/engine/base.py", line 2192, in 
contextual_connect
Apr 26 00:00:06 host logrotate[12668]:     
self._wrap_pool_connect(self.pool.connect, None),
Apr 26 00:00:06 host logrotate[12668]:   File 
"/usr/lib/python3/dist-packages/sqlalchemy/engine/base.py", line 2232, in 
_wrap_pool_connect
Apr 26 00:00:06 host logrotate[12668]:     e, dialect, self
Apr 26 00:00:06 host logrotate[12668]:   File 
"/usr/lib/python3/dist-packages/sqlalchemy/engine/base.py", line 1528, in 
_handle_dbapi_exception_noconnection
Apr 26 00:00:06 host logrotate[12668]:     
util.raise_from_cause(sqlalchemy_exception, exc_info)
Apr 26 00:00:06 host logrotate[12668]:   File 
"/usr/lib/python3/dist-packages/sqlalchemy/util/compat.py", line 296, in 
raise_from_cause
Apr 26 00:00:06 host logrotate[12668]:     reraise(type(exception), exception, 
tb=exc_tb, cause=cause)
Apr 26 00:00:06 host logrotate[12668]:   File 
"/usr/lib/python3/dist-packages/sqlalchemy/util/compat.py", line 276, in reraise
Apr 26 00:00:06 host logrotate[12668]:     raise value.with_traceback(tb)
Apr 26 00:00:06 host logrotate[12668]:   File 
"/usr/lib/python3/dist-packages/sqlalchemy/engine/base.py", line 2228, in 
_wrap_pool_connect
Apr 26 00:00:06 host logrotate[12668]:     return fn()
Apr 26 00:00:06 host logrotate[12668]:   File 
"/usr/lib/python3/dist-packages/sqlalchemy/pool.py", line 425, in connect
Apr 26 00:00:06 host logrotate[12668]:     return 
_ConnectionFairy._checkout(self)
Apr 26 00:00:06 host logrotate[12668]:   File 
"/usr/lib/python3/dist-packages/sqlalchemy/pool.py", line 822, in _checkout
Apr 26 00:00:06 host logrotate[12668]:     fairy = 
_ConnectionRecord.checkout(pool)
Apr 26 00:00:06 host logrotate[12668]:   File 
"/usr/lib/python3/dist-packages/sqlalchemy/pool.py", line 554, in checkout
Apr 26 00:00:06 host logrotate[12668]:     rec = pool._do_get()
Apr 26 00:00:06 host logrotate[12668]:   File 
"/usr/lib/python3/dist-packages/sqlalchemy/pool.py", line 1250, in _do_get
Apr 26 00:00:06 host logrotate[12668]:     self._dec_overflow()
Apr 26 00:00:06 host logrotate[12668]:   File 
"/usr/lib/python3/dist-packages/sqlalchemy/util/langhelpers.py", line 67, in 
__exit__
Apr 26 00:00:06 host logrotate[12668]:     compat.reraise(exc_type, exc_value, 
exc_tb)
Apr 26 00:00:06 host logrotate[12668]:   File 
"/usr/lib/python3/dist-packages/sqlalchemy/util/compat.py", line 277, in reraise
Apr 26 00:00:06 host logrotate[12668]:     raise value
Apr 26 00:00:06 host logrotate[12668]:   File 
"/usr/lib/python3/dist-packages/sqlalchemy/pool.py", line 1247, in _do_get
Apr 26 00:00:06 host logrotate[12668]:     return self._create_connection()
Apr 26 00:00:06 host logrotate[12668]:   File 
"/usr/lib/python3/dist-packages/sqlalchemy/pool.py", line 370, in 
_create_connection
Apr 26 00:00:06 host logrotate[12668]:     return _ConnectionRecord(self)
Apr 26 00:00:06 host logrotate[12668]:   File 
"/usr/lib/python3/dist-packages/sqlalchemy/pool.py", line 499, in __init__
Apr 26 00:00:06 host logrotate[12668]:     
self.__connect(first_connect_check=True)
Apr 26 00:00:06 host logrotate[12668]:   File 
"/usr/lib/python3/dist-packages/sqlalchemy/pool.py", line 701, in __connect
Apr 26 00:00:06 host logrotate[12668]:     connection = 
pool._invoke_creator(self)
Apr 26 00:00:06 host logrotate[12668]:   File 
"/usr/lib/python3/dist-packages/sqlalchemy/engine/strategies.py", line 114, in 
connect
Apr 26 00:00:06 host logrotate[12668]:     return dialect.connect(*cargs, 
**cparams)
Apr 26 00:00:06 host logrotate[12668]:   File 
"/usr/lib/python3/dist-packages/sqlalchemy/engine/default.py", line 437, in 
connect
Apr 26 00:00:06 host logrotate[12668]:     return self.dbapi.connect(*cargs, 
**cparams)
Apr 26 00:00:06 host logrotate[12668]:   File 
"/usr/lib/python3/dist-packages/psycopg2/__init__.py", line 130, in connect
Apr 26 00:00:06 host logrotate[12668]:     conn = _connect(dsn, 
connection_factory=connection_factory, **kwasync)
Apr 26 00:00:06 host logrotate[12668]: sqlalchemy.exc.OperationalError: 
(psycopg2.OperationalError) FATAL:  role "root" does not exist
Apr 26 00:00:06 host logrotate[12668]:  (Background on this error at: 
http://sqlalche.me/e/e3q8)
Apr 26 00:00:06 host logrotate[12668]: error: error running non-shared 
postrotate script for /var/log/mailman3/mailman.log of 
'/var/log/mailman3/mailman.log '
Apr 26 00:00:06 host systemd[1]: logrotate.service: Main process exited, 
code=exited, status=1/FAILURE
Apr 26 00:00:06 host systemd[1]: logrotate.service: Failed with result 
'exit-code'.
Apr 26 00:00:06 host systemd[1]: Failed to start Rotate log files.

Attachment: signature.asc
Description: PGP signature

Reply via email to