Skip to content

Commit e477d14

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 61f08c0 commit e477d14

File tree

2 files changed

+156
-70
lines changed

2 files changed

+156
-70
lines changed

doc/src/sgml/libpq.sgml

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

75547560
<para>
7561+
To allow the client to verify the identity of the server, place a root
7562+
certificate on the client and a leaf certificate signed by the root
7563+
certificate on the server. To allow the server to verify the identity
7564+
of the client, place a root certificate on the server and a leaf and
7565+
optional intermediate certificates signed by the root certificate on
7566+
the client. Intermediate certificates (usually stored with the leaf
7567+
certificate) can also be used to link the leaf certificate to the
7568+
root certificate.
7569+
</para>
7570+
7571+
<para>
7572+
Once a chain of trust has been established, there are two ways for
7573+
the client to validate the leaf certificate sent by the server.
75557574
If the parameter <literal>sslmode</> is set to <literal>verify-ca</>,
75567575
libpq will verify that the server is trustworthy by checking the
7557-
certificate chain up to a trusted certificate authority
7558-
(<acronym>CA</>). If <literal>sslmode</> is set to <literal>verify-full</>,
7559-
libpq will <emphasis>also</> verify that the server host name matches its
7560-
certificate. The SSL connection will fail if the server certificate cannot
7561-
be verified. <literal>verify-full</> is recommended in most
7576+
certificate chain up to the root certificate stored on the client.
7577+
If <literal>sslmode</> is set to <literal>verify-full</>,
7578+
libpq will <emphasis>also</> verify that the server host
7579+
name matches the name stored in the server certificate. The
7580+
SSL connection will fail if the server certificate cannot be
7581+
verified. <literal>verify-full</> is recommended in most
75627582
security-sensitive environments.
75637583
</para>
75647584

@@ -7575,13 +7595,13 @@ ldap://ldap.acme.com/cn=dbserver,cn=hosts?pgconnectinfo?base?(objectclass=*)
75757595
</para>
75767596

75777597
<para>
7578-
To allow server certificate verification, the certificate(s) of one or more
7579-
trusted <acronym>CA</>s must be
7580-
placed in the file <filename>~/.postgresql/root.crt</> in the user's home
7581-
directory. If intermediate <acronym>CA</>s appear in
7582-
<filename>root.crt</filename>, the file must also contain certificate
7583-
chains to their root <acronym>CA</>s. (On Microsoft Windows the file is named
7584-
<filename>%APPDATA%\postgresql\root.crt</filename>.)
7598+
To allow server certificate verification, one or more root certificates
7599+
must be placed in the file <filename>~/.postgresql/root.crt</>
7600+
in the user's home directory. (On Microsoft Windows the file is named
7601+
<filename>%APPDATA%\postgresql\root.crt</>.) Intermediate
7602+
certificates should also be added to the file if they are needed to link
7603+
the certificate chain sent by the server to the root certificates
7604+
stored on the client.
75857605
</para>
75867606

75877607
<para>
@@ -7615,11 +7635,12 @@ ldap://ldap.acme.com/cn=dbserver,cn=hosts?pgconnectinfo?base?(objectclass=*)
76157635
<title>Client Certificates</title>
76167636

76177637
<para>
7618-
If the server requests a trusted client certificate,
7619-
<application>libpq</application> will send the certificate stored in
7638+
If the server attempts to verify the identity of the
7639+
client by requesting the client's leaf certificate,
7640+
<application>libpq</> will send the certificates stored in
76207641
file <filename>~/.postgresql/postgresql.crt</> in the user's home
7621-
directory. The certificate must be signed by one of the certificate
7622-
authorities (<acronym>CA</acronym>) trusted by the server. A matching
7642+
directory. The certificates must chain to the root certificate trusted
7643+
by the server. A matching
76237644
private key file <filename>~/.postgresql/postgresql.key</> must also
76247645
be present. The private
76257646
key file must not allow any access to world or group; achieve this by the
@@ -7634,23 +7655,17 @@ ldap://ldap.acme.com/cn=dbserver,cn=hosts?pgconnectinfo?base?(objectclass=*)
76347655
</para>
76357656

