diff --git a/docs/schema.md b/docs/schema.md index 0924ce89..6ec1cb29 100644 --- a/docs/schema.md +++ b/docs/schema.md @@ -204,6 +204,7 @@ Supports versions starting from `v1beta1`. Represents the type of the input in the form for that property. #### Supported types + - `string` - `integer` - `boolean` @@ -240,7 +241,7 @@ A regex pattern. The value needs to match `pattern`. ### x-google-marketplace -This serves as an annotation to tell gcp to handle that property in a special way, depending on `type`. +This serves as an annotation to tell GCP to handle that property in a special way, depending on `type`. It has several usages and more will be added based on demand. ### [Examples](https://github.com/GoogleCloudPlatform/marketplace-k8s-app-example/blob/master/wordpress/schema.yaml). @@ -253,6 +254,7 @@ It has several usages and more will be added based on demand. It defines how this object will be handled. Each type has a different set of properties. #### Supported types + - `NAME`: To be used as the name of the app. - `NAMESPACE`: To be used as the kubernetes namespace where the app will installed. - `IMAGE`: Link to a docker image. @@ -264,6 +266,7 @@ It defines how this object will be handled. Each type has a different set of pro - `APPLICATION_UID`: The uuid of the created `Application` object. - `ISTIO_ENABLED`: Indicates whether Istio is enabled for the deployment. - `INGRESS_AVAILABLE`: Indicates whether the cluster is detected to have Ingress support. +- `TLS_CERTIFICATE`: To be used to support a custom certificate or generate a self-signed certificate. --- @@ -421,6 +424,66 @@ This boolean property receives a True value if the cluster is detected to have I --- +### type: TLS_CERTIFICATE + +This property provides an SSL/TLS certificate for the Kubernetes manifest. By default, a self-signed certificate is generated. + +Example: + +```yaml +properties: + certificate: + type: string + x-google-marketplace: + type: TLS_CERTIFICATE + tlsCertificate: + generatedProperties: + base64EncodedPrivateKey: TLS_CERTIFICATE_KEY + base64EncodedCertificate: TLS_CERTIFICATE_CRT +``` + +* `base64EncodedPrivateKey`: Denotes the name of a property receive a private key. +* `base64EncodedCertificate`: Denotes the name of a property receive a certificate. + +You can provide your custom certificate by overwrite the `certificate` property in the JSON format as following: + +```json +{ + "private_key": "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----", + "certificate": "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----" +} +``` + +In your helm chart, based on the above example, you can handle the certificate: + +```yaml +apiVersion: v1 +kind: Secret +metadata: + name: tls-secret + namespace: demo +data: + tls.key: {{ .Values.TLS_CERTIFICATE_KEY }} + tls.crt: {{ .Values.TLS_CERTIFICATE_CRT }} +type: kubernetes.io/tls +``` + +In your `envsubst` manifest, based on the above example, you can handle the certificate: + +```yaml +apiVersion: v1 +kind: Secret +metadata: + name: tls-secret + namespace: demo +data: + tls.key: $TLS_CERTIFICATE_KEY + tls.crt: $TLS_CERTIFICATE_CRT +type: kubernetes.io/tls +``` + +--- + ## clusterConstraints Nested under `x-google-marketplace`, this can be used for specifying constraints on the kubernetes cluster. These constraints help determine if the application can be successfully deployed to the cluster. The UI can filter out ineligible clusters following these constraints. diff --git a/marketplace/deployer_envsubst_base/Dockerfile b/marketplace/deployer_envsubst_base/Dockerfile index b398c3ca..474ca231 100644 --- a/marketplace/deployer_envsubst_base/Dockerfile +++ b/marketplace/deployer_envsubst_base/Dockerfile @@ -6,6 +6,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ gettext \ jq \ python \ + python-openssl \ python-pip \ python-setuptools \ python-yaml \ diff --git a/marketplace/deployer_helm_base/Dockerfile b/marketplace/deployer_helm_base/Dockerfile index b5d3daf6..15903d8c 100644 --- a/marketplace/deployer_helm_base/Dockerfile +++ b/marketplace/deployer_helm_base/Dockerfile @@ -6,6 +6,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ gettext \ jq \ python \ + python-openssl \ python-pip \ python-setuptools \ python-yaml \ diff --git a/marketplace/deployer_helm_tiller_base/Dockerfile b/marketplace/deployer_helm_tiller_base/Dockerfile index 6cfb3eaf..6a194430 100644 --- a/marketplace/deployer_helm_tiller_base/Dockerfile +++ b/marketplace/deployer_helm_tiller_base/Dockerfile @@ -9,6 +9,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ jq \ procps \ python \ + python-openssl \ python-pip \ python-setuptools \ python-yaml \ diff --git a/marketplace/deployer_util/config_helper.py b/marketplace/deployer_util/config_helper.py index c9c89082..1cb9e6b1 100644 --- a/marketplace/deployer_util/config_helper.py +++ b/marketplace/deployer_util/config_helper.py @@ -37,6 +37,7 @@ XTYPE_APPLICATION_UID = 'APPLICATION_UID' XTYPE_ISTIO_ENABLED = 'ISTIO_ENABLED' XTYPE_INGRESS_AVAILABLE = 'INGRESS_AVAILABLE' +XTYPE_TLS_CERTIFICATE = 'TLS_CERTIFICATE' WIDGET_TYPES = ['help'] @@ -465,9 +466,11 @@ def __init__(self, name, dictionary, required): self._service_account = None self._storage_class = None self._string = None + self._tls_certificate = None if not NAME_RE.match(name): raise InvalidSchema('Invalid property name: {}'.format(name)) + self._type = _must_get_and_apply( dictionary, 'type', lambda v: { 'int': int, @@ -476,6 +479,7 @@ def __init__(self, name, dictionary, required): 'number': float, 'boolean': bool, }.get(v, None), 'Property {} has no type'.format(name)) + if not self._type: raise InvalidSchema('Property {} has unsupported type: {}'.format( name, dictionary['type'])) @@ -488,6 +492,7 @@ def __init__(self, name, dictionary, required): if self._x: xt = _must_get(self._x, 'type', 'Property {} has {} without a type'.format(name, XGOOGLE)) + if xt in (XTYPE_NAME, XTYPE_NAMESPACE, XTYPE_DEPLOYER_IMAGE): _property_must_have_type(self, str) elif xt in (XTYPE_ISTIO_ENABLED, XTYPE_INGRESS_AVAILABLE): @@ -525,6 +530,10 @@ def __init__(self, name, dictionary, required): _property_must_have_type(self, str) d = self._x.get('reportingSecret', {}) self._reporting_secret = SchemaXReportingSecret(d) + elif xt == XTYPE_TLS_CERTIFICATE: + _property_must_have_type(self, str) + d = self._x.get('tlsCertificate', {}) + self._tls_certificate = SchemaXTlsCertificate(d) else: raise InvalidSchema('Property {} has an unknown type: {}'.format( name, xt)) @@ -580,6 +589,10 @@ def storage_class(self): def string(self): return self._string + @property + def tls_certificate(self): + return self._tls_certificate + def str_to_type(self, str_val): if self._type == bool: if str_val in {'true', 'True', 'yes', 'Yes'}: @@ -745,6 +758,26 @@ def __init__(self, dictionary): pass +class SchemaXTlsCertificate: + """Accesses TLS_CERTIFICATE property.""" + + def __init__(self, dictionary): + generated_properties = dictionary.get('generatedProperties', {}) + + self._base64_encoded_private_key = generated_properties.get( + 'base64EncodedPrivateKey', None) + self._base64_encoded_certificate = generated_properties.get( + 'base64EncodedCertificate', None) + + @property + def base64_encoded_private_key(self): + return self._base64_encoded_private_key + + @property + def base64_encoded_certificate(self): + return self._base64_encoded_certificate + + def _must_get(dictionary, key, error_msg): """Gets the value of the key, or raises InvalidSchema.""" if key not in dictionary: diff --git a/marketplace/deployer_util/config_helper_test.py b/marketplace/deployer_util/config_helper_test.py index 493ef306..8dd11821 100644 --- a/marketplace/deployer_util/config_helper_test.py +++ b/marketplace/deployer_util/config_helper_test.py @@ -70,6 +70,14 @@ type: boolean x-google-marketplace: type: INGRESS_AVAILABLE + certificate: + type: string + x-google-marketplace: + type: TLS_CERTIFICATE + tlsCertificate: + generatedProperties: + base64EncodedPrivateKey: keyEncoded + base64EncodedCertificate: crtEncoded required: - propertyString - propertyPassword @@ -113,14 +121,16 @@ def load_and_validate(schema_yaml): def test_types_and_defaults(self): schema = config_helper.Schema.load_yaml(SCHEMA) - self.assertEqual({ - 'propertyString', 'propertyStringWithDefault', 'propertyInt', - 'propertyIntWithDefault', 'propertyInteger', - 'propertyIntegerWithDefault', 'propertyNumber', - 'propertyNumberWithDefault', 'propertyBoolean', - 'propertyBooleanWithDefault', 'propertyImage', 'propertyDeployerImage', - 'propertyPassword', 'applicationUid', 'istioEnabled', 'ingressAvailable' - }, set(schema.properties)) + self.assertEqual( + { + 'propertyString', 'propertyStringWithDefault', 'propertyInt', + 'propertyIntWithDefault', 'propertyInteger', + 'propertyIntegerWithDefault', 'propertyNumber', + 'propertyNumberWithDefault', 'propertyBoolean', + 'propertyBooleanWithDefault', 'propertyImage', + 'propertyDeployerImage', 'propertyPassword', 'applicationUid', + 'istioEnabled', 'ingressAvailable', 'certificate' + }, set(schema.properties)) self.assertEqual(str, schema.properties['propertyString'].type) self.assertIsNone(schema.properties['propertyString'].default) self.assertEqual(str, schema.properties['propertyStringWithDefault'].type) @@ -161,6 +171,8 @@ def test_types_and_defaults(self): self.assertEqual(bool, schema.properties['ingressAvailable'].type) self.assertEqual('INGRESS_AVAILABLE', schema.properties['ingressAvailable'].xtype) + self.assertEqual(str, schema.properties['certificate'].type) + self.assertEqual('TLS_CERTIFICATE', schema.properties['certificate'].xtype) def test_invalid_names(self): self.assertRaises( @@ -385,6 +397,40 @@ def test_password(self): self.assertEqual(True, schema.properties['pw'].password.include_symbols) self.assertEqual(False, schema.properties['pw'].password.base64) + def test_certificate(self): + schema = config_helper.Schema.load_yaml(""" + properties: + c1: + type: string + x-google-marketplace: + type: TLS_CERTIFICATE + """) + + self.assertIsNotNone(schema.properties['c1'].tls_certificate) + self.assertIsNone( + schema.properties['c1'].tls_certificate.base64_encoded_private_key) + self.assertIsNone( + schema.properties['c1'].tls_certificate.base64_encoded_certificate) + + schema = config_helper.Schema.load_yaml(""" + properties: + c1: + type: string + x-google-marketplace: + type: TLS_CERTIFICATE + tlsCertificate: + generatedProperties: + base64EncodedPrivateKey: c1.Base64Key + base64EncodedCertificate: c1.Base64Crt + """) + self.assertIsNotNone(schema.properties['c1'].tls_certificate) + self.assertEqual( + 'c1.Base64Key', + schema.properties['c1'].tls_certificate.base64_encoded_private_key) + self.assertEqual( + 'c1.Base64Crt', + schema.properties['c1'].tls_certificate.base64_encoded_certificate) + def test_int_type(self): schema = config_helper.Schema.load_yaml(""" properties: diff --git a/marketplace/deployer_util/expand_config.py b/marketplace/deployer_util/expand_config.py index 1ddd2598..675cb43d 100755 --- a/marketplace/deployer_util/expand_config.py +++ b/marketplace/deployer_util/expand_config.py @@ -15,7 +15,10 @@ # limitations under the License. import base64 +import json import os +import OpenSSL +import random from argparse import ArgumentParser import yaml @@ -65,17 +68,29 @@ def expand(values_dict, schema, app_uid=''): if k not in schema.properties: raise InvalidProperty('No such property defined in schema: {}'.format(k)) + # Captures the final property name-value mappings. + # This has both properties directly specified under schema's `properties` and + # generated properties. See below for details about generated properties. result = {} + # Captures only the generated properties. These are not directly specified in the schema + # under `properties`. Rather, their name are specified in special `generatedProperties` fields + # under individual property `x-google-marketplace`. + # Note that properties with generated values are NOT generated properties. generated = {} + + # Copy explicitly specified values and generate values into result. for k, prop in schema.properties.iteritems(): v = values_dict.get(k, None) + # The value is not explicitly specified and thus is eligible for auto-generation. if v is None: if prop.password: v = 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() elif prop.xtype == config_helper.XTYPE_ISTIO_ENABLED: # For backward compatibility. v = False @@ -84,18 +99,26 @@ def expand(values_dict, schema, app_uid=''): v = True elif prop.default is not None: v = prop.default - else: # if v is None + + # Generate additional properties from this property. + if v is not None: if prop.image: if not isinstance(v, str): raise InvalidProperty( 'Invalid value for IMAGE property {}: {}'.format(k, v)) generate_properties_for_image(prop, v, generated) - if prop.string: + elif prop.string: if not isinstance(v, str): raise InvalidProperty( 'Invalid value for STRING property {}: {}'.format(k, v)) generate_properties_for_string(prop, v, generated) + elif prop.tls_certificate: + if not isinstance(v, str): + raise InvalidProperty( + 'Invalid value for TLS_CERTIFICATE property {}: {}'.format(k, v)) + generate_properties_for_tls_certificate(prop, v, generated) + # Copy generated properties into result, validating that there are no collisions. if v is not None: result[k] = v @@ -174,6 +197,40 @@ def generate_password(config): 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: + result[prop.tls_certificate.base64_encoded_private_key] = base64.b64encode( + certificate['private_key']) + if prop.tls_certificate.base64_encoded_certificate: + result[prop.tls_certificate.base64_encoded_certificate] = base64.b64encode( + certificate['certificate']) + + def write_values(values, values_file): if not os.path.exists(os.path.dirname(values_file)): os.makedirs(os.path.dirname(values_file)) diff --git a/marketplace/deployer_util/expand_config_test.py b/marketplace/deployer_util/expand_config_test.py index 220c307a..8da537d7 100644 --- a/marketplace/deployer_util/expand_config_test.py +++ b/marketplace/deployer_util/expand_config_test.py @@ -12,7 +12,10 @@ # See the License for the specific language governing permissions and # limitations under the License. +import base64 +import json import re +import OpenSSL import tempfile import unittest @@ -59,11 +62,12 @@ def test_generate_properties_for_image_split_by_colon(self): after: i1.after """) result = expand_config.expand({'i1': 'gcr.io/foo:bar'}, schema) - self.assertEqual({ - 'i1': 'gcr.io/foo:bar', - 'i1.before': 'gcr.io/foo', - 'i1.after': 'bar', - }, result) + self.assertEqual( + { + 'i1': 'gcr.io/foo:bar', + 'i1.before': 'gcr.io/foo', + 'i1.after': 'bar', + }, result) def test_generate_properties_for_image_split_to_registry_repo_tag(self): schema = config_helper.Schema.load_yaml(""" @@ -81,12 +85,13 @@ def test_generate_properties_for_image_split_to_registry_repo_tag(self): tag: i1.tag """) result = expand_config.expand({'i1': 'gcr.io/foo/bar:baz'}, schema) - self.assertEqual({ - 'i1': 'gcr.io/foo/bar:baz', - 'i1.registry': 'gcr.io', - 'i1.repo': 'foo/bar', - 'i1.tag': 'baz', - }, result) + self.assertEqual( + { + 'i1': 'gcr.io/foo/bar:baz', + 'i1.registry': 'gcr.io', + 'i1.repo': 'foo/bar', + 'i1.tag': 'baz', + }, result) def test_generate_properties_for_string_base64_encoded(self): schema = config_helper.Schema.load_yaml(""" @@ -106,6 +111,89 @@ def test_generate_properties_for_string_base64_encoded(self): 's1.encoded': 'dGVzdA==', }, result) + def test_generate_certificate(self): + schema = config_helper.Schema.load_yaml(""" + applicationApiVersion: v1beta1 + properties: + c1: + type: string + x-google-marketplace: + type: TLS_CERTIFICATE + """) + result = expand_config.expand({}, schema) + cert_json = json.loads(result['c1']) + self.assertIsNotNone(cert_json['private_key']) + self.assertIsNotNone(cert_json['certificate']) + + schema = config_helper.Schema.load_yaml(""" + applicationApiVersion: v1beta1 + properties: + c1: + type: string + x-google-marketplace: + type: TLS_CERTIFICATE + tlsCertificate: + generatedProperties: + base64EncodedPrivateKey: c1.Base64Key + base64EncodedCertificate: c1.Base64Crt + """) + result = expand_config.expand({}, schema) + + cert_json = json.loads(result['c1']) + self.assertIsNotNone(result['c1']) + self.assertEqual(result['c1.Base64Key'], + base64.b64encode(cert_json['private_key'])) + self.assertEqual(result['c1.Base64Crt'], + base64.b64encode(cert_json['certificate'])) + + key = OpenSSL.crypto.load_privatekey( + OpenSSL.crypto.FILETYPE_PEM, base64.b64decode(result['c1.Base64Key'])) + self.assertEqual(key.bits(), 2048) + self.assertEqual(key.type(), OpenSSL.crypto.TYPE_RSA) + + cert = OpenSSL.crypto.load_certificate( + OpenSSL.crypto.FILETYPE_PEM, base64.b64decode(result['c1.Base64Crt'])) + self.assertEqual(cert.get_subject(), cert.get_issuer()) + self.assertEqual(cert.get_subject().OU, 'GCP Marketplace K8s App Tools') + self.assertEqual(cert.get_subject().CN, 'Temporary Certificate') + self.assertEqual(cert.get_signature_algorithm(), 'sha256WithRSAEncryption') + self.assertFalse(cert.has_expired()) + + def test_generate_properties_for_certificate(self): + schema = config_helper.Schema.load_yaml(""" + applicationApiVersion: v1beta1 + properties: + c1: + type: string + x-google-marketplace: + type: TLS_CERTIFICATE + """) + result = expand_config.expand( + {'c1': '{"private_key": "key", "certificate": "vrt"}'}, schema) + self.assertEqual({'c1': '{"private_key": "key", "certificate": "vrt"}'}, + result) + + schema = config_helper.Schema.load_yaml(""" + applicationApiVersion: v1beta1 + properties: + c1: + type: string + x-google-marketplace: + type: TLS_CERTIFICATE + tlsCertificate: + generatedProperties: + base64EncodedPrivateKey: c1.Base64Key + base64EncodedCertificate: c1.Base64Crt + """) + result = expand_config.expand( + {'c1': '{"private_key": "key", "certificate": "vrt"}'}, schema) + self.assertEqual( + { + 'c1': '{"private_key": "key", "certificate": "vrt"}', + 'c1.Base64Key': 'a2V5', + 'c1.Base64Crt': 'dnJ0', + }, result) + def test_generate_password(self): schema = config_helper.Schema.load_yaml(""" applicationApiVersion: v1beta1 @@ -136,10 +224,11 @@ def test_application_uid(self): createApplicationBoolean: application.create """) result = expand_config.expand({}, schema, app_uid='1234-abcd') - self.assertEqual({ - 'application_uid': '1234-abcd', - 'application.create': False - }, result) + self.assertEqual( + { + 'application_uid': '1234-abcd', + 'application.create': False + }, result) result = expand_config.expand({}, schema, app_uid='') self.assertEqual({ 'application_uid': '', diff --git a/marketplace/deployer_util/provision_test.py b/marketplace/deployer_util/provision_test.py index c72cd6fe..c483703f 100644 --- a/marketplace/deployer_util/provision_test.py +++ b/marketplace/deployer_util/provision_test.py @@ -58,5 +58,6 @@ def test_deployer_image_inject(self): values = {} deployer_image = 'gcr.io/cloud-marketplace/partner/solution/deployer:latest' self.assertEquals( - provision.inject_deployer_image_properties( - values, schema, deployer_image), {"deployer_image": deployer_image}) + provision.inject_deployer_image_properties(values, schema, + deployer_image), + {"deployer_image": deployer_image}) diff --git a/tests/marketplace/deployer_envsubst_base/full/manifest/application.yaml.template b/tests/marketplace/deployer_envsubst_base/full/manifest/application.yaml.template index 43ce6196..1eec31d5 100644 --- a/tests/marketplace/deployer_envsubst_base/full/manifest/application.yaml.template +++ b/tests/marketplace/deployer_envsubst_base/full/manifest/application.yaml.template @@ -60,6 +60,19 @@ spec: After accessing the WordPress main page, you will see the installation wizard. Follow the instructions presented on the screen to finish the process. + info: + - name: TLS Cert + type: Reference + valueFrom: + secretKeyRef: + key: tls.crt + name: $name-tls-secret + - name: TLS Key + type: Reference + valueFrom: + secretKeyRef: + key: tls.key + name: $name-tls-secret selector: matchLabels: app.kubernetes.io/name: "$name" diff --git a/tests/marketplace/deployer_envsubst_base/full/manifest/manifests.yaml.template b/tests/marketplace/deployer_envsubst_base/full/manifest/manifests.yaml.template index 66118ce4..98737f4b 100644 --- a/tests/marketplace/deployer_envsubst_base/full/manifest/manifests.yaml.template +++ b/tests/marketplace/deployer_envsubst_base/full/manifest/manifests.yaml.template @@ -10,6 +10,18 @@ type: Opaque data: password: "$dbPassword" --- +apiVersion: v1 +kind: Secret +metadata: + name: $name-tls-secret + labels: + app.kubernetes.io/name: $name + app.kubernetes.io/component: tls-secret +data: + tls.key: $TLS_CERTIFICATE_KEY + tls.crt: $TLS_CERTIFICATE_CRT +type: kubernetes.io/tls +--- apiVersion: apps/v1beta2 kind: Deployment metadata: diff --git a/tests/marketplace/deployer_envsubst_base/full/schema.yaml b/tests/marketplace/deployer_envsubst_base/full/schema.yaml index b895fee5..2b2da230 100644 --- a/tests/marketplace/deployer_envsubst_base/full/schema.yaml +++ b/tests/marketplace/deployer_envsubst_base/full/schema.yaml @@ -68,6 +68,14 @@ properties: type: boolean x-google-marketplace: type: INGRESS_AVAILABLE + certificate: + type: string + x-google-marketplace: + type: TLS_CERTIFICATE + tlsCertificate: + generatedProperties: + base64EncodedPrivateKey: TLS_CERTIFICATE_KEY + base64EncodedCertificate: TLS_CERTIFICATE_CRT required: - name - namespace @@ -80,6 +88,7 @@ required: - customInteger - customBoolean - reportingSecret +- certificate form: - widget: help description: My arbitrary description diff --git a/tests/marketplace/deployer_helm_tiller_base/onbuild/standard/chart/minimal-helm-chart/templates/pod.yaml b/tests/marketplace/deployer_helm_tiller_base/onbuild/standard/chart/minimal-helm-chart/templates/pod.yaml index 1fd16e7f..2fccd1d6 100644 --- a/tests/marketplace/deployer_helm_tiller_base/onbuild/standard/chart/minimal-helm-chart/templates/pod.yaml +++ b/tests/marketplace/deployer_helm_tiller_base/onbuild/standard/chart/minimal-helm-chart/templates/pod.yaml @@ -10,3 +10,15 @@ spec: - name: {{ .Release.Name }} image: busybox command: ['sleep', '3600'] +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ .Release.Name }}-tls-secret + labels: + app.kubernetes.io/name: {{ .Release.Name }} + app.kubernetes.io/component: tls-secret +data: + tls.key: {{ .Values.tls.base64EncodedPrivateKey }} + tls.crt: {{ .Values.tls.base64EncodedCertificate }} +type: kubernetes.io/tls diff --git a/tests/marketplace/deployer_helm_tiller_base/onbuild/standard/chart/minimal-helm-chart/values.yaml b/tests/marketplace/deployer_helm_tiller_base/onbuild/standard/chart/minimal-helm-chart/values.yaml index e69de29b..5c43c1a0 100644 --- a/tests/marketplace/deployer_helm_tiller_base/onbuild/standard/chart/minimal-helm-chart/values.yaml +++ b/tests/marketplace/deployer_helm_tiller_base/onbuild/standard/chart/minimal-helm-chart/values.yaml @@ -0,0 +1,3 @@ +tls: + base64EncodedPrivateKey: null + base64EncodedCertificate: null diff --git a/tests/marketplace/deployer_helm_tiller_base/onbuild/standard/schema.yaml b/tests/marketplace/deployer_helm_tiller_base/onbuild/standard/schema.yaml index eed6f759..9551c6ce 100644 --- a/tests/marketplace/deployer_helm_tiller_base/onbuild/standard/schema.yaml +++ b/tests/marketplace/deployer_helm_tiller_base/onbuild/standard/schema.yaml @@ -28,9 +28,18 @@ properties: - type: Role rulesType: PREDEFINED rulesFromRoleName: cluster-admin + certificate: + type: string + x-google-marketplace: + type: TLS_CERTIFICATE + tlsCertificate: + generatedProperties: + base64EncodedPrivateKey: tls.base64EncodedPrivateKey + base64EncodedCertificate: tls.base64EncodedCertificate required: - name - namespace - application_uid - marketplace-integration.image - marketplace-integration.service_account +- certificate diff --git a/tests/py/Dockerfile b/tests/py/Dockerfile index e0332919..a8448a2a 100644 --- a/tests/py/Dockerfile +++ b/tests/py/Dockerfile @@ -2,8 +2,9 @@ FROM python RUN apt-get update \ && apt-get install -y --no-install-recommends \ + python-openssl \ python-pip \ - python-setuptools \ + python-setuptools \ python-yaml \ && rm -rf /var/lib/apt/lists/*