Motivated by a recent complaint [1] I found the hostssl related material in
our docs quite verbose and even repetitive.  Some of that is normal since
we have both an overview/walk-through section as well as a reference
section.  But the overview in particular was self-repetitive.  Here is a
first pass at some improvements.  The commit message contains both the
intent of the patch and some thoughts/questions still being considered.

David J.

[1]
https://www.postgresql.org/message-id/170672433664.663.11895343120533141715%40wrigleys.postgresql.org
From 5bd53027d5f1cbe9021c9b4f7abe3be5792589dd Mon Sep 17 00:00:00 2001
From: "David G. Johnston" <david.g.johns...@gmail.com>
Date: Thu, 1 Feb 2024 15:24:30 -0700
Subject: [PATCH] docs: improve hostssl related descriptions and option
 presentation

runtime.sgml discussion regarding SSL was repetitive with itself
and presented in a problematic order - with discussion about
setting up the server configuration happening before a broad
overview of what all of the moving parts are.  Put describing
the two approaches first, with links to the reference material,
and then discuss the implementation detail of a trusted root
certificate.

client-auth.sgml treatment of hostssl ssl auth options and
the cert auth method is confusing.  They are related and so
discuss them once, together.  The cert method page provides
a nice place to isolate these, in addition to a largely
repeated discussion on the runtime.sgml page which points
back to this one spot for the extra layer of details for,
in particular, the user mapping.

NOTES:

I left the "comparison is done with the DN in RFC"
paragraph content as-is though I think its presence or
content needs re-evaluation.

I moved the wording regarding "trust+clientcert" to
the runtime page as that material fits better in
overview than reference.  I also changed it from
words to an actual pg_hba.conf line; which seems
a bit out of place but going with it for now.

The method pages are all children of the pg_hba.conf
page so if you land on cert from the runtime page
going from their directly to pg_hba.conf, or
realizing that you are basically in a section
that only pertains to pg_hba.conf, is not that
obvious.  Seems like these pages should have
xrefs added to them giving that context and
linking back to pg_hba.conf directly.
---
 doc/src/sgml/client-auth.sgml | 106 ++++++++++++++++++----------------
 doc/src/sgml/runtime.sgml     |  87 ++++++++++++----------------
 2 files changed, 92 insertions(+), 101 deletions(-)

diff --git a/doc/src/sgml/client-auth.sgml b/doc/src/sgml/client-auth.sgml
index 56747c0e36..638c8e7057 100644
--- a/doc/src/sgml/client-auth.sgml
+++ b/doc/src/sgml/client-auth.sgml
@@ -621,8 +621,9 @@ include_dir         <replaceable>directory</replaceable>
         <term><literal>cert</literal></term>
         <listitem>
          <para>
-          Authenticate using SSL client certificates. See
-          <xref linkend="auth-cert"/> for details.
+          Authenticate the hostssl connection attempt using only the SSL certificate.
+          See <xref linkend="auth-cert"/> for details regarding the auth-options
+          any hostssl connection line can specify.
          </para>
         </listitem>
        </varlistentry>
@@ -660,45 +661,15 @@ include_dir         <replaceable>directory</replaceable>
        After the <replaceable>auth-method</replaceable> field, there can be field(s) of
        the form <replaceable>name</replaceable><literal>=</literal><replaceable>value</replaceable> that
        specify options for the authentication method. Details about which
-       options are available for which authentication methods appear below.
+       options are available for which authentication methods appear on their
+       individual detail pages.
       </para>
 
       <para>
-       In addition to the method-specific options listed below, there is a
-       method-independent authentication option <literal>clientcert</literal>, which
-       can be specified in any <literal>hostssl</literal> record.
-       This option can be set to <literal>verify-ca</literal> or
-       <literal>verify-full</literal>. Both options require the client
-       to present a valid (trusted) SSL certificate, while
-       <literal>verify-full</literal> additionally enforces that the
-       <literal>cn</literal> (Common Name) in the certificate matches
-       the username or an applicable mapping.
-       This behavior is similar to the <literal>cert</literal> authentication
-       method (see <xref linkend="auth-cert"/>) but enables pairing
-       the verification of client certificates with any authentication
-       method that supports <literal>hostssl</literal> entries.
-      </para>
-      <para>
-       On any record using client certificate authentication (i.e. one
-       using the <literal>cert</literal> authentication method or one
-       using the <literal>clientcert</literal> option), you can specify
-       which part of the client certificate credentials to match using
-       the <literal>clientname</literal> option. This option can have one
-       of two values. If you specify <literal>clientname=CN</literal>, which
-       is the default, the username is matched against the certificate's
-       <literal>Common Name (CN)</literal>. If instead you specify
-       <literal>clientname=DN</literal> the username is matched against the
-       entire <literal>Distinguished Name (DN)</literal> of the certificate.
-       This option is probably best used in conjunction with a username map.
-       The comparison is done with the <literal>DN</literal> in
-       <ulink url="https://tools.ietf.org/html/rfc2253";>RFC 2253</ulink>
-       format. To see the <literal>DN</literal> of a client certificate
-       in this format, do
-<programlisting>
-openssl x509 -in myclient.crt -noout -subject -nameopt RFC2253 | sed "s/^subject=//"
-</programlisting>
-        Care needs to be taken when using this option, especially when using
-        regular expression matching against the <literal>DN</literal>.
+       The <literal>hostssl</literal> connection type, in addition to allowing any
+       authentication-method-specific options, allows the
+       <literal>auth-options</literal> detailed in <xref linkend="auth-cert"/> for
+       the <literal>cert</literal> authentication method.
       </para>
      </listitem>
     </varlistentry>
