Skip to content

Commit 5474ab5

Browse files
committed
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
1 parent 0d99370 commit 5474ab5

File tree

2 files changed

+164
-89
lines changed

2 files changed

+164
-89
lines changed

doc/src/sgml/libpq.sgml

Lines changed: 45 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -7226,17 +7226,37 @@ ldap://ldap.acme.com/cn=dbserver,cn=hosts?pgconnectinfo?base?(objectclass=*)
72267226
the server certificate. This means that it is possible to spoof the server
72277227
identity (for example by modifying a DNS record or by taking over the server
72287228
IP address) without the client knowing. In order to prevent spoofing,
7229-
<acronym>SSL</> certificate verification must be used.
7229+
the client must be able to verify the server's identity via a chain of
7230+
trust. A chain of trust is established by placing a root (self-signed)
7231+
certificate authority (<acronym>CA</>) certificate on one
7232+
computer and a leaf certificate <emphasis>signed</> by the
7233+
root certificate on another computer. It is also possible to use an
7234+
<quote>intermediate</> certificate which is signed by the root
7235+
certificate and signs leaf certificates.
72307236
</para>
72317237

72327238
<para>
7239+
To allow the client to verify the identity of the server, place a root
7240+
certificate on the client and a leaf certificate signed by the root
7241+
certificate on the server. To allow the server to verify the identity
7242+
of the client, place a root certificate on the server and a leaf and
7243+
optional intermediate certificates signed by the root certificate on
7244+
the client. Intermediate certificates (usually stored with the leaf
7245+
certificate) can also be used to link the leaf certificate to the
7246+
root certificate.
7247+
</para>
7248+
7249+
<para>
7250+
Once a chain of trust has been established, there are two ways for
7251+
the client to validate the leaf certificate sent by the server.
72337252
If the parameter <literal>sslmode</> is set to <literal>verify-ca</>,
72347253
libpq will verify that the server is trustworthy by checking the
7235-
certificate chain up to a trusted certificate authority
7236-
(<acronym>CA</>). If <literal>sslmode</> is set to <literal>verify-full</>,
7237-
libpq will <emphasis>also</> verify that the server host name matches its
7238-
certificate. The SSL connection will fail if the server certificate cannot
7239-
be verified. <literal>verify-full</> is recommended in most
7254+
certificate chain up to the root certificate stored on the client.
7255+
If <literal>sslmode</> is set to <literal>verify-full</>,
7256+
libpq will <emphasis>also</> verify that the server host
7257+
name matches the name stored in the server certificate. The
7258+
SSL connection will fail if the server certificate cannot be
7259+
verified. <literal>verify-full</> is recommended in most
72407260
security-sensitive environments.
72417261
</para>
72427262

@@ -7253,13 +7273,13 @@ ldap://ldap.acme.com/cn=dbserver,cn=hosts?pgconnectinfo?base?(objectclass=*)
72537273
</para>
72547274

72557275
<para>
7256-
To allow server certificate verification, the certificate(s) of one or more
7257-
trusted <acronym>CA</>s must be
7258-
placed in the file <filename>~/.postgresql/root.crt</> in the user's home
7259-
directory. If intermediate <acronym>CA</>s appear in
7260-
<filename>root.crt</filename>, the file must also contain certificate
7261-
chains to their root <acronym>CA</>s. (On Microsoft Windows the file is named
7262-
<filename>%APPDATA%\postgresql\root.crt</filename>.)
7276+
To allow server certificate verification, one or more root certificates
7277+
must be placed in the file <filename>~/.postgresql/root.crt</>
7278+
in the user's home directory. (On Microsoft Windows the file is named
7279+
<filename>%APPDATA%\postgresql\root.crt</>.) Intermediate
7280+
certificates should also be added to the file if they are needed to link
7281+
the certificate chain sent by the server to the root certificates
7282+
stored on the client.
72637283
</para>
72647284

72657285
<para>
@@ -7293,11 +7313,12 @@ ldap://ldap.acme.com/cn=dbserver,cn=hosts?pgconnectinfo?base?(objectclass=*)
72937313
<title>Client Certificates</title>
72947314

