diff --git a/pyproject.toml b/pyproject.toml index f8bd842a5..5bfecaf59 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "smol_k8s_lab" -version = "2.0.0a1" +version = "2.0.0a2" description = "Bootstrap simple projects on Kubernetes with kind, k3d, and k3s. this is an alpha release" authors = ["Jesse Hitch ", "Max Roby "] diff --git a/smol_k8s_lab/__init__.py b/smol_k8s_lab/__init__.py index 4fc6298ed..d8df0f2d0 100755 --- a/smol_k8s_lab/__init__.py +++ b/smol_k8s_lab/__init__.py @@ -216,7 +216,7 @@ def main(config: str = "", apps.pop('ingress_nginx'), apps['cert_manager'], argo_enabled, - apps['appset_secret_plugin']['enabled'], + apps['argocd']['argo']['directory_recursion'], SECRETS, bw) @@ -226,7 +226,7 @@ def main(config: str = "", setup_k8s_secrets_management(k8s_obj, distro, apps.pop('external_secrets_operator'), - apps.pop('bitwarden_eso_provider'), + SECRETS['global_external_secrets'], apps.pop('infisical'), apps.pop('vault'), bw) @@ -285,9 +285,8 @@ def main(config: str = "", header("Installing the rest of the Argo CD apps") for app_key, app_meta in apps.items(): if app_meta['enabled']: - app_of_apps = app_meta['argo'].get('part_of_app_of_apps', False) app_installed = check_if_argocd_app_exists(app_key) - if not app_of_apps and not app_installed: + if not app_installed: argo_app = app_key.replace('_', '-') sub_header(f"Installing app: {argo_app}") install_with_argocd(k8s_obj, argo_app, app_meta['argo']) diff --git a/smol_k8s_lab/config/default_config.yaml b/smol_k8s_lab/config/default_config.yaml index c7705114a..997162bf8 100644 --- a/smol_k8s_lab/config/default_config.yaml +++ b/smol_k8s_lab/config/default_config.yaml @@ -147,6 +147,12 @@ apps: [link=https://argo-cd.readthedocs.io/en/stable/]Argo CD[/link] is a declarative, GitOps continuous delivery tool for Kubernetes. smol-k8s-lab installs Argo CD with helm initially to support initial configuration of your admin user and disabling of dex. After your OIDC provider is configured, Argo CD begins managing itself using the below configured Argo CD repo. + + The Appset Secret Plugin is required if you want to use the default [link="https://github.com/small-hack/argocd-apps"]small-hack/argocd-apps[/link] [gold3]argo.repo[/gold3] and default enabled if Argo CD is enabled, so we can create a k8s Secret with your more private info such as hostnames, IP addresses, and emails in a deployment that runs alongside Argo CD to provide Argo CD ApplicationSets This plugin has no ingress and cannot be reached from outside the cluster. + + To disable Appset Secret Plugin, please set directory recursion to false. + + Learn more: [link=https://github.com/small-hack/appset-secret-plugin]https://github.com/small-hack/appset-secret-plugin[/link] argo: # secrets keys to make available to Argo CD ApplicationSets secret_keys: @@ -158,13 +164,13 @@ apps: repo: "https://github.com/small-hack/argocd-apps" # path in the argo repo to point to. Trailing slash very important! # change to argocd/argocd to not use app of apps with secret plugin - path: "argocd/" + path: "argocd/app_of_apps/" # either the branch or tag to point at in the argo repo above revision: main # namespace to install the k8s app in namespace: "argocd" - # recurse directories in the provided git repo - directory_recursion: false + # recurse directories in the provided git repo, if true, we also deploy the appset secret plugin + directory_recursion: true # source repos for Argo CD argo-cd Project (in addition to argo_cd.argo.repo) project: source_repos: @@ -175,83 +181,6 @@ apps: namespaces: - prometheus - appset_secret_plugin: - # Required if you want to use the default small-hack/argocd-apps argo.repo and - # default enabled if ArgoCD is enabled, so we can create a k8s Secret with - # your more private info such as hostnames, IP addresses, and emails in a - # deployment that runs alongside ArgoCD to provide Argo CD ApplicationSets - # This plugin has no ingress and cannot be reached from outside the cluster - enabled: true - description: | - Required if you want to use the default [link="https://github.com/small-hack/argocd-apps"]small-hack/argocd-apps[/link] [gold3]argo.repo[/gold3] and default enabled if Argo CD is enabled, so we can create a k8s Secret with your more private info such as hostnames, IP addresses, and emails in a deployment that runs alongside Argo CD to provide Argo CD ApplicationSets This plugin has no ingress and cannot be reached from outside the cluster - - Switch to initialization off if you don't want to deploy a default secret with all keys in each apps.{app}.argo.secret_keys - - Learn more: [link=https://github.com/small-hack/appset-secret-plugin]https://github.com/small-hack/appset-secret-plugin[/link] - init: - # switch to false if you don't want to create an initial secret of values - # to provide to other Argo CD ApplicationSets - enabled: true - argo: - # secrets keys to make available to Argo CD ApplicationSet itself - secret_keys: {} - # skip installing this app b/c its part of another app of apps with this - # name. If equals "" we'll instead use the repo, path, revision, and namespace - part_of_app_of_apps: "argo_cd" - # git repo to install the Argo CD app from - repo: "https://github.com/small-hack/argocd-apps" - # path in the argo repo to point to. Trailing slash very important! - path: "argocd/" - # either the branch or tag to point at in the argo repo above - revision: main - # namespace to install the k8s app in - namespace: "argocd" - # recurse directories in the provided git repo - directory_recursion: false - project: - source_repos: - - https://small-hack.github.io/appset-secret-plugin - destination: - # automatically includes the app's namespace and argocd's namespace - namespaces: [] - - bitwarden_eso_provider: - enabled: true - description: | - The [link="https://github.com/jessebot/bitwarden-eso-provider/"]Bitwarden External Secrets Provider[/link] is used to store k8s secrets in Bitwarden®. This deployment has no ingress and can't be connected to from outside the cluster. There is a networkPolicy that only allows the pod to communicate with the External Secrets Operator in the same namespaces. - - smol-k8s-lab support initialization by creating a Kubernetes secret with your Bitwarden credentials so that the provider can unlock your vault. You will need to setup an [link=https://bitwarden.com/help/personal-api-key/]API key[/link] ahead of time. You can pass these credentials in by setting the following environment variables: - - BITWARDEN_PASSWORD, BITWARDEN_CLIENTSECRET, BITWARDEN_CLIENTID - init: - # Switch to false if you don't want to be prompted for your Bitwarden - # API credentials to be created as a Kubernetes secret. - enabled: true - argo: - # skip installing this app b/c its part of another app of apps with this - # name. If equals "" we'll instead use the below repo, path, revision, and namespace - part_of_app_of_apps: external_secrets_operator - # git repo to install the Argo CD app from - repo: https://github.com/small-hack/argocd-apps - # path in the argo repo to point to. Trailing slash very important! - path: external-secrets-operator/bitwarden - # either the branch or tag to point at in the argo repo above - revision: main - # namespace to install the k8s app in - namespace: external-secrets - # recurse directories in the provided git repo - directory_recursion: false - # optional secrets keys to pass to the Argo CD Appset secret plugin generator - secret_keys: {} - # source repos for Argo CD App Project (in addition to app.argo.repo) - project: - # where the helm chart lives. Go here for more info - source_repos: - - https://small-hack.github.io/bitwarden-eso-provider - destination: - # automatically includes the app's namespace and argocd's namespace - namespaces: [] - # This app is installed with helm or manifests depending on what is recommended # for your k8s distro. Becomes managed by Argo CD if you enable it below cert_manager: @@ -355,6 +284,14 @@ apps: enabled: true description: | [link=https://external-secrets.io/latest/]External Secrets Operator[/link] is a Kubernetes operator that integrates external secret management systems like HashiCorp Vault, CyberArk Conjur, Bitwarden, Gitlab, and many more. The operator reads information from external APIs and automatically injects the values into a Kubernetes Secret. + + To deploy the Bitwarden provider, please set apps_global_config.external_secrets to "bitwarden". + + The [link="https://github.com/jessebot/bitwarden-eso-provider/"]Bitwarden External Secrets Provider[/link] is used to store k8s secrets in Bitwarden®. This deployment has no ingress and can't be connected to from outside the cluster. There is a networkPolicy that only allows the pod to communicate with the External Secrets Operator in the same namespaces. + + smol-k8s-lab support initialization by creating a Kubernetes secret with your Bitwarden credentials so that the provider can unlock your vault. You will need to setup an [link=https://bitwarden.com/help/personal-api-key/]API key[/link] ahead of time. You can pass these credentials in by setting the following environment variables: + + BITWARDEN_PASSWORD, BITWARDEN_CLIENTSECRET, BITWARDEN_CLIENTID # Initialization of the app through smol-k8s-lab init: enabled: false @@ -366,7 +303,7 @@ apps: # ONLY the external-secrets-operator, so this will not use app of apps and # therefore we will not deploy the Bitwarden ESO provider. Use if you want to use # a different provider - path: external-secrets-operator/ + path: external-secrets-operator/app_of_apps/ # either the branch or tag to point at in the argo repo above revision: main # namespace to install the k8s app in @@ -1070,7 +1007,7 @@ apps: # git repo to install the Argo CD app from repo: "https://github.com/small-hack/argocd-apps" # path in the argo repo to point to. Trailing slash very important! - path: "vouch-proxy/" + path: "vouch-proxy/app_of_apps/" # either the branch or tag to point at in the argo repo above revision: main # namespace to install the k8s app in diff --git a/smol_k8s_lab/k8s_apps/__init__.py b/smol_k8s_lab/k8s_apps/__init__.py index a9c60cb91..9e581d022 100644 --- a/smol_k8s_lab/k8s_apps/__init__.py +++ b/smol_k8s_lab/k8s_apps/__init__.py @@ -33,7 +33,7 @@ def setup_k8s_secrets_management(k8s_obj: K8s, k8s_distro: str, eso_dict: dict = {}, - bitwarden_eso_provider_dict: dict = {}, + eso_provider: str = "", infisical_dict: dict = {}, vault_dict: dict = {}, bitwarden: BwCLI = None) -> None: @@ -45,13 +45,11 @@ def setup_k8s_secrets_management(k8s_obj: K8s, # setup external secrets operator and bitwarden external secrets if eso_dict['enabled']: - header_msg += 'External Secrets Operator[/]' - if bitwarden_eso_provider_dict['enabled']: - header_msg += ' and [blue]Bitwarden[/] as the Provider' + header_msg += f'External Secrets Operator[/] and [blue]{eso_provider}[/] as the Provider' header(header_msg, '🤫') configure_external_secrets(k8s_obj, eso_dict, - bitwarden_eso_provider_dict, + eso_provider, k8s_distro, bitwarden) diff --git a/smol_k8s_lab/k8s_apps/identity_provider/vouch.py b/smol_k8s_lab/k8s_apps/identity_provider/vouch.py index 855bae1ad..815d20b06 100644 --- a/smol_k8s_lab/k8s_apps/identity_provider/vouch.py +++ b/smol_k8s_lab/k8s_apps/identity_provider/vouch.py @@ -86,7 +86,9 @@ def configure_vouch(k8s_obj: K8s, create_custom_field("endSessionEndpoint", auth_dict['end_session_url']), create_custom_field("preferredDomain", preferred_domain) ] + log.info(f"vouch oauth fields are {fields}") + # create oauth OIDC bitwarden item oauth_id = bitwarden.create_login( name='vouch-oauth-config', @@ -100,7 +102,9 @@ def configure_vouch(k8s_obj: K8s, domains_obj = create_custom_field("domains", domains) emails_obj = create_custom_field("allowList", emails) jwt_secret_obj = create_custom_field("jwtSecret", jwt_secret) + log.debug(f"emails_obj is {emails_obj} and domains_obj is {domains_obj}") + # create vouch config bitwarden item vouch_id = bitwarden.create_login( name='vouch-config', @@ -111,10 +115,11 @@ def configure_vouch(k8s_obj: K8s, ) # update the vouch values for the argocd appset - fields = {'vouch_oauth_config_bitwarden_id': oauth_id, - 'vouch_config_bitwarden_id': vouch_id} - - update_argocd_appset_secret(k8s_obj, fields) + update_argocd_appset_secret( + k8s_obj, + {'vouch_oauth_config_bitwarden_id': oauth_id, + 'vouch_config_bitwarden_id': vouch_id} + ) # reload the bitwarden ESO provider try: @@ -163,10 +168,11 @@ def configure_vouch(k8s_obj: K8s, )[0]['id'] # update the vouch values for the argocd appset - fields = {'vouch_oauth_bitwarden_id': oauth_id, - 'vouch_config_bitwarden_id': vouch_id} - - update_argocd_appset_secret(k8s_obj, fields) + update_argocd_appset_secret( + k8s_obj, + {'vouch_oauth_config_bitwarden_id': oauth_id, + 'vouch_config_bitwarden_id': vouch_id} + ) def create_vouch_app(provider: str, diff --git a/smol_k8s_lab/k8s_apps/secrets_management/external_secrets_operator.py b/smol_k8s_lab/k8s_apps/secrets_management/external_secrets_operator.py index fcee89831..44c2d03ce 100644 --- a/smol_k8s_lab/k8s_apps/secrets_management/external_secrets_operator.py +++ b/smol_k8s_lab/k8s_apps/secrets_management/external_secrets_operator.py @@ -1,85 +1,63 @@ #!/usr/bin/env python3.11 """ Name: external_secrets -DESCRIPTION: configures external secrets, currently only with gitlab +DESCRIPTION: configures external secrets, currently only with Bitwarden and GitLab hopefully with more supported providers in the future AUTHOR: @jessebot LICENSE: GNU AFFERO GENERAL PUBLIC LICENSE Version 3 """ -import logging as log from smol_k8s_lab.bitwarden.bw_cli import BwCLI from smol_k8s_lab.k8s_tools.argocd_util import install_with_argocd, wait_for_argocd_app from smol_k8s_lab.k8s_tools.k8s_lib import K8s -from smol_k8s_lab.utils.rich_cli.console_logging import sub_header from smol_k8s_lab.utils.subproc import subproc def configure_external_secrets(k8s_obj: K8s, eso_dict: dict, - bweso_dict: dict = {}, + eso_provider: str = "", distro: str = "", bitwarden: BwCLI = None) -> None: """ - configure external secrets and provider. (and optionally bweso) + configure external secrets and provider. (and optionally bweso or gitlab) """ + k8s_obj.create_namespace("external-secrets") + + if eso_provider == "bitwarden": + setup_bweso_provider(k8s_obj, distro, bitwarden) + elif eso_provider == "gitlab": + setup_gitlab_provider(k8s_obj, eso_dict['init']['values']['gitlab_access_token']) + install_with_argocd(k8s_obj, 'external-secrets-operator', eso_dict['argo']) wait_for_argocd_app('external-secrets-operator') - if bweso_dict['enabled']: - setup_bweso(k8s_obj, distro, bweso_dict['argo'], bitwarden) + # wait for bitwarden external secrets provider to be up + wait_for_argocd_app('bitwarden-eso-provider') -def setup_bweso(k8s_obj: K8s, - distro: str, - bweso_argo_dict: dict = {}, - bitwarden: BwCLI = None) -> None: +def setup_bweso_provider(k8s_obj: K8s, distro: str, bitwarden: BwCLI = None) -> None: """ Creates an initial secret for use with the bitwarden provider for ESO """ - sub_header("Installing the Bitwarden External Secrets Provider...") - # this is a standard k8s secrets yaml - k8s_obj.create_secret('bweso-login', 'external-secrets', + k8s_obj.create_secret('bweso-login', + 'external-secrets', {"BW_PASSWORD": bitwarden.password, "BW_CLIENTSECRET": bitwarden.client_secret, "BW_CLIENTID": bitwarden.client_id, "BW_HOST": bitwarden.host}) if distro == 'kind': - image = "docker.io/jessebot/bweso:v0.2.0" + image = "docker.io/jessebot/bweso:v0.5.0" cmds = [f"docker pull --platform=linux/amd64 {image}", f"kind load docker-image {image} --name smol-k8s-lab-kind"] subproc(cmds) - if bweso_argo_dict.get('part_of_app_of_apps', None): - log.debug("Looks like this app is actually part of an app of apps " - "that will be deployed") - return True - - install_with_argocd(k8s_obj, 'bitwarden-eso-provider', bweso_argo_dict) - # wait for bitwarden external secrets provider to be up - wait_for_argocd_app('bitwarden-eso-provider') - -def setup_gitlab_provider(k8s_obj: K8s, external_secrets_config: dict) -> None: +def setup_gitlab_provider(k8s_obj: K8s, gitlab_access_token: str) -> None: """ - setup the gitlab external secrets operator config - Accepts dict as arg: - dict = {'namespace': 'somenamespace', 'access_token': 'tokenhere'} + setup the GitLab external secrets operator provider config by creating a + secret with the GitLab access token """ - gitlab_access_token = external_secrets_config['access_token'] - gitlab_namespace = external_secrets_config['namespace'] - - # create the namespace if does not exist - subproc([f'kubectl create namespace {gitlab_namespace}'], error_ok=True) - - # this currently only works with gitlab - gitlab_secret = {'apiVersion': 'v1', - 'kind': 'Secret', - 'metadata': {'name': 'gitlab-secret', - 'namespace': gitlab_namespace, - 'labels': {'type': 'gitlab'}}, - 'type': 'Opaque', - 'stringData': {'token': gitlab_access_token}} - - k8s_obj.apply_custom_resources([gitlab_secret]) + k8s_obj.create_secret('gitlab-secret', + 'external-secrets', + {'token': gitlab_access_token}) diff --git a/smol_k8s_lab/k8s_tools/argocd_util.py b/smol_k8s_lab/k8s_tools/argocd_util.py index eca520306..222e9aefe 100644 --- a/smol_k8s_lab/k8s_tools/argocd_util.py +++ b/smol_k8s_lab/k8s_tools/argocd_util.py @@ -34,11 +34,6 @@ def install_with_argocd(k8s_obj: K8s, app: str, argo_dict: dict) -> None: proj_namespaces = argo_dict['project']['destination']['namespaces'] proj_namespaces.append(app_namespace) - if argo_dict.get('part_of_app_of_apps', None): - log.debug("Looks like this app is actually part of an app of apps " - "that will be deployed") - return True - # make sure the namespace already exists k8s_obj.create_namespace(app_namespace)