From: Bruce Momjian Date: Sun, 21 Jan 2018 02:47:02 +0000 (-0500) Subject: doc: update intermediate certificate instructions X-Git-Tag: REL9_6_7~16 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d516aea6591e03edd92e781dad07367117a7cd91;p=postgresql 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 --- diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml index 7a90cb09a9..5762ef8acc 100644 --- a/doc/src/sgml/libpq.sgml +++ b/doc/src/sgml/libpq.sgml @@ -7333,17 +7333,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, - SSL 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 (CA) certificate on one + computer and a leaf certificate signed by the + root certificate on another computer. It is also possible to use an + intermediate certificate which is signed by the root + certificate and signs leaf certificates. + 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. + + + + 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 sslmode is set to verify-ca, libpq will verify that the server is trustworthy by checking the - certificate chain up to a trusted certificate authority - (CA). If sslmode is set to verify-full, - libpq will also verify that the server host name matches its - certificate. The SSL connection will fail if the server certificate cannot - be verified. verify-full is recommended in most + certificate chain up to the root certificate stored on the client. + If sslmode is set to verify-full, + libpq will also 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. verify-full is recommended in most security-sensitive environments. @@ -7360,13 +7380,13 @@ ldap://ldap.acme.com/cn=dbserver,cn=hosts?pgconnectinfo?base?(objectclass=*) - To allow server certificate verification, the certificate(s) of one or more - trusted CAs must be - placed in the file ~/.postgresql/root.crt in the user's home - directory. If intermediate CAs appear in - root.crt, the file must also contain certificate - chains to their root CAs. (On Microsoft Windows the file is named - %APPDATA%\postgresql\root.crt.) + To allow server certificate verification, one or more root certificates + must be placed in the file ~/.postgresql/root.crt + in the user's home directory. (On Microsoft Windows the file is named + %APPDATA%\postgresql\root.crt.) 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. @@ -7400,11 +7420,12 @@ ldap://ldap.acme.com/cn=dbserver,cn=hosts?pgconnectinfo?base?(objectclass=*) Client Certificates - If the server requests a trusted client certificate, - libpq will send the certificate stored in + If the server attempts to verify the identity of the + client by requesting the client's leaf certificate, + libpq will send the certificates stored in file ~/.postgresql/postgresql.crt in the user's home - directory. The certificate must be signed by one of the certificate - authorities (CA) trusted by the server. A matching + directory. The certificates must chain to the root certificate trusted + by the server. A matching private key file ~/.postgresql/postgresql.key must also be present. The private key file must not allow any access to world or group; achieve this by the @@ -7419,23 +7440,17 @@ ldap://ldap.acme.com/cn=dbserver,cn=hosts?pgconnectinfo?base?(objectclass=*) - In some cases, the client certificate might be signed by an - intermediate 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 postgresql.crt - file, then its parent authority's certificate, and so on up to a certificate - authority, root or intermediate, that is trusted by - the server, i.e. signed by a certificate in the server's - root.crt file. + The first certificate in postgresql.crt must be the + client's certificate because it must match the client's private key. + Intermediate certificates can be optionally appended + to the file — doing so avoids requiring storage of intermediate + certificates on the server's root.crt file. - Note that the client's ~/.postgresql/root.crt 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 . - diff --git a/doc/src/sgml/runtime.sgml b/doc/src/sgml/runtime.sgml index 08e678eccc..aa313c9636 100644 --- a/doc/src/sgml/runtime.sgml +++ b/doc/src/sgml/runtime.sgml @@ -2276,40 +2276,46 @@ pg_dumpall -p 5432 | psql -d postgres -p 5433 - In some cases, the server certificate might be signed by an - intermediate 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 server.crt file, - then its parent authority's certificate, and so on up to a certificate - authority, root or intermediate, that is trusted by - clients, i.e. signed by a certificate in the clients' - root.crt files. + The first certificate in server.crt must be the + server's certificate because it must match the server's private key. + The certificates of intermediate 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 v3_ca + extensions. This allows easier expiration of intermediate certificates. + + + + It is not necessary to add the root certificate to + server.crt. Instead, clients must have the root + certificate of the server's certificate chain. Using Client Certificates - To require the client to supply a trusted certificate, place - certificates of the certificate authorities (CAs) - you trust in the file root.crt in the data + To require the client to supply a trusted certificate, + place certificates of the root certificate authorities + (CAs) you trust in a file in the data directory, set the parameter in - postgresql.conf to root.crt, - and add the authentication option clientcert=1 to the - appropriate hostssl line(s) in pg_hba.conf. - A certificate will then be requested from the client during - SSL connection startup. (See for a - description of how to set up certificates on the client.) The server will + postgresql.conf to the new file name, and add the + authentication option clientcert=1 to the appropriate + hostssl line(s) in pg_hba.conf. + A certificate will then be requested from the client during SSL + connection startup. (See 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. - If intermediate CAs appear in - root.crt, the file must also contain certificate - chains to their root CAs. Certificate Revocation List - (CRL) entries - are also checked if the parameter is set. + Intermediate certificates that chain up to existing root certificates + can also appear in the file root.crt if + you wish to avoid storing them on clients (assuming the root and + intermediate certificates were created with v3_ca + extensions). Certificate Revocation List (CRL) entries are also + checked if the parameter is set. (See @@ -2325,14 +2331,6 @@ pg_dumpall -p 5432 | psql -d postgres -p 5433 it will not insist that a client certificate be presented. - - Note that the server's root.crt 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. - - If you are setting up client certificates, you may wish to use the cert authentication method, so that the certificates @@ -2405,31 +2403,18 @@ pg_dumpall -p 5432 | psql -d postgres -p 5433 - Creating a Self-signed Certificate + Creating Certificates - To create a quick self-signed certificate for the server, use the - following OpenSSL command: - -openssl req -new -text -out server.req - - Fill out the information that openssl asks for. Make sure - you enter the local host name as Common Name; the challenge - password can be left blank. The program will generate a key that is - passphrase protected; it will not accept a passphrase that is less - than four characters long. To remove the passphrase (as you must if - you want automatic start-up of the server), run the commands: - -openssl rsa -in privkey.pem -out server.key -rm privkey.pem - - Enter the old passphrase to unlock the existing key. Now do: + To create a simple self-signed certificate for the server, valid for 365 + days, use the following OpenSSL command, + replacing dbhost.yourdomain.com with the + server's host name: -openssl req -x509 -in server.req -text -key server.key -out server.crt +openssl req -new -x509 -days 365 -nodes -text -out server.crt \ + -keyout server.key -subj "/CN=dbhost.yourdomain.com" - to turn the certificate into a self-signed certificate and to copy - the key and certificate to where the server will look for them. - Finally do: + Then do: chmod og-rwx server.key @@ -2440,14 +2425,86 @@ chmod og-rwx server.key - A self-signed certificate can be used for testing, but a certificate - signed by a certificate authority (CA) (either one of the - global CAs 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 CA is - recommended. + While a self-signed certificate can be used for testing, a certificate + signed by a certificate authority (CA) (usually an + enterprise-wide root CA) should be used in production. + + To create a server certificate whose identity can be validated + by clients, first create a certificate signing request + (CSR) and a public/private key file: + +openssl req -new -nodes -text -out root.csr \ + -keyout root.key -subj "/CN=root.yourdomain.com" +chmod og-rwx root.key + + Then, sign the request with the key to create a root certificate + authority (using the default OpenSSL + configuration file location on Linux): + +openssl x509 -req -in root.csr -text -days 3650 \ + -extfile /etc/ssl/openssl.cnf -extensions v3_ca \ + -signkey root.key -out root.crt + + Finally, create a server certificate signed by the new root certificate + authority: + +openssl req -new -nodes -text -out server.csr \ + -keyout server.key -subj "/CN=dbhost.yourdomain.com" +chmod og-rwx server.key + +openssl x509 -req -in server.csr -text -days 365 \ + -CA root.crt -CAkey root.key -CAcreateserial \ + -out server.crt + + server.crt and server.key + should be stored on the server, and root.crt should + be stored on the client so the client can verify that the server's leaf + certificate was signed by its trusted root certificate. + root.key should be stored offline for use in + creating future certificates. + + + + It is also possible to create a chain of trust that includes + intermediate certificates: + +# root +openssl req -new -nodes -text -out root.csr \ + -keyout root.key -subj "/CN=root.yourdomain.com" +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=intermediate.yourdomain.com" +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=dbhost.yourdomain.com" +chmod og-rwx server.key +openssl x509 -req -in server.csr -text -days 365 \ + -CA intermediate.crt -CAkey intermediate.key -CAcreateserial \ + -out server.crt + + server.crt and + intermediate.crt should be concatenated + into a certificate file bundle and stored on the server. + server.key should also be stored on the server. + root.crt 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. + root.key and intermediate.key + should be stored offline for use in creating future certificates. +