From 13b7d05f2c457cea4a5f78fe4dbb6d1d99a6f450 Mon Sep 17 00:00:00 2001 From: Aleksandra Maciaga Date: Thu, 26 Mar 2020 17:28:47 +0100 Subject: [PATCH] Change AAF Certservice CSITs to send requests via HTTPS Signed-off-by: Aleksandra Maciaga Signed-off-by: Michal Banka Change-Id: Ia7b5d8d548f4ae3727302772fc56e6b0142b0da0 Issue-ID: AAF-1084 --- plans/aaf/certservice/certs/Makefile | 110 +++++++++++++++++++++ plans/aaf/certservice/docker-compose.yml | 18 ++-- plans/aaf/certservice/setup.sh | 17 +++- plans/aaf/certservice/teardown.sh | 5 + .../certservice/assets/invalid_client_docker.env | 4 + .../aaf/certservice/assets/valid_client_docker.env | 4 + .../aaf/certservice/libraries/CertClientManager.py | 9 +- .../resources/cert-service-keywords.robot | 15 +-- .../resources/cert-service-properties.robot | 11 ++- 9 files changed, 171 insertions(+), 22 deletions(-) create mode 100644 plans/aaf/certservice/certs/Makefile diff --git a/plans/aaf/certservice/certs/Makefile b/plans/aaf/certservice/certs/Makefile new file mode 100644 index 00000000..126e0533 --- /dev/null +++ b/plans/aaf/certservice/certs/Makefile @@ -0,0 +1,110 @@ +all: step_1 step_2 step_3 step_4 step_5 step_6 step_7 step_8 step_9 step_10 step_11 step_12 step_13 step_14 step_15 +.PHONY: all +#Clear certificates +clear: + @echo "Clear certificates" + rm -f certServiceClient-keystore.jks certServiceServer-keystore.jks root.crt truststore.jks certServiceServer-keystore.p12 + @echo "#####done#####" + +#Generate root private and public keys +step_1: + @echo "Generate root private and public keys" + keytool -genkeypair -v -alias root -keyalg RSA -keysize 4096 -validity 3650 -keystore root-keystore.jks \ + -dname "CN=root.com, OU=Root Org, O=Root Company, L=Wroclaw, ST=Dolny Slask, C=PL" -keypass secret \ + -storepass secret -ext BasicConstraints:critical="ca:true" + @echo "#####done#####" + +#Export public key as certificate +step_2: + @echo "(Export public key as certificate)" + keytool -exportcert -alias root -keystore root-keystore.jks -storepass secret -file root.crt -rfc + @echo "#####done#####" + +#Self-signed root (import root certificate into truststore) +step_3: + @echo "(Self-signed root (import root certificate into truststore))" + keytool -importcert -alias root -keystore truststore.jks -file root.crt -storepass secret -noprompt + @echo "#####done#####" + +#Generate certService's client private and public keys +step_4: + @echo "Generate certService's client private and public keys" + keytool -genkeypair -v -alias certServiceClient -keyalg RSA -keysize 2048 -validity 730 \ + -keystore certServiceClient-keystore.jks -storetype JKS \ + -dname "CN=certServiceClient.com,OU=certServiceClient company,O=certServiceClient org,L=Wroclaw,ST=Dolny Slask,C=PL" \ + -keypass secret -storepass secret + @echo "####done####" + +#Generate certificate signing request for certService's client +step_5: + @echo "Generate certificate signing request for certService's client" + keytool -certreq -keystore certServiceClient-keystore.jks -alias certServiceClient -storepass secret -file certServiceClient.csr + @echo "####done####" + +#Sign certService's client certificate by root CA +step_6: + @echo "Sign certService's client certificate by root CA" + keytool -gencert -v -keystore root-keystore.jks -storepass secret -alias root -infile certServiceClient.csr \ + -outfile certServiceClientByRoot.crt -rfc -ext bc=0 -ext ExtendedkeyUsage="serverAuth,clientAuth" + @echo "####done####" + +#Import root certificate into client +step_7: + @echo "Import root certificate into intermediate" + cat root.crt >> certServiceClientByRoot.crt + @echo "####done####" + +#Import signed certificate into certService's client +step_8: + @echo "Import signed certificate into certService's client" + keytool -importcert -file certServiceClientByRoot.crt -destkeystore certServiceClient-keystore.jks -alias certServiceClient -storepass secret -noprompt + @echo "####done####" + +#Generate certService private and public keys +step_9: + @echo "Generate certService private and public keys" + keytool -genkeypair -v -alias aaf-cert-service -keyalg RSA -keysize 2048 -validity 730 \ + -keystore certServiceServer-keystore.jks -storetype JKS \ + -dname "CN=aaf-cert-service,OU=certServiceServer company,O=certServiceServer org,L=Wroclaw,ST=Dolny Slask,C=PL" \ + -keypass secret -storepass secret -ext BasicConstraints:critical="ca:false" + @echo "####done####" + +#Generate certificate signing request for certService +step_10: + @echo "Generate certificate signing request for certService" + keytool -certreq -keystore certServiceServer-keystore.jks -alias aaf-cert-service -storepass secret -file certServiceServer.csr + @echo "####done####" + +#Sign certService certificate by root CA +step_11: + @echo "Sign certService certificate by root CA" + keytool -gencert -v -keystore root-keystore.jks -storepass secret -alias root -infile certServiceServer.csr \ + -outfile certServiceServerByRoot.crt -rfc -ext bc=0 -ext ExtendedkeyUsage="serverAuth,clientAuth" \ + -ext SubjectAlternativeName:="DNS:aaf-cert-service,DNS:localhost" + @echo "####done####" + +#Import root certificate into server +step_12: + @echo "Import root certificate into intermediate(server)" + cat root.crt >> certServiceServerByRoot.crt + @echo "####done####" + +#Import signed certificate into certService +step_13: + @echo "Import signed certificate into certService" + keytool -importcert -file certServiceServerByRoot.crt -destkeystore certServiceServer-keystore.jks -alias aaf-cert-service \ + -storepass secret -noprompt + @echo "####done####" + +#Convert certServiceServer-keystore(.jks) to PCKS12 format(.p12) +step_14: + @echo "Convert certServiceServer-keystore(.jks) to PCKS12 format(.p12)" + keytool -importkeystore -srckeystore certServiceServer-keystore.jks -srcstorepass secret \ + -destkeystore certServiceServer-keystore.p12 -deststoretype PKCS12 -deststorepass secret + @echo "#####done#####" + +#Clear unused certificates +step_15: + @echo "Clear unused certificates" + rm -f certServiceClientByRoot.crt certServiceClient.csr root-keystore.jks certServiceServerByRoot.crt certServiceServer.csr + @echo "#####done#####" diff --git a/plans/aaf/certservice/docker-compose.yml b/plans/aaf/certservice/docker-compose.yml index ae7ee878..dcac7df0 100644 --- a/plans/aaf/certservice/docker-compose.yml +++ b/plans/aaf/certservice/docker-compose.yml @@ -10,9 +10,6 @@ services: - "443:8443" volumes: - $SCRIPTS_PATH:/opt/primekey/scripts - command: bash -c " - /opt/primekey/bin/start.sh - " healthcheck: test: ["CMD-SHELL", "curl -kI https://localhost:8443/ejbca/publicweb/healthcheck/ejbcahealth"] interval: 20s @@ -21,16 +18,25 @@ services: networks: - certservice - certservice: + aaf-cert-service: image: nexus3.onap.org:10001/onap/org.onap.aaf.certservice.aaf-certservice-api:latest volumes: - $CONFIGURATION_PATH:/etc/onap/aaf/certservice/cmpServers.json - container_name: aafcert + - ./certs/truststore.jks:/etc/onap/aaf/certservice/certs/truststore.jks + - ./certs/root.crt:/etc/onap/aaf/certservice/certs/root.crt + - ./certs/certServiceServer-keystore.jks:/etc/onap/aaf/certservice/certs/certServiceServer-keystore.jks + - ./certs/certServiceServer-keystore.p12:/etc/onap/aaf/certservice/certs/certServiceServer-keystore.p12 + container_name: aafcert-service ports: - - "8080:8080" + - "8443:8443" depends_on: ejbca: condition: service_healthy + healthcheck: + test: ["CMD-SHELL", "curl https://localhost:8443/actuator/health --cacert /etc/onap/aaf/certservice/certs/root.crt --cert-type p12 --cert /etc/onap/aaf/certservice/certs/certServiceServer-keystore.p12 --pass secret"] + interval: 10s + timeout: 3s + retries: 15 networks: - certservice diff --git a/plans/aaf/certservice/setup.sh b/plans/aaf/certservice/setup.sh index 93d65f78..b23b7192 100644 --- a/plans/aaf/certservice/setup.sh +++ b/plans/aaf/certservice/setup.sh @@ -71,15 +71,26 @@ echo "Use configuration from: $CONFIGURATION_PATH" export CONFIGURATION_PATH=${CONFIGURATION_PATH} export SCRIPTS_PATH=${SCRIPTS_PATH} +#Generate keystores, truststores, certificates and keys +mkdir -p ${WORKSPACE}/tests/aaf/certservice/assets/certs/ +make all -C ./certs/ +cp ${WORKSPACE}/plans/aaf/certservice/certs/root.crt ${WORKSPACE}/tests/aaf/certservice/assets/certs/root.crt +echo "Generated keystores" +openssl pkcs12 -in ${WORKSPACE}/plans/aaf/certservice/certs/certServiceServer-keystore.p12 -clcerts -nokeys -password pass:secret | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > ${WORKSPACE}/tests/aaf/certservice/assets/certs/certServiceServer.crt +echo "Generated server certificate" +openssl pkcs12 -in ${WORKSPACE}/plans/aaf/certservice/certs/certServiceServer-keystore.p12 -nocerts -nodes -password pass:secret| sed -ne '/-BEGIN PRIVATE KEY-/,/-END PRIVATE KEY-/p' > ${WORKSPACE}/tests/aaf/certservice/assets/certs/certServiceServer.key +echo "Generated server key" + docker-compose up -d AAFCERT_IP='none' # Wait container ready for i in {1..9} do - AAFCERT_IP=`get-instance-ip.sh aafcert` - RESP_CODE=$(curl -I -s -o /dev/null -w "%{http_code}" http://${AAFCERT_IP}:8080/actuator/health) - if [[ "$RESP_CODE" == '200' ]]; then + AAFCERT_IP=`get-instance-ip.sh aafcert-service` + RESP_CODE=$(curl -s https://localhost:8443/actuator/health --cacert ./certs/root.crt --cert-type p12 --cert ./certs/certServiceServer-keystore.p12 --pass secret | \ + python2 -c 'import json,sys;obj=json.load(sys.stdin);print obj["status"]') + if [[ "$RESP_CODE" == "UP" ]]; then echo 'AAF Cert Service is ready' export AAFCERT_IP=${AAFCERT_IP} docker exec aafcert-ejbca /opt/primekey/scripts/ejbca-configuration.sh diff --git a/plans/aaf/certservice/teardown.sh b/plans/aaf/certservice/teardown.sh index 83737f0d..71e20b7c 100644 --- a/plans/aaf/certservice/teardown.sh +++ b/plans/aaf/certservice/teardown.sh @@ -17,4 +17,9 @@ docker-compose down +make clear -C ./certs/ +echo "Removed old keystores" +rm -rf ${WORKSPACE}/tests/aaf/certservice/assets/certs +echo "Removed old certificates" + kill-instance.sh ${ClientContainerName} \ No newline at end of file diff --git a/tests/aaf/certservice/assets/invalid_client_docker.env b/tests/aaf/certservice/assets/invalid_client_docker.env index 3e7d879b..e96237ca 100644 --- a/tests/aaf/certservice/assets/invalid_client_docker.env +++ b/tests/aaf/certservice/assets/invalid_client_docker.env @@ -2,6 +2,10 @@ REQUEST_TIMEOUT=5000 OUTPUT_PATH=/var/certs CA_NAME=Invalid +KEYSTORE_PATH=/etc/onap/aaf/certservice/certs/certServiceClient-keystore.jks +KEYSTORE_PASSWORD=secret +TRUSTSTORE_PATH=/etc/onap/aaf/certservice/certs/truststore.jks +TRUSTSTORE_PASSWORD=secret #Csr config envs COMMON_NAME=onap.org ORGANIZATION=Linux-Foundation diff --git a/tests/aaf/certservice/assets/valid_client_docker.env b/tests/aaf/certservice/assets/valid_client_docker.env index 01818960..55fefa3e 100644 --- a/tests/aaf/certservice/assets/valid_client_docker.env +++ b/tests/aaf/certservice/assets/valid_client_docker.env @@ -2,6 +2,10 @@ REQUEST_TIMEOUT=30000 OUTPUT_PATH=/var/certs CA_NAME=RA +KEYSTORE_PATH=/etc/onap/aaf/certservice/certs/certServiceClient-keystore.jks +KEYSTORE_PASSWORD=secret +TRUSTSTORE_PATH=/etc/onap/aaf/certservice/certs/truststore.jks +TRUSTSTORE_PASSWORD=secret #Csr config envs COMMON_NAME=onap.org ORGANIZATION=Linux-Foundation diff --git a/tests/aaf/certservice/libraries/CertClientManager.py b/tests/aaf/certservice/libraries/CertClientManager.py index a959c9ee..a4a0df23 100644 --- a/tests/aaf/certservice/libraries/CertClientManager.py +++ b/tests/aaf/certservice/libraries/CertClientManager.py @@ -10,10 +10,12 @@ ARCHIVES_PATH = os.getenv("WORKSPACE") + "/archives/" ERROR_API_REGEX = 'Error on API response.*[0-9]{3}' RESPONSE_CODE_REGEX = '[0-9]{3}' + class CertClientManager: - def __init__(self, mount_path): + def __init__(self, mount_path, truststore_path): self.mount_path = mount_path + self.truststore_path = truststore_path def run_client_container(self, client_image, container_name, path_to_env, request_url, network): self.create_mount_dir() @@ -25,8 +27,9 @@ class CertClientManager: name=container_name, environment=environment, network=network, - user='root', #Run container as root to avoid permission issues with volume mount access - mounts=[Mount(target='/var/certs', source=self.mount_path, type='bind')], + user='root', # Run container as root to avoid permission issues with volume mount access + mounts=[Mount(target='/var/certs', source=self.mount_path, type='bind'), + Mount(target='/etc/onap/aaf/certservice/certs/', source=self.truststore_path, type='bind')], detach=True ) exitcode = container.wait() diff --git a/tests/aaf/certservice/resources/cert-service-keywords.robot b/tests/aaf/certservice/resources/cert-service-keywords.robot index a128178c..d4d4fd93 100644 --- a/tests/aaf/certservice/resources/cert-service-keywords.robot +++ b/tests/aaf/certservice/resources/cert-service-keywords.robot @@ -5,19 +5,20 @@ Resource ./cert-service-properties.robot Library RequestsLibrary Library HttpLibrary.HTTP Library Collections -Library ../libraries/CertClientManager.py ${MOUNT_PATH} +Library ../libraries/CertClientManager.py ${MOUNT_PATH} ${TRUSTSTORE_PATH} Library ../libraries/JksFilesValidator.py ${MOUNT_PATH} *** Keywords *** Create sessions [Documentation] Create all required sessions - Create Session aaf_cert_service_url ${AAFCERT_URL} - Set Suite Variable ${http_session} aaf_cert_service_url + ${certs}= Create List ${CERTSERVICE_SERVER_CRT} ${CERTSERVICE_SERVER_KEY} + Create Client Cert Session alias ${AAFCERT_URL} client_certs=${certs} verify=${ROOTCA} + Set Suite Variable ${https_valid_cert_session} alias Run Healthcheck [Documentation] Run Healthcheck - ${resp}= Get Request ${http_session} /actuator/health + ${resp}= Get Request ${https_valid_cert_session} /actuator/health Should Be Equal As Strings ${resp.status_code} 200 Validate Recieved Response ${resp} status UP @@ -31,7 +32,7 @@ Validate Recieved Response Send Get Request And Validate Response [Documentation] Send request to passed url and validate received response [Arguments] ${path} ${resp_code} - ${resp}= Get Request ${http_session} ${path} + ${resp}= Get Request ${https_valid_cert_session} ${path} Should Be Equal As Strings ${resp.status_code} ${resp_code} Send Get Request with Header @@ -39,7 +40,7 @@ Send Get Request with Header [Arguments] ${path} ${csr_file} ${pk_file} [Return] ${resp} ${headers}= Create Header with CSR and PK ${csr_file} ${pk_file} - ${resp}= Get Request ${http_session} ${path} headers=${headers} + ${resp}= Get Request ${https_valid_cert_session} ${path} headers=${headers} Send Get Request with Header And Expect Success [Documentation] Send request to passed url and validate received response @@ -81,7 +82,7 @@ Create Header with CSR and PK Send Post Request And Validate Response [Documentation] Send request to passed url and validate received response [Arguments] ${path} ${resp_code} - ${resp}= Post Request ${http_session} ${path} + ${resp}= Post Request ${https_valid_cert_session} ${path} Should Be Equal As Strings ${resp.status_code} ${resp_code} Run Cert Service Client And Validate JKS File Creation And Client Exit Code diff --git a/tests/aaf/certservice/resources/cert-service-properties.robot b/tests/aaf/certservice/resources/cert-service-properties.robot index 0dd8b066..53d6b246 100644 --- a/tests/aaf/certservice/resources/cert-service-properties.robot +++ b/tests/aaf/certservice/resources/cert-service-properties.robot @@ -1,10 +1,14 @@ *** Variables *** -${CERT_SERVICE_PORT} 8080 -${AAFCERT_URL} http://localhost:${cert_service_port} +${CERT_SERVICE_CONTAINER_NAME} aaf-cert-service +${CERT_SERVICE_PORT} 8443 +${AAFCERT_URL} https://localhost:${cert_service_port} ${CLIENT_CA_NAME} Client ${RA_CA_NAME} RA ${CERT_SERVICE_ENDPOINT} /v1/certificate/ +${ROOTCA} %{WORKSPACE}/tests/aaf/certservice/assets/certs/root.crt +${CERTSERVICE_SERVER_CRT} %{WORKSPACE}/tests/aaf/certservice/assets/certs/certServiceServer.crt +${CERTSERVICE_SERVER_KEY} %{WORKSPACE}/tests/aaf/certservice/assets/certs/certServiceServer.key ${VALID_CLIENT_CSR_FILE} %{WORKSPACE}/tests/aaf/certservice/assets/valid_client.csr ${VALID_CLIENT_PK_FILE} %{WORKSPACE}/tests/aaf/certservice/assets/valid_client.pk ${VALID_RA_CSR_FILE} %{WORKSPACE}/tests/aaf/certservice/assets/valid_ra.csr @@ -13,10 +17,11 @@ ${INVALID_CSR_FILE} %{WORKSPACE}/tests/aaf/certservice/asse ${INVALID_PK_FILE} %{WORKSPACE}/tests/aaf/certservice/assets/invalid.key -${CERT_SERVICE_ADDRESS} http://%{AAFCERT_IP}:${cert_service_port} +${CERT_SERVICE_ADDRESS} https://${CERT_SERVICE_CONTAINER_NAME}:${CERT_SERVICE_PORT} ${VALID_ENV_FILE} %{WORKSPACE}/tests/aaf/certservice/assets/valid_client_docker.env ${INVALID_ENV_FILE} %{WORKSPACE}/tests/aaf/certservice/assets/invalid_client_docker.env ${DOCKER_CLIENT_IMAGE} nexus3.onap.org:10001/onap/org.onap.aaf.certservice.aaf-certservice-client:latest ${CLIENT_CONTAINER_NAME} %{ClientContainerName} ${CERT_SERVICE_NETWORK} certservice_certservice ${MOUNT_PATH} %{WORKSPACE}/tests/aaf/certservice/tmp +${TRUSTSTORE_PATH} %{WORKSPACE}/plans/aaf/certservice/certs -- 2.16.6