1# How to configure the server TLS certificates for authentication
2Author:
3  Zbigniew Kurzynski <zbigniew.kurzynski@intel.com>
4
5Created:
6  May 8, 2020
7
8Related documents:
9* [Redfish TLS User Authentication](https://github.com/openbmc/docs/blob/master/designs/redfish-tls-user-authentication.md)
10
11## Introduction
12With help of this guidebook you should be able to create both client and
13server certificates signed by a CA that can be used to authenticate user
14requests to an OpenBMC server. You will also learn how to enable and test
15the OpenBMC TLS authentication.
16
17## Certificates
18For a certificate to be marked as valid, it (and every certificate in the
19chain) has to meet these conditions:
20
21* `KeyUsage` contains required purpose `digitalSignature` and `keyAgreement`
22(see rfc 3280 4.2.1.3)
23* `ExtendedKeyUsage` contains required purpose `clientAuth` for client
24certificate and `serverAuth` for server certificate (see rfc 3280 4.2.1.13)
25* public key meets minimal bit length requirement
26* certificate has to be in its validity period
27* `notBefore` and `notAfter` fields have to contain valid time
28* has to be properly signed by certificate authority
29* certificate is well-formed according to X.509
30* issuer name has to match CA's subject name for client certificate
31* issuer name has to match the fully qualified domain name of your OpenBMC
32host
33
34If you already have certificates you can skip to [Enable TLS authentication
35](#Enable-TLS-authentication) or go to [Verify certificates](#Verify-certificates)
36and check if they meet the above requirements.
37
38### Prepare configuration files
39
40To generate certificates with required parameters some modification must be
41made to the default openssl configuration file.
42
43First create a new folder named `ca` and create a configuration file using
44the default configuration as a template (we do not want to change the
45original one). The location of the configuration file may vary depending on
46the operating system. For Ubuntu it is usually `/usr/lib/ssl/openssl.cnf`,
47but can also can be at `/etc/ssl/openssl.cnf`. For Cygwin it might be
48`/etc/defaults/etc/pki/tls/openssl.cnf` or `/etc/pki/tls/openssl.cnf`.
49
50```
51mkdir ~/ca
52cd ~/ca
53cp /usr/lib/ssl/openssl.cnf openssl-client.cnf
54```
55
56Then open the client `~/ca/openssl-client.cnf` file in your favorite editor,
57for example `vi`.
58
59```
60vi ~/ca/openssl-client.cnf
61```
62
63Find the sections listed below and add or choose the presented values.
64
65```
66[ req ]
67req_extensions = v3_req
68
69[ usr_cert ]
70extendedKeyUsage = clientAuth
71
72[ v3_req ]
73extendedKeyUsage = clientAuth
74keyUsage = digitalSignature, keyAgreement
75```
76
77Now create a server configuration `openssl-server.cnf` by copying the client
78file
79
80```
81cp ~/ca/openssl-client.cnf openssl-server.cnf
82```
83
84and changing values presented in the sections listed below.
85
86```
87[ usr_cert ]
88extendedKeyUsage = serverAuth
89
90[ v3_req ]
91extendedKeyUsage = serverAuth
92```
93
94Create two additional configuration files `myext-client.cnf` and
95`myext-server.cnf` for the client and server certificates respectively.
96Without these files no extensions are added to the certificate.
97
98```
99cat << END > myext-client.cnf
100[ my_ext_section ]
101keyUsage = digitalSignature, keyAgreement
102extendedKeyUsage = clientAuth
103authorityKeyIdentifier = keyid
104END
105```
106```
107cat << END > myext-server.cnf
108[ my_ext_section ]
109keyUsage = digitalSignature, keyAgreement
110extendedKeyUsage = serverAuth
111authorityKeyIdentifier = keyid
112END
113```
114
115### Create a new CA certificate
116First we need to create a private key to sign the CA certificate.
117```
118openssl genrsa -out CA-key.pem 2048
119```
120
121Now we can create a CA certificate, using the previously generated key.
122You will be prompted for information which will be incorporated into the
123certificate, such as Country, City, Company Name, etc.
124
125```
126openssl req -new -config openssl-client.cnf -key CA-key.pem -x509 -days 1000 -out CA-cert.pem
127```
128
129### Create client certificate signed by given CA certificate
130To create a client certificate, a signing request must be created first. For
131this another private key will be needed.
132
133Generate a new key that will be used to sign the certificate signing request:
134```
135openssl genrsa -out client-key.pem 2048
136```
137Generate a certificate signing request.
138
139You will be prompted for the same information as during CA generation, but
140provide **the OpenBMC system user name**  for the `CommonName` attribute of
141this certificate.  In this example, use **root**.
142
143```
144openssl req -new -config openssl-client.cnf -key client-key.pem -out signingReqClient.csr
145```
146
147Sign the certificate using your `CA-cert.pem` certificate with following
148command:
149```
150openssl x509 -req -extensions my_ext_section -extfile myext-client.cnf -days 365 -in signingReqClient.csr -CA CA-cert.pem -CAkey CA-key.pem -CAcreateserial -out client-cert.pem
151```
152The file `client-cert.pem` now contains a signed client certificate.
153
154### Create server certificate signed by given CA certificate
155For convenience we will use the same CA generated in paragraph [Create a new
156CA certificate](#Create-a-new-CA-certificate), although a different one could
157be used.
158
159Generate a new key that will be used to sign the server certificate signing
160request:
161```
162openssl genrsa -out server-key.pem 2048
163```
164Generate a certificate signing request. You will be prompted for the same
165information as during CA generation, but provide **the fully qualified
166domain name of your OpenBMC server** for the `CommonName` attribute of this
167certificate. In this example it will be `bmc.example.com`. A wildcard can
168be used to protect multiple host, for example a certificate configured for
169`*.example.com` will secure www.example.com, as well as mail.example.com,
170blog.example.com, and others.
171
172```
173openssl req -new -config openssl-server.cnf -key server-key.pem -out signingReqServer.csr
174```
175
176Sign the certificate using your `CA-cert.pem` certificate with following
177command:
178```
179openssl x509 -req -extensions my_ext_section -extfile myext-server.cnf -days 365 -in signingReqServer.csr -CA CA-cert.pem -CAkey CA-key.pem -CAcreateserial -out server-cert.pem
180```
181The file `server-cert.pem` now contains a signed client certificate.
182
183### Verify certificates
184To verify the signing request and both certificates you can use following
185commands.
186
187```
188openssl x509 -in CA-cert.pem -text -noout
189openssl x509 -in client-cert.pem -text -noout
190openssl x509 -in server-cert.pem -text -noout
191openssl req -in signingReqClient.csr -noout -text
192openssl req -in signingReqServer.csr -noout -text
193```
194
195Below are example listings that you can compare with your results. Pay special
196attention to attributes like:
197 * Validity in both certificates,
198 * `Issuer` in `client-cert.pem`, it must match to `Subject` in `CA-cert.pem`,
199 * Section *X509v3 extensions* in `client-cert.pem` it should contain proper
200values,
201 * `Public-Key` length, it cannot be less than 2048 bits.
202 * `Subject` CN in `client-cert.pem`, it should match existing OpemBMC user
203name.
204In this example it is **root**.
205 * `Subject` CN in `server-cert.pem`, it should match OpemBMC host name.
206In this example it is **bmc.example.com **. (see rfc 3280
2074.2.1.11 for name constraints)
208
209Below are fragments of generated certificates that you can compare with.
210```
211CA-cert.pem
212    Data:
213        Version: 3 (0x2)
214        Serial Number: 16242916899984461675 (0xe16a6edca3c34f6b)
215    Signature Algorithm: sha256WithRSAEncryption
216        Issuer: C=US, ST=California, L=San Francisco, O=Intel, CN=Test CA
217        Validity
218            Not Before: May 11 11:40:48 2020 GMT
219            Not After : Feb  5 11:40:48 2023 GMT
220        Subject: C=US, ST=California, L=San Francisco, O=Intel, CN=Test CA
221        Subject Public Key Info:
222            Public Key Algorithm: rsaEncryption
223                Public-Key: (2048 bit)
224                Modulus:
225                    00:d4:24:c1:1d:ac:85:8c:5b:42:e4:f8:a8:d8:7c:
226                    ...
227                    55:83:8b:aa:ac:ac:6e:e3:01:2b:ce:f7:ee:87:21:
228                    f9:2b
229                Exponent: 65537 (0x10001)
230        X509v3 extensions:
231            X509v3 Subject Key Identifier:
232                ED:FF:80:A7:F8:DA:99:7F:94:35:95:F0:92:74:1A:55:CD:DF:BA:FE
233            X509v3 Authority Key Identifier:
234                keyid:ED:FF:80:A7:F8:DA:99:7F:94:35:95:F0:92:74:1A:55:CD:DF:BA:FE
235
236            X509v3 Basic Constraints:
237                CA:TRUE
238    Signature Algorithm: sha256WithRSAEncryption
239         cc:8b:61:6a:55:60:2b:26:55:9f:a6:0c:42:b0:47:d4:ec:e0:
240         ...
241         45:47:91:62:10:bd:3e:a8:da:98:33:65:cc:11:23:95:06:1b:
242         ee:d3:78:84
243```
244```
245client-cert.pem
246    Data:
247        Version: 3 (0x2)
248        Serial Number: 10150871893861973895 (0x8cdf2434b223bf87)
249    Signature Algorithm: sha256WithRSAEncryption
250        Issuer: C=US, ST=California, L=San Francisco, O=Intel, CN=Test CA
251        Validity
252            Not Before: May 11 11:42:58 2020 GMT
253            Not After : May 11 11:42:58 2021 GMT
254        Subject: C=US, ST=California, L=San Francisco, O=Intel, CN=root
255        Subject Public Key Info:
256            Public Key Algorithm: rsaEncryption
257                Public-Key: (2048 bit)
258                Modulus:
259                    00:cf:d6:d0:a2:09:62:df:e9:a9:b1:e1:3d:7f:2f:
260                    ...
261                    30:7b:48:dc:c5:2c:3f:a9:c0:d1:b6:04:d4:1a:c8:
262                    8a:51
263                Exponent: 65537 (0x10001)
264        X509v3 extensions:
265            X509v3 Key Usage:
266                Digital Signature, Key Agreement
267            X509v3 Extended Key Usage:
268                TLS Web Client Authentication
269            X509v3 Authority Key Identifier:
270                keyid:ED:FF:80:A7:F8:DA:99:7F:94:35:95:F0:92:74:1A:55:CD:DF:BA:FE
271
272    Signature Algorithm: sha256WithRSAEncryption
273         7f:a4:57:f5:97:48:2a:c4:8e:d3:ef:d8:a1:c9:65:1b:20:fd:
274         ...
275         25:cb:5e:0a:37:fb:a1:ab:b0:c4:62:fe:51:d3:1c:1b:fb:11:
276         56:57:4c:6a
277```
278```
279server-cert.pem
280    Data:
281        Version: 3 (0x2)
282        Serial Number: 10622848005881387807 (0x936beffaa586db1f)
283    Signature Algorithm: sha256WithRSAEncryption
284        Issuer: C=US, ST=z, L=z, O=z, OU=z, CN=bmc.example.com
285        Validity
286            Not Before: May 22 13:46:02 2020 GMT
287            Not After : May 22 13:46:02 2021 GMT
288        Subject: C=US, ST=z, L=z, O=z, OU=z, CN=bmc.example.com
289        Subject Public Key Info:
290            Public Key Algorithm: rsaEncryption
291                Public-Key: (2048 bit)
292                Modulus:
293                    00:d9:34:9c:da:83:c6:eb:af:8f:e8:11:56:2a:59:
294                    ...
295                    92:60:09:fc:f9:66:82:d0:27:03:44:2f:9d:6d:c0:
296                    a5:6d
297                Exponent: 65537 (0x10001)
298        X509v3 extensions:
299            X509v3 Key Usage:
300                Digital Signature, Key Agreement
301            X509v3 Extended Key Usage:
302                TLS Web Server Authentication
303            X509v3 Authority Key Identifier:
304                keyid:5B:1D:0E:76:CC:54:B8:BF:AE:46:10:43:6F:79:0B:CA:14:5C:E0:90
305
306    Signature Algorithm: sha256WithRSAEncryption
307         bf:41:e2:2f:87:44:25:d8:54:9c:4e:dc:cc:b3:f9:af:5a:a3:
308         ...
309         ef:0f:90:a6
310
311```
312
313## Installing CA certificate on OpenBMC
314
315The CA certificate can be installed via Redfish Service. The file `CA-cert.pem`
316can not be uploaded directly but must be sent embedded in a valid JSON
317string, which requires `\`, `"`, and control characters must be escaped.
318This means all content is placed in a single string on a single line by
319encoding the line endings as `\n`. The command below prepares a whole POST
320body and puts it into a file named: `install_ca.json`.
321
322```
323cat << END > install_ca.json
324{
325  "CertificateString":"$(cat CA-cert.pem | sed -n -e '1h;1!H;${x;s/\n/\\n/g;p;}')",
326  "CertificateType": "PEM"
327}
328END
329```
330
331To install the CA certificate on the OpenBMC server post the content of
332`install_ca.json` with this command:
333
334Where `${bmc}` should be `bmc.example.com`. It is convenient to export it
335as an environment variable.
336
337```
338curl --user root:0penBmc -d @install_ca.json -k -X POST https://${bmc}/redfish/v1/Managers/bmc/Truststore/Certificates
339
340```
341
342Credentials `root:0penBmc` can be replaced with any system user name and
343password of your choice but with proper access rights to resources used here.
344
345
346After successful certificate installation you should get positive HTTP
347response and a new certificate should be available under this resource
348collection.
349```
350curl --user root:0penBmc -k https://${bmc}/redfish/v1/Managers/bmc/Truststore/Certificates
351
352```
353
354An auto-generated self-signed server certificate is already present on
355OpenBMC by default. To use the certificate signed by our CA it must be
356replaced. Additionally we must upload to OpenBMC the private key that was
357used to sign the server certificate. A proper message mody can be prepared
358the with this command:
359
360```
361cat << END > replace_cert.json
362{
363  "CertificateString":"$(cat server-key.pem server-cert.pem | sed -n -e '1h;1!H;${x;s/\n/\\n/g;p;}')",
364   "CertificateUri":
365   {
366      "@odata.id": "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/1"
367   },
368  "CertificateType": "PEM"
369}
370END
371```
372
373To replace the server certificate on the OpenBMC server post the content of
374`replace_cert.json` with this command:
375
376```
377curl --user root:0penBmc -d @replace_cert.json -k -X POST https://${bmc}/redfish/v1/CertificateService/Actions/CertificateService.ReplaceCertificate/
378
379```
380
381## Enable TLS authentication
382
383To check current state of the TLS authentication method use this command:
384
385```
386curl --user root:0penBmc -k https://${bmc}/redfish/v1/AccountService
387```
388and verify that the attribute `Oem->OpenBMC->AuthMethods->TLS` is set to true.
389
390To enable TLS authentication use this command:
391
392```
393curl --user root:0penBmc  -k -X PATCH -H "ContentType:application/json" --data '{"Oem": {"OpenBMC": {"AuthMethods": { "TLS": true} } } }' https://${bmc}/redfish/v1/AccountService
394```
395
396To disable TLS authentication use this command:
397
398```
399curl --user root:0penBmc  -k -X PATCH -H "ContentType:application/json" --data '{"Oem": {"OpenBMC": {"AuthMethods": { "TLS": false} } } }' https://${bmc}/redfish/v1/AccountService
400```
401
402Other authentication methods like basic authentication can be enabled or
403disabled as well using the same mechanism. All supported authentication
404methods are available under attribute `Oem->OpenBMC->AuthMethods` of the
405`/redfish/v1/AccountService` resource.
406
407## Using TLS to access OpenBMC resources
408
409If TLS is enabled, valid CA certificate was uploaded and the server
410certificate was replaced it should be possible to execute curl requests
411using only client certificate, key, and CA like below.
412
413```
414curl --cert client-cert.pem --key client-key.pem -vvv --cacert CA-cert.pem https://${bmc}/redfish/v1/SessionService/Sessions
415```
416## Common mistakes during TLS configuration
417
418* Invalid date and time on OpenBMC,
419
420* Testing Redfish resources, like `https://${bmc}/redfish/v1` which are
421always available without any authentication will always result with success,
422even when TLS is disabled or certificates are invalid.
423
424* Certificates do not meet the requirements. See paragraphs
425[Verify certificates](#Verify-certificates).
426
427* Attempting to load the same certificate twice will end up with an error.
428