76367657
<para>
7637-
In some cases, the client certificate might be signed by an
7638-
<quote>intermediate</> certificate authority, rather than one that is
7639-
directly trusted by the server. To use such a certificate, append the
7640-
certificate of the signing authority to the <filename>postgresql.crt</>
7641-
file, then its parent authority's certificate, and so on up to a certificate
7642-
authority, <quote>root</> or <quote>intermediate</>, that is trusted by
7643-
the server, i.e. signed by a certificate in the server's
7644-
<filename>root.crt</filename> file.
7658+
The first certificate in <filename>postgresql.crt</> must be the
7659+
client's certificate because it must match the client's private key.
7660+
<quote>Intermediate</> certificates can be optionally appended
7661+
to the file &mdash; doing so avoids requiring storage of intermediate
7662+
certificates on the server's <filename>root.crt</filename> file.
76457663
</para>
76467664

76477665
<para>
7648-
Note that the client's <filename>~/.postgresql/root.crt</> lists the top-level CAs
7649-
that are considered trusted for signing server certificates. In principle it need
7650-
not list the CA that signed the client's certificate, though in most cases
7651-
that CA would also be trusted for server certificates.
7666+
For instructions on creating certificates, see <xref
7667+
linkend="ssl-certificate-creation">.
76527668
</para>
7653-
76547669
</sect2>
76557670

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

doc/src/sgml/runtime.sgml

Lines changed: 111 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -2248,40 +2248,46 @@ pg_dumpall -p 5432 | psql -d postgres -p 5433
22482248
</para>
22492249

22502250
<para>
2251-
In some cases, the server certificate might be signed by an
2252-
<quote>intermediate</> certificate authority, rather than one that is
2253-
directly trusted by clients. To use such a certificate, append the
2254-
certificate of the signing authority to the <filename>server.crt</> file,
2255-
then its parent authority's certificate, and so on up to a certificate
2256-
authority, <quote>root</> or <quote>intermediate</>, that is trusted by
2257-
clients, i.e. signed by a certificate in the clients'
2258-
<filename>root.crt</filename> files.
2251+
The first certificate in <filename>server.crt</> must be the
2252+
server's certificate because it must match the server's private key.
2253+
The certificates of <quote>intermediate</> certificate authorities
2254+
can also be appended to the file. Doing this avoids the necessity of
2255+
storing intermediate certificates on clients, assuming the root and
2256+
intermediate certificates were created with <literal>v3_ca</>
2257+
extensions. This allows easier expiration of intermediate certificates.
2258+
</para>
2259+
2260+
<para>
2261+
It is not necessary to add the root certificate to
2262+
<filename>server.crt</>. Instead, clients must have the root
2263+
certificate of the server's certificate chain.
22592264
</para>
22602265

22612266
<sect2 id="ssl-client-certificates">
22622267
<title>Using Client Certificates</title>
22632268

22642269
<para>
2265-
To require the client to supply a trusted certificate, place
2266-
certificates of the certificate authorities (<acronym>CA</acronym>s)
2267-
you trust in the file <filename>root.crt</filename> in the data
2270+
To require the client to supply a trusted certificate,
2271+
place certificates of the root certificate authorities
2272+
(<acronym>CA</>s) you trust in a file in the data
22682273
directory, set the parameter <xref linkend="guc-ssl-ca-file"> in
2269-
<filename>postgresql.conf</filename> to <literal>root.crt</literal>,
2270-
and add the authentication option <literal>clientcert=1</literal> to the
2271-
appropriate <literal>hostssl</> line(s) in <filename>pg_hba.conf</>.
2272-
A certificate will then be requested from the client during
2273-
SSL connection startup. (See <xref linkend="libpq-ssl"> for a
2274-
description of how to set up certificates on the client.) The server will
2274+
<filename>postgresql.conf</> to the new file name, and add the
2275+
authentication option <literal>clientcert=1</> to the appropriate
2276+
<literal>hostssl</> line(s) in <filename>pg_hba.conf</>.
2277+
A certificate will then be requested from the client during SSL
2278+
connection startup. (See <xref linkend="libpq-ssl"> for a description
2279+
of how to set up certificates on the client.) The server will
22752280
verify that the client's certificate is signed by one of the trusted
22762281
certificate authorities.
22772282
</para>
22782283

