Commit 815f84aa authored by Bruce Momjian's avatar Bruce Momjian

doc: update intermediate certificate instructions

Document how to properly create root and intermediate certificates using
v3_ca extensions and where to place intermediate certificates so they
are properly transferred to the remote side with the leaf certificate to
link to the remote root certificate.  This corrects docs that used to
say that intermediate certificates must be stored with the root
certificate.

Also add instructions on how to create root, intermediate, and leaf
certificates.

Discussion: https://postgr.es/m/20180116002238.GC12724@momjian.us

Reviewed-by: Michael Paquier

Backpatch-through: 9.3
parent 918e02a2
......@@ -7574,17 +7574,37 @@ ldap://ldap.acme.com/cn=dbserver,cn=hosts?pgconnectinfo?base?(objectclass=*)
the server certificate. This means that it is possible to spoof the server
identity (for example by modifying a DNS record or by taking over the server
IP address) without the client knowing. In order to prevent spoofing,
<acronym>SSL</acronym> certificate verification must be used.
the client must be able to verify the server's identity via a chain of
trust. A chain of trust is established by placing a root (self-signed)
certificate authority (<acronym>CA</acronym>) certificate on one
computer and a leaf certificate <emphasis>signed</emphasis> by the
root certificate on another computer. It is also possible to use an
<quote>intermediate</quote> certificate which is signed by the root
certificate and signs leaf certificates.
</para>
<para>
To allow the client to verify the identity of the server, place a root
certificate on the client and a leaf certificate signed by the root
certificate on the server. To allow the server to verify the identity
of the client, place a root certificate on the server and a leaf and
optional intermediate certificates signed by the root certificate on
the client. Intermediate certificates (usually stored with the leaf
certificate) can also be used to link the leaf certificate to the
root certificate.
</para>
<para>
Once a chain of trust has been established, there are two ways for
the client to validate the leaf certificate sent by the server.
If the parameter <literal>sslmode</literal> is set to <literal>verify-ca</literal>,
libpq will verify that the server is trustworthy by checking the
certificate chain up to a trusted certificate authority
(<acronym>CA</acronym>). If <literal>sslmode</literal> is set to <literal>verify-full</literal>,
libpq will <emphasis>also</emphasis> verify that the server host name matches its
certificate. The SSL connection will fail if the server certificate cannot
be verified. <literal>verify-full</literal> is recommended in most
certificate chain up to the root certificate stored on the client.
If <literal>sslmode</literal> is set to <literal>verify-full</literal>,
libpq will <emphasis>also</emphasis> verify that the server host
name matches the name stored in the server certificate. The
SSL connection will fail if the server certificate cannot be
verified. <literal>verify-full</literal> is recommended in most
security-sensitive environments.
</para>
......@@ -7601,13 +7621,13 @@ ldap://ldap.acme.com/cn=dbserver,cn=hosts?pgconnectinfo?base?(objectclass=*)
</para>
<para>
To allow server certificate verification, the certificate(s) of one or more
trusted <acronym>CA</acronym>s must be
placed in the file <filename>~/.postgresql/root.crt</filename> in the user's home
directory. If intermediate <acronym>CA</acronym>s appear in
<filename>root.crt</filename>, the file must also contain certificate
chains to their root <acronym>CA</acronym>s. (On Microsoft Windows the file is named
<filename>%APPDATA%\postgresql\root.crt</filename>.)
To allow server certificate verification, one or more root certificates
must be placed in the file <filename>~/.postgresql/root.crt</filename>
in the user's home directory. (On Microsoft Windows the file is named
<filename>%APPDATA%\postgresql\root.crt</filename>.) Intermediate
certificates should also be added to the file if they are needed to link
the certificate chain sent by the server to the root certificates
stored on the client.
</para>
<para>
......@@ -7641,11 +7661,12 @@ ldap://ldap.acme.com/cn=dbserver,cn=hosts?pgconnectinfo?base?(objectclass=*)
<title>Client Certificates</title>
<para>
If the server requests a trusted client certificate,
<application>libpq</application> will send the certificate stored in
If the server attempts to verify the identity of the
client by requesting the client's leaf certificate,
<application>libpq</application> will send the certificates stored in
file <filename>~/.postgresql/postgresql.crt</filename> in the user's home
directory. The certificate must be signed by one of the certificate
authorities (<acronym>CA</acronym>) trusted by the server. A matching
directory. The certificates must chain to the root certificate trusted
by the server. A matching
private key file <filename>~/.postgresql/postgresql.key</filename> must also
be present. The private
key file must not allow any access to world or group; achieve this by the
......@@ -7660,23 +7681,17 @@ ldap://ldap.acme.com/cn=dbserver,cn=hosts?pgconnectinfo?base?(objectclass=*)
</para>
<para>
In some cases, the client certificate might be signed by an
<quote>intermediate</quote> certificate authority, rather than one that is
directly trusted by the server. To use such a certificate, append the
certificate of the signing authority to the <filename>postgresql.crt</filename>
file, then its parent authority's certificate, and so on up to a certificate
authority, <quote>root</quote> or <quote>intermediate</quote>, that is trusted by
the server, i.e. signed by a certificate in the server's root CA file
(<xref linkend="guc-ssl-ca-file"/>).
The first certificate in <filename>postgresql.crt</filename> must be the
client's certificate because it must match the client's private key.
<quote>Intermediate</quote> certificates can be optionally appended
to the file &mdash; doing so avoids requiring storage of intermediate
certificates on the server (<xref linkend="guc-ssl-ca-file"/>).
</para>
<para>
Note that the client's <filename>~/.postgresql/root.crt</filename> lists the top-level CAs
that are considered trusted for signing server certificates. In principle it need
not list the CA that signed the client's certificate, though in most cases
that CA would also be trusted for server certificates.
For instructions on creating certificates, see <xref
linkend="ssl-certificate-creation"/>.
</para>
</sect2>
<sect2 id="libpq-ssl-protection">
......
......@@ -2247,40 +2247,46 @@ pg_dumpall -p 5432 | psql -d postgres -p 5433
</para>
<para>
In some cases, the server certificate might be signed by an
<quote>intermediate</quote> certificate authority, rather than one that is
directly trusted by clients. To use such a certificate, append the
certificate of the signing authority to the <filename>server.crt</filename> file,
then its parent authority's certificate, and so on up to a certificate
authority, <quote>root</quote> or <quote>intermediate</quote>, that is trusted by
clients, i.e. signed by a certificate in the clients'
<filename>root.crt</filename> files.
The first certificate in <filename>server.crt</filename> must be the
server's certificate because it must match the server's private key.
The certificates of <quote>intermediate</quote> certificate authorities
can also be appended to the file. Doing this avoids the necessity of
storing intermediate certificates on clients, assuming the root and
intermediate certificates were created with <literal>v3_ca</literal>
extensions. This allows easier expiration of intermediate certificates.
</para>
<para>
It is not necessary to add the root certificate to
<filename>server.crt</filename>. Instead, clients must have the root
certificate of the server's certificate chain.
</para>
<sect2 id="ssl-client-certificates">
<title>Using Client Certificates</title>
<para>
To require the client to supply a trusted certificate, place
certificates of the certificate authorities (<acronym>CA</acronym>s)
you trust in a file named <filename>root.crt</filename> in the data
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 <literal>root.crt</literal>,
and add the authentication option <literal>clientcert=1</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.) The server will
<filename>postgresql.conf</filename> to the new file name, and add the
authentication option <literal>clientcert=1</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.) The server will
verify that the client's certificate is signed by one of the trusted
certificate authorities.
</para>
<para>
If intermediate <acronym>CA</acronym>s appear in
<filename>root.crt</filename>, the file must also contain certificate
chains to their root <acronym>CA</acronym>s. Certificate Revocation List
(CRL) entries
are also checked if the parameter <xref linkend="guc-ssl-crl-file"/> is set.
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"/> is set.
<!-- If this URL changes replace it with a URL to www.archive.org. -->
(See <ulink
url="http://h71000.www7.hp.com/doc/83final/ba554_90007/ch04s02.html"></ulink>
......@@ -2296,14 +2302,6 @@ pg_dumpall -p 5432 | psql -d postgres -p 5433
it will not insist that a client certificate be presented.
</para>
<para>
Note that the server's <filename>root.crt</filename> lists the top-level
CAs that are considered trusted for signing client certificates.
In principle it need
not list the CA that signed the server's certificate, though in most cases
that CA would also be trusted for client certificates.
</para>
<para>
If you are setting up client certificates, you may wish to use
the <literal>cert</literal> authentication method, so that the certificates
......@@ -2385,15 +2383,16 @@ pg_dumpall -p 5432 | psql -d postgres -p 5433
</sect2>
<sect2 id="ssl-certificate-creation">
<title>Creating a Self-signed Certificate</title>
<title>Creating Certificates</title>
<para>
To create a quick self-signed certificate for the server, valid for 365
To create a simple self-signed certificate for the server, valid for 365
days, use the following <productname>OpenSSL</productname> command,
replacing <replaceable>yourdomain.com</replaceable> with the server's host name:
replacing <replaceable>dbhost.yourdomain.com</replaceable> with the
server's host name:
<programlisting>
openssl req -new -x509 -days 365 -nodes -text -out server.crt \
-keyout server.key -subj "/CN=<replaceable>yourdomain.com</replaceable>"
-keyout server.key -subj "/CN=<replaceable>dbhost.yourdomain.com</replaceable>"
</programlisting>
Then do:
<programlisting>
......@@ -2406,14 +2405,86 @@ chmod og-rwx server.key
</para>
<para>
A self-signed certificate can be used for testing, but a certificate
signed by a certificate authority (<acronym>CA</acronym>) (either one of the
global <acronym>CAs</acronym> or a local one) should be used in production
so that clients can verify the server's identity. If all the clients
are local to the organization, using a local <acronym>CA</acronym> is
recommended.
While a self-signed certificate can be used for testing, a certificate
signed by a certificate authority (<acronym>CA</acronym>) (usually an
enterprise-wide root <acronym>CA</acronym>) should be used in production.
</para>
<para>
To create a server certificate whose identity can be validated
by clients, first create a certificate signing request
(<acronym>CSR</acronym>) and a public/private key file:
<programlisting>
openssl req -new -nodes -text -out root.csr \
-keyout root.key -subj "/CN=<replaceable>root.yourdomain.com</replaceable>"
chmod og-rwx root.key
</programlisting>
Then, sign the request with the key to create a root certificate
authority (using the default <productname>OpenSSL</productname>
configuration file location on <productname>Linux</productname>):
<programlisting>
openssl x509 -req -in root.csr -text -days 3650 \
-extfile /etc/ssl/openssl.cnf -extensions v3_ca \
-signkey root.key -out root.crt
</programlisting>
Finally, create a server certificate signed by the new root certificate
authority:
<programlisting>
openssl req -new -nodes -text -out server.csr \
-keyout server.key -subj "/CN=<replaceable>dbhost.yourdomain.com</replaceable>"
chmod og-rwx server.key
openssl x509 -req -in server.csr -text -days 365 \
-CA root.crt -CAkey root.key -CAcreateserial \
-out server.crt
</programlisting>
<filename>server.crt</filename> and <filename>server.key</filename>
should be stored on the server, and <filename>root.crt</filename> should
be stored on the client so the client can verify that the server's leaf
certificate was signed by its trusted root certificate.
<filename>root.key</filename> should be stored offline for use in
creating future certificates.
</para>
<para>
It is also possible to create a chain of trust that includes
intermediate certificates:
<programlisting>
# root
openssl req -new -nodes -text -out root.csr \
-keyout root.key -subj "/CN=<replaceable>root.yourdomain.com</replaceable>"
chmod og-rwx root.key
openssl x509 -req -in root.csr -text -days 3650 \
-extfile /etc/ssl/openssl.cnf -extensions v3_ca \
-signkey root.key -out root.crt
# intermediate
openssl req -new -nodes -text -out intermediate.csr \
-keyout intermediate.key -subj "/CN=<replaceable>intermediate.yourdomain.com</replaceable>"
chmod og-rwx intermediate.key
openssl x509 -req -in intermediate.csr -text -days 1825 \
-extfile /etc/ssl/openssl.cnf -extensions v3_ca \
-CA root.crt -CAkey root.key -CAcreateserial \
-out intermediate.crt
# leaf
openssl req -new -nodes -text -out server.csr \
-keyout server.key -subj "/CN=<replaceable>dbhost.yourdomain.com</replaceable>"
chmod og-rwx server.key
openssl x509 -req -in server.csr -text -days 365 \
-CA intermediate.crt -CAkey intermediate.key -CAcreateserial \
-out server.crt
</programlisting>
<filename>server.crt</filename> and
<filename>intermediate.crt</filename> should be concatenated
into a certificate file bundle and stored on the server.
<filename>server.key</filename> should also be stored on the server.
<filename>root.crt</filename> should be stored on the client so
the client can verify that the server's leaf certificate was signed
by a chain of certificates linked to its trusted root certificate.
<filename>root.key</filename> and <filename>intermediate.key</filename>
should be stored offline for use in creating future certificates.
</para>
</sect2>
</sect1>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment