Document use of ldapurl with LDAP simple bind

Started by Jacob Championover 1 year ago5 messages
#1Jacob Champion
jacob.champion@enterprisedb.com
2 attachment(s)

Hi all,

Our documentation implies that the ldapurl setting in pg_hba is used
for search+bind mode only. It was pointed out to me recently that this
is not true, and if you're dealing with simple bind on a non-standard
scheme or port, then ldapurl makes the HBA easier to read:

... ldap ldapurl="ldaps://ldap.example.net:49151" ldapprefix="cn="
ldapsuffix=", dc=example, dc=net"

0001 tries to document this helpful behavior a little better, and 0002
pins it with a test. WDYT?

Thanks,
--Jacob

Attachments:

0001-docs-explain-how-to-use-ldapurl-with-simple-bind.patchapplication/octet-stream; name=0001-docs-explain-how-to-use-ldapurl-with-simple-bind.patchDownload
From 4db1fc14f33af6a880a3ee0b7ad7d8cf00ad995c Mon Sep 17 00:00:00 2001
From: Jacob Champion <jacob.champion@enterprisedb.com>
Date: Wed, 22 May 2024 06:51:53 -0700
Subject: [PATCH 1/2] docs: explain how to use ldapurl with simple bind

The docs currently imply that ldapurl is for search+bind only, but
that's not true.
---
 doc/src/sgml/client-auth.sgml | 23 ++++++++++++++++++++---
 1 file changed, 20 insertions(+), 3 deletions(-)

diff --git a/doc/src/sgml/client-auth.sgml b/doc/src/sgml/client-auth.sgml
index cf5eb22fc8..3abbdd6791 100644
--- a/doc/src/sgml/client-auth.sgml
+++ b/doc/src/sgml/client-auth.sgml
@@ -1911,13 +1911,19 @@ omicron         bryanh                  guest1
         </para>
        </listitem>
       </varlistentry>
+     </variablelist>
+    </para>
+
+    <para>
+     The following option may be used as an alternative way to write some of the
+     above LDAP options in a more compact and standard form:
+     <variablelist>
       <varlistentry>
        <term><literal>ldapurl</literal></term>
        <listitem>
         <para>
          An <ulink url="https://datatracker.ietf.org/doc/html/rfc4516">RFC 4516</ulink>
-         LDAP URL.  This is an alternative way to write some of the
-         other LDAP options in a more compact and standard form.  The format is
+         LDAP URL.  The format is
 <synopsis>
 ldap[s]://<replaceable>host</replaceable>[:<replaceable>port</replaceable>]/<replaceable>basedn</replaceable>[?[<replaceable>attribute</replaceable>][?[<replaceable>scope</replaceable>][?[<replaceable>filter</replaceable>]]]]
 </synopsis>
@@ -1959,7 +1965,8 @@ ldap[s]://<replaceable>host</replaceable>[:<replaceable>port</replaceable>]/<rep
 
    <para>
     It is an error to mix configuration options for simple bind with options
-    for search+bind.
+    for search+bind.  To use <literal>ldapurl</literal> in simple bind mode, the
+    URL must not contain a <literal>basedn</literal> or query elements.
    </para>
 
    <para>
@@ -1995,6 +2002,16 @@ host ... ldap ldapserver=ldap.example.net ldapprefix="cn=" ldapsuffix=", dc=exam
     succeeds, the database access is granted.
    </para>
 
+   <para>
+    Here is a different simple-bind configuration, which uses the LDAPS scheme
+    and a custom port number, written as a URL:
+<programlisting>
+host ... ldap ldapurl="ldaps://ldap.example.net:49151" ldapprefix="cn=" ldapsuffix=", dc=example, dc=net"
+</programlisting>
+    This is slightly more compact than specifying <literal>ldapserver</literal>,
+    <literal>ldapscheme</literal>, and <literal>ldapport</literal> separately.
+   </para>
+
    <para>
     Here is an example for a search+bind configuration:
 <programlisting>
-- 
2.34.1

