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