Project: KubeDB by AppsCode (App Definition and Development / Database)
File: issue-certificate.md

title: X-Pack Certificate menu: docs_{{ .version }}: identifier: es-issue-certificate-x-pack name: Issue Certificate parent: es-x-pack weight: 25 menuname: docs{{ .version }} sectionmenuid: guides New to KubeDB? Please start . X-Pack requires certificates to enable TLS. KubeDB creates necessary certificates automatically. However, if you want to use your own certificates, you can provide them through `spec.certificateSecret` field of Elasticsearch object. This tutorial will show you how to generate certificates for X-Pack and use them with Elasticsearch database. In KubeDB Elasticsearch, keystore and truststore files in JKS format are used instead of certificates and private keys in PEM format. KubeDB applies same truststore for both transport layer TLS and REST layer TLS. But, KubeDB distinguishes between the following types of keystore for security purpose. transport layer keystore are used to identify and secure traffic between Elasticsearch nodes on the transport layer http layer keystore are used to identify Elasticsearch clients on the REST and transport layer. At first, you need to have a Kubernetes cluster, and the kubectl command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using . Now, install KubeDB cli on your workstation and KubeDB operator in your cluster following the steps . To keep things isolated, this tutorial uses a separate namespace called `demo` throughout this tutorial. ```bash $ kubectl create ns demo namespace/demo created ``` You also need to have and Java keytool for generating all required artifacts. In order to find out if you have OpenSSL installed, open a terminal and type ```bash $ openssl version OpenSSL 1.0.2g 1 Mar 2016 ``` Make sure its version 1.0.1k or higher And check keytool by calling ```bash keytool ``` If already installed, it will print a list of available commands. To keep generated files separated, open a new terminal and create a directory `/tmp/kubedb/certs` ```bash mkdir -p /tmp/kubedb/certs cd /tmp/kubedb/certs ``` Note: YAML files used in this tutorial are stored in folder in GitHub repository . First, we need root certificate to sign other server & client certificates. And also this certificate is imported as truststore. You need to follow these steps Get root certificate configuration file ```bash $ wget https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/elasticsearch/x-pack/openssl-config/openssl-ca.ini ``` ```ini [ ca ] defaultca = CAdefault [ CA_default ] private_key = root-key.pem default_days = 1000 # how long to certify for default_md = sha256 # use public key default MD copy_extensions = copy # Required to copy SANs from CSR to cert [ req ] prompt = no default_bits = 4096 distinguishedname = cadistinguished_name [ cadistinguishedname ] O = Elasticsearch Operator CN = KubeDB Com. Root CA ``` Set a password of your keystore and truststore files ```bash $ export KEY_PASS=secret ``` > Note: You need to provide this KEYPASS in your Secret as `keypass` Generate private key and certificate ```bash $ openssl req -x509 -config openssl-ca.ini -newkey rsa:4096 -sha256 -nodes -out root.pem -keyout root-key.pem -batch -passin "pass:$KEY_PASS" ``` Here, `root-key.pem` holds Private Key `root.pem`holds CA Certificate Finally, import certificate as keystore ```bash $ keytool -import -file root.pem -keystore root.jks -storepass $KEY_PASS -srcstoretype pkcs12 -noprompt ``` Here, `root.jks` is truststore for Elasticsearch Here are the steps for generating certificate and keystore for Elasticsearch: Get certificate configuration file Generate private key and certificate signing request (CSR) Sign certificate using root certificate Generate PKCS12 file using root certificate Import PKCS12 as keystore You need to follow these steps to generate three

