From 5b400f4c22f678ae96787f29a2a7618d8579d6e1 Mon Sep 17 00:00:00 2001 From: Sam Chow Date: Wed, 15 Aug 2018 17:17:41 -0400 Subject: [PATCH] Add one-action transplant of kube secret --- .../config/TransientDirectoryProvider.py | 21 ++++++++-- config_app/config_util/k8saccessor.py | 38 +++++++++++++++++-- util/config/validator.py | 1 + 3 files changed, 53 insertions(+), 7 deletions(-) diff --git a/config_app/config_util/config/TransientDirectoryProvider.py b/config_app/config_util/config/TransientDirectoryProvider.py index 2525baaea..33c6f4216 100644 --- a/config_app/config_util/config/TransientDirectoryProvider.py +++ b/config_app/config_util/config/TransientDirectoryProvider.py @@ -1,8 +1,12 @@ import os +import base64 + from backports.tempfile import TemporaryDirectory from config_app.config_util.config.fileprovider import FileConfigProvider from config_app.config_util.k8saccessor import KubernetesAccessorSingleton +from util.config.validator import EXTRA_CA_DIRECTORY, EXTRA_CA_DIRECTORY_PREFIX + class TransientDirectoryProvider(FileConfigProvider): @@ -38,10 +42,21 @@ class TransientDirectoryProvider(FileConfigProvider): return self.config_volume def save_configuration_to_kubernetes(self): - config_path = self.get_config_dir_path() + data = {} - for name in os.listdir(config_path): + certs_dir = os.path.join(self.config_volume, EXTRA_CA_DIRECTORY) + if os.path.exists(certs_dir): + for extra_cert in os.listdir(certs_dir): + with open(os.path.join(certs_dir, extra_cert)) as f: + data[EXTRA_CA_DIRECTORY_PREFIX + extra_cert] = base64.b64encode(f.read()) + + + for name in os.listdir(self.config_volume): file_path = os.path.join(self.config_volume, name) - KubernetesAccessorSingleton.get_instance().save_file_as_secret(name, file_path) + if not os.path.isdir(file_path): + with open(file_path) as f: + data[name] = base64.b64encode(f.read()) + + KubernetesAccessorSingleton.get_instance().replace_qe_secret(data) return 200 diff --git a/config_app/config_util/k8saccessor.py b/config_app/config_util/k8saccessor.py index 61efb04fc..d498ede4d 100644 --- a/config_app/config_util/k8saccessor.py +++ b/config_app/config_util/k8saccessor.py @@ -35,10 +35,40 @@ class KubernetesAccessorSingleton(object): return cls._instance - def save_file_as_secret(self, name, file_path): - with open(file_path) as f: - value = f.read() - self._update_secret_file(name, value) + def save_file_as_secret(self, name, file_pointer): + value = file_pointer.read() + self._update_secret_file(name, value) + + def replace_qe_secret(self, new_secret_data): + """ + Removes the old config and replaces it with the new_secret_data as one action + """ + # Check first that the namespace for Quay Enterprise exists. If it does not, report that + # as an error, as it seems to be a common issue. + namespace_url = 'namespaces/%s' % (self.kube_config.qe_namespace) + response = self._execute_k8s_api('GET', namespace_url) + if response.status_code // 100 != 2: + msg = 'A Kubernetes namespace with name `%s` must be created to save config' % self.kube_config.qe_namespace + raise Exception(msg) + + # Check if the secret exists. If not, then we create an empty secret and then update the file + # inside. + secret_url = 'namespaces/%s/secrets/%s' % (self.kube_config.qe_namespace, self.kube_config.qe_config_secret) + secret = self._lookup_secret() + if secret is None: + self._assert_success(self._execute_k8s_api('POST', secret_url, { + "kind": "Secret", + "apiVersion": "v1", + "metadata": { + "name": self.kube_config.qe_config_secret + }, + "data": {} + })) + + # Update the secret to reflect the file change. + secret['data'] = new_secret_data + + self._assert_success(self._execute_k8s_api('PUT', secret_url, secret)) def get_qe_deployments(self): """" diff --git a/util/config/validator.py b/util/config/validator.py index 54f23938d..24d45570d 100644 --- a/util/config/validator.py +++ b/util/config/validator.py @@ -41,6 +41,7 @@ CONFIG_FILENAMES = (SSL_FILENAMES + DB_SSL_FILENAMES + JWT_FILENAMES + ACI_CERT_ LDAP_FILENAMES) CONFIG_FILE_SUFFIXES = ['-cloudfront-signing-key.pem'] EXTRA_CA_DIRECTORY = 'extra_ca_certs' +EXTRA_CA_DIRECTORY_PREFIX = 'extra_ca_certs_' VALIDATORS = { DatabaseValidator.name: DatabaseValidator.validate,