From: Gabriel Cuba Date: Wed, 26 Apr 2023 17:01:25 +0000 (-0500) Subject: Add client TLS to gRPC server X-Git-Url: https://osm.etsi.org/gitweb/?a=commitdiff_plain;h=refs%2Fheads%2Fclient-tls;p=osm%2Fdocker-api-fe.git Add client TLS to gRPC server --- diff --git a/Dockerfile b/Dockerfile index 62702f2..6761fe1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -23,7 +23,8 @@ RUN apt-get update && apt-get install -y git python3 python3-pip \ && python3 -m pip install --upgrade pip \ && python3 -m pip install -U grpcio-tools \ && python3 -m pip install -U grpclib \ - && python3 -m pip install -U PyYAML + && python3 -m pip install -U PyYAML \ + && python3 -m pip install -U kubernetes # Libraries used by the vnf: asyncssh, ansible #RUN apt-get update && apt-get install software-properties-common \ diff --git a/osm_ee/util/util_grpc.py b/osm_ee/util/util_grpc.py index df904c1..5fe8fc5 100644 --- a/osm_ee/util/util_grpc.py +++ b/osm_ee/util/util_grpc.py @@ -1,26 +1,46 @@ +from base64 import b64decode import logging import ssl +from .util_kubernetes import get_secret_data logger = logging.getLogger("osm_ee.util_grpc") - -SERVER_CERT = "/etc/ssl/grpc-tls/tls.crt" -SERVER_KEY = "/etc/ssl/grpc-tls/tls.key" +SERVER_CERT_SECRET = "ee-tls" +CLIENT_CA_SECRET = "osm-ca" +SERVER_CERT_FILE = "/etc/ssl/ee-tls.crt" +SERVER_KEY_FILE = "/etc/ssl/ee-tls.key" +CLIENT_CA_FILE = "/etc/ssl/osm-ca.crt" def create_secure_context() -> ssl.SSLContext: - ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) - # ctx.verify_mode = ssl.CERT_REQUIRED - try: - ctx.load_cert_chain(str(SERVER_CERT), str(SERVER_KEY)) - except FileNotFoundError: - logger.warning("TLS Certificate not found, starting gRPC server in unsecure mode") + # retrieve certificates from secrets + if not _retrieve_certs(): + logger.warning("TLS Certificates not found, starting gRPC server in unsecure mode") return None - # TODO: client TLS - # ctx.load_verify_locations(str(trusted)) + # create SSL context + ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) + ctx.verify_mode = ssl.CERT_REQUIRED + ctx.load_cert_chain(SERVER_CERT_FILE, SERVER_KEY_FILE) + ctx.load_verify_locations(CLIENT_CA_FILE) ctx.set_ciphers('ECDHE+AESGCM:ECDHE+CHACHA20:DHE+AESGCM:DHE+CHACHA20') ctx.set_alpn_protocols(['h2']) try: ctx.set_npn_protocols(['h2']) except NotImplementedError: pass - return ctx \ No newline at end of file + return ctx + + +def _retrieve_certs(): + _server_data = get_secret_data(SERVER_CERT_SECRET) + lcm_ca = get_secret_data(CLIENT_CA_SECRET).get("ca.crt") + if not (_server_data and lcm_ca): + return False + server_cert = _server_data.get("tls.crt") + with open(SERVER_CERT_FILE, "w") as server_cert_file: + server_cert_file.write(b64decode(server_cert).decode()) + server_key = _server_data.get("tls.key") + with open(SERVER_KEY_FILE, "w") as server_key_file: + server_key_file.write(b64decode(server_key).decode()) + with open(CLIENT_CA_FILE, "w") as client_ca_file: + client_ca_file.write(b64decode(lcm_ca).decode()) + return True diff --git a/osm_ee/util/util_kubernetes.py b/osm_ee/util/util_kubernetes.py new file mode 100644 index 0000000..d4594d9 --- /dev/null +++ b/osm_ee/util/util_kubernetes.py @@ -0,0 +1,23 @@ +from kubernetes import client, config +from kubernetes.client.rest import ApiException + + +def get_secret_data(name) -> dict: + # assume that we are executing in a kubernetes pod + try: + config.load_incluster_config() + except config.ConfigException: + # we are not running in kubernetes + return {} + # Read the namespace from the service account + current_namespace = open("/var/run/secrets/kubernetes.io/serviceaccount/namespace").read() + + v1 = client.CoreV1Api() + try: + secret = v1.read_namespaced_secret(name, current_namespace) + except ApiException as e: + if e.reason == 'Not Found': # Backwards compatibility: we run in k8s but certs don't exist + return {} + else: + raise + return secret.data