72957315
<para>
7296-
If the server requests a trusted client certificate,
7297-
<application>libpq</application> will send the certificate stored in
7316+
If the server attempts to verify the identity of the
7317+
client by requesting the client's leaf certificate,
7318+
<application>libpq</> will send the certificates stored in
72987319
file <filename>~/.postgresql/postgresql.crt</> in the user's home
7299-
directory. The certificate must be signed by one of the certificate
7300-
authorities (<acronym>CA</acronym>) trusted by the server. A matching
7320+
directory. The certificates must chain to the root certificate trusted
7321+
by the server. A matching
73017322
private key file <filename>~/.postgresql/postgresql.key</> must also
73027323
be present. The private
73037324
key file must not allow any access to world or group; achieve this by the
@@ -7312,23 +7333,17 @@ ldap://ldap.acme.com/cn=dbserver,cn=hosts?pgconnectinfo?base?(objectclass=*)
73127333
</para>
73137334

73147335
<para>
7315-
In some cases, the client certificate might be signed by an
7316-
<quote>intermediate</> certificate authority, rather than one that is
7317-
directly trusted by the server. To use such a certificate, append the
7318-
certificate of the signing authority to the <filename>postgresql.crt</>
7319-
file, then its parent authority's certificate, and so on up to a certificate
7320-
authority, <quote>root</> or <quote>intermediate</>, that is trusted by
7321-
the server, i.e. signed by a certificate in the server's
7322-
<filename>root.crt</filename> file.
7336+
The first certificate in <filename>postgresql.crt</> must be the
7337+
client's certificate because it must match the client's private key.
7338+
<quote>Intermediate</> certificates can be optionally appended
7339+
to the file &mdash; doing so avoids requiring storage of intermediate
7340+
certificates on the server's <filename>root.crt</filename> file.
73237341
</para>
73247342

73257343
<para>
7326-
Note that the client's <filename>~/.postgresql/root.crt</> lists the top-level CAs
7327-
that are considered trusted for signing server certificates. In principle it need
7328-
not list the CA that signed the client's certificate, though in most cases
7329-
that CA would also be trusted for server certificates.
7344+
For instructions on creating certificates, see <xref
7345+
linkend="ssl-certificate-creation">.
73307346
</para>
7331-
73327347
</sect2>
73337348

73347349
<sect2 id="libpq-ssl-protection">

doc/src/sgml/runtime.sgml

Lines changed: 119 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -2211,37 +2211,46 @@ pg_dumpall -p 5432 | psql -d postgres -p 5433
22112211
</para>
22122212

22132213
<para>
2214-
In some cases, the server certificate might be signed by an
2215-
<quote>intermediate</> certificate authority, rather than one that is
2216-
directly trusted by clients. To use such a certificate, append the
2217-
certificate of the signing authority to the <filename>server.crt</> file,
2218-
then its parent authority's certificate, and so on up to a certificate
2219-
authority, <quote>root</> or <quote>intermediate</>, that is trusted by
2220-
clients, i.e. signed by a certificate in the clients'
2221-
<filename>root.crt</filename> files.
2214+
The first certificate in <filename>server.crt</> must be the
2215+
server's certificate because it must match the server's private key.
2216+
The certificates of <quote>intermediate</> certificate authorities
2217+
can also be appended to the file. Doing this avoids the necessity of
2218+
storing intermediate certificates on clients, assuming the root and
2219+
intermediate certificates were created with <literal>v3_ca</>
2220+
extensions. This allows easier expiration of intermediate certificates.
2221+
</para>
2222+
2223+
<para>
2224+
It is not necessary to add the root certificate to
2225+
<filename>server.crt</>. Instead, clients must have the root
2226+
certificate of the server's certificate chain.
22222227
</para>
22232228

22242229
<sect2 id="ssl-client-certificates">
22252230
<title>Using Client Certificates</title>
22262231

