summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Malkiewicz <jan.malkiewicz@nokia.com>2020-08-19 15:49:10 +0200
committerJan Malkiewicz <jan.malkiewicz@nokia.com>2020-08-28 09:00:24 +0200
commit92f74ae2a3506cea96635e922c0217dc1ef96bb9 (patch)
tree054b49c3216c5075d8e3ffb40b7c502157b67f64
parent43f0c2c84a1d1c0e9dd49e41c748f56b5820760b (diff)
Add init container support for truststore merger.
Issue-ID: DCAEGEN2-2253 Signed-off-by: Jan Malkiewicz <jan.malkiewicz@nokia.com> Change-Id: I98f27834b36cad333728d41ec079b86a090e77f3
-rw-r--r--.gitignore23
-rw-r--r--k8s/ChangeLog.md3
-rw-r--r--k8s/Makefile15
-rw-r--r--k8s/README.md3
-rw-r--r--k8s/centos.wagon-builder.dockerfile16
-rw-r--r--k8s/configure/configure.py4
-rw-r--r--k8s/k8sclient/k8sclient.py65
-rw-r--r--k8s/k8splugin/tasks.py4
-rw-r--r--k8s/k8splugin_types.yaml2
-rw-r--r--k8s/pom.xml2
-rw-r--r--k8s/setup.py4
-rw-r--r--k8s/tests/common.py35
-rw-r--r--k8s/tests/test_k8sclient_deploy.py4
13 files changed, 165 insertions, 15 deletions
diff --git a/.gitignore b/.gitignore
index 5a7dcdf..f99c97a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -79,3 +79,26 @@ target/
# tox output
xunit-results*
htmlcov
+
+# Idea IntelliJ project files
+/.idea/*
+*.iml
+
+# Output files
+/k8splugin-*.tgz
+/k8splugin-*.zip
+/pgaas-*.tgz
+/pgaas-*.zip
+/clamppolicyplugin-*.tgz
+/clamppolicyplugin-*.zip
+/dcaepolicyplugin-*.tgz
+/dcaepolicyplugin-*.zip
+/dmaap-*.tgz
+/dmaap-*.zip
+/helm-*.tgz
+/helm-*.zip
+/relationshipplugin-*.tgz
+/relationshipplugin-*.zip
+/sshkeyshare-*.tgz
+/sshkeyshare-*.zip
+/k8s/k8splugin-*.zip
diff --git a/k8s/ChangeLog.md b/k8s/ChangeLog.md
index d7b1da6..7c014e8 100644
--- a/k8s/ChangeLog.md
+++ b/k8s/ChangeLog.md
@@ -5,6 +5,9 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).
+## [3.4.0]
+* DCAEGEN2-2253 - Add support to truststore merger init container
+
## [3.3.0]
* DCAEGEN2-2252 - Add support to request certificates from CMPv2 server in DCAE cloudify blueprints
- handle incorrect blueprint
diff --git a/k8s/Makefile b/k8s/Makefile
new file mode 100644
index 0000000..0add666
--- /dev/null
+++ b/k8s/Makefile
@@ -0,0 +1,15 @@
+build-wagon:
+ @echo "### Copy generated k8s plugin"
+ cp ../k8splugin-*.zip .
+
+ @echo "### Create docker image (CentOS)"
+ docker build -t k8splugin -f centos.wagon-builder.dockerfile .
+
+ @echo "### Run docker container and generate wagon file"
+ docker run -t --name k8s_container k8splugin:latest
+
+ @echo "### Copy wagon file from docker image to current directory"
+ docker cp k8s_container:/opt/app-root/src/output .
+
+ @echo "### Remove docker container"
+ docker rm k8s_container
diff --git a/k8s/README.md b/k8s/README.md
index 21e7564..e310dee 100644
--- a/k8s/README.md
+++ b/k8s/README.md
@@ -67,7 +67,8 @@ The configuration is provided as JSON object with the following properties:
- `state`: State name, for which certificate will be created
- `organizational_unit`: Organizational unit name, for which certificate will be created
- `location`: Location name, for which certificate will be created
-
+ - `truststore_merger`: object containing configuration for setting up truststore-merger init container
+ - `image_tag`: truststore-merger image name and version
#### Kubernetes access information
The plugin accesses a Kubernetes cluster. The information and credentials for accessing a cluster are stored in a "kubeconfig"
diff --git a/k8s/centos.wagon-builder.dockerfile b/k8s/centos.wagon-builder.dockerfile
new file mode 100644
index 0000000..401c1a5
--- /dev/null
+++ b/k8s/centos.wagon-builder.dockerfile
@@ -0,0 +1,16 @@
+FROM centos/python-27-centos7:latest as cent
+
+# Sometimes it's necessary to set a proxy (e.g. in case of local development).
+# To do it just uncomment those two env variables and set appriopriate values for them.
+#ENV HTTP_PROXY=
+#ENV HTTPS_PROXY=
+
+RUN bash -c "pip install --upgrade pip"
+RUN bash -c "pip install wagon"
+
+COPY / k8s/
+
+USER root
+RUN bash -c "wagon create -r k8s/requirements.txt k8s/"
+RUN bash -c "mkdir output"
+RUN bash -c "mv k8splugin*.wgn output/"
diff --git a/k8s/configure/configure.py b/k8s/configure/configure.py
index c0dcd3f..fbf578c 100644
--- a/k8s/configure/configure.py
+++ b/k8s/configure/configure.py
@@ -50,6 +50,7 @@ EXT_TLS_LOCATION = "San-Francisco"
EXT_TLS_KEYSTORE_PASSWORD = "secret"
EXT_TLS_TRUSTSTORE_PASSWORD = "secret"
+TRUST_STORE_MERGER_IMAGE = "nexus3.onap.org:10001/onap/org.onap.dcae.truststore-merger:1.2.0"
CBS_BASE_URL = "https://config-binding-service:10443/service_component_all"
def _set_defaults():
@@ -85,6 +86,9 @@ def _set_defaults():
"keystore_password" : EXT_TLS_KEYSTORE_PASSWORD, # Password to keystore file
"truststore_password" : EXT_TLS_TRUSTSTORE_PASSWORD # Password to truststore file
},
+ "truststore_merger": {
+ "image_tag": TRUST_STORE_MERGER_IMAGE
+ },
"cbs": {
"base_url" : CBS_BASE_URL # URL prefix for accessing config binding service
}
diff --git a/k8s/k8sclient/k8sclient.py b/k8s/k8sclient/k8sclient.py
index b972ce1..4b58b0e 100644
--- a/k8s/k8sclient/k8sclient.py
+++ b/k8s/k8sclient/k8sclient.py
@@ -21,6 +21,7 @@
import os
import re
import uuid
+
from kubernetes import config, client, stream
# Default values for readiness probe
@@ -304,7 +305,7 @@ def _add_elk_logging_sidecar(containers, volumes, volume_mounts, component_name,
# Finally create the container for the sidecar
containers.append(_create_container_object("filebeat", filebeat["image"], False, volume_mounts=sidecar_volume_mounts))
-def _add_tls_init_container(init_containers, volumes, volume_mounts, tls_info, tls_config):
+def _add_tls_init_container(ctx, init_containers, volumes, volume_mounts, tls_info, tls_config):
# Adds an InitContainer to the pod to set up TLS certificate information. For components that act as a
# server(tls_info["use_tls"] is True), the InitContainer will populate a directory with server and CA certificate
# materials in various formats. For other components (tls_info["use_tls"] is False, or tls_info is not specified),
@@ -312,6 +313,8 @@ def _add_tls_init_container(init_containers, volumes, volume_mounts, tls_info, t
# In either case, the certificate directory is mounted onto the component container filesystem at the location
# specified by tls_info["component_cert_dir"], if present, otherwise at the configured default mount point
# (tls_config["component_cert_dir"]).
+ docker_image = tls_config["image"]
+ ctx.logger.info("Creating init container: TLS \n * [" + docker_image + "]")
cert_directory = tls_info.get("cert_directory") or tls_config.get("component_cert_dir")
env = {}
@@ -323,9 +326,13 @@ def _add_tls_init_container(init_containers, volumes, volume_mounts, tls_info, t
init_volume_mounts = [client.V1VolumeMount(name="tls-info", mount_path=tls_config["cert_path"])]
# Create the init container
- init_containers.append(_create_container_object("init-tls", tls_config["image"], False, volume_mounts=init_volume_mounts, env=env))
+ init_containers.append(_create_container_object("init-tls", docker_image, False, volume_mounts=init_volume_mounts, env=env))
+
+def _add_external_tls_init_container(ctx, init_containers, volumes, external_cert, external_tls_config):
+ # Adds an InitContainer to the pod which will generate external TLS certificates.
+ docker_image = external_tls_config["image_tag"]
+ ctx.logger.info("Creating init container: external TLS \n * [" + docker_image + "]")
-def _add_external_tls_init_container(init_containers, volumes, external_cert, external_tls_config):
env = {}
output_path = external_cert.get("external_cert_directory")
if not output_path.endswith('/'):
@@ -355,7 +362,48 @@ def _add_external_tls_init_container(init_containers, volumes, external_cert, ex
client.V1VolumeMount(name="tls-volume", mount_path=MOUNT_PATH)]
# Create the init container
- init_containers.append(_create_container_object("cert-service-client", external_tls_config["image_tag"], False, volume_mounts=init_volume_mounts, env=env))
+ init_containers.append(_create_container_object("cert-service-client", docker_image, False, volume_mounts=init_volume_mounts, env=env))
+
+
+def _add_truststore_merger_init_container(ctx, init_containers, tls_info, tls_config, external_cert, truststore_merger_config):
+ # Adds an InitContainer to the pod to merge TLS and external TLS truststore into single file.
+ docker_image = truststore_merger_config["image_tag"]
+ ctx.logger.info("Creating init container: truststore merger \n * [" + docker_image + "]")
+
+ tls_cert_dir = tls_info.get("cert_directory") or tls_config.get("component_cert_dir")
+ if not tls_cert_dir.endswith('/'):
+ tls_cert_dir += '/'
+
+ tls_cert_file_path = tls_cert_dir + "trust.jks"
+ tls_cert_file_pass = tls_cert_dir + "trust.pass"
+
+ ext_cert_dir = tls_cert_dir + "external/"
+
+ output_type = (external_cert.get("cert_type") or 'p12').lower()
+ ext_truststore_path = ext_cert_dir + "truststore." + _get_file_extension(output_type)
+ ext_truststore_pass = ''
+ if output_type != 'pem':
+ ext_truststore_pass = ext_cert_dir + "truststore.pass"
+
+ env = {}
+ env["TRUSTSTORES_PATHS"] = tls_cert_file_path + ":" + ext_truststore_path
+ env["TRUSTSTORES_PASSWORDS_PATHS"] = tls_cert_file_pass + ":" + ext_truststore_pass
+
+ ctx.logger.info("TRUSTSTORES_PATHS: " + env["TRUSTSTORES_PATHS"])
+ ctx.logger.info("TRUSTSTORES_PASSWORDS_PATHS: " + env["TRUSTSTORES_PASSWORDS_PATHS"])
+
+ # Create the volumes and volume mounts
+ init_volume_mounts = [client.V1VolumeMount(name="tls-info", mount_path=tls_cert_dir)]
+
+ # Create the init container
+ init_containers.append(_create_container_object("truststore-merger", docker_image, False, volume_mounts=init_volume_mounts, env=env))
+
+def _get_file_extension(output_type):
+ return {
+ 'p12': 'p12',
+ 'pem': 'pem',
+ 'jks': 'jks',
+ }[output_type]
def _process_port_map(port_map):
service_ports = [] # Ports exposed internally on the k8s network
@@ -448,7 +496,7 @@ def _execute_command_in_pod(location, namespace, pod_name, command):
return {"pod" : pod_name, "output" : output}
-def deploy(namespace, component_name, image, replicas, always_pull, k8sconfig, **kwargs):
+def deploy(ctx, namespace, component_name, image, replicas, always_pull, k8sconfig, **kwargs):
'''
This will create a k8s Deployment and, if needed, one or two k8s Services.
(We are being opinionated in our use of k8s... this code decides what k8s abstractions and features to use.
@@ -476,6 +524,8 @@ def deploy(namespace, component_name, image, replicas, always_pull, k8sconfig, *
"cert_path": mount point for certificate volume in init container
"image": Docker image to use for TLS init container
"component_cert_dir" : default mount point for certs
+ - truststore-merger: a dictionary of trustore-merger information:
+ "image_tag": docker image to use for truststore-merger init container
kwargs may have:
- volumes: array of volume objects, where a volume object is:
{"host":{"path": "/path/on/host"}, "container":{"bind":"/path/on/container","mode":"rw_or_ro"}
@@ -545,12 +595,13 @@ def deploy(namespace, component_name, image, replicas, always_pull, k8sconfig, *
_add_elk_logging_sidecar(containers, volumes, volume_mounts, component_name, kwargs.get("log_info"), k8sconfig.get("filebeat"))
# Set up TLS information
- _add_tls_init_container(init_containers, volumes, volume_mounts, kwargs.get("tls_info") or {}, k8sconfig.get("tls"))
+ _add_tls_init_container(ctx, init_containers, volumes, volume_mounts, kwargs.get("tls_info") or {}, k8sconfig.get("tls"))
# Set up external TLS information
external_cert = kwargs.get("external_cert")
if external_cert and external_cert.get("use_external_tls"):
- _add_external_tls_init_container(init_containers, volumes, external_cert, k8sconfig.get("external_cert"))
+ _add_external_tls_init_container(ctx, init_containers, volumes, external_cert, k8sconfig.get("external_cert"))
+ _add_truststore_merger_init_container(ctx, init_containers, kwargs.get("tls_info") or {}, k8sconfig.get("tls"), external_cert, k8sconfig.get("truststore_merger"))
# Create the container for the component
# Make it the first container in the pod
diff --git a/k8s/k8splugin/tasks.py b/k8s/k8splugin/tasks.py
index e03e4d2..3d24277 100644
--- a/k8s/k8splugin/tasks.py
+++ b/k8s/k8splugin/tasks.py
@@ -292,7 +292,9 @@ def _create_and_start_container(container_name, image, **kwargs):
ctx.logger.info("Passing k8sconfig: {}".format(plugin_conf))
replicas = kwargs.get("replicas", 1)
resource_config = _get_resources(**kwargs)
- _, dep = k8sclient.deploy(DCAE_NAMESPACE,
+ _, dep = k8sclient.deploy(
+ ctx,
+ DCAE_NAMESPACE,
container_name,
image,
replicas=replicas,
diff --git a/k8s/k8splugin_types.yaml b/k8s/k8splugin_types.yaml
index 5d354f7..81bd7ff 100644
--- a/k8s/k8splugin_types.yaml
+++ b/k8s/k8splugin_types.yaml
@@ -23,7 +23,7 @@ plugins:
k8s:
executor: 'central_deployment_agent'
package_name: k8splugin
- package_version: 3.3.0
+ package_version: 3.4.0
data_types:
diff --git a/k8s/pom.xml b/k8s/pom.xml
index c91dcbf..31cc737 100644
--- a/k8s/pom.xml
+++ b/k8s/pom.xml
@@ -28,7 +28,7 @@ limitations under the License.
<groupId>org.onap.dcaegen2.platform.plugins</groupId>
<artifactId>k8s</artifactId>
<name>k8s-plugin</name>
- <version>3.3.0-SNAPSHOT</version>
+ <version>3.4.0-SNAPSHOT</version>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
diff --git a/k8s/setup.py b/k8s/setup.py
index 7ff694b..fb6efcb 100644
--- a/k8s/setup.py
+++ b/k8s/setup.py
@@ -23,8 +23,8 @@ from setuptools import setup
setup(
name='k8splugin',
description='Cloudify plugin for containerized components deployed using Kubernetes',
- version="3.3.0",
- author='J. F. Lucas, Michael Hwang, Tommy Carpenter, Joanna Jeremicz, Sylwia Jakubek',
+ version="3.4.0",
+ author='J. F. Lucas, Michael Hwang, Tommy Carpenter, Joanna Jeremicz, Sylwia Jakubek, Jan Malkiewicz',
packages=['k8splugin','k8sclient','configure'],
zip_safe=False,
install_requires=[
diff --git a/k8s/tests/common.py b/k8s/tests/common.py
index 9778d1f..35d34ba 100644
--- a/k8s/tests/common.py
+++ b/k8s/tests/common.py
@@ -48,6 +48,9 @@ def _set_k8s_configuration():
"keystore_password" : "secret1",
"truststore_password" : "secret2"
},
+ "truststore_merger": {
+ "image_tag": "repo/oom-truststore-merger:1.2.3"
+ },
"cbs": {
"base_url": "https://config-binding-service:10443/service_component_all/test-component"
}
@@ -160,6 +163,25 @@ def verify_external_cert(dep):
for k in expected_envs:
assert (k in envs and expected_envs[k] == envs[k])
+def verify_truststore_merger(dep):
+ cert_container = dep.spec.template.spec.init_containers[2]
+ print(cert_container)
+ assert cert_container.image == "repo/oom-truststore-merger:1.2.3"
+ assert cert_container.name == "truststore-merger"
+ assert len(cert_container.volume_mounts) == 1
+ assert cert_container.volume_mounts[0].name == "tls-info"
+ assert cert_container.volume_mounts[0].mount_path == "/opt/dcae/cacert/"
+
+ expected_envs = {
+ "TRUSTSTORES_PATHS": "/opt/dcae/cacert/trust.jks:/opt/dcae/cacert/external/truststore.p12",
+ "TRUSTSTORES_PASSWORDS_PATHS": "/opt/dcae/cacert/trust.pass:/opt/dcae/cacert/external/truststore.pass",
+ }
+
+ envs = {k.name: k.value for k in cert_container.env}
+ for k in expected_envs:
+ assert (k in envs and expected_envs[k] == envs[k])
+
+
def do_deploy(tls_info=None):
''' Common deployment operations '''
import k8sclient.k8sclient
@@ -172,7 +194,7 @@ def do_deploy(tls_info=None):
if tls_info:
kwargs["tls_info"] = tls_info
- dep, deployment_description = k8sclient.k8sclient.deploy("k8stest", "testcomponent", "example.com/testcomponent:1.4.3", 1, False, k8s_test_config, **kwargs)
+ dep, deployment_description = k8sclient.k8sclient.deploy(k8s_ctx(), "k8stest", "testcomponent", "example.com/testcomponent:1.4.3", 1, False, k8s_test_config, **kwargs)
# Make sure all of the basic k8s parameters are correct
verify_common(dep, deployment_description)
@@ -190,9 +212,18 @@ def do_deploy_ext(ext_tls_info):
kwargs['resources'] = _set_resources()
kwargs["external_cert"] = ext_tls_info
- dep, deployment_description = k8sclient.k8sclient.deploy("k8stest", "testcomponent", "example.com/testcomponent:1.4.3", 1, False, k8s_test_config, **kwargs)
+ dep, deployment_description = k8sclient.k8sclient.deploy(k8s_ctx(), "k8stest", "testcomponent", "example.com/testcomponent:1.4.3", 1, False, k8s_test_config, **kwargs)
# Make sure all of the basic k8s parameters are correct
verify_common(dep, deployment_description)
return dep, deployment_description
+
+class k8s_logger:
+ def info(self, text):
+ print(text)
+
+class k8s_ctx:
+ logger = k8s_logger()
+
+
diff --git a/k8s/tests/test_k8sclient_deploy.py b/k8s/tests/test_k8sclient_deploy.py
index 30490a6..a325b68 100644
--- a/k8s/tests/test_k8sclient_deploy.py
+++ b/k8s/tests/test_k8sclient_deploy.py
@@ -25,6 +25,7 @@ import pytest
from common import do_deploy
from common import do_deploy_ext
from common import verify_external_cert
+from common import verify_truststore_merger
def test_deploy_full_tls(mockk8sapi):
''' Deploy component with a full TLS configuration, to act as a server '''
@@ -67,3 +68,6 @@ def test_deploy_external_cert(mockk8sapi):
# Make sure all of the external init container parameters are correct
verify_external_cert(dep)
+ verify_truststore_merger(dep)
+
+