@@ -2170,24 +2141,53 @@ host ... radius radiusservers="server1,server2" radiussecrets="""secret one"",""
     This authentication method uses SSL client certificates to perform
     authentication. It is therefore only available for SSL connections;
     see <xref linkend="ssl-openssl-config"/> for SSL configuration instructions.
-    When using this authentication method, the server will require that
-    the client provide a valid, trusted certificate.  No password prompt
-    will be sent to the client.  The <literal>cn</literal> (Common Name)
-    attribute of the certificate
-    will be compared to the requested database user name, and if they match
-    the login will be allowed.  User name mapping can be used to allow
-    <literal>cn</literal> to be different from the database user name.
+    When using this (<literal>cert</literal>) authentication method,
+    the server will require that the client provide a valid, trusted certificate,
+    containing their certificate name in either the <literal>Common Name (CN)</literal>
+    or <literal>Distinguished Name (DN)</literal> as specifed by the
+    <literal>clientname</literal> option.  User name mapping can be used to allow
+    certificate name to be different from the database user name.
+   </para>
+
+   <para>
+    SSL connections using some other authentication method will not, by default,
+    look for or use a client certificate.  The <literal>clientcert</literal>
+    option can be added to the <literal>auth-options</literal> to also require
+    and optionally use a client certificate.
    </para>
 
    <para>
     The following configuration options are supported for SSL certificate
     authentication:
     <variablelist>
+     <varlistentry>
+      <term><literal>clientcert</literal></term>
+      <listitem>
+       <para>
+        Enables requiring a client certificate be present on the SSL connection.
+        Values of <literal>verify-ca</literal> and <literal>verify-full</literal>,
+        specify <literal>verify-full</literal> to include certificate name extraction
+        and verification.  The authentication method <literal>host</literal> applies
+        a non-overrideable value of <literal>verify-full</literal> for this option.
+       </para>
+      </listitem>
+     </varlistentry>
+     <varlistentry>
+      <term><literal>clientname</literal></term>
+      <listitem>
+       <para>
+        Under <literal>verify-full</literal> this specifies where to obtain the certificate name.
+        Values of <literal>CN</literal> and <literal>DN</literal> are allowed, matching
+        the Common Name and Distinguished Name on the certificate respectively.  The default
+        value is <literal>CN</literal>
+       </para>
+      </listitem>
+     </varlistentry>
      <varlistentry>
       <term><literal>map</literal></term>
       <listitem>
        <para>
-        Allows for mapping between system and database user names. See
+        Allows for mapping between certificate and database user names. See
         <xref linkend="auth-username-maps"/> for details.
        </para>
       </listitem>
@@ -2196,11 +2196,17 @@ host ... radius radiusservers="server1,server2" radiussecrets="""secret one"",""
    </para>
 
    <para>
-    It is redundant to use the <literal>clientcert</literal> option with
-    <literal>cert</literal> authentication because <literal>cert</literal>
-    authentication is effectively <literal>trust</literal> authentication
-    with <literal>clientcert=verify-full</literal>.
+    The comparison is done with the <literal>DN</literal> in
+    <ulink url="https://tools.ietf.org/html/rfc2253";>RFC 2253</ulink>
+    format. To see the <literal>DN</literal> of a client certificate
+    in this format, do
+<programlisting>
+openssl x509 -in myclient.crt -noout -subject -nameopt RFC2253 | sed "s/^subject=//"
+</programlisting>
+    Care needs to be taken when using this option, especially when using
+    regular expression matching against the <literal>DN</literal>.
    </para>
+
   </sect1>
 
   <sect1 id="auth-pam">
diff --git a/doc/src/sgml/runtime.sgml b/doc/src/sgml/runtime.sgml
index 64753d9c01..9e4bede7d0 100644
--- a/doc/src/sgml/runtime.sgml
+++ b/doc/src/sgml/runtime.sgml
@@ -2330,62 +2330,17 @@ pg_dumpall -p 5432 | psql -d postgres -p 5433
    <title>Using Client Certificates</title>
 
   <para>
