From 4a160c38320ed95ff4dd3d81ef5e1e7cc537034d Mon Sep 17 00:00:00 2001
From: Sherif Abdel-Naby <sherifabdlnaby@gmail.com>
Date: Mon, 16 Dec 2019 14:27:31 +0200
Subject: [PATCH] Use PEM instead of PKCS12 for SSL certs + Enable HTTPS for
 Kibana.

Signed-off-by: Sherif Abdel-Naby <sherifabdlnaby@gmail.com>
---
 README.md                              |  8 +++---
 docker-compose.nodes.yml               | 16 ++++++++---
 docker-compose.yml                     | 27 ++++++++++++++++---
 elasticsearch/config/elasticsearch.yml | 12 +++++----
 kibana/config/kibana.yml               |  8 +++++-
 setup/instances.yml                    | 14 ++++++++++
 setup/setup-certs.sh                   | 37 ++++++++++++++------------
 7 files changed, 88 insertions(+), 34 deletions(-)
 create mode 100644 setup/instances.yml

diff --git a/README.md b/README.md
index a1c5867..6089a8a 100644
--- a/README.md
+++ b/README.md
@@ -36,10 +36,10 @@ Stack Version: [7.5.0](https://www.elastic.co/blog/elastic-stack-7-5-0-released)
 
 - Configured as Production Single Node Cluster. (With a multi-node option for experimenting).
 - Security Enabled (under basic license).
-- SSL Enabled for Transport Layer.
+- SSL Enabled for Transport Layer and Kibana.
 - Use Docker-Compose and `.env` to configure your stack.
 - Automated Script that initializes and persist Elasticsearch's Keystore and SSL Certifications.
-- Curator Preconfigured for Automated Snapshotting (Need to setup S3 Repository).
+- Curator with Crond preconfigured for Automated Scheduled tasks (e.g Snapshots to S3).
 - Self-Monitoring Metrics Enabled.
 - Prometheus Exporters for Stack Metrics.
 - Filebeat instance for shipping Stack logs to Elasticsearch itself.
@@ -69,12 +69,14 @@ $ make elk
 ---- OR ----
 $ docker-compose up -d
 ```
-4. Visit Kibana at [localhost:5601](http://localhost:5601) 
+4. Visit Kibana at [https://localhost:5601](https://localhost:5601) 
 
 Username: `elastic` Password: `changeme` (or `ELASTIC_PASSWORD` value in `.env`)
 
 > Modify `.env` file for your needs, most importantly `ELASTIC_PASSWORD` that setup your superuser `elastic`'s password, `ELASTICSEARCH_HEAP` & `LOGSTASH_HEAP` for Elasticsearch & Logstash Heap Size and `ELK_VERSION` for, yk, Stack Version.
 
+> Notice that Kibana is configured to use HTTPS, so you'll need to write `https://` before `localhost:5601` in the browser.
+
 ### Additional Commands
 
 #### To Start Monitoring and Prometheus Exporters
diff --git a/docker-compose.nodes.yml b/docker-compose.nodes.yml
index 623b896..3a339f9 100644
--- a/docker-compose.nodes.yml
+++ b/docker-compose.nodes.yml
@@ -28,8 +28,12 @@ services:
     secrets:
       - source: elasticsearch.keystore
         target: /usr/share/elasticsearch/config/elasticsearch.keystore
-      - source: elastic.certificates
-        target: /usr/share/elasticsearch/config/certs/elastic-certificates.p12
+      - source: elastic.ca
+        target: /usr/share/elasticsearch/config/certs/ca.crt
+      - source: elasticsearch.certificate
+        target: /usr/share/elasticsearch/config/certs/elasticsearch.crt
+      - source: elasticsearch.key
+        target: /usr/share/elasticsearch/config/certs/elasticsearch.key
     ulimits:
       memlock:
         soft: -1
@@ -59,8 +63,12 @@ services:
     secrets:
       - source: elasticsearch.keystore
         target: /usr/share/elasticsearch/config/elasticsearch.keystore
-      - source: elastic.certificates
-        target: /usr/share/elasticsearch/config/certs/elastic-certificates.p12
+      - source: elastic.ca
+        target: /usr/share/elasticsearch/config/certs/ca.crt
+      - source: elasticsearch.certificate
+        target: /usr/share/elasticsearch/config/certs/elasticsearch.crt
+      - source: elasticsearch.key
+        target: /usr/share/elasticsearch/config/certs/elasticsearch.key
     ulimits:
       memlock:
         soft: -1
diff --git a/docker-compose.yml b/docker-compose.yml
index 95ccbe8..76dd644 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -13,8 +13,16 @@ volumes:
 secrets:
   elasticsearch.keystore:
     file: ./secrets/keystore/elasticsearch.keystore
-  elastic.certificates:
-    file: ./secrets/certs/elastic-certificates.p12
+  elastic.ca:
+    file: ./secrets/certs/ca/ca.crt
+  elasticsearch.certificate:
+    file: ./secrets/certs/elasticsearch/elasticsearch.crt
+  elasticsearch.key:
+    file: ./secrets/certs/elasticsearch/elasticsearch.key
+  kibana.certificate:
+    file: ./secrets/certs/kibana/kibana.crt
+  kibana.key:
+    file: ./secrets/certs/kibana/kibana.key
 
 services:
   elasticsearch:
@@ -39,8 +47,12 @@ services:
     secrets:
       - source: elasticsearch.keystore
         target: /usr/share/elasticsearch/config/elasticsearch.keystore
-      - source: elastic.certificates
-        target: /usr/share/elasticsearch/config/certs/elastic-certificates.p12
+      - source: elastic.ca
+        target: /usr/share/elasticsearch/config/certs/ca.crt
+      - source: elasticsearch.certificate
+        target: /usr/share/elasticsearch/config/certs/elasticsearch.crt
+      - source: elasticsearch.key
+        target: /usr/share/elasticsearch/config/certs/elasticsearch.key
     ports:
       - "9200:9200"
       - "9300:9300"
@@ -80,5 +92,12 @@ services:
       ELASTIC_USERNAME: ${ELASTIC_USERNAME}
       ELASTIC_PASSWORD: ${ELASTIC_PASSWORD}
       ELASTICSEARCH_HOST_PORT: ${ELASTICSEARCH_HOST}:${ELASTICSEARCH_PORT}
+    secrets:
+      - source: elastic.ca
+        target: /certs/ca.crt
+      - source: kibana.certificate
+        target: /certs/kibana.crt
+      - source: kibana.key
+        target: /certs/kibana.key
     ports:
       - "5601:5601"
diff --git a/elasticsearch/config/elasticsearch.yml b/elasticsearch/config/elasticsearch.yml
index 7d8c067..0909706 100644
--- a/elasticsearch/config/elasticsearch.yml
+++ b/elasticsearch/config/elasticsearch.yml
@@ -19,14 +19,16 @@ xpack.security.enabled: true
 ## - ssl
 xpack.security.transport.ssl.enabled: true
 xpack.security.transport.ssl.verification_mode: certificate
-xpack.security.transport.ssl.keystore.path: certs/elastic-certificates.p12
-xpack.security.transport.ssl.truststore.path: certs/elastic-certificates.p12
+xpack.security.transport.ssl.key: certs/elasticsearch.key
+xpack.security.transport.ssl.certificate: certs/elasticsearch.crt
+xpack.security.transport.ssl.certificate_authorities: certs/ca.crt
 
 ## - http
 #xpack.security.http.ssl.enabled: true
-#xpack.security.http.ssl.verification_mode: certificate
-#xpack.security.http.ssl.keystore.path: certs/elastic-certificates.p12
-#xpack.security.http.ssl.truststore.path: certs/elastic-certificates.p12
+#xpack.security.http.ssl.key: certs/elasticsearch.key
+#xpack.security.http.ssl.certificate: certs/elasticsearch.crt
+#xpack.security.http.ssl.certificate_authorities: certs/ca.crt
+#xpack.security.http.ssl.client_authentication: optional
 
 # Monitoring
 xpack.monitoring.enabled: true
diff --git a/kibana/config/kibana.yml b/kibana/config/kibana.yml
index 8b977e7..77ef7c1 100644
--- a/kibana/config/kibana.yml
+++ b/kibana/config/kibana.yml
@@ -5,10 +5,16 @@
 server.name: kibana
 server.host: "0"
 
+# Elasticsearch Connection
 elasticsearch.hosts: [ "http://${ELASTICSEARCH_HOST_PORT}" ]
 
+# SSL settings
+server.ssl.enabled: true
+server.ssl.certificate: /certs/kibana.crt
+server.ssl.key: /certs/kibana.key
+elasticsearch.ssl.certificateAuthorities: [ "/certs/ca.crt" ]
+
 ## X-Pack security credentials
-#
 elasticsearch.username: ${ELASTIC_USERNAME}
 elasticsearch.password: ${ELASTIC_PASSWORD}
 
diff --git a/setup/instances.yml b/setup/instances.yml
new file mode 100644
index 0000000..2025ecb
--- /dev/null
+++ b/setup/instances.yml
@@ -0,0 +1,14 @@
+instances:
+  - name: elasticsearch
+    dns:
+      - elasticsearch
+      - localhost
+    ip:
+      - 127.0.0.1
+
+  - name: kibana
+    dns:
+      - kibana
+      - localhost
+    ip:
+      - 127.0.0.1
\ No newline at end of file
diff --git a/setup/setup-certs.sh b/setup/setup-certs.sh
index 3450c3d..9a3b97b 100644
--- a/setup/setup-certs.sh
+++ b/setup/setup-certs.sh
@@ -2,25 +2,28 @@
 set -e
 
 OUTPUT_DIR=/secrets/certs
-CA_FILE=$OUTPUT_DIR/elastic-stack-ca.p12
-CERT_FILE=$OUTPUT_DIR/elastic-certificates.p12
+ZIP_FILE=$OUTPUT_DIR/certs.zip
 
-printf "====== Generating Elasticsearch Certifications ======\n"
+printf "======= Generating Elastic Stack Certificates =======\n"
 printf "=====================================================\n"
-if [ -f "$CA_FILE" ]; then
-    echo "Removing current Certificate Authority (CA)..."
-    rm $CA_FILE
-fi
-if [ -f "$CERT_FILE" ]; then
-    echo "Removing current Certificate (P12)..."
-    rm $CERT_FILE
-fi
-elasticsearch-certutil ca -s --pass "" --out $CA_FILE
-elasticsearch-certutil cert -s --ca $CA_FILE --ca-pass "" --out $CERT_FILE --pass ""
-chmod 0644 $CA_FILE
-chmod 0644 $CERT_FILE
-printf "Certificate Authority created at $CA_FILE\n"
-printf "Certificate created at $CERT_FILE\n"
+
+printf "Installing Necessary Tools... \n"
+yum install -y -q -e 0 unzip;
+
+printf "Clearing Old Certificates if exits... \n"
+find $OUTPUT_DIR -mindepth 1 -type d -exec rm -rf -- {} +
+rm -f $ZIP_FILE
+
+printf "Generating... \n"
+bin/elasticsearch-certutil cert --silent --pem --in /setup/instances.yml -out $ZIP_FILE;
+
+printf "Unzipping Certifications... \n"
+unzip -qq $ZIP_FILE -d $OUTPUT_DIR;
+
+printf "Applying Permissions... \n"
+chown -R 1000:0 $OUTPUT_DIR
+find $OUTPUT_DIR -type f -exec chmod 655 -- {} +
+
 printf "=====================================================\n"
 printf "SSL Certifications generation completed successfully.\n"
 printf "=====================================================\n"