2227-
<para>
2228-
To require the client to supply a trusted certificate, place
2229-
certificates of the certificate authorities (<acronym>CA</acronym>s)
2230-
you trust in the file <filename>root.crt</filename> in the data
2232+
<para>
2233+
To require the client to supply a trusted certificate,
2234+
place certificates of the root certificate authorities
2235+
(<acronym>CA</>s) you trust in a file in the data
22312236
directory, set the parameter <xref linkend="guc-ssl-ca-file"> in
2232-
<filename>postgresql.conf</filename> to <literal>root.crt</literal>,
2233-
and set the <literal>clientcert</literal> parameter
2234-
to 1 on the appropriate <literal>hostssl</> line(s) in
2235-
<filename>pg_hba.conf</>.
2236-
A certificate will then be requested from the client during
2237-
SSL connection startup. (See <xref linkend="libpq-ssl"> for a
2238-
description of how to set up certificates on the client.) The server will
2237+
<filename>postgresql.conf</> to the new file name, and add the
2238+
authentication option <literal>clientcert=1</> to the appropriate
2239+
<literal>hostssl</> line(s) in <filename>pg_hba.conf</>.
2240+
A certificate will then be requested from the client during SSL
2241+
connection startup. (See <xref linkend="libpq-ssl"> for a description
2242+
of how to set up certificates on the client.) The server will
22392243
verify that the client's certificate is signed by one of the trusted
2240-
certificate authorities. If intermediate <acronym>CA</>s appear in
2241-
<filename>root.crt</filename>, the file must also contain certificate
2242-
chains to their root <acronym>CA</>s. Certificate Revocation List
2243-
(CRL) entries
2244-
are also checked if the parameter <xref linkend="guc-ssl-crl-file"> is set.
2244+
certificate authorities.
2245+
</para>
2246+
2247+
<para>
2248+
Intermediate certificates that chain up to existing root certificates
2249+
can also appear in the file <filename>root.crt</filename> if
2250+
you wish to avoid storing them on clients (assuming the root and
2251+
intermediate certificates were created with <literal>v3_ca</>
2252+
extensions). Certificate Revocation List (CRL) entries are also
2253+
checked if the parameter <xref linkend="guc-ssl-crl-file"> is set.
22452254
<!-- If this URL changes replace it with a URL to www.archive.org. -->
22462255
(See <ulink
22472256
url="http://h71000.www7.hp.com/doc/83final/ba554_90007/ch04s02.html"></>
@@ -2257,14 +2266,6 @@ pg_dumpall -p 5432 | psql -d postgres -p 5433
22572266
&mdash; but it will not insist that a client certificate be presented.
22582267
</para>
22592268

2260-
<para>
2261-
Note that the server's <filename>root.crt</filename> lists the top-level
2262-
CAs that are considered trusted for signing client certificates.
2263-
In principle it need
2264-
not list the CA that signed the server's certificate, though in most cases
2265-
that CA would also be trusted for client certificates.
2266-
</para>
2267-
22682269
<para>
22692270
If you are setting up client certificates, you may wish to use
22702271
the <literal>cert</> authentication method, so that the certificates
@@ -2335,31 +2336,18 @@ pg_dumpall -p 5432 | psql -d postgres -p 5433
23352336
</sect2>
23362337

23372338
<sect2 id="ssl-certificate-creation">
2338-
<title>Creating a Self-signed Certificate</title>
2339+
<title>Creating Certificates</title>
23392340

23402341
<para>
2341-
To create a quick self-signed certificate for the server, use the
2342-
following <productname>OpenSSL</productname> command:
2343-
<programlisting>
2344-
openssl req -new -text -out server.req
2345-
</programlisting>
2346-
Fill out the information that <application>openssl</> asks for. Make sure
2347-
you enter the local host name as <quote>Common Name</>; the challenge
2348-
password can be left blank. The program will generate a key that is
2349-
passphrase protected; it will not accept a passphrase that is less
2350-
than four characters long. To remove the passphrase (as you must if
2351-
you want automatic start-up of the server), run the commands:
2352-
<programlisting>
2353-
openssl rsa -in privkey.pem -out server.key
2354-
rm privkey.pem
2355-
</programlisting>
2356-
Enter the old passphrase to unlock the existing key. Now do:
2342+
To create a simple self-signed certificate for the server, valid for 365
2343+
days, use the following <productname>OpenSSL</productname> command,
2344+
replacing <replaceable>dbhost.yourdomain.com</> with the
2345+
server's host name:
23572346
<programlisting>
2358-
openssl req -x509 -in server.req -text -key server.key -out server.crt
2347+
openssl req -new -x509 -days 365 -nodes -text -out server.crt \
2348+
-keyout server.key -subj "/CN=<replaceable>dbhost.yourdomain.com</>"
23592349
</programlisting>
2360-
to turn the certificate into a self-signed certificate and to copy
2361-
the key and certificate to where the server will look for them.
2362-
Finally do:
2350+
Then do:
23632351
<programlisting>
23642352
chmod og-rwx server.key
23652353
</programlisting>
@@ -2370,14 +2358,86 @@ chmod og-rwx server.key
23702358
</para>
23712359

23722360
<para>
2373-
A self-signed certificate can be used for testing, but a certificate
2374-
signed by a certificate authority (<acronym>CA</>) (either one of the
2375-
global <acronym>CAs</> or a local one) should be used in production
2376-
so that clients can verify the server's identity. If all the clients
2377-
are local to the organization, using a local <acronym>CA</> is
2378-
recommended.
2361+
While a self-signed certificate can be used for testing, a certificate
2362+
signed by a certificate authority (<acronym>CA</>) (usually an
2363+
enterprise-wide root <acronym>CA</>) should be used in production.
23792364
</para>
23802365

2366+
<para>
2367+
To create a server certificate whose identity can be validated
2368+
by clients, first create a certificate signing request
2369+
(<acronym>CSR</>) and a public/private key file:
2370+
<programlisting>
2371+
openssl req -new -nodes -text -out root.csr \
2372+
-keyout root.key -subj "/CN=<replaceable>root.yourdomain.com</>"
2373+
chmod og-rwx root.key
2374+
</programlisting>
2375+
Then, sign the request with the key to create a root certificate
2376+
authority (using the default <productname>OpenSSL</>
2377+
configuration file location on <productname>Linux</>):
2378+
<programlisting>
2379+
openssl x509 -req -in root.csr -text -days 3650 \
2380+
-extfile /etc/ssl/openssl.cnf -extensions v3_ca \
2381+
-signkey root.key -out root.crt
2382+
</programlisting>
2383+
Finally, create a server certificate signed by the new root certificate
2384+
authority:
2385+
<programlisting>
2386+
openssl req -new -nodes -text -out server.csr \
2387+
-keyout server.key -subj "/CN=<replaceable>dbhost.yourdomain.com</>"
2388+
chmod og-rwx server.key
2389+
2390+
openssl x509 -req -in server.csr -text -days 365 \
2391+
-CA root.crt -CAkey root.key -CAcreateserial \
2392+
-out server.crt
2393+
</programlisting>
2394+
<filename>server.crt</> and <filename>server.key</>
2395+
should be stored on the server, and <filename>root.crt</> should
2396+
be stored on the client so the client can verify that the server's leaf
2397+
certificate was signed by its trusted root certificate.
2398+
<filename>root.key</> should be stored offline for use in
2399+
creating future certificates.
2400+
</para>
2401+
2402+
<para>
2403+
It is also possible to create a chain of trust that includes
2404+
intermediate certificates:
2405+
<programlisting>
2406+
# root
2407+
openssl req -new -nodes -text -out root.csr \
2408+
-keyout root.key -subj "/CN=<replaceable>root.yourdomain.com</>"
2409+
chmod og-rwx root.key
2410+
openssl x509 -req -in root.csr -text -days 3650 \
2411+
-extfile /etc/ssl/openssl.cnf -extensions v3_ca \
2412+
-signkey root.key -out root.crt
2413+
2414+
# intermediate
2415+
openssl req -new -nodes -text -out intermediate.csr \
2416+
-keyout intermediate.key -subj "/CN=<replaceable>intermediate.yourdomain.com</>"
2417+
chmod og-rwx intermediate.key
2418+
openssl x509 -req -in intermediate.csr -text -days 1825 \
2419+
-extfile /etc/ssl/openssl.cnf -extensions v3_ca \
2420+
-CA root.crt -CAkey root.key -CAcreateserial \
2421+
-out intermediate.crt
2422+
2423+
# leaf
2424+
openssl req -new -nodes -text -out server.csr \
2425+
-keyout server.key -subj "/CN=<replaceable>dbhost.yourdomain.com</>"
2426+
chmod og-rwx server.key
2427+
openssl x509 -req -in server.csr -text -days 365 \
2428+
-CA intermediate.crt -CAkey intermediate.key -CAcreateserial \
2429+
-out server.crt
2430+
</programlisting>
2431+
<filename>server.crt</> and
2432+
<filename>intermediate.crt</> should be concatenated
2433+
into a certificate file bundle and stored on the server.
2434+
<filename>server.key</> should also be stored on the server.
2435+
<filename>root.crt</> should be stored on the client so
2436+
the client can verify that the server's leaf certificate was signed
2437+
by a chain of certificates linked to its trusted root certificate.
2438+
<filename>root.key</> and <filename>intermediate.key</>
2439+
should be stored offline for use in creating future certificates.
2440+
</para>
23812441
</sect2>
23822442

23832443
</sect1>

0 commit comments

Comments
 (0)