Use PKCS12 key and trust store in HV-VES Collector 77/68377/4
authorPiotr Jaszczyk <piotr.jaszczyk@nokia.com>
Fri, 21 Sep 2018 09:31:59 +0000 (11:31 +0200)
committerPiotr Jaszczyk <piotr.jaszczyk@nokia.com>
Tue, 25 Sep 2018 06:40:25 +0000 (08:40 +0200)
Usage of keystore and truststore allows us to use JDK security
framework instead of openssl JNI bindings which are sometimes
problematic.

* Replace openssl with keytool when generating the scripts

Change-Id: Icaa21cd1db443b1dd8fe7e7c0523123df5ea2545
Issue-ID: DCAEGEN2-816
Signed-off-by: Piotr Jaszczyk <piotr.jaszczyk@nokia.com>
test/csit/plans/dcaegen2-collectors-hv-ves/testsuites/docker-compose.yml
test/csit/plans/dcaegen2-collectors-hv-ves/testsuites/setup.sh
test/csit/plans/dcaegen2-collectors-hv-ves/testsuites/ssl/.gitignore [new file with mode: 0644]
test/csit/plans/dcaegen2-collectors-hv-ves/testsuites/ssl/Makefile-openssl [moved from test/csit/plans/dcaegen2-collectors-hv-ves/testsuites/ssl/Makefile with 64% similarity]
test/csit/plans/dcaegen2-collectors-hv-ves/testsuites/ssl/README.md
test/csit/plans/dcaegen2-collectors-hv-ves/testsuites/ssl/gen-certs.sh [new file with mode: 0755]
test/csit/plans/dcaegen2-collectors-hv-ves/testsuites/teardown.sh
test/csit/tests/dcaegen2-collectors-hv-ves/testcases/libraries/XnfSimulatorLibrary.py

index 1673715..2a92821 100644 (file)
@@ -42,12 +42,15 @@ services:
     command: ["-server", "-bootstrap"]
 
   ves-hv-collector:
-    image: $DOCKER_REGISTRY/onap/org.onap.dcaegen2.collectors.hv-ves.hv-collector-main:latest
+    image: ${DOCKER_REGISTRY_PREFIX}onap/org.onap.dcaegen2.collectors.hv-ves.hv-collector-main:latest
     ports:
       - "6060:6060"
       - "6061:6061/tcp"
     entrypoint: ["java", "-Dio.netty.leakDetection.level=paranoid", "-cp", "*:", "org.onap.dcae.collectors.veshv.main.MainKt"]
-    command: ["--listen-port", "6061","--config-url", "http://consul:8500/v1/kv/veshv-config"]
+    command: ["--listen-port", "6061",
+              "--config-url", "http://consul:8500/v1/kv/veshv-config",
+              "--key-store-password", "onaponap",
+              "--trust-store-password", "onaponap"]
     healthcheck:
       interval: 10s
       timeout: 5s
@@ -61,7 +64,7 @@ services:
       - ves-hv-default
 
   unencrypted-ves-hv-collector:
-    image: $DOCKER_REGISTRY/onap/org.onap.dcaegen2.collectors.hv-ves.hv-collector-main:latest
+    image: ${DOCKER_REGISTRY_PREFIX}onap/org.onap.dcaegen2.collectors.hv-ves.hv-collector-main:latest
     ports:
       - "7060:6060"
       - "7061:6061/tcp"
@@ -80,7 +83,7 @@ services:
       - ves-hv-default
 
   dcae-app-simulator:
-    image: $DOCKER_REGISTRY/onap/org.onap.dcaegen2.collectors.hv-ves.hv-collector-dcae-app-simulator:latest
+    image: ${DOCKER_REGISTRY_PREFIX}onap/org.onap.dcaegen2.collectors.hv-ves.hv-collector-dcae-app-simulator:latest
     ports:
       - "6063:6063/tcp"
     command: ["--listen-port", "6063", "--kafka-bootstrap-servers", "kafka:9092", "--kafka-topics", "ves_hvRanMeas"]
index 6b527fc..6f72521 100755 (executable)
@@ -2,14 +2,25 @@
 
 set -euo pipefail
 
