Added reference to RFC2818 along with guidance to add subjectAltNames… (#748)
* Added reference to RFC2818 along with guidance to add subjectAltNames ext when generating certs Signed-off-by: jeffhuss <jeffhuss@amazon.com> * Cleaned up wording in cert generation section Wording before was redundant and there was a fragment sentence left in. I cleaned that up to make it readable. Signed-off-by: jeffhuss <jeffhuss@amazon.com> * Spot fixes of terms, added SAN guidance and references and cleaned up sample script Signed-off-by: jeffhuss <jeffhuss@amazon.com> * Updated sample script to clean up the extension files too Signed-off-by: jeffhuss <jeffhuss@amazon.com> * Cleaned up formatting, removed SAN reference in admin cert steps Signed-off-by: jeffhuss <jeffhuss@amazon.com> * Removed extra word from node cert steps Signed-off-by: jeffhuss <jeffhuss@amazon.com> * Removed reference to admin.ext from sample script since it doesn't exist anymore Signed-off-by: jeffhuss <jeffhuss@amazon.com>
This commit is contained in:
parent
7d8048f026
commit
9f3434c10c
|
@ -26,7 +26,7 @@ brew install openssl
|
|||
|
||||
## Generate a private key
|
||||
|
||||
The first step in this process is to generate a private key using the `genrsa` command. As the name suggests, you should keep this file private.
|
||||
The first step in this process is to generate a private key using the `openssl genrsa` command. As the name suggests, you should keep this file private.
|
||||
|
||||
Private keys must be of sufficient length to be secure, so specify `2048`:
|
||||
|
||||
|
@ -39,7 +39,7 @@ You can optionally add the `-aes256` option to encrypt the key using the AES-256
|
|||
|
||||
## Generate a root certificate
|
||||
|
||||
Next, use the key to generate a self-signed certificate for the root CA:
|
||||
Next, use the private key to generate a self-signed certificate for the root CA:
|
||||
|
||||
```bash
|
||||
openssl req -new -x509 -sha256 -key root-ca-key.pem -out root-ca.pem -days 730
|
||||
|
@ -75,7 +75,11 @@ openssl req -new -key admin-key.pem -out admin.csr
|
|||
|
||||
Follow the prompts to fill in the details. You don't need to specify a challenge password. As noted in the [OpenSSL Cookbook](https://www.feistyduck.com/books/openssl-cookbook/){:target='\_blank'}, "Having a challenge password does not increase the security of the CSR in any way."
|
||||
|
||||
Finally, generate the certificate itself:
|
||||
If you generate TLS certificates and have enabled hostname verification by setting `plugins.security.ssl.transport.enforce_hostname_verification` to `true` (default), be sure to specify a common name (CN) for each certificate signing request (CSR) that matches the corresponding DNS A record of the intended node.
|
||||
|
||||
If you want to use the same node certificate on all nodes (not recommended), set hostname verification to `false`. For more information, see [Configure TLS certificates]({{site.url}}{{site.baseurl}}/security-plugin/configuration/tls#advanced-hostname-verification-and-dns-lookup).
|
||||
|
||||
Now that the private key and signing request have been created, generate the certificate:
|
||||
|
||||
```bash
|
||||
openssl x509 -req -in admin.csr -CA root-ca.pem -CAkey root-ca-key.pem -CAcreateserial -sha256 -out admin.pem -days 730
|
||||
|
@ -86,9 +90,40 @@ Just like the root certificate, use the `-days` option to specify an expiration
|
|||
|
||||
## (Optional) Generate node and client certificates
|
||||
|
||||
Follow the steps in [Generate an admin certificate](#generate-an-admin-certificate) with new file names to generate a new certificate for each node and as many client certificates as you need. For example, you might generate one client certificate for OpenSearch Dashboards and another for a Python client. Each certificate should use its own private key.
|
||||
Similar to the steps in [Generate an admin certificate](#generate-an-admin-certificate), you will generate keys and CSRs with new file names for each node and as many client certificates as you need. For example, you might generate one client certificate for OpenSearch Dashboards and another for a Python client. Each certificate should use its own private key and should be generated from a unique CSR with matching SAN extension specific to the intended host. A SAN extension is not needed for the admin cert because that cert is not tied to a specific host.
|
||||
|
||||
If you generate node certificates and have `plugins.security.ssl.transport.enforce_hostname_verification` set to `true` (default), be sure to specify a common name (CN) for the certificate that matches the hostname of the intended node. If you want to use the same node certificate on all nodes (not recommended), set hostname verification to `false`. For more information, see [Configure TLS certificates]({{site.url}}{{site.baseurl}}/security-plugin/configuration/tls#advanced-hostname-verification-and-dns-lookup).
|
||||
To generate a node or client certificate, first create a new key:
|
||||
|
||||
```bash
|
||||
openssl genrsa -out node1-key-temp.pem 2048
|
||||
```
|
||||
|
||||
Then convert that key to PKCS#8 format for use in Java using a PKCS#12-compatible algorithm (3DES):
|
||||
|
||||
```bash
|
||||
openssl pkcs8 -inform PEM -outform PEM -in node1-key-temp.pem -topk8 -nocrypt -v1 PBE-SHA1-3DES -out node1-key.pem
|
||||
```
|
||||
|
||||
Next, create the CSR:
|
||||
|
||||
```bash
|
||||
openssl req -new -key node1-key.pem -out node1.csr
|
||||
```
|
||||
|
||||
For all host and client certificates, you should specify a subject alternative name (SAN) to ensure compliance with [RFC 2818 (HTTP Over TLS)](https://datatracker.ietf.org/doc/html/rfc2818). The SAN should match the corresponding CN so that both refer to the same DNS A record.
|
||||
{: .note }
|
||||
|
||||
Before generating a signed certificate, create a SAN extension file which describes the DNS A record for the host:
|
||||
|
||||
```bash
|
||||
echo 'subjectAltName=DNS:node1.dns.a-record' > node1.ext
|
||||
```
|
||||
|
||||
Generate the certificate:
|
||||
|
||||
```bash
|
||||
openssl x509 -req -in node1.csr -CA root-ca.pem -CAkey root-ca-key.pem -CAcreateserial -sha256 -out node1.pem -days 730 -extfile node1.ext
|
||||
```
|
||||
|
||||
|
||||
## Sample script
|
||||
|
@ -99,36 +134,42 @@ If you already know the certificate details and don't want to specify them inter
|
|||
#!/bin/sh
|
||||
# Root CA
|
||||
openssl genrsa -out root-ca-key.pem 2048
|
||||
openssl req -new -x509 -sha256 -key root-ca-key.pem -subj "/C=CA/ST=ONTARIO/L=TORONTO/O=ORG/OU=UNIT/CN=ROOT" -out root-ca.pem -days 730
|
||||
openssl req -new -x509 -sha256 -key root-ca-key.pem -subj "/C=CA/ST=ONTARIO/L=TORONTO/O=ORG/OU=UNIT/CN=root.dns.a-record" -out root-ca.pem -days 730
|
||||
# Admin cert
|
||||
openssl genrsa -out admin-key-temp.pem 2048
|
||||
openssl pkcs8 -inform PEM -outform PEM -in admin-key-temp.pem -topk8 -nocrypt -v1 PBE-SHA1-3DES -out admin-key.pem
|
||||
openssl req -new -key admin-key.pem -subj "/C=CA/ST=ONTARIO/L=TORONTO/O=ORG/OU=UNIT/CN=ADMIN" -out admin.csr
|
||||
openssl req -new -key admin-key.pem -subj "/C=CA/ST=ONTARIO/L=TORONTO/O=ORG/OU=UNIT/CN=A" -out admin.csr
|
||||
openssl x509 -req -in admin.csr -CA root-ca.pem -CAkey root-ca-key.pem -CAcreateserial -sha256 -out admin.pem -days 730
|
||||
# Node cert 1
|
||||
openssl genrsa -out node1-key-temp.pem 2048
|
||||
openssl pkcs8 -inform PEM -outform PEM -in node1-key-temp.pem -topk8 -nocrypt -v1 PBE-SHA1-3DES -out node1-key.pem
|
||||
openssl req -new -key node1-key.pem -subj "/C=CA/ST=ONTARIO/L=TORONTO/O=ORG/OU=UNIT/CN=node1.example.com" -out node1.csr
|
||||
openssl x509 -req -in node1.csr -CA root-ca.pem -CAkey root-ca-key.pem -CAcreateserial -sha256 -out node1.pem -days 730
|
||||
openssl req -new -key node1-key.pem -subj "/C=CA/ST=ONTARIO/L=TORONTO/O=ORG/OU=UNIT/CN=node1.dns.a-record" -out node1.csr
|
||||
echo 'subjectAltName=DNS:node1.dns.a-record' > node1.ext
|
||||
openssl x509 -req -in node1.csr -CA root-ca.pem -CAkey root-ca-key.pem -CAcreateserial -sha256 -out node1.pem -days 730 -extfile node1.ext
|
||||
# Node cert 2
|
||||
openssl genrsa -out node2-key-temp.pem 2048
|
||||
openssl pkcs8 -inform PEM -outform PEM -in node2-key-temp.pem -topk8 -nocrypt -v1 PBE-SHA1-3DES -out node2-key.pem
|
||||
openssl req -new -key node2-key.pem -subj "/C=CA/ST=ONTARIO/L=TORONTO/O=ORG/OU=UNIT/CN=node2.example.com" -out node2.csr
|
||||
openssl x509 -req -in node2.csr -CA root-ca.pem -CAkey root-ca-key.pem -CAcreateserial -sha256 -out node2.pem -days 730
|
||||
openssl req -new -key node2-key.pem -subj "/C=CA/ST=ONTARIO/L=TORONTO/O=ORG/OU=UNIT/CN=node2.dns.a-record" -out node2.csr
|
||||
echo 'subjectAltName=DNS:node2.dns.a-record' > node2.ext
|
||||
openssl x509 -req -in node2.csr -CA root-ca.pem -CAkey root-ca-key.pem -CAcreateserial -sha256 -out node2.pem -days 730 -extfile node2.ext
|
||||
# Client cert
|
||||
openssl genrsa -out client-key-temp.pem 2048
|
||||
openssl pkcs8 -inform PEM -outform PEM -in client-key-temp.pem -topk8 -nocrypt -v1 PBE-SHA1-3DES -out client-key.pem
|
||||
openssl req -new -key client-key.pem -subj "/C=CA/ST=ONTARIO/L=TORONTO/O=ORG/OU=UNIT/CN=CLIENT" -out client.csr
|
||||
openssl x509 -req -in client.csr -CA root-ca.pem -CAkey root-ca-key.pem -CAcreateserial -sha256 -out client.pem -days 730
|
||||
openssl req -new -key client-key.pem -subj "/C=CA/ST=ONTARIO/L=TORONTO/O=ORG/OU=UNIT/CN=client.dns.a-record" -out client.csr
|
||||
echo 'subjectAltName=DNS:client.dns.a-record' > client.ext
|
||||
openssl x509 -req -in client.csr -CA root-ca.pem -CAkey root-ca-key.pem -CAcreateserial -sha256 -out client.pem -days 730 -extfile client.ext
|
||||
# Cleanup
|
||||
rm admin-key-temp.pem
|
||||
rm admin.csr
|
||||
rm node1-key-temp.pem
|
||||
rm node1.csr
|
||||
rm node1.ext
|
||||
rm node2-key-temp.pem
|
||||
rm node2.csr
|
||||
rm node2.ext
|
||||
rm client-key-temp.pem
|
||||
rm client.csr
|
||||
rm client.ext
|
||||
```
|
||||
|
||||
|
||||
|
@ -138,16 +179,16 @@ You must specify the distinguished names (DNs) for all admin and node certificat
|
|||
|
||||
```yml
|
||||
plugins.security.authcz.admin_dn:
|
||||
- 'CN=ADMIN,OU=UNIT,O=ORG,L=TORONTO,ST=ONTARIO,C=CA'
|
||||
- 'CN=A,OU=UNIT,O=ORG,L=TORONTO,ST=ONTARIO,C=CA'
|
||||
plugins.security.nodes_dn:
|
||||
- 'CN=node1.example.com,OU=UNIT,O=ORG,L=TORONTO,ST=ONTARIO,C=CA'
|
||||
- 'CN=node2.example.com,OU=UNIT,O=ORG,L=TORONTO,ST=ONTARIO,C=CA'
|
||||
- 'CN=node1.dns.a-record,OU=UNIT,O=ORG,L=TORONTO,ST=ONTARIO,C=CA'
|
||||
- 'CN=node2.dns.a-record,OU=UNIT,O=ORG,L=TORONTO,ST=ONTARIO,C=CA'
|
||||
```
|
||||
|
||||
But if you look at the `subject` of the certificate after creating it, you might see different formatting:
|
||||
|
||||
```
|
||||
subject=/C=CA/ST=ONTARIO/L=TORONTO/O=ORG/OU=UNIT/CN=node1.example.com
|
||||
subject=/C=CA/ST=ONTARIO/L=TORONTO/O=ORG/OU=UNIT/CN=node1.dns.a-record
|
||||
```
|
||||
|
||||
If you compare this string to the ones above, you can see that you need to invert the order of elements and use commas rather than slashes. Enter this command to get the correct string:
|
||||
|
@ -181,10 +222,10 @@ plugins.security.ssl.http.pemcert_filepath: node1.pem
|
|||
plugins.security.ssl.http.pemkey_filepath: node1-key.pem
|
||||
plugins.security.ssl.http.pemtrustedcas_filepath: root-ca.pem
|
||||
plugins.security.authcz.admin_dn:
|
||||
- 'CN=ADMIN,OU=UNIT,O=ORG,L=TORONTO,ST=ONTARIO,C=CA'
|
||||
- 'CN=A,OU=UNIT,O=ORG,L=TORONTO,ST=ONTARIO,C=CA'
|
||||
plugins.security.nodes_dn:
|
||||
- 'CN=node1.example.com,OU=UNIT,O=ORG,L=TORONTO,ST=ONTARIO,C=CA'
|
||||
- 'CN=node2.example.com,OU=UNIT,O=ORG,L=TORONTO,ST=ONTARIO,C=CA'
|
||||
- 'CN=node1.dns.a-record,OU=UNIT,O=ORG,L=TORONTO,ST=ONTARIO,C=CA'
|
||||
- 'CN=node2.dns.a-record,OU=UNIT,O=ORG,L=TORONTO,ST=ONTARIO,C=CA'
|
||||
```
|
||||
|
||||
For more information about adding and using these certificates in your own setup, see [Docker security configuration]({{site.url}}{{site.baseurl}}//opensearch/install/docker-security/), [Configure TLS certificates]({{site.url}}{{site.baseurl}}/security-plugin/configuration/tls/), and [Client certificate authentication]({{site.url}}{{site.baseurl}}/security-plugin/configuration/client-auth/).
|
||||
|
|
Loading…
Reference in New Issue