-   To require the client to supply a trusted certificate,
-   place certificates of the root certificate authorities
-   (<acronym>CA</acronym>s) you trust in a file in the data
-   directory, set the parameter <xref linkend="guc-ssl-ca-file"/> in
-   <filename>postgresql.conf</filename> to the new file name, and add the
-   authentication option <literal>clientcert=verify-ca</literal> or
-   <literal>clientcert=verify-full</literal> to the appropriate
-   <literal>hostssl</literal> line(s) in <filename>pg_hba.conf</filename>.
-   A certificate will then be requested from the client during SSL
-   connection startup.  (See <xref linkend="libpq-ssl"/> for a description
-   of how to set up certificates on the client.)
-  </para>
-
-  <para>
-   For a <literal>hostssl</literal> entry with
-   <literal>clientcert=verify-ca</literal>, the server will verify
-   that the client's certificate is signed by one of the trusted
-   certificate authorities. If <literal>clientcert=verify-full</literal>
-   is specified, the server will not only verify the certificate
-   chain, but it will also check whether the username or its mapping
-   matches the <literal>cn</literal> (Common Name) of the provided certificate.
-   Note that certificate chain validation is always ensured when the
-   <literal>cert</literal> authentication method is used
-   (see <xref linkend="auth-cert"/>).
-  </para>
-
-  <para>
-   Intermediate certificates that chain up to existing root certificates
-   can also appear in the <xref linkend="guc-ssl-ca-file"/> file if
-   you wish to avoid storing them on clients (assuming the root and
-   intermediate certificates were created with <literal>v3_ca</literal>
-   extensions).  Certificate Revocation List (CRL) entries are also
-   checked if the parameter <xref linkend="guc-ssl-crl-file"/> or
-   <xref linkend="guc-ssl-crl-dir"/> is set.
-  </para>
-
-  <para>
-   The <literal>clientcert</literal> authentication option is available for
-   all authentication methods, but only in <filename>pg_hba.conf</filename> lines
-   specified as <literal>hostssl</literal>.  When <literal>clientcert</literal> is
-   not specified, the server verifies the client certificate against its CA
-   file only if a client certificate is presented and the CA is configured.
-  </para>
-
-  <para>
-   There are two approaches to enforce that users provide a certificate during login.
+   There are two approaches to enforce that users provide an SSL certificate during login.
   </para>
 
   <para>
    The first approach makes use of the <literal>cert</literal> authentication
    method for <literal>hostssl</literal> entries in <filename>pg_hba.conf</filename>,
-   such that the certificate itself is used for authentication while also
-   providing ssl connection security. See <xref linkend="auth-cert"/> for details.
-   (It is not necessary to specify any <literal>clientcert</literal> options
+   (see <xref linkend="auth-pg-hba-conf"/>) such that the certificate itself
+   is used for authentication while also providing ssl connection security.
+   (It is not necessary to specify the <literal>clientcert</literal> option
    explicitly when using the <literal>cert</literal> authentication method.)
-   In this case, the <literal>cn</literal> (Common Name) provided in
+   By default, the <literal>cn</literal> (Common Name) provided in
    the certificate is checked against the user name or an applicable mapping.
   </para>
 
@@ -2394,10 +2349,40 @@ pg_dumpall -p 5432 | psql -d postgres -p 5433
    entries with the verification of client certificates by setting the
    <literal>clientcert</literal> authentication option to <literal>verify-ca</literal>
    or <literal>verify-full</literal>. The former option only enforces that
-   the certificate is valid, while the latter also ensures that the
+   the certificate is valid, while the latter also ensures that, by default, the
    <literal>cn</literal> (Common Name) in the certificate matches
    the user name or an applicable mapping.
   </para>
+
+  <para>
+   As the first approach is really just a special case of the second, the reference
+   documentation for both is detailed in the same place, <xref linkend="auth-cert"/>.
+   Specifically, the <literal>cert</literal> authentication method is equivalent to:
+<programlisting>
+hostssl DATABASE USER IP trust clientcert=verify-full
+</programlisting>
+  </para>
+
+  <para>
+   Verifying client-supplied certificates requires that certificates of the
+   trusted root certificate authorities (<acronym>CA</acronym>s) exist in a
+   file in the data directory.  Set the parameter
+   <xref linkend="guc-ssl-ca-file"/> in
+   <filename>postgresql.conf</filename> to this file name.
+   (See <xref linkend="libpq-ssl"/> for a description
+   of how to set up certificates on the client.)
+  </para>
+
+  <para>
+   Intermediate certificates that chain up to existing root certificates
+   can also appear in the <xref linkend="guc-ssl-ca-file"/> file if
+   you wish to avoid storing them on clients (assuming the root and
+   intermediate certificates were created with <literal>v3_ca</literal>
+   extensions).  Certificate Revocation List (CRL) entries are also
+   checked if the parameter <xref linkend="guc-ssl-crl-file"/> or
+   <xref linkend="guc-ssl-crl-dir"/> is set.
+  </para>
+
   </sect2>
 
   <sect2 id="ssl-server-files">
-- 
2.34.1

Reply via email to