[[certificate-authority]] == Appendix 1. Running a Certificate Authority A Certificate Authority (CA) can greatly simplify managing trust. Instead of trusting hundreds of certificates individually, a client only needs to trust the certificate from the CA. When the CA signs other node certificates, nodes that trust the CA also trust other nodes with certificates signed by the CA. NOTE: This procedure is an example of how to set up a CA and cannot universally address a wide array of security needs. To properly secure a production site, consult your organization's security experts to discuss requirements. To run a CA, generate a public and private key, and wrap the public key in a certificate that clients will trust. Node certificates are sent in a _Certificate Signing Request_ (CSR). Your CA signs the CSR, producing a newly signed certificate that you install on the node. IMPORTANT: Because a Certificate Authority is a central point for trust, the private keys to the CA must be protected from compromise. === Setting up a CA To set up a CA, generate a private and public key pair and build a certificate from the public key. This procedure uses OpenSSL to create the CA certificate and sign CSRs. First, set up a file structure and configuration template for the CA. ==== Creating the Certificate Authority Create the `ca` directory along with the `private`, `certs`, and `conf` subdirectories, then populate the required `serial` and `index.txt` files. [source,shell] -------------------------------------------------- mkdir -p ca/private ca/certs ca/conf cd ca echo '01' > serial touch index.txt -------------------------------------------------- A configuration template file specifies several configurations settings that cannot be passed from the command line. The following sample configuration file highlights fields of particular interest. Create the `ca/conf/caconfig.cnf` file with contents similar to the following: [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 the certificates signed by a CA must expire before the CA certificate expires. <4> Certificate Defaults: The `OrganizationName`, `localityName`, `stateOrProvinceName`, `countryName`, and `emailAddress` fields are informational. The settings in the above example are the defaults for these values. === Create a CA Certificate In the `ca` directory, create the CA certificate and export the certificate. The following command creates and signs the CA certificate, resulting in a _self-signed_ certificate that establishes the CA as an authority. [source,shell] ------------------------------------------------------------------------------ openssl req -new -x509 -extensions v3_ca \ -keyout private/cakey.pem \ <1> -out certs/cacert.pem \ <2> -days 1460 \ <3> -config conf/caconfig.cnf ------------------------------------------------------------------------------ <1> The path to the file where the private key is stored. <2> The path to the file where the CA certificate is stored. <3> The duration, in days, that the CA certificate is valid. After the expiration, trust in the CA is revoked and requires generation of a new CA certificate and re-signing of certificates. The command prompts you to supply information to place in the certificate. You will have to pick a PEM passphrase to encrypt the private key for your CA. WARNING: You cannot recover the CA without this passphrase. The following shows a sample interaction with the command above: [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 ------------------------------------------------------------------------------------------------------------------------ You now have a CA private key and a CA certificate (which includes the public key). You can now distribute the CA certificate and sign CSRs. [[sign-csr]] ==== Signing a CSR Signing a certificate with the CA means that the CA vouches for the owner of the certificate. The private key that is linked to the certificate proves certificate ownership. The CSR includes the certificate. Signing a CSR results in a new certificate that includes the old certificate, the CA certificate, and a signature. This resulting certificate is a _certificate chain_. Send the certificate chain back to the private key's holder for use on the node. TIP: If you do not yet have a CSR, you need to follow the steps described in <> and <> before continuing. The following commands sign the CSR with the CA: [source,shell] ----------------------------------------------------------------------------- openssl ca -in node01.csr -notext -out node01-signed.crt -config conf/caconfig.cnf -extensions v3_req ----------------------------------------------------------------------------- The newly signed certificate chain `node01-signed.crt` can now be sent to the node to be imported back into its keystore. NOTE: If you plan on allowing more than one certificate per common name, OpenSSL must be configured to allow non-unique subjects. This is necessary when running multiple nodes on a single host and requesting unique certificates per node. Edit the `ca/index.txt.attr` file and ensure the `unique_subject` line matches below: [source, shell] ----------------------- unique_subject = no ----------------------- These steps provide you with a basic CA that can sign certificates for your Shield nodes. OpenSSL is an extremely powerful tool and there are many more options available for your certification strategy, such as intermediate authorities and restrictions on the use of certificates. There are many tutorials on the internet for these advanced options, and the OpenSSL website details all the intricacies.