22792284
<para>
2280-
If intermediate <acronym>CA</>s appear in
2281-
<filename>root.crt</filename>, the file must also contain certificate
2282-
chains to their root <acronym>CA</>s. Certificate Revocation List
2283-
(CRL) entries
2284-
are also checked if the parameter <xref linkend="guc-ssl-crl-file"> is set.
2285+
Intermediate certificates that chain up to existing root certificates
2286+
can also appear in the file <filename>root.crt</filename> if
2287+
you wish to avoid storing them on clients (assuming the root and
2288+
intermediate certificates were created with <literal>v3_ca</>
2289+
extensions). Certificate Revocation List (CRL) entries are also
2290+
checked if the parameter <xref linkend="guc-ssl-crl-file"> is set.
22852291
<!-- If this URL changes replace it with a URL to www.archive.org. -->
22862292
(See <ulink
22872293
url="http://h71000.www7.hp.com/doc/83final/ba554_90007/ch04s02.html"></>
@@ -2297,14 +2303,6 @@ pg_dumpall -p 5432 | psql -d postgres -p 5433
22972303
it will not insist that a client certificate be presented.
22982304
</para>
22992305

2300-
<para>
2301-
Note that the server's <filename>root.crt</filename> lists the top-level
2302-
CAs that are considered trusted for signing client certificates.
2303-
In principle it need
2304-
not list the CA that signed the server's certificate, though in most cases
2305-
that CA would also be trusted for client certificates.
2306-
</para>
2307-
23082306
<para>
23092307
If you are setting up client certificates, you may wish to use
23102308
the <literal>cert</> authentication method, so that the certificates
@@ -2386,15 +2384,16 @@ pg_dumpall -p 5432 | psql -d postgres -p 5433
23862384
</sect2>
23872385

23882386
<sect2 id="ssl-certificate-creation">
2389-
<title>Creating a Self-signed Certificate</title>
2387+
<title>Creating Certificates</title>
23902388

23912389
<para>
2392-
To create a quick self-signed certificate for the server, valid for 365
2390+
To create a simple self-signed certificate for the server, valid for 365
23932391
days, use the following <productname>OpenSSL</productname> command,
2394-
replacing <replaceable>yourdomain.com</> with the server's host name:
2392+
replacing <replaceable>dbhost.yourdomain.com</> with the
2393+
server's host name:
23952394
<programlisting>
23962395
openssl req -new -x509 -days 365 -nodes -text -out server.crt \
2397-
-keyout server.key -subj "/CN=<replaceable>yourdomain.com</>"
2396+
-keyout server.key -subj "/CN=<replaceable>dbhost.yourdomain.com</>"
23982397
</programlisting>
23992398
Then do:
24002399
<programlisting>
@@ -2407,14 +2406,86 @@ chmod og-rwx server.key
24072406
</para>
24082407

24092408
<para>
2410-
A self-signed certificate can be used for testing, but a certificate
2411-
signed by a certificate authority (<acronym>CA</>) (either one of the
2412-
global <acronym>CAs</> or a local one) should be used in production
2413-
so that clients can verify the server's identity. If all the clients
2414-
are local to the organization, using a local <acronym>CA</> is
2415-
recommended.
2409+
While a self-signed certificate can be used for testing, a certificate
2410+
signed by a certificate authority (<acronym>CA</>) (usually an
2411+
enterprise-wide root <acronym>CA</>) should be used in production.
24162412
</para>
24172413

2414+
<para>
2415+
To create a server certificate whose identity can be validated
2416+
by clients, first create a certificate signing request
2417+
(<acronym>CSR</>) and a public/private key file:
2418+
<programlisting>
2419+
openssl req -new -nodes -text -out root.csr \
2420+
-keyout root.key -subj "/CN=<replaceable>root.yourdomain.com</>"
2421+
chmod og-rwx root.key
2422+
</programlisting>
2423+
Then, sign the request with the key to create a root certificate
2424+
authority (using the default <productname>OpenSSL</>
2425+
configuration file location on <productname>Linux</>):
2426+
<programlisting>
2427+
openssl x509 -req -in root.csr -text -days 3650 \
2428+
-extfile /etc/ssl/openssl.cnf -extensions v3_ca \
2429+
-signkey root.key -out root.crt
2430+
</programlisting>
2431+
Finally, create a server certificate signed by the new root certificate
2432+
authority:
2433+
<programlisting>
2434+
openssl req -new -nodes -text -out server.csr \
2435+
-keyout server.key -subj "/CN=<replaceable>dbhost.yourdomain.com</>"
2436+
chmod og-rwx server.key
2437+
2438+
openssl x509 -req -in server.csr -text -days 365 \
2439+
-CA root.crt -CAkey root.key -CAcreateserial \
2440+
-out server.crt
2441+
</programlisting>
2442+
<filename>server.crt</> and <filename>server.key</>
2443+
should be stored on the server, and <filename>root.crt</> should
2444+
be stored on the client so the client can verify that the server's leaf
2445+
certificate was signed by its trusted root certificate.
2446+
<filename>root.key</> should be stored offline for use in
2447+
creating future certificates.
2448+
</para>
2449+
2450+
<para>
2451+
It is also possible to create a chain of trust that includes
2452+
intermediate certificates:
2453+
<programlisting>
2454+
# root
2455+
openssl req -new -nodes -text -out root.csr \
2456+
-keyout root.key -subj "/CN=<replaceable>root.yourdomain.com</>"
2457+
chmod og-rwx root.key
2458+
openssl x509 -req -in root.csr -text -days 3650 \
2459+
-extfile /etc/ssl/openssl.cnf -extensions v3_ca \
2460+
-signkey root.key -out root.crt
2461+
2462+
# intermediate
2463+
openssl req -new -nodes -text -out intermediate.csr \
2464+
-keyout intermediate.key -subj "/CN=<replaceable>intermediate.yourdomain.com</>"
2465+
chmod og-rwx intermediate.key
2466+
openssl x509 -req -in intermediate.csr -text -days 1825 \
2467+
-extfile /etc/ssl/openssl.cnf -extensions v3_ca \
2468+
-CA root.crt -CAkey root.key -CAcreateserial \
2469+
-out intermediate.crt
2470+
2471+
# leaf
2472+
openssl req -new -nodes -text -out server.csr \
2473+
-keyout server.key -subj "/CN=<replaceable>dbhost.yourdomain.com</>"
2474+
chmod og-rwx server.key
2475+
openssl x509 -req -in server.csr -text -days 365 \
2476+
-CA intermediate.crt -CAkey intermediate.key -CAcreateserial \
2477+
-out server.crt
2478+
</programlisting>
2479+
<filename>server.crt</> and
2480+
<filename>intermediate.crt</> should be concatenated
2481+
into a certificate file bundle and stored on the server.
2482+
<filename>server.key</> should also be stored on the server.
2483+
<filename>root.crt</> should be stored on the client so
2484+
the client can verify that the server's leaf certificate was signed
2485+
by a chain of certificates linked to its trusted root certificate.
2486+
<filename>root.key</> and <filename>intermediate.key</>
2487+
should be stored offline for use in creating future certificates.
2488+
</para>
24182489
</sect2>
24192490

24202491
</sect1>

0 commit comments

Comments
 (0)