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
This commit is contained in:
Alexander Kukushkin
2024-08-27 13:39:03 +02:00
committed by GitHub
parent 8cdb0c25d9
commit 835d93951d
2 changed files with 9 additions and 3 deletions
+5 -3
View File
@@ -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.
+4
View File
@@ -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')