From 5f9a720a526471286864d92559e6361460ca04cb Mon Sep 17 00:00:00 2001 From: Andrew Jackson Date: Sat, 28 Mar 2026 23:29:48 -0500 Subject: [PATCH] Allow LDAP lookup from pgservice connection parameter Currently there exists, only in pg_service.conf, the ability to look up connection parameters from a centralized LDAP server. This patch expands the usability of this be allowing it to be specified directly in a connection string instead of only in a pg_service.conf file. This patch adds a check in parseServiceInfo that checks if pgservice is an LDAP scheme address and if so attempts to connect to that LDAP server and grab connection parameters from there. This is a breaking change in that it is possible that people previously named their pgservice after an LDAP address. --- doc/src/sgml/libpq.sgml | 4 +++ src/interfaces/libpq/fe-connect.c | 5 ++++ .../t/003_ldap_connection_param_lookup.pl | 25 +++++++++++++++++++ 3 files changed, 34 insertions(+) diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml index 6db823808fc..4d230a2a65f 100644 --- a/doc/src/sgml/libpq.sgml +++ b/doc/src/sgml/libpq.sgml @@ -2333,6 +2333,10 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname name in pg_service.conf that holds additional connection parameters. This allows applications to specify only a service name so connection parameters can be centrally maintained. See . + + You can also specify and LDAP address here which will look up parameters from an LDAP + server. See . Please note that if an LDAP address is specified + no attempt will be made to look up parameters in pg_service.conf. diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c index db9b4c8edbf..50ada2939b6 100644 --- a/src/interfaces/libpq/fe-connect.c +++ b/src/interfaces/libpq/fe-connect.c @@ -6006,6 +6006,11 @@ parseServiceInfo(PQconninfoOption *options, PQExpBuffer errorMessage) if (service == NULL) return 0; +#ifdef USE_LDAP + if (pg_strncasecmp(service, LDAP_URL, strlen(LDAP_URL)) == 0) + return ldapServiceLookup(service, options, errorMessage); +#endif + /* * First, try the "servicefile" option in connection string. Then, try * the PGSERVICEFILE environment variable. Finally, check diff --git a/src/test/ldap/t/003_ldap_connection_param_lookup.pl b/src/test/ldap/t/003_ldap_connection_param_lookup.pl index 359fc7a998a..67da90578cf 100644 --- a/src/test/ldap/t/003_ldap_connection_param_lookup.pl +++ b/src/test/ldap/t/003_ldap_connection_param_lookup.pl @@ -80,6 +80,9 @@ append_to_file( $srvfile_valid, qq{ [my_srv] ldap://localhost:$ldap_port/dc=example,dc=net?description?one?(cn=mydatabase) + +[my_srv_2] +ldapservice=ldap://localhost:$ldap_port/dc=example,dc=net?description?one?(cn=mydatabase) }); # File defined with no contents, used as default value for @@ -196,6 +199,28 @@ local $ENV{PGSERVICEFILE} = "$srvfile_empty"; expected_stdout => qr/definition of service "undefined-service" not found/); + delete $ENV{PGSERVICE}; + + $dummy_node->connect_ok( + "service=ldap://localhost:$ldap_port/dc=example,dc=net?description?one?(cn=mydatabase)", + 'connection with correct "service" string populated with LDAP address', + sql => "SELECT 'connect2_4'", + expected_stdout => qr/connect2_4/); + + $dummy_node->connect_ok( + "postgres://?service=ldap%3A%2F%2Flocalhost%3A$ldap_port%2Fdc%3Dexample%2Cdc%3Dnet%3Fdescription%3Fone%3F%28cn%3Dmydatabase%29", + 'connection with correct "ldapservice" string populated with LDAP address', + sql => "SELECT 'connect2_5'", + expected_stdout => qr/connect2_5/); + + local $ENV{PGSERVICE} = "ldap://localhost:$ldap_port/dc=example,dc=net?description?one?(cn=mydatabase)"; + $dummy_node->connect_ok( + "", + 'connection with correct "service" provided by env var populated with LDAP address', + sql => "SELECT 'connect2_6'", + expected_stdout => qr/connect2_6/); + delete $ENV{PGLDAPSERVICE}; + # Remove default pg_service.conf. unlink($srvfile_default); } -- 2.51.2