-pip uninstall -y docker-py
-pip install docker
-
-COMPOSE_VERSION=1.22.0
-COMPOSE_LOCATION='/usr/local/bin/docker-compose'
-sudo curl -L https://github.com/docker/compose/releases/download/${COMPOSE_VERSION}/docker-compose-$(uname -s)-$(uname -m) -o ${COMPOSE_LOCATION}
-sudo chmod +x ${COMPOSE_LOCATION}
-
+if [[ $# -eq 1 ]] && [[ $1 == "local-test-run" ]]; then
+  echo "Building locally - assuming all dependencies are installed"
+  export DOCKER_REGISTRY=""
+  export DOCKER_REGISTRY_PREFIX=""
+  export WORKSPACE=$(git rev-parse --show-toplevel)
+else
+  echo "Default run - install all dependencies"
+
+  pip uninstall -y docker-py
+  pip install docker
+
+  COMPOSE_VERSION=1.22.0
+  COMPOSE_LOCATION='/usr/local/bin/docker-compose'
+  sudo curl -L https://github.com/docker/compose/releases/download/${COMPOSE_VERSION}/docker-compose-$(uname -s)-$(uname -m) -o ${COMPOSE_LOCATION}
+  sudo chmod +x ${COMPOSE_LOCATION}
+
+  export DOCKER_REGISTRY="nexus3.onap.org:10001"
+  export DOCKER_REGISTRY_PREFIX="${DOCKER_REGISTRY}/"
+fi
 
 echo "Removing not used docker networks"
 docker network prune -f
@@ -19,14 +30,11 @@ echo "Creating network for containers: ${CONTAINERS_NETWORK}"
 docker network create ${CONTAINERS_NETWORK}
 
 cd ssl
-make FILE=client
-make FILE=server
-make FILE=invalid_client CA=invalid_trust
+./gen-certs.sh
 cd ..
 
-export DOCKER_REGISTRY="nexus3.onap.org:10001"
 docker-compose up -d
 
-mkdir ${WORKSPACE}/archives/containers_logs
+mkdir -p ${WORKSPACE}/archives/containers_logs
 
-export ROBOT_VARIABLES="--pythonpath ${WORKSPACE}/test/csit/tests/dcaegen2-collectors-hv-ves/testcases/libraries"
\ No newline at end of file
+export ROBOT_VARIABLES="--pythonpath ${WORKSPACE}/test/csit/tests/dcaegen2-collectors-hv-ves/testcases/libraries"
diff --git a/test/csit/plans/dcaegen2-collectors-hv-ves/testsuites/ssl/.gitignore b/test/csit/plans/dcaegen2-collectors-hv-ves/testsuites/ssl/.gitignore
new file mode 100644 (file)
index 0000000..0729569
--- /dev/null
@@ -0,0 +1,6 @@
+*.crt
+*.key
+*.srl
+*.csr
+*.pkcs12
+*.p12
@@ -1,12 +1,13 @@
 FILE=sample
-CA_PASSWD=onap
+PASSWD=onaponap
+CA_PASSWD=onaponap
 SUBJ=/C=PL/ST=DL/L=Wroclaw/O=Nokia/OU=MANO
 CA=trust
 
 sign: $(FILE).crt
 
 clean:
-       rm -f *.crt *.key *.srl *.csr
+       rm -f *.crt *.key *.srl *.csr *.pkcs12
 
 generate-ca-certificate: $(CA).crt
 
@@ -16,6 +17,11 @@ create-public-key: $(FILE).pub
 
 create-sign-request: $(FILE).csr
 
+create-key-store: $(FILE).ks.pkcs12
+
+create-trust-store: $(CA).crt
+       openssl pkcs12 -export -in $(CA).crt -CAfile $(CA).crt -out $(CA).pkcs12 -nokeys -noiter -nomaciter -passout pass:$(PASSWD)
+
 $(CA).crt:
        openssl req -new -x509 -keyout $(CA).key -out $(CA).crt -days 365 -passout pass:$(CA_PASSWD) -subj "$(SUBJ)"
 
@@ -29,4 +35,7 @@ $(FILE).csr: $(FILE).key
        openssl req -new -sha256 -key $(FILE).key -out $(FILE).csr -subj "$(SUBJ)"
 
 $(FILE).crt: $(CA).crt $(FILE).csr
-       openssl x509 -req -days 360 -in $(FILE).csr -CA $(CA).crt -CAkey $(CA).key -out $(FILE).crt -CAcreateserial -passin pass:$(CA_PASSWD)
\ No newline at end of file
+       openssl x509 -req -days 360 -in $(FILE).csr -CA $(CA).crt -CAkey $(CA).key -out $(FILE).crt -CAcreateserial -passin pass:$(CA_PASSWD)
+
+$(FILE).ks.pkcs12: $(FILE).key $(FILE).crt $(CA).crt
+       openssl pkcs12 -export -in $(FILE).crt -inkey $(FILE).key -CAfile $(CA).crt -out $(FILE).ks.pkcs12 -noiter -nomaciter -passout pass:$(PASSWD)
index 174c166..c2819d2 100644 (file)
@@ -1,5 +1,23 @@
 # Generating SSL certificates
 
+## Java keytool way (recommended)
+
+To generate:
+
+```shell
+./gen-certs.sh
+```
+
+To clean (remove generated files):
+
+```shell
+./gen-certs.sh clean
+```
+
+## OpenSSL way (currently might not work)
+
+> Add `-f Makefile-openssl` to each command
+
 Typical usage:
 
 ```shell
@@ -7,12 +25,30 @@ make FILE=client
 make FILE=server
 ```
 
+or (to generate PKCS12 key and trust stores):
+
+```shell
+make create-key-store FILE=client
+make create-key-store FILE=server
+make create-trust-store
+```
+
 Will generate CA certificate and signed client and server certificates.
 
 More "low-level" usage:
 
 ```shell
 make generate-ca-certificate
-make generate-private-key FILE=client
+make generate-private-key FILE=client 
 make sign FILE=client
 ```
+
+# Connecting to a server
+
+First generate *client* and *server* certificates. Then start a server with it's cert and make ca.crt a trusted certification authority.
+
+After that you can:
+
+```shell
+./connect.sh client localhost:8600 < file_with_a_data_to_be_sent.dat
+```
diff --git a/test/csit/plans/dcaegen2-collectors-hv-ves/testsuites/ssl/gen-certs.sh b/test/csit/plans/dcaegen2-collectors-hv-ves/testsuites/ssl/gen-certs.sh
new file mode 100755 (executable)
index 0000000..34572f7
--- /dev/null
@@ -0,0 +1,59 @@
+#!/usr/bin/env bash
+
+set -eu -o pipefail -o xtrace
+
+STORE_PASS=onaponap
+CN_PREFIX=dcaegen2-hvves
+DNAME_PREFIX="C=PL,ST=DL,L=Wroclaw,O=Nokia,OU=MANO,CN=${CN_PREFIX}"
+
+store_opts="-storetype PKCS12 -storepass ${STORE_PASS} -noprompt"
+
+function gen_key() {
+  local key_name="$1"
+  local ca="$2"
+  local keystore="-keystore ${key_name}.p12 ${store_opts}"
+  keytool -genkey -alias ${key_name} \
+      ${keystore} \
+      -keyalg RSA \
+      -validity 730 \
+      -keysize 2048 \
+      -dname "${DNAME_PREFIX}-${key_name}"
+  keytool -import -trustcacerts -alias ${ca} -file ${ca}.crt ${keystore}
+
+  keytool -certreq -alias ${key_name} -keyalg RSA ${keystore} | \
+      keytool -alias ${ca} -gencert -ext "san=dns:${CN_PREFIX}-${ca}" ${store_opts} -keystore ${ca}.p12 | \
+      keytool -alias ${key_name} -importcert ${keystore}
+}
+
+
+function gen_ca() {
+  local ca="$1"
+  keytool -genkeypair ${store_opts} -alias ${ca} -dname "${DNAME_PREFIX}-${ca}" -keystore ${ca}.p12
+  keytool -export -alias ${ca} -file ${ca}.crt ${store_opts} -keystore ${ca}.p12
+}
+
+function gen_truststore() {
+  local name="$1"
+  local trusted_ca="$2"
+  keytool -import -trustcacerts -alias ca -file ${trusted_ca}.crt ${store_opts} -keystore ${name}.p12
+}
+
+function clean() {
+  rm -f *.crt *.p12
+}
+
+if [[ $# -eq 0 ]]; then
+  gen_ca ca
+  gen_ca untrustedca
+  gen_truststore trust ca
+  gen_truststore untrustedtrust untrustedca
+  gen_key client ca
+  gen_key server ca
+  gen_key untrustedclient untrustedca
+elif [[ $1 == "clean" ]]; then
+  clean
+else
+  echo "usage: $0 [clean]"
+  exit 1
+fi
+
index 246fb83..fe922ed 100755 (executable)
@@ -1,7 +1,7 @@
 #!/usr/bin/env bash
 
 cd ssl
-make clean
+./gen-certs.sh clean
 cd ..
 
 COMPOSE_LOGS_FILE=${WORKSPACE}/archives/containers_logs/docker-compose.log
@@ -12,6 +12,5 @@ docker-compose rm -f
 docker network rm ${CONTAINERS_NETWORK}
 
 if grep "LEAK:" ${COMPOSE_LOGS_FILE}; then
-    echo "Teardown failed. Memory leak detected in docker-compose logs."
-    exit 1
+    echo "WARNING: Memory leak detected in docker-compose logs."
 fi
index 26d5a91..f6a9787 100644 (file)
@@ -6,7 +6,7 @@ from time import sleep
 
 XNF_SIMULATOR_NAME = "xNF Simulator"
 SIMULATOR_IMAGE_NAME = "onap/org.onap.dcaegen2.collectors.hv-ves.hv-collector-xnf-simulator"
-SIMULATOR_IMAGE_FULL_NAME = os.getenv("DOCKER_REGISTRY") + "/" + SIMULATOR_IMAGE_NAME + ":latest"
+SIMULATOR_IMAGE_FULL_NAME = os.getenv("DOCKER_REGISTRY_PREFIX") + SIMULATOR_IMAGE_NAME + ":latest"
 WORKSPACE_ENV = os.getenv("WORKSPACE")
 certificates_dir_path = WORKSPACE_ENV + "/test/csit/plans/dcaegen2-collectors-hv-ves/testsuites/ssl/"
 collector_certs_lookup_dir = "/etc/ves-hv/"
@@ -128,11 +128,11 @@ class XnfSimulator:
                  should_disable_ssl,
                  should_connect_to_unencrypted_hv_ves):
         self.port = port
-        cert_name_prefix = "" if should_use_valid_certs else "invalid_"
+        cert_name_prefix = "" if should_use_valid_certs else "untrusted"
         certificates_path_with_file_prefix = collector_certs_lookup_dir + cert_name_prefix
-        self.cert_path = certificates_path_with_file_prefix + "client.crt"
-        self.key_path = certificates_path_with_file_prefix + "client.key"
-        self.trust_cert_path = certificates_path_with_file_prefix + "trust.crt"
+        self.key_store_path = certificates_path_with_file_prefix + "client.p12"
+        self.trust_store_path = certificates_path_with_file_prefix + "trust.p12"
+        self.sec_store_passwd = "onaponap"
         self.disable_ssl = should_disable_ssl
         self.hv_collector_host = "unencrypted-ves-hv-collector" \
             if should_connect_to_unencrypted_hv_ves else "ves-hv-collector"
@@ -141,10 +141,12 @@ class XnfSimulator:
         startup_command = ["--listen-port", self.port,
                            "--ves-host", self.hv_collector_host,
                            "--ves-port", "6061",
-                           "--cert-file", self.cert_path,
-                           "--private-key-file", self.key_path,
-                           "--trust-cert-file", self.trust_cert_path]
-        if (self.disable_ssl):
+                           "--key-store", self.key_store_path,
+                           "--trust-store", self.trust_store_path,
+                           "--key-store-password", self.sec_store_passwd,
+                           "--trust-store-password", self.sec_store_passwd
+                           ]
+        if self.disable_ssl:
             startup_command.append("--ssl-disable")
         return startup_command