To sign certificate, we need another configuration file. ```bash $ wget https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/info.version" >}}/docs/examples/elasticsearch/x-pack/openssl-config/openssl-sign.ini ``` ```ini [ ca ] defaultca = CAdefault [ CA_default ] base_dir = . certificate = $base_dir/root.pem # The CA certifcate privatekey = $basedir/root-key.pem # The CA private key newcertsdir = $base_dir # Location for new certs after signing database = $base_dir/index.txt # Database index file serial = $base_dir/serial.txt # The current serial number unique_subject = no # Set to 'no' to allow creation of several certificates with same subject. default_days = 1000 # how long to certify for default_md = sha256 # use public key default MD emailindn = no copy_extensions = copy # Required to copy SANs from CSR to cert [ req ] default_bits = 4096 default_keyfile = root-key.pem distinguishedname = cadistinguished_name [ cadistinguishedname ] O = Elasticsearch Operator CN = KubeDB Com. Root CA [ signing_req ] keyUsage = digitalSignature, keyEncipherment [ signing_policy ] organizationName = optional commonName = supplied ``` Here, `certificate` denotes CA certificate path `private_key` denotes CA key path Also, you need to create a `index.txt` file and `serial.txt` file with value `01` ```bash touch index.txt echo '01' > serial.txt ``` Following configuration is used to generate CSR for node certificate. ```ini [ req ] prompt = no default_bits = 4096 distinguishedname = nodedistinguished_name reqextensions = nodereq_extensions [ nodedistinguishedname ] O = Elasticsearch Operator CN = custom-certificate-es-ssl [ nodereqextensions ] keyUsage = digitalSignature, keyEncipherment extendedKeyUsage = serverAuth, clientAuth subjectAltName = @alternate_names [ alternate_names ] DNS.1 = localhost RID.1 = 1.2.3.4.5.5 ``` Here, `RID.1=1.2.3.4.5.5` is used in node certificate. All certificates with registeredID `1.2.3.4.5.5` is considered as valid certificate for transport layer. Now run following commands ```bash $ wget https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/elasticsearch/x-pack/openssl-config/openssl-node.ini $ openssl req -config openssl-node.ini -newkey rsa:4096 -sha256 -nodes -out node-csr.pem -keyout node-key.pem $ openssl ca -config openssl-sign.ini -batch -policy signingpolicy -extensions signingreq -out node.pem -infiles node-csr.pem $ openssl pkcs12 -export -certfile root.pem -inkey node-key.pem -in node.pem -password "pass:$KEY_PASS" -out node.pkcs12 $ keytool -importkeystore -srckeystore node.pkcs12 -storepass $KEYPASS -srcstoretype pkcs12 -srcstorepass $KEYPASS -destkeystore node.jks -deststoretype pkcs12 ``` Generated `node.jks` will be used as keystore for transport layer TLS. Following configuration is used to generate CSR for client certificate. ```ini [ req ] prompt = no default_bits = 4096 distinguishedname = clientdistinguished_name reqextensions = clientreq_extensions [ clientdistinguishedname ] O = Elasticsearch Operator CN = custom-certificate-es-ssl [ clientreqextensions ] keyUsage = digitalSignature, keyEncipherment extendedKeyUsage = serverAuth, clientAuth subjectAltName = @alternate_names [ alternate_names ] DNS.1 = localhost DNS.2 = custom-certificate-es-ssl.demo.svc ``` Here, `custom-certificate-es-ssl` is used as a Common Name so that host `custom-certificate-es-ssl` is verified as valid Client. Now run following commands ```bash $ wget https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/elasticsearch/x-pack/openssl-config/openssl-client.ini $ openssl req -config openssl-client.ini -newkey rsa:4096 -sha256 -nodes -out client-csr.pem -keyout client-key.pem $ openssl ca -config openssl-sign.ini -batch -policy signingpolicy -extensions signingreq -out client.pem -infiles client-csr.pem $ openssl pkcs12 -export -certfile root.pem -inkey client-key.pem -in client.pem -password "pass:$KEY_PASS" -out client.pkcs12 $ keytool -importkeystore -srckeystore client.pkcs12 -storepass $KEYPASS -srcstoretype pkcs12 -srcstorepass $KEYPASS -destkeystore client.jks -deststoretype pkcs12 ``` Generated `client.jks` will be used as keystore for http layer TLS. Now create a Secret with these certificates to use in your Elasticsearch object. ```bash $ kubectl create secret generic -n demo custom-certificate-es-ssl-cert \ --from-file=root.pem \ --from-file=root.jks \ --from-file=node.jks \ --from-file=client.jks \ --from-literal=keypass=$KEYPASS secret/custom-certificate-es-ssl-cert created ``` Note: `root.pem` is added in Secret so that user can use these to connect Elasticsearch Use this Secret `custom-certificate-es-ssl-cert` in your Elasticsearch

