[[certificate-authority]]
== Setting Up a Certificate Authority

You can set up your own Certificate Authority (CA) to sign node certificates. Using a CA 
makes it easier to manage trust within your cluster than using self-signed certificates. Each node 
only needs to trust the CA, rather that trusting all of the other nodes' certificates individually. When nodes are added to the cluster, as long as their certificates are signed by a trusted CA, the new nodes are trusted automatically. In contrast, if you use self-signed certificates, you would have to manually configure each node to trust the new node and restart Elasticsearch. 

This topic shows how you can use https://www.openssl.org/[OpenSSL] to create a self-signed CA 
certificate and sign CSRs. While it demonstrates how you can set up a CA, it does not necessarily 
address your organization's particular security requirements. Before moving to production, you 
should consult your organization's security  experts to discuss the security requirements for your 
use case. 

IMPORTANT: Because a Certificate Authority is a central point of trust, the private keys to the 
		   CA must be protected from compromise.

To set up a CA:

. Create the directory structure where the CA configuration and certificates will be stored. You 
need to create a `ca` directory and three subdirectories: `private`, `certs`, and `conf`.
+
[source,shell]
--------------------------------------------------
mkdir -p ca/private ca/certs ca/conf
--------------------------------------------------

. Populate two required files, `serial` and `index.txt`.
+
[source,shell]
--------------------------------------------------
cd ca
echo '01' > serial
touch index.txt
--------------------------------------------------

. Create a CA configuration template and store it in `conf/caconfig.cnf`. You use the 
configuration template to set options for the CA that cannot be passed in from the
command line. The following template defines a basic CA configuration you 
can use as a starting point.
+
[source,shell]
-------------------------------------------------------------------------------------
#..................................
[ ca ]
default_ca = CA_default
[ CA_default ]
copy_extensions = copy <1>
dir = /PATH/TO/YOUR/DIR/ca <2>
serial = $dir/serial
database = $dir/index.txt
new_certs_dir = $dir/certs
certificate = $dir/certs/cacert.pem
private_key = $dir/private/cakey.pem
default_days = 712 <3>
default_md = sha256
preserve = no
email_in_dn = no
x509_extensions = v3_ca
name_opt = ca_default
cert_opt = ca_default
policy = policy_anything
[ policy_anything ]
countryName             = optional
stateOrProvinceName     = optional
localityName            = optional
organizationName        = optional
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional
[ req ]
default_bits = 2048 # Size of keys
default_keyfile = key.pem # name of generated keys
default_md = sha256 # message digest algorithm
string_mask = nombstr # permitted characters
distinguished_name = req_distinguished_name
req_extensions = v3_req
[ req_distinguished_name ]
# Variable name Prompt string
#------------------------- ----------------------------------
0.organizationName = Organization Name (company)
organizationalUnitName = Organizational Unit Name (department, division)
emailAddress = Email Address
emailAddress_max = 40
localityName = Locality Name (city, district)
stateOrProvinceName = State or Province Name (full name)
countryName = Country Name (2 letter code)
countryName_min = 2
countryName_max = 2
commonName = Common Name (hostname, IP, or your name)
commonName_max = 64
# Default values for the above, for consistency and less typing.
# Variable name Value
#------------------------ ------------------------------
0.organizationName_default = Elasticsearch Test Org <4>
localityName_default = Amsterdam
stateOrProvinceName_default = Amsterdam
countryName_default = NL
emailAddress_default = cacerttest@YOUR.COMPANY.TLD
[ v3_ca ]
basicConstraints = CA:TRUE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer:always
[ v3_req ]
basicConstraints = CA:FALSE
subjectKeyIdentifier = hash
---------------------------------------------------------------------------------------
<1> Copy extensions: Copies all X509 V3 extensions from a Certificate Signing Request into the 
signed certificate. With the value set to `copy`, you need to ensure the extensions and their 
values are valid for the certificate being requested prior to signing the certificate.
<2> CA directory: Add the full path to this newly created CA.
<3> Certificate validity period:  The default number of days that a certificate signed by this 
CA is valid for. Note that certificates signed by a CA must expire before the CA certificate 
expires.
<4> Certificate defaults: The `OrganizationName`, `localityName`, `stateOrProvinceName`, 
`countryName`, and `emailAddress` fields specify the default Distinguished Name information.

. Generate a self-signed CA certificate to establish your CA as an authority. For example, the following command generates a key and certificate using the `caconfig.cnf` template. You specify 
where you want to store the CA's private key and certificate with the `-keyout` and `-out` options, and specify how long the certificate is valid with the `-days` option.
+
[source,shell]
------------------------------------------------------------------------------
openssl req -new -x509 -extensions v3_ca -keyout private/cakey.pem -out certs/cacert.pem -days 1460  -config conf/caconfig.cnf
------------------------------------------------------------------------------
+
NOTE: When the CA certificate expires, trust in the CA is revoked and you need to generate a new CA certificate and re-sign your node certificates.
+
When you run `openssl` to generate a CA certificate, you are prompted to enter a PEM passphrase to encrypt the CA's private key and can override the default Distinguished Name information.
+
WARNING: You cannot recover the CA without the PEM passphrase.
+
The following example shows what the interaction looks like:
+
[source,shell]
---------------------------------------------------------------------------------------------------
openssl req -new -x509 -extensions v3_ca -keyout private/cakey.pem -out certs/cacert.pem -days 1460 -config conf/caconfig.cnf
Generating a 2048 bit RSA private key
.....................++++++
.......++++++
writing new private key to 'private/cakey.pem'
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
#-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
#-----
Organization Name (company) [Elasticsearch Test Org]:
Organizational Unit Name (department, division) []:.
Email Address [cacerttest@YOUR.COMPANY.TLD]:.
Locality Name (city, district) [Amsterdam]:.
State or Province Name (full name) [Amsterdam]:.
Country Name (2 letter code) [NL]:.
Common Name (hostname, IP, or your name) []:Elasticsearch Test CA
---------------------------------------------------------------------------------------------------

Once you've generated a certificate for your CA, you can use it to enable trust between your nodes. 
You sign each node's certificate using your CA, and install the CA certificate and signed node
certificate in each node's keystore or truststore. For more information, see 
<<sign-csr, Signing CSRs>> and <<installing-node-certificates, Installing Node Certificates>>.

[float]
[[sign-csr]]
=== Signing CSRs

You sign a node's certificate to vouch for that node's identity. If a node trusts your CA 
certificate, it automatically trusts any certificates you sign. 

To sign a node's certificate:

. <<generate-csr, Generate a certificate signing request (CSR)>> from the node. 

. Use your CA to sign the CSR using `openssl`. For example, the following command signs
the `node01.csr` and saves the signed certificate in `node01-signed.crt`. You must specify 
your CA's configuration file with the `-config` option.
+
[source,shell]
-----------------------------------------------------------------------------
openssl ca -in node01.csr -notext -out node01-signed.crt -config conf/caconfig.cnf -extensions v3_req
-----------------------------------------------------------------------------
+
The signed certificate contains the node's original unsigned certificate, your CA certificate, and 
a signature.

Once you've signed the CSR, you need to <<install-signed-cert, install the signed 
certificate>> in the node's keystore. 


