From 835d93951d437cacc24e3925272559cb20267c4d Mon Sep 17 00:00:00 2001 From: Alexander Kukushkin Date: Tue, 27 Aug 2024 13:39:03 +0200 Subject: [PATCH] Add line with localhost to pgpass when unix sockets are detected (#3139) There are two cases when libpq may search for "localhost": 1. When host in the connection string is not specified and it is using default socket directory path. 2. When specified host matches default socket directory path. Since we don't know the value of default socket directory path and effectively can't detect the case 2, the best strategy to mitigate the problem would be to add "localhost" if we detected a "host" be a unix socket directory (it starts with '/' character). Close #3134 --- patroni/postgresql/config.py | 8 +++++--- tests/test_postgresql.py | 4 ++++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/patroni/postgresql/config.py b/patroni/postgresql/config.py index bcab56a0..18f5c055 100644 --- a/patroni/postgresql/config.py +++ b/patroni/postgresql/config.py @@ -911,10 +911,12 @@ class ConfigHandler(object): return re.sub(r'([:\\])', r'\\\1', str(value)) # 'host' could be several comma-separated hostnames, in this case we need to write on pgpass line per host - hosts = map(escape, filter(None, map(str.strip, - (record.get('host', '') or '*').split(',')))) # pyright: ignore [reportUnknownArgumentType] + hosts = [escape(host) for host in filter(None, map(str.strip, + (record.get('host', '') or '*').split(',')))] # pyright: ignore [reportUnknownArgumentType] + if any(host.startswith('/') for host in hosts) and 'localhost' not in hosts: + hosts.append('localhost') record = {n: escape(record.get(n) or '*') for n in ('port', 'user', 'password')} - return '\n'.join('{host}:{port}:*:{user}:{password}'.format(**record, host=host) for host in hosts) + return ''.join('{host}:{port}:*:{user}:{password}\n'.format(**record, host=host) for host in hosts) def write_pgpass(self, record: Dict[str, Any]) -> Dict[str, str]: """Maybe creates :attr:`_passfile` based on connection parameters. diff --git a/tests/test_postgresql.py b/tests/test_postgresql.py index 76b51aeb..383c3a3a 100644 --- a/tests/test_postgresql.py +++ b/tests/test_postgresql.py @@ -262,6 +262,10 @@ class TestPostgresql(BaseTestPostgresql): self.p.config.write_pgpass({'host': 'localhost', 'port': '5432', 'user': 'foo'}) self.p.config.write_pgpass({'host': 'localhost', 'port': '5432', 'user': 'foo', 'password': 'bar'}) + def test__pgpass_content(self): + pgpass = self.p.config._pgpass_content({'host': '/tmp', 'port': '5432', 'user': 'foo', 'password': 'bar'}) + self.assertEqual(pgpass, "/tmp:5432:*:foo:bar\nlocalhost:5432:*:foo:bar\n") + def test_checkpoint(self): with patch.object(MockCursor, 'fetchone', Mock(return_value=(True, ))): self.assertEqual(self.p.checkpoint({'user': 'postgres'}), 'is_in_recovery=true')