Below is the Elasticsearch object created in this tutorial. ```yaml apiVersion: kubedb.com/v1alpha2 kind: Elasticsearch metadata: name: custom-certificate-es-ssl namespace: demo spec: version: xpack-8.11.1 enableSSL: true storage: storageClassName: "standard" accessModes: ReadWriteOnce resources: requests: storage: 1Gi ``` Here, `spec.certificateSecret` specifies Secret with certificates those will be used in Elasticsearch database. Create example above with following command ```bash $ kubectl create -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/elasticsearch/x-pack/custom-certificate-es-ssl.yaml elasticsearch.kubedb.com/custom-certificate-es-ssl created ``` KubeDB operator sets the `status.phase` to `Running` once the database is successfully created. ```bash $ kubectl get es -n demo custom-certificate-es-ssl -o wide NAME VERSION STATUS AGE custom-certificate-es-ssl 7.3.2 Running 1m ``` We need to provide `root.pem` to connect to elasticsearch nodes. Let's forward port 9200 of `custom-certificate-es-ssl-0` pod. Run following command in a separate terminal, ```bash $ kubectl port-forward -n demo custom-certificate-es-ssl-0 9200 Forwarding from 127.0.0.1:9200 -> 9200 Forwarding from [::1]:9200 -> 9200 ``` Now, we can connect with the database at `localhost:9200`. Connection information: Address: `localhost:9200` Username: Run following command to get username ```bash $ kubectl get secrets -n demo custom-certificate-es-ssl-auth -o jsonpath='{.data.\ADMIN_USERNAME}' | base64 -d elastic ``` Password: Run following command to get password ```bash $ kubectl get secrets -n demo custom-certificate-es-ssl-auth -o jsonpath='{.data.\ADMIN_PASSWORD}' | base64 -d uft73z6j ``` Root CA: Run following command to get `root.pem` file ```bash $ kubectl get secrets -n demo custom-certificate-es-ssl-cert -o jsonpath='{.data.\root\.pem}' | base64 --decode > root.pem ``` Now, let's check health of our Elasticsearch database. ```bash $ curl --user "elastic:uft73z6j" "https://localhost:9200/_cluster/health?pretty" --cacert root.pem ``` ```json { "cluster_name" : "custom-certificate-es-ssl", "status" : "green", "timed_out" : false, "numberofnodes" : 1, "numberofdata_nodes" : 1, "activeprimaryshards" : 0, "active_shards" : 0, "relocating_shards" : 0, "initializing_shards" : 0, "unassigned_shards" : 0, "delayedunassignedshards" : 0, "numberofpending_tasks" : 0, "numberofinflightfetch" : 0, "taskmaxwaitinginqueue_millis" : 0, "activeshardspercentasnumber" : 100.0 } ``` Additionally, to query the settings about xpack, ```json $ curl --user "elastic:uft73z6j" "https://localhost:9200/nodes/all/settings?pretty" --cacert root.pem { "_nodes" : { "total" : 1, "successful" : 1, "failed" : 0 }, "cluster_name" : "custom-certificate-es-ssl", "nodes" : { "L75i6kmaRRWqy7-IqnDbbA" : { "name" : "custom-certificate-es-ssl-0", "transport_address" : "10.4.0.166:9300", "host" : "10.4.0.166", "ip" : "10.4.0.166", "version" : "7.3.2", "build_flavor" : "default", "build_type" : "docker", "build_hash" : "508c38a", "roles" : [ "master", "data", "ingest" ], "attributes" : { "ml.machine_memory" : "7841263616", "xpack.installed" : "true", "ml.maxopenjobs" : "20" }, "settings" : { "cluster" : { "initialmasternodes" : "custom-certificate-es-ssl-0", "name" : "custom-certificate-es-ssl" }, "node" : { "name" : "custom-certificate-es-ssl-0", "attr" : { "xpack" : { "installed" : "true" }, "ml" : { "machine_memory" : "7841263616", "maxopenjobs" : "20" } }, "data" : "true", "ingest" : "true", "master" : "true" }, "path" : { "logs" : "/usr/share/elasticsearch/logs", "home" : "/usr/share/elasticsearch" }, "discovery" : { "seed_hosts" : "custom-certificate-es-ssl-master" }, "client" : { "type" : "node" }, "http" : { "compression" : "false", "type" : "security4", "type.default" : "netty4" }, "transport" : { "type" : "security4", "features" : { "x-pack" : "true" }, "type.default" : "netty4" }, "xpack" : { "security" : { "http" : { "ssl" : { "enabled" : "true" } }, "enabled" : "true", "transport" : { "ssl" : { "enabled" : "true" } } } }, "network" : { "host" : "0.0.0.0" } } } } } ``` To cleanup the Kubernetes resources created by this tutorial, run: ```bash kubectl patch -n demo es/custom-certificate-es-ssl -p '{"spec":{"terminationPolicy":"WipeOut"}}' --type="merge" kubectl delete -n demo es/custom-certificate-es-ssl kubectl delete ns demo ``` Learn how to use TLS certificates to connect Elasticsearch from . Learn how to generate . Want to hack on KubeDB? Check our .