From cb793a7490be00924bb5fcf52252f77f94fd916a Mon Sep 17 00:00:00 2001 From: Tobias Trabelsi Date: Sat, 26 Nov 2022 18:55:42 +0100 Subject: [PATCH] wip for jinja template type --- Dockerfile | 2 +- charts/bitwarden-crd-operator/Chart.yaml | 27 ++++++- .../crds/bitwarden-secrets.yaml | 1 + ...template.yaml => bitwarden-templates.yaml} | 4 + .../crds/registry-credentials.yaml | 1 + example_template.yaml | 19 +++++ src/dockerlogin.py | 4 +- src/filters/bitwarden_filter.py | 8 -- src/kv.py | 4 +- src/{filters => lookups}/__init__.py | 0 src/lookups/bitwarden_lookup.py | 5 ++ src/template.py | 73 ++++++++++++++++++- src/utils/utils.py | 3 +- 13 files changed, 131 insertions(+), 20 deletions(-) rename charts/bitwarden-crd-operator/crds/{template.yaml => bitwarden-templates.yaml} (90%) create mode 100644 example_template.yaml delete mode 100644 src/filters/bitwarden_filter.py rename src/{filters => lookups}/__init__.py (100%) create mode 100644 src/lookups/bitwarden_lookup.py diff --git a/Dockerfile b/Dockerfile index 962a902..85c284e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -27,4 +27,4 @@ COPY --chown=bw-operator:bw-operator src /home/bw-operator USER bw-operator ENTRYPOINT [ "kopf", "run", "--all-namespaces", "--liveness=http://0.0.0.0:8080/healthz" ] -CMD [ "/home/bw-operator/bitwardenCrdOperator.py", "/home/bw-operator/kv.py", "/home/bw-operator/dockerlogin.py" ] +CMD [ "/home/bw-operator/bitwardenCrdOperator.py", "/home/bw-operator/kv.py", "/home/bw-operator/dockerlogin.py", "/home/bw-operator/template.py"] diff --git a/charts/bitwarden-crd-operator/Chart.yaml b/charts/bitwarden-crd-operator/Chart.yaml index e8bd95e..1167885 100644 --- a/charts/bitwarden-crd-operator/Chart.yaml +++ b/charts/bitwarden-crd-operator/Chart.yaml @@ -13,6 +13,8 @@ keywords: - bitwarden - vaultwarden +icon: https://lerentis.github.io/bitwarden-crd-operator/logo.png + home: https://lerentis.github.io/bitwarden-crd-operator/ sources: @@ -39,6 +41,11 @@ annotations: name: registry-credential displayName: Regestry Credentials description: Management Object to create regestry secrets from bitwarden + - kind: BitwardenTemplate + version: v1beta1 + name: bitwarden-template + displayName: Bitwarden Template + description: Management Object to create secrets from a jinja template with a bitwarden lookup artifacthub.io/crdsExamples: | - apiVersion: lerentis.uploadfilter24.eu/v1beta3 kind: BitwardenSecret @@ -66,6 +73,24 @@ annotations: id: "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee" name: "test-regcred" namespace: "default" + - apiVersion: "lerentis.uploadfilter24.eu/v1beta1" + kind: BitwardenTemplate + metadata: + name: test + spec: + filename: "config.yaml" + name: "test-regcred" + namespace: "default" + template: | + --- + api: + enabled: True + key: {{ bitwarden_lookup("466fc4b0-ffca-4444-8d88-b59d4de3d928", "key") }} + allowCrossOrigin: false + apps: + "some.app.identifier:some_version": + pubkey: {{ bitwarden_lookup("466fc4b0-ffca-4444-8d88-b59d4de3d928", "public_key") }} + enabled: true artifacthub.io/license: MIT artifacthub.io/operator: "true" artifacthub.io/changes: | @@ -75,4 +100,4 @@ annotations: description: "Added logo" artifacthub.io/images: | - name: bitwarden-crd-operator - image: lerentis/bitwarden-crd-operator:0.3.0 + image: lerentis/bitwarden-crd-operator:0.4.0 diff --git a/charts/bitwarden-crd-operator/crds/bitwarden-secrets.yaml b/charts/bitwarden-crd-operator/crds/bitwarden-secrets.yaml index 38b026c..f58e8fd 100644 --- a/charts/bitwarden-crd-operator/crds/bitwarden-secrets.yaml +++ b/charts/bitwarden-crd-operator/crds/bitwarden-secrets.yaml @@ -1,3 +1,4 @@ +--- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: diff --git a/charts/bitwarden-crd-operator/crds/template.yaml b/charts/bitwarden-crd-operator/crds/bitwarden-templates.yaml similarity index 90% rename from charts/bitwarden-crd-operator/crds/template.yaml rename to charts/bitwarden-crd-operator/crds/bitwarden-templates.yaml index 9a5dd75..004b70e 100644 --- a/charts/bitwarden-crd-operator/crds/template.yaml +++ b/charts/bitwarden-crd-operator/crds/bitwarden-templates.yaml @@ -1,3 +1,4 @@ +--- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: @@ -22,6 +23,8 @@ spec: spec: type: object properties: + filename: + type: string template: type: string namespace: @@ -29,6 +32,7 @@ spec: name: type: string required: + - filename - template - namespace - name diff --git a/charts/bitwarden-crd-operator/crds/registry-credentials.yaml b/charts/bitwarden-crd-operator/crds/registry-credentials.yaml index fd7bcb3..5d6171c 100644 --- a/charts/bitwarden-crd-operator/crds/registry-credentials.yaml +++ b/charts/bitwarden-crd-operator/crds/registry-credentials.yaml @@ -1,3 +1,4 @@ +--- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: diff --git a/example_template.yaml b/example_template.yaml new file mode 100644 index 0000000..a488bcc --- /dev/null +++ b/example_template.yaml @@ -0,0 +1,19 @@ +--- +apiVersion: "lerentis.uploadfilter24.eu/v1beta1" +kind: BitwardenTemplate +metadata: + name: test +spec: + filename: "config.yaml" + name: "test-regcred" + namespace: "default" + template: | + --- + api: + enabled: True + key: {{ bitwarden_lookup("466fc4b0-ffca-4444-8d88-b59d4de3d928", "key") }} + allowCrossOrigin: false + apps: + "some.app.identifier:some_version": + pubkey: {{ bitwarden_lookup("466fc4b0-ffca-4444-8d88-b59d4de3d928", "public_key") }} + enabled: true \ No newline at end of file diff --git a/src/dockerlogin.py b/src/dockerlogin.py index 94fd48b..0928231 100644 --- a/src/dockerlogin.py +++ b/src/dockerlogin.py @@ -33,8 +33,8 @@ def create_managed_registry_secret(spec, name, namespace, logger, **kwargs): secret_namespace = spec.get('namespace') unlock_bw(logger) - - secret_json_object = json.loads(get_secret_from_bitwarden(logger, id)) + logger.info(f"Locking up secret with ID: {id}") + secret_json_object = json.loads(get_secret_from_bitwarden(id)) api = kubernetes.client.CoreV1Api() diff --git a/src/filters/bitwarden_filter.py b/src/filters/bitwarden_filter.py deleted file mode 100644 index cf0183c..0000000 --- a/src/filters/bitwarden_filter.py +++ /dev/null @@ -1,8 +0,0 @@ -from utils.utils import get_secret_from_bitwarden - - -def datetime_format(value, format="%H:%M %d-%m-%y"): - return value.strftime(format) - -def bitwarden_lookup(value, id, field): - pass \ No newline at end of file diff --git a/src/kv.py b/src/kv.py index 9b65b78..cb4f9b2 100644 --- a/src/kv.py +++ b/src/kv.py @@ -27,8 +27,8 @@ def create_managed_secret(spec, name, namespace, logger, body, **kwargs): secret_namespace = spec.get('namespace') unlock_bw(logger) - - secret_json_object = json.loads(get_secret_from_bitwarden(logger, id)) + logger.info(f"Locking up secret with ID: {id}") + secret_json_object = json.loads(get_secret_from_bitwarden(id)) api = kubernetes.client.CoreV1Api() diff --git a/src/filters/__init__.py b/src/lookups/__init__.py similarity index 100% rename from src/filters/__init__.py rename to src/lookups/__init__.py diff --git a/src/lookups/bitwarden_lookup.py b/src/lookups/bitwarden_lookup.py new file mode 100644 index 0000000..559b937 --- /dev/null +++ b/src/lookups/bitwarden_lookup.py @@ -0,0 +1,5 @@ +from utils.utils import get_secret_from_bitwarden + +def bitwarden_lookup(id, field): + _secret_json = get_secret_from_bitwarden(id) + return _secret_json["login"][field] \ No newline at end of file diff --git a/src/template.py b/src/template.py index ca5d40e..4a00029 100644 --- a/src/template.py +++ b/src/template.py @@ -1,7 +1,72 @@ -import kopf -from filters.bitwarden_filter import bitwarden_lookup -from jinja2 import Environment +import kopf +import base64 +import kubernetes + +from utils.utils import unlock_bw +from lookups.bitwarden_lookup import bitwarden_lookup +from jinja2 import Environment, BaseLoader -Environment.filters["bitwarden"] = bitwarden_lookup +lookup_func_dict = { + "bitwarden_lookup": bitwarden_lookup, +} +def render_template(template): + jinja_template = Environment(loader=BaseLoader()).from_string(template) + jinja_template.globals.update(lookup_func_dict) + return jinja_template.render() + +def create_template_secret(secret, filename, template): + secret.type = "Opaque" + secret.data = {} + secret.data[filename] = str(base64.b64encode(render_template(template).encode("utf-8")), "utf-8") + return secret + +@kopf.on.create('bitwarden-templates.lerentis.uploadfilter24.eu') +def create_managed_secret(spec, name, namespace, logger, body, **kwargs): + + template = spec.get('template') + filename = spec.get('filename') + secret_name = spec.get('name') + secret_namespace = spec.get('namespace') + + unlock_bw(logger) + + api = kubernetes.client.CoreV1Api() + + annotations = { + "managed": "bitwarden-templates.lerentis.uploadfilter24.eu", + "managedObject": f"{namespace}/{name}" + } + secret = kubernetes.client.V1Secret() + secret.metadata = kubernetes.client.V1ObjectMeta(name=secret_name, annotations=annotations) + secret = create_managed_secret(secret, filename, template) + + obj = api.create_namespaced_secret( + secret_namespace, secret + ) + + logger.info(f"Secret {secret_namespace}/{secret_name} has been created") + +@kopf.on.update('bitwarden-templates.lerentis.uploadfilter24.eu') +def my_handler(spec, old, new, diff, **_): + pass + +@kopf.on.delete('bitwarden-templates.lerentis.uploadfilter24.eu') +def delete_managed_secret(spec, name, namespace, logger, **kwargs): + secret_name = spec.get('name') + secret_namespace = spec.get('namespace') + api = kubernetes.client.CoreV1Api() + + try: + api.delete_namespaced_secret(secret_name, secret_namespace) + logger.info(f"Secret {secret_namespace}/{secret_name} has been deleted") + except: + logger.warn(f"Could not delete secret {secret_namespace}/{secret_name}!") + +#if __name__ == '__main__': +# tpl = """ +# Calling the 'bitwarden_lookup' function: +# {{ bitwarden_lookup(2, 2) }} +# """ +# print(render_template(tpl)) \ No newline at end of file diff --git a/src/utils/utils.py b/src/utils/utils.py index 86e0472..7700a3f 100644 --- a/src/utils/utils.py +++ b/src/utils/utils.py @@ -1,8 +1,7 @@ import os import subprocess -def get_secret_from_bitwarden(logger, id): - logger.info(f"Locking up secret with ID: {id}") +def get_secret_from_bitwarden(id): return command_wrapper(logger, f"get item {id}") def unlock_bw(logger):