0002-ldap-test-ldapurl-with-simple-bind.patchapplication/octet-stream; name=0002-ldap-test-ldapurl-with-simple-bind.patchDownload
From 2b87dc96a4462f88507a876bc8bfa8677c6886d2 Mon Sep 17 00:00:00 2001
From: Jacob Champion <jacob.champion@enterprisedb.com>
Date: Fri, 24 May 2024 11:33:18 -0700
Subject: [PATCH 2/2] ldap: test ldapurl with simple bind

This was previously allowed but unexercised, and now that it's
documented it'd be good to pin the behavior.
---
 src/test/ldap/t/001_auth.pl | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/src/test/ldap/t/001_auth.pl b/src/test/ldap/t/001_auth.pl
index 850db34503..70ba4927cf 100644
--- a/src/test/ldap/t/001_auth.pl
+++ b/src/test/ldap/t/001_auth.pl
@@ -145,6 +145,21 @@ test_access($node, 'test1', 0, 'search+bind authentication succeeds');
 
 note "LDAP URLs";
 
+unlink($node->data_dir . '/pg_hba.conf');
+$node->append_conf('pg_hba.conf',
+	qq{local all all ldap ldapurl="$ldap_url" ldapprefix="uid=" ldapsuffix=",dc=example,dc=net"});
+$node->restart;
+
+$ENV{"PGPASSWORD"} = 'wrong';
+test_access($node, 'test0', 2,
+	'simple bind with LDAP URL authentication fails if user not found in LDAP'
+);
+test_access($node, 'test1', 2,
+	'simple bind with LDAP URL authentication fails with wrong password');
+$ENV{"PGPASSWORD"} = 'secret1';
+test_access($node, 'test1', 0,
+	'simple bind with LDAP URL authentication succeeds');
+
 unlink($node->data_dir . '/pg_hba.conf');
 $node->append_conf('pg_hba.conf',
 	qq{local all all ldap ldapurl="$ldap_url/$ldap_basedn?uid?sub"});
-- 
2.34.1

#2Peter Eisentraut
peter@eisentraut.org
In reply to: Jacob Champion (#1)
Re: Document use of ldapurl with LDAP simple bind

On 24.05.24 20:54, Jacob Champion wrote:

Our documentation implies that the ldapurl setting in pg_hba is used
for search+bind mode only. It was pointed out to me recently that this
is not true, and if you're dealing with simple bind on a non-standard
scheme or port, then ldapurl makes the HBA easier to read:

... ldap ldapurl="ldaps://ldap.example.net:49151" ldapprefix="cn="
ldapsuffix=", dc=example, dc=net"

0001 tries to document this helpful behavior a little better, and 0002
pins it with a test. WDYT?

Yes, this looks correct. Since ldapurl is really just a shorthand that
is expanded to various other parameters, it makes sense that it would
work for simple bind as well.

hba.c has this error message:

"cannot use ldapbasedn, ldapbinddn, ldapbindpasswd, ldapsearchattribute,
ldapsearchfilter, or ldapurl together with ldapprefix"

This appears to imply that specifying ldapurl is only applicable for
search+bind. Maybe that whole message should be simplified to something
like

"configuration mixes arguments for simple bind and search+bind"

(The old wording also ignores that the error might arise via "ldapsuffix".)

#3Jacob Champion
jacob.champion@enterprisedb.com
In reply to: Peter Eisentraut (#2)
3 attachment(s)
Re: Document use of ldapurl with LDAP simple bind

On Fri, Jun 28, 2024 at 12:11 AM Peter Eisentraut <peter@eisentraut.org> wrote:

This appears to imply that specifying ldapurl is only applicable for
search+bind. Maybe that whole message should be simplified to something
like

"configuration mixes arguments for simple bind and search+bind"

(The old wording also ignores that the error might arise via "ldapsuffix".)

I kept the imperative "cannot" and tried to match the terminology with
our documentation at [1]https://www.postgresql.org/docs/17/auth-ldap.html:

cannot mix options for simple bind and search+bind modes

WDYT?

--Jacob

[1]: https://www.postgresql.org/docs/17/auth-ldap.html

Attachments:

v2-0001-docs-explain-how-to-use-ldapurl-with-simple-bind.patchapplication/octet-stream; name=v2-0001-docs-explain-how-to-use-ldapurl-with-simple-bind.patchDownload
From 41c80627219d8c5bde17b7e6e6fd0a505c685fca Mon Sep 17 00:00:00 2001
From: Jacob Champion <jacob.champion@enterprisedb.com>
Date: Wed, 22 May 2024 06:51:53 -0700
Subject: [PATCH v2 1/3] docs: explain how to use ldapurl with simple bind

The docs currently imply that ldapurl is for search+bind only, but
that's not true.
---
 doc/src/sgml/client-auth.sgml | 23 ++++++++++++++++++++---
 1 file changed, 20 insertions(+), 3 deletions(-)

diff --git a/doc/src/sgml/client-auth.sgml b/doc/src/sgml/client-auth.sgml
index f1eb3b279e..51343de7ca 100644
--- a/doc/src/sgml/client-auth.sgml
+++ b/doc/src/sgml/client-auth.sgml
@@ -1910,13 +1910,19 @@ omicron         bryanh                  guest1
         </para>
        </listitem>
       </varlistentry>
+     </variablelist>
+    </para>
+
+    <para>
+     The following option may be used as an alternative way to write some of the
+     above LDAP options in a more compact and standard form:
+     <variablelist>
       <varlistentry>
        <term><literal>ldapurl</literal></term>
        <listitem>
         <para>
          An <ulink url="https://datatracker.ietf.org/doc/html/rfc4516">RFC 4516</ulink>
-         LDAP URL.  This is an alternative way to write some of the
-         other LDAP options in a more compact and standard form.  The format is
+         LDAP URL.  The format is
 <synopsis>
 ldap[s]://<replaceable>host</replaceable>[:<replaceable>port</replaceable>]/<replaceable>basedn</replaceable>[?[<replaceable>attribute</replaceable>][?[<replaceable>scope</replaceable>][?[<replaceable>filter</replaceable>]]]]
 </synopsis>
@@ -1958,7 +1964,8 @@ ldap[s]://<replaceable>host</replaceable>[:<replaceable>port</replaceable>]/<rep
 
    <para>
     It is an error to mix configuration options for simple bind with options
-    for search+bind.
+    for search+bind.  To use <literal>ldapurl</literal> in simple bind mode, the
+    URL must not contain a <literal>basedn</literal> or query elements.
    </para>
 
    <para>
@@ -1994,6 +2001,16 @@ host ... ldap ldapserver=ldap.example.net ldapprefix="cn=" ldapsuffix=", dc=exam
     succeeds, the database access is granted.
    </para>
 
+   <para>
+    Here is a different simple-bind configuration, which uses the LDAPS scheme
+    and a custom port number, written as a URL:
+<programlisting>
+host ... ldap ldapurl="ldaps://ldap.example.net:49151" ldapprefix="cn=" ldapsuffix=", dc=example, dc=net"
+</programlisting>
+    This is slightly more compact than specifying <literal>ldapserver</literal>,
+    <literal>ldapscheme</literal>, and <literal>ldapport</literal> separately.
+   </para>
+
    <para>
     Here is an example for a search+bind configuration:
 <programlisting>
-- 
2.34.1

v2-0002-ldap-test-ldapurl-with-simple-bind.patchapplication/octet-stream; name=v2-0002-ldap-test-ldapurl-with-simple-bind.patchDownload
From 0fbf70f188741457aa3660498227c0c4f2910933 Mon Sep 17 00:00:00 2001
From: Jacob Champion <jacob.champion@enterprisedb.com>
Date: Fri, 24 May 2024 11:33:18 -0700
Subject: [PATCH v2 2/3] ldap: test ldapurl with simple bind

This was previously allowed but unexercised, and now that it's
documented it'd be good to pin the behavior.
---
 src/test/ldap/t/001_auth.pl | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/src/test/ldap/t/001_auth.pl b/src/test/ldap/t/001_auth.pl
index 850db34503..70ba4927cf 100644
--- a/src/test/ldap/t/001_auth.pl
+++ b/src/test/ldap/t/001_auth.pl
@@ -145,6 +145,21 @@ test_access($node, 'test1', 0, 'search+bind authentication succeeds');
 
 note "LDAP URLs";
 
+unlink($node->data_dir . '/pg_hba.conf');
+$node->append_conf('pg_hba.conf',
+	qq{local all all ldap ldapurl="$ldap_url" ldapprefix="uid=" ldapsuffix=",dc=example,dc=net"});
+$node->restart;
+
+$ENV{"PGPASSWORD"} = 'wrong';
+test_access($node, 'test0', 2,
+	'simple bind with LDAP URL authentication fails if user not found in LDAP'
+);
+test_access($node, 'test1', 2,
+	'simple bind with LDAP URL authentication fails with wrong password');
+$ENV{"PGPASSWORD"} = 'secret1';
+test_access($node, 'test1', 0,
+	'simple bind with LDAP URL authentication succeeds');
+
 unlink($node->data_dir . '/pg_hba.conf');
 $node->append_conf('pg_hba.conf',
 	qq{local all all ldap ldapurl="$ldap_url/$ldap_basedn?uid?sub"});
-- 
2.34.1

v2-0003-hba-improve-error-when-mixing-LDAP-bind-modes.patchapplication/octet-stream; name=v2-0003-hba-improve-error-when-mixing-LDAP-bind-modes.patchDownload
From 7c68e41f19f35f857c7956f94d6f768a8be09562 Mon Sep 17 00:00:00 2001
From: Jacob Champion <jacob.champion@enterprisedb.com>
Date: Mon, 8 Jul 2024 12:16:41 -0700
Subject: [PATCH v2 3/3] hba: improve error when mixing LDAP bind modes

The option names had gone stale; replace them with a more general
statement.

Based on a suggestion from Peter Eisentraut.
---
 src/backend/libpq/hba.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/backend/libpq/hba.c b/src/backend/libpq/hba.c
index 18271def2e..75d588e36a 100644
--- a/src/backend/libpq/hba.c
+++ b/src/backend/libpq/hba.c
@@ -1907,10 +1907,10 @@ parse_hba_line(TokenizedAuthLine *tok_line, int elevel)
 			{
 				ereport(elevel,
 						(errcode(ERRCODE_CONFIG_FILE_ERROR),
-						 errmsg("cannot use ldapbasedn, ldapbinddn, ldapbindpasswd, ldapsearchattribute, ldapsearchfilter, or ldapurl together with ldapprefix"),
+						 errmsg("cannot mix options for simple bind and search+bind modes"),
 						 errcontext("line %d of configuration file \"%s\"",
 									line_num, file_name)));
-				*err_msg = "cannot use ldapbasedn, ldapbinddn, ldapbindpasswd, ldapsearchattribute, ldapsearchfilter, or ldapurl together with ldapprefix";
+				*err_msg = "cannot mix options for simple bind and search+bind modes";
 				return NULL;
 			}
 		}
-- 
2.34.1

#4Peter Eisentraut
peter@eisentraut.org
In reply to: Jacob Champion (#3)
Re: Document use of ldapurl with LDAP simple bind

On 08.07.24 23:27, Jacob Champion wrote:

On Fri, Jun 28, 2024 at 12:11 AM Peter Eisentraut <peter@eisentraut.org> wrote:

This appears to imply that specifying ldapurl is only applicable for
search+bind. Maybe that whole message should be simplified to something
like

"configuration mixes arguments for simple bind and search+bind"

(The old wording also ignores that the error might arise via "ldapsuffix".)

I kept the imperative "cannot" and tried to match the terminology with
our documentation at [1]:

cannot mix options for simple bind and search+bind modes

Committed.

(I suppose this could be considered a bug fix, but I don't feel an
urgency to go backpatching this. Let me know if there are different
opinions.)

#5Jacob Champion
jacob.champion@enterprisedb.com
In reply to: Peter Eisentraut (#4)
Re: Document use of ldapurl with LDAP simple bind

On Tue, Jul 23, 2024 at 1:37 AM Peter Eisentraut <peter@eisentraut.org> wrote:

Committed.

Thanks!

(I suppose this could be considered a bug fix, but I don't feel an
urgency to go backpatching this. Let me know if there are different
opinions.)

Certainly no urgency. The docs part of the patch also could be
backported alone, but I don't feel strongly either way.

--Jacob