From cd96f0d72a70457b590c511de77701e356ef063a Mon Sep 17 00:00:00 2001 From: Huy Huynh Date: Tue, 28 May 2019 14:09:41 -0700 Subject: [PATCH] Generate passwords and TLS certificates at provisioning time (#359) --- marketplace/deployer_util/expand_config.py | 42 ++------------- .../deployer_util/property_generator.py | 53 +++++++++++++++++++ marketplace/deployer_util/provision.py | 7 ++- marketplace/dev/Dockerfile | 1 + 4 files changed, 65 insertions(+), 38 deletions(-) create mode 100644 marketplace/deployer_util/property_generator.py diff --git a/marketplace/deployer_util/expand_config.py b/marketplace/deployer_util/expand_config.py index e007a2bb..8d0ffc3e 100755 --- a/marketplace/deployer_util/expand_config.py +++ b/marketplace/deployer_util/expand_config.py @@ -17,15 +17,13 @@ import base64 import json import os -import OpenSSL -import random from argparse import ArgumentParser import yaml import config_helper +import property_generator import schema_values_common -from password import GeneratePassword _PROG_HELP = """ Modifies the configuration parameter files in a directory @@ -98,12 +96,11 @@ def expand(values_dict, schema, app_uid=''): # thus is eligible for auto-generation. if v is None: if prop.password: - v = generate_password(prop.password) + v = property_generator.generate_password(prop.password) elif prop.application_uid: v = app_uid or '' - generate_properties_for_appuid(prop, app_uid, generated) elif prop.tls_certificate: - v = generate_tls_certificate() + v = property_generator.generate_tls_certificate() elif prop.xtype == config_helper.XTYPE_ISTIO_ENABLED: # For backward compatibility. v = False @@ -132,6 +129,8 @@ def expand(values_dict, schema, app_uid=''): raise InvalidProperty( 'Invalid value for TLS_CERTIFICATE property {}: {}'.format(k, v)) generate_properties_for_tls_certificate(prop, v, generated) + elif prop.application_uid: + generate_properties_for_appuid(prop, v, generated) if v is not None: result[k] = v @@ -247,37 +246,6 @@ def generate_properties_for_string(prop, value, result): result[prop.string.base64_encoded] = base64.b64encode(value) -def generate_password(config): - pw = GeneratePassword(config.length, config.include_symbols) - if config.base64: - pw = base64.b64encode(pw) - return pw - - -def generate_tls_certificate(): - cert_seconds_to_expiry = 60 * 60 * 24 * 365 # one year - - key = OpenSSL.crypto.PKey() - key.generate_key(OpenSSL.crypto.TYPE_RSA, 2048) - - cert = OpenSSL.crypto.X509() - cert.get_subject().OU = 'GCP Marketplace K8s App Tools' - cert.get_subject().CN = 'Temporary Certificate' - cert.gmtime_adj_notBefore(0) - cert.gmtime_adj_notAfter(cert_seconds_to_expiry) - cert.set_serial_number(random.getrandbits(64)) - cert.set_issuer(cert.get_subject()) - cert.set_pubkey(key) - cert.sign(key, 'sha256') - - return json.dumps({ - 'private_key': - OpenSSL.crypto.dump_privatekey(OpenSSL.crypto.FILETYPE_PEM, key), - 'certificate': - OpenSSL.crypto.dump_certificate(OpenSSL.crypto.FILETYPE_PEM, cert) - }) - - def generate_properties_for_tls_certificate(prop, value, result): certificate = json.loads(value) if prop.tls_certificate.base64_encoded_private_key: diff --git a/marketplace/deployer_util/property_generator.py b/marketplace/deployer_util/property_generator.py new file mode 100644 index 00000000..242e8dfe --- /dev/null +++ b/marketplace/deployer_util/property_generator.py @@ -0,0 +1,53 @@ +# Copyright 2018 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import base64 +import json +import OpenSSL +import random + +from password import GeneratePassword + + +def generate_password(config): + """Generate password value for SchemaXPassword config.""" + pw = GeneratePassword(config.length, config.include_symbols) + if config.base64: + pw = base64.b64encode(pw) + return pw + + +def generate_tls_certificate(): + """Generate TLS value, a json string.""" + cert_seconds_to_expiry = 60 * 60 * 24 * 365 # one year + + key = OpenSSL.crypto.PKey() + key.generate_key(OpenSSL.crypto.TYPE_RSA, 2048) + + cert = OpenSSL.crypto.X509() + cert.get_subject().OU = 'GCP Marketplace K8s App Tools' + cert.get_subject().CN = 'Temporary Certificate' + cert.gmtime_adj_notBefore(0) + cert.gmtime_adj_notAfter(cert_seconds_to_expiry) + cert.set_serial_number(random.getrandbits(64)) + cert.set_issuer(cert.get_subject()) + cert.set_pubkey(key) + cert.sign(key, 'sha256') + + return json.dumps({ + 'private_key': + OpenSSL.crypto.dump_privatekey(OpenSSL.crypto.FILETYPE_PEM, key), + 'certificate': + OpenSSL.crypto.dump_certificate(OpenSSL.crypto.FILETYPE_PEM, cert) + }) diff --git a/marketplace/deployer_util/provision.py b/marketplace/deployer_util/provision.py index 6a4743af..2aa5fc97 100755 --- a/marketplace/deployer_util/provision.py +++ b/marketplace/deployer_util/provision.py @@ -21,6 +21,7 @@ import yaml import config_helper +import property_generator import schema_values_common import storage @@ -97,8 +98,12 @@ def process(schema, values, deployer_image, deployer_entrypoint, version_repo, # TODO: Really populate this value. props[prop.name] = False elif prop.xtype == config_helper.XTYPE_INGRESS_AVAILABLE: - # TODO: Really populate this value. + # TODO(#360): Really populate this value. props[prop.name] = True + elif prop.password: + props[prop.name] = property_generator.generate_password(prop.password) + elif prop.tls_certificate: + props[prop.name] = property_generator.generate_tls_certificate() # Merge input and provisioned properties. app_params = dict(list(values.iteritems()) + list(props.iteritems())) diff --git a/marketplace/dev/Dockerfile b/marketplace/dev/Dockerfile index 607c136f..e923512f 100644 --- a/marketplace/dev/Dockerfile +++ b/marketplace/dev/Dockerfile @@ -9,6 +9,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ jq \ make \ python \ + python-openssl \ python-pip \ python-setuptools \ python-yaml \