Skip to content

Commit

Permalink
Generate passwords and TLS certificates at provisioning time (#359)
Browse files Browse the repository at this point in the history
  • Loading branch information
huyhg authored May 28, 2019
1 parent e1c5099 commit cd96f0d
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 38 deletions.
42 changes: 5 additions & 37 deletions marketplace/deployer_util/expand_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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:
Expand Down
53 changes: 53 additions & 0 deletions marketplace/deployer_util/property_generator.py
Original file line number Diff line number Diff line change
@@ -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)
})
7 changes: 6 additions & 1 deletion marketplace/deployer_util/provision.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import yaml

import config_helper
import property_generator
import schema_values_common
import storage

Expand Down Expand Up @@ -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()))
Expand Down
1 change: 1 addition & 0 deletions marketplace/dev/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Expand Down

0 comments on commit cd96f0d

Please sign in to comment.