{"id":20155291,"url":"https://github.com/redhat-cop/vault-config-operator","last_synced_at":"2025-04-09T18:24:26.227Z","repository":{"id":39916644,"uuid":"413599990","full_name":"redhat-cop/vault-config-operator","owner":"redhat-cop","description":"An operator to support Haschicorp Vault configuration workflows from within Kubernetes","archived":false,"fork":false,"pushed_at":"2024-05-28T17:03:20.000Z","size":3145,"stargazers_count":104,"open_issues_count":43,"forks_count":49,"subscribers_count":16,"default_branch":"main","last_synced_at":"2024-05-29T03:50:38.890Z","etag":null,"topics":["container-cop","k8s-operator"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/redhat-cop.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":"docs/contributing-vault-apis.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-10-04T22:22:28.000Z","updated_at":"2024-06-04T05:38:43.473Z","dependencies_parsed_at":"2023-02-18T20:00:44.558Z","dependency_job_id":"122fff69-9457-4dc3-8b54-78e6e58c78ed","html_url":"https://github.com/redhat-cop/vault-config-operator","commit_stats":null,"previous_names":[],"tags_count":45,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/redhat-cop%2Fvault-config-operator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/redhat-cop%2Fvault-config-operator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/redhat-cop%2Fvault-config-operator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/redhat-cop%2Fvault-config-operator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/redhat-cop","download_url":"https://codeload.github.com/redhat-cop/vault-config-operator/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248086218,"owners_count":21045300,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["container-cop","k8s-operator"],"created_at":"2024-11-13T23:31:23.282Z","updated_at":"2025-04-09T18:24:26.196Z","avatar_url":"https://github.com/redhat-cop.png","language":"Go","funding_links":[],"categories":["Building"],"sub_categories":["Workflows"],"readme":"![build status](https://github.com/redhat-cop/vault-config-operator/workflows/push/badge.svg)\n[![Go Report Card](https://goreportcard.com/badge/github.com/redhat-cop/vault-config-operator)](https://goreportcard.com/report/github.com/redhat-cop/vault-config-operator)\n![GitHub go.mod Go version](https://img.shields.io/github/go-mod/go-version/redhat-cop/vault-config-operator)\n[![CRD Docs](https://img.shields.io/badge/CRD-Docs-brightgreen)](https://doc.crds.dev/github.com/redhat-cop/vault-config-operator)\n\n- [Vault Config Operator](#vault-config-operator)\n  - [Authentication Engines](#authentication-engines)\n  - [Policy management](#policy-management)\n  - [Secret Engines](#secret-engines)\n  - [Secret Management](#secret-management)\n  - [Identities](#identities)\n  - [The common authentication section](#the-common-authentication-section)\n  - [End to end example](#end-to-end-example)\n  - [Contributing a new Vault type](#contributing-a-new-vault-type)\n  - [Initializing the connection to Vault](#initializing-the-connection-to-vault)\n  - [The Common connection section](#the-common-connection-section)\n  - [Node on deleting resources](#note-on-deleting-resources)\n  - [Deploying the Operator](#deploying-the-operator)\n    - [Multiarch Support](#multiarch-support)\n    - [Deploying from OperatorHub](#deploying-from-operatorhub)\n      - [Deploying from OperatorHub UI](#deploying-from-operatorhub-ui)\n      - [Deploying from OperatorHub using CLI](#deploying-from-operatorhub-using-cli)\n    - [Deploying with Helm](#deploying-with-helm)\n  - [Metrics](#metrics)\n    - [Testing metrics](#testing-metrics)\n  - [Development](#development)\n    - [Setup](#setup)\n    - [Running the operator locally](#running-the-operator-locally)\n      - [Deploy a Vault instance](#deploy-a-vault-instance)\n      - [Configure an Kubernetes Authentication mount point](#configure-an-kubernetes-authentication-mount-point)\n      - [Run the operator](#run-the-operator)\n    - [Test Manually](#test-manually)\n    - [Test helm chart locally](#test-helm-chart-locally)\n      - [Run the automated helmchart test](#run-the-automated-helmchart-test)\n      - [Manually test the helmchart](#manually-test-the-helmchart)\n  - [Building/Pushing the operator image](#buildingpushing-the-operator-image)\n  - [Deploy to OLM via bundle](#deploy-to-olm-via-bundle)\n  - [Integration Test](#integration-test)\n  - [Releasing](#releasing)\n    - [Cleaning up](#cleaning-up)\n\n# Vault Config Operator\n\nThis operator helps set up Vault Configurations. The main intent is to do so such that subsequently pods can consume the secrets made available.\nThere are two main principles through all of the capabilities of this operator:\n\n1. high-fidelity API. The CRD exposed by this operator reflect field by field the Vault APIs. This is because we don't want to make any assumption on the kinds of configuration workflow that user will set up. That being said the Vault API is very extensive and we are starting with enough API coverage to support, we think, some simple and very common configuration workflows.\n2. attention to security (after all we are integrating with a security tool). To prevent credential leaks we give no permissions to the operator itself against Vault. All APIs exposed by this operator contains enough information to authenticate to Vault using a local service account (local to the namespace where the API exist). In other word for a namespace user to be abel to successfully configure Vault, a service account in that namespace must have been previously given the needed Vault permissions.\n\nCurrently this operator covers the following Vault APIs:\n\n## Authentication Engines\n\n1. [AuthEngineMount](./docs/auth-engines.md#authenginemount) Sets up a [Vault Authentication Endpoint](https://www.vaultproject.io/docs/auth)\n2. [KubernetesAuthEngineConfig](./docs/auth-engines.md#kubernetesauthengineconfig) Configures a [Vault Kubernetes Authentication Endpoint](https://www.vaultproject.io/docs/auth/kubernetes).\n3. [KubernetesAuthEngineRole](./docs/auth-engines.md#KubernetesAuthEngineRole) Configures a Vault [Kubernetes Authentication](https://www.vaultproject.io/docs/auth/kubernetes) Role\n4. [LDAPAuthEngineConfig](./docs/auth-engines.md#ldapauthengineconfig) Configures a [Vault LDAP Authentication Endpoint](https://www.vaultproject.io/docs/auth/ldap).\n   - [LDAPAuthEngineGroup](./docs/auth-engines.md#ldapauthenginegroup) Creates or updates [Vault LDAP Authentication Engine Group](https://www.vaultproject.io/api-docs/auth/ldap#create-update-ldap-group) policies.\n5. [JWTOIDCAuthEngineConfig](./docs/auth-engines.md#jwtoidcauthengineconfig) Configures a [Vault JWT/OIDC Authentication Endpoint](https://developer.hashicorp.com/vault/api-docs/auth/jwt)\n   - [JWTOIDCAuthEngineRole](./docs/auth-engines.md#jwtoidcauthenginerole) Register a role in an Authentication Engine Mount of type [JWT/OIDC](https://developer.hashicorp.com/vault/api-docs/auth/jwt#create-role)\n6. [AzureAuthEngineConfig](./docs/auth-engines.md#azureauthengineconfig) Configures a [Vault Azure Authentication Endpoint](https://developer.hashicorp.com/vault/api-docs/auth/azure)\n\n## Policy management\n\n1. [Policy](./docs/policy-management.md#policy) Configures Vault [Policies](https://www.vaultproject.io/docs/concepts/policies)\n2. [PasswordPolicy](./docs/policy-management.md#passwordpolicy) Configures Vault [Password Policies](https://www.vaultproject.io/docs/concepts/password-policies)\n\n## Secret Engines\n\n1. [SecretEngineMount](./docs/secret-engines.md#SecretEngineMount) Configures a Mount point for a [SecretEngine](https://www.vaultproject.io/docs/secrets)\n2. [DatabaseSecretEngineConfig](./docs/secret-engines.md#DatabaseSecretEngineConfig) Configures a [Database Secret Engine](https://www.vaultproject.io/docs/secrets/databases) Connection\n3. [DatabaseSecretEngineRole](./docs/secret-engines.md#DatabaseSecretEngineRole) Configures a [Database Secret Engine](https://www.vaultproject.io/docs/secrets/databases) Role\n4. [GitHubSecretEngineConfig](./docs/secret-engines.md#GitHubSecretEngineConfig) Configures a Github Application to produce tokens, see the also the [vault-plugin-secrets-github](https://github.com/martinbaillie/vault-plugin-secrets-github)\n5. [GitHubSecretEngineRole](./docs/secret-engines.md#GitHubSecretEngineRole) Configures a Github Application to produce scoped tokens, see the also the [vault-plugin-secrets-github](https://github.com/martinbaillie/vault-plugin-secrets-github)\n6. [PKISecretEngineConfig](./docs/secret-engines.md#pkisecretengineconfig)  Configures a [PKI Secret Engine](https://www.vaultproject.io/docs/secrets/pki)\n7. [PKISecretEngineRole](./docs/secret-engines.md#pkisecretenginerole)  Configures a [PKI Secret Engine](https://www.vaultproject.io/docs/secrets/pki) Role\n8. [QuaySecretEngineConfig](./docs/secret-engines.md#QuaySecretEngineConfig) Configures a Quay server to produce Robot accounts, see the also the [vault-plugin-secrets-quay](https://github.com/redhat-cop/vault-plugin-secrets-quay)\n9. [QuaySecretEngineRole](./docs/secret-engines.md#QuaySecretEngineRole) Configures a Quay server to produce credentials for a Robot account, see the also the [vault-plugin-secrets-quay](https://github.com/redhat-cop/vault-plugin-secrets-quay)\n10. [QuaySecretEngineStaticRole](./docs/secret-engines.md#QuaySecretEngineStaticRole) Configures a Quay server to produce credentials for a Robot account using a fixed username and generated credentials, see the also the [vault-plugin-secrets-quay](https://github.com/redhat-cop/vault-plugin-secrets-quay)\n11. [RabbitMQSecretEngineConfig](./docs/secret-engines.md#rabbitmqsecretengineconfig) Configures a [RabbitMQ Secret Engine](https://www.vaultproject.io/docs/secrets/rabbitmq#rabbitmq-secrets-engine)\n12. [RabbitMQSecretEngineRole](./docs/secret-engines.md#rabbitmqsecretenginerole) Configures a [RabbitMQ Secret Engine Role](https://www.vaultproject.io/docs/secrets/rabbitmq#rabbitmq-secrets-engine)\n\n## Secret Management\n\n1. [RandomSecret](./docs/secret-management.md#RandomSecret) Creates a random secret in a vault [kv Secret Engine](https://www.vaultproject.io/docs/secrets/kv) with one password field generated using a [PasswordPolicy](https://www.vaultproject.io/docs/concepts/password-policies)\n2. [VaultSecret](./docs/secret-management.md#VaultSecret) Creates a K8s Secret from one or more Vault Secrets\n\n## Identities\n\n1. [Group](./docs/identities.md#Group) Creates a [Vault Group](https://developer.hashicorp.com/vault/docs/concepts/identity#identity-groups).\n2. [GroupAlias](./docs/identities.md#GroupAlias) Creates a [Vault GroupAlias](https://developer.hashicorp.com/vault/api-docs/secret/identity/group-alias).\n\n## The common authentication section\n\nAll APIs share a common authentication section, details can be found [here](./docs/auth-section.md)\nEvery time a resource is reconciled a new authentication is performed and a new token is requeued from Vault. For the token will be used for reconcile cycle possible for a few calls and then forgotten. The whole process should normally take a fraction of a second, maybe a few seconds on a very busy pod. It is recommended to dedicate an authentication engine just for the vault-configuration-operator controller and keep the token TTL so 10-20s. This will prevent a proliferation of tokens on the Vault side.\n\n\n\n## End to end example\n\nSee [this section](./docs/end-to-end-example.md) for an example scenario in which this operator could be used.\n\n## Contributing a new Vault type\n\nSee [this section](./docs/contributing-vault-apis.md) of the documentation for a details on how to contribute a new type.\n\n## Initializing the connection to Vault\n\nAt the moment the connection to Vault can be initialized with [Vault's standard environment variables](https://www.vaultproject.io/docs/commands#environment-variables).\nSee the [OLM documentation](https://github.com/operator-framework/operator-lifecycle-manager/blob/master/doc/design/subscription-config.md#env) on how to pass environment variables via a Subscription.\nThe variable that are read at client initialization are listed [here](https://github.com/hashicorp/vault/blob/14101f866414d2ed7850648b465c746ac8fda621/api/client.go#L35).\n\nAdditionally, the operator checks for an environment variable named `CACHE_VAULT_TOKEN`. If set to a value of `\"true\"`, the operator will cache the Vault clients (and tokens) it creates per tuple of:\n- Vault namespace\n- Kubernetes namespace\n- Kubernetes service account\n- Kubernetes auth engine path\n- Kubernetes auth engine role\n\nBy default, or if the variable is set to any other value, the operator will create a new client with a new token for each request it makes to Vault.\n\nSyncPeriod determines the minimum frequency at which watched resources are reconciled. Set the environment variable named `SYNC_PERIOD_SECONDS` to update the frequency at which watched resources are reconciled. It defaults to 10 hours if unset.\n\nFor certificates, the recommended approach is to mount the secret or configmap containing the certificate as described [here](https://github.com/operator-framework/operator-lifecycle-manager/blob/master/doc/design/subscription-config.md#volumes), and the configure the corresponding variables to point at the files location in the mounted path.\n\nHere is an example:\n\nThis is a configmap that will be injected with the OpenShift service-ca, you will have different ways of injecting your CA:\n\n```yaml\napiVersion: v1\nkind: ConfigMap\nmetadata:\n  annotations:\n    service.beta.openshift.io/inject-cabundle: \"true\"\n  name: ocp-service-ca\n```\n\nHere is the subscription using that configmap:\n\n```yaml\napiVersion: operators.coreos.com/v1alpha1\nkind: Subscription\nmetadata:\n  name: vault-config-operator\nspec:\n  channel: alpha\n  installPlanApproval: Automatic\n  name: vault-config-operator\n  source: community-operators\n  sourceNamespace: openshift-marketplace\n  config:\n    env:\n    - name: VAULT_CACERT\n      value: /vault-ca/ca.crt\n    volumes:\n    - name: vault-ca\n      configMap:\n        name: ocp-service-ca\n    volumeMounts:\n    - mountPath: /vault-ca\n      name: vault-ca\n```\n\n## The Common connection section\n\nAll APIs share a common connection section. This section can be used to override how connections to Vault are established, essentially changing the above explained behavior. With feature it is potentially possible to connect to multiple vault instance from a single cluster.\n\nHere is an example:\n\n```yaml\n  connection:\n    address: 'https://vault.vault2.svc:8200'\n    tLSConfig:\n      cacert: |\n        -----BEGIN CERTIFICATE-----\n        MIIDUTCCAjmgAwIBAgIIW+spyyCjRaIwDQYJKoZIhvcNAQELBQAwNjE0MDIGA1UE\n        Awwrb3BlbnNoaWZ0LXNlcnZpY2Utc2VydmluZy1zaWduZXJAMTY3NDc3NDQ3MzAe\n        Fw0yMzAxMjYyMzA3NTNaFw0yNTAzMjYyMzA3NTRaMDYxNDAyBgNVBAMMK29wZW5z\n        aGlmdC1zZXJ2aWNlLXNlcnZpbmctc2lnbmVyQDE2NzQ3NzQ0NzMwggEiMA0GCSqG\n        SIb3DQEBAQUAA4IBDwAwggEKAoIBAQC8+qF40DBauBGBgk14iCwzDZ5s9J/0rzRi\n        x/aLm9DYabtrar1mz6T41UstX4ulgxnU+QrQYN8X1NROzlksC4fFPI3lmmjI95PU\n        xshv5z3wjKlEq5sI4RqyzAqgww5EMnBz5aaaElFBRZhgFymylc347kR7ZMpx8H9b\n        LuyAf4zOuherbUO6xYREPKyZwFC1HHZpjnXtrTYNsFvB2GQjnTNWHZdCfdZVHtZx\n        /vmTlPQGXMnoYBvKH74jxbQVYcu/UGtifj/Q4LpPn05YYvq6xQcYq+H6dLC4gD/W\n        Z1bFgLZUH5+Xx/mPldrvZBhqINvVo3qR+7U8TiGnoyGUYCdv8k2RAgMBAAGjYzBh\n        MA4GA1UdDwEB/wQEAwICpDAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSaW5QB\n        6lFBObTYaebBNKMlOXp8VDAfBgNVHSMEGDAWgBSaW5QB6lFBObTYaebBNKMlOXp8\n        VDANBgkqhkiG9w0BAQsFAAOCAQEAmVnCbvFRs0Z13tgWE3J51dcrzhyuBEbdAWfU\n        5MHrDKw7Sm3N67UC/Av01G6XDIZh8lW6s+foOES3IXWv/ayH4Sc91U92/K17Cls6\n        s6ZuC6KDd/X0ez6G8URbvB9gwlrst3WVnD0Qefb36K4YqfRF9j4KTAbDXLZuGpZK\n        lMk0STHHRm7IeVBnSEqrs8AxLdn+wgnPEdag7Z89BvRhhscQivZwsSBwSegalmdb\n        UIfKX64wKllQs2sd6eSvDZxDheB1YGM2nYQDYZeWb0gskPsakYUcTfouvXBYrXMf\n        mHyYxYdDK+drEiV6RB1s8swFPdVaLMe2U0KedY486JFk1aKHqA==\n        -----END CERTIFICATE-----\n```\n\nThis section features the same options that are available via environment variables when using the `vault` client. Keep in mind that this configuration override the default explained above, so you need to specify only the field that need to be different.\n\n## Note on deleting resources\n\nAs mentioned in the introduction, this operator is built on the philosophy of a one to one high fidelity mapping between CRDs and vault APIs. Some Vault APIs though are not fully REST compliant. In particular some resources cannot be deleted. This mostly happens on configuration resources (either authentication or secret engine configuration). Configuration resources in general cannot be deleted when there is a 1 to 1 relationship (as opposed to one to many) between the mount and the configuration.\nCRDs corresponding to configuration resources can be identified by the Config postfix. When a CRD of a non deletable configuration is deleted in Kubernetes, this result in a no-op. The only way to delete the configuration is to also delete the corresponding mount.\n\n## Deploying the Operator\n\nThis is a cluster-level operator that you can deploy in any namespace, `vault-config-operator` is recommended.\n\nIt is recommended to deploy this operator via [`OperatorHub`](https://operatorhub.io/), but you can also deploy it using [`Helm`](https://helm.sh/).\n\n### Multiarch Support\n\n| Arch  | Support  |\n|:-:|:-:|\n| amd64  | ✅ |\n| arm64  | ✅  |\n| ppc64le  | ✅  |\n| s390x  | ✅  |\n\n### Deploying from OperatorHub\n\n\u003e **Note**: This operator supports being installed disconnected environments\n\nIf you want to utilize the Operator Lifecycle Manager (OLM) to install this operator, you can do so in two ways: from the UI or the CLI.\n\n#### Deploying from OperatorHub UI\n\n- If you would like to launch this operator from the UI, you'll need to navigate to the OperatorHub tab in the console. Before starting, make sure you've created the namespace that you want to install this operator to with the following:\n\n```sh\noc new-project vault-config-operator\n```\n\n- Once there, you can search for this operator by name: `vault config operator`. This will then return an item for our operator and you can select it to get started. Once you've arrived here, you'll be presented with an option to install, which will begin the process.\n- After clicking the install button, you can then select the namespace that you would like to install this to as well as the installation strategy you would like to proceed with (`Automatic` or `Manual`).\n- Once you've made your selection, you can select `Subscribe` and the installation will begin. After a few moments you can go ahead and check your namespace and you should see the operator running.\n\n![Cert Utils Operator](./media/vault-config-operator.png)\n\n#### Deploying from OperatorHub using CLI\n\nIf you'd like to launch this operator from the command line, you can use the manifests contained in this repository by running the following:\n\noc new-project vault-config-operator\n\n```sh\noc apply -f config/operatorhub -n vault-config-operator\n```\n\nThis will create the appropriate OperatorGroup and Subscription and will trigger OLM to launch the operator in the specified namespace.\n\n### Deploying with Helm\n\nHere are the instructions to install the latest release with Helm.\n\n```sh\noc new-project vault-config-operator\nhelm repo add vault-config-operator https://redhat-cop.github.io/vault-config-operator\nhelm repo update\nhelm install vault-config-operator vault-config-operator/vault-config-operator\n```\n\nThis can later be updated with the following commands:\n\n```sh\nhelm repo update\nhelm upgrade vault-config-operator vault-config-operator/vault-config-operator\n```\n\nIf you want the installation to create self-signed certificates for the webhook and the metrics server, set `enableCertManager` to `true`. The installation will create a self-signed issuer and the required certificates.\n\nIf you want to provide your own `cert-manager` certificates instead, please create the following two certificates:\n- A certificate with a name of your choice in the operator's target namespace, with secret name `vault-config-operator-webhook-service-cert`, for the following domain names:\n  - `vault-config-operator-webhook-service.\u003ctarget namespace\u003e.svc`\n  - `vault-config-operator-webhook-service.\u003ctarget namespace\u003e.svc.cluster.local`\n- A certificate with a name of your choice in the operator's target namespace, with secret name `vault-config-operator-metrics-service-cert`, for the following domain names:\n  - `vault-config-operator-controller-manager-metrics-service.\u003ctarget namespace\u003e.svc`\n  - `vault-config-operator-controller-manager-metrics-service.\u003ctarget namespace\u003e.svc.cluster.local`\n\n## Metrics\n\nPrometheus compatible metrics are exposed by the Operator and can be integrated into OpenShift's default cluster monitoring. To enable OpenShift cluster monitoring, label the namespace the operator is deployed in with the label `openshift.io/cluster-monitoring=\"true\"`.\n\n```sh\noc label namespace \u003cnamespace\u003e openshift.io/cluster-monitoring=\"true\"\n```\n\n### Testing metrics\n\nOpenshift monitoring...\n\n```sh\nexport operatorNamespace=vault-config-operator\noc label namespace ${operatorNamespace} openshift.io/cluster-monitoring=\"true\"\noc rsh -n openshift-monitoring -c prometheus prometheus-k8s-0 /bin/bash\nexport operatorNamespace=vault-config-operator\ncurl -v --data-urlencode \"query=controller_runtime_active_workers{namespace=\\\"${operatorNamespace}\\\"}\" localhost:9090/api/v1/query\nexit\n```\n\nin Kubernetes...\n\nSee the [Test helm chart locally](#test-helm-chart-locally) section to run the helmchart test which will also test that metrics work against a k8s kind cluster.\n\n## Development\n\n### Setup\n\nIf using vscode, you may need a `./.vscode/settings.json` file in this directory to make gopls happy since build tags are used.\n\nSee \u003chttps://github.com/golang/vscode-go/blob/master/docs/settings.md#buildbuildflags\u003e\n\n```json\n{\n    \"gopls\": {\n        \"ui.completion.usePlaceholders\": true,\n        \"build.buildFlags\": [\n            \"--tags=integration\"\n        ]\n    },\n}\n```\n\nTo launch the debugger locally in vscode you may need a `./.vscode/launch.json` to specify a different Vault address instance and/or disable webhooks (see the operator-sdk [webhooks run-locally](https://sdk.operatorframework.io/docs/building-operators/golang/webhook/#run-locally) docs for more info).\n\nThe following example allows for running a debugger using the Vault instance created by first running the `make integration` command.\n\n```json\n{\n    // Use IntelliSense to learn about possible attributes.\n    // Hover to view descriptions of existing attributes.\n    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387\n    \"version\": \"0.2.0\",\n    \"configurations\": [\n        {\n            \"name\": \"Launch Package\",\n            \"type\": \"go\",\n            \"request\": \"launch\",\n            \"mode\": \"auto\",\n            \"program\": \"${workspaceRoot}\",\n            \"args\": [\n                \"--health-probe-bind-address\", \":8888\",\n            ],\n            \"env\": {\n                \"ENABLE_WEBHOOKS\": \"false\",\n                \"VAULT_ADDR\": \"http://localhost:8200\",\n            }\n        }\n    ]\n}\n```\n\nAfterwards, selecting Run-\u003eStart Debugging in vscode should start the debugger.\n\n### Running the operator locally\n\n#### Deploy a Vault instance\n\nIf you don't have a Vault instance available for testing, deploy one with these steps:\n\n```sh\nhelm repo add hashicorp https://helm.releases.hashicorp.com\noc new-project vault\noc adm policy add-role-to-user admin -z vault -n vault\nexport cluster_base_domain=$(oc get dns cluster -o jsonpath='{.spec.baseDomain}')\nhelm upgrade vault hashicorp/vault -i --create-namespace -n vault --atomic -f ./config/local-development/vault-values.yaml --set server.route.host=vault-vault.apps.${cluster_base_domain}\n```\n\n\u003e Note: you may need to manually remove the `service.beta.openshift.io/serving-cert-secret-name: vault-server-tls` annotation from the Service `vault-internal` and force the recreation of the service serving certificate since the annotation gets applied to both `vault` and `vault-internal` Services by the helm chart. The implementation expects the vault.vault.svc certificate. See [server-service.yaml](https://github.com/hashicorp/vault-helm/blob/main/templates/server-service.yaml) and [server-headless-service.yaml](https://github.com/hashicorp/vault-helm/blob/main/templates/server-headless-service.yaml).\n\n#### Configure an Kubernetes Authentication mount point\n\nAll the configuration made by the operator need to authenticate via a Kubernetes Authentication. So you need a root Kubernetes Authentication mount point and role. The you can create more roles via the operator.\nIf you don't have a root mount point and role, you can create them as follows:\n\n```sh\noc new-project vault-admin\nexport cluster_base_domain=$(oc get dns cluster -o jsonpath='{.spec.baseDomain}')\nexport VAULT_ADDR=https://vault-vault.apps.${cluster_base_domain}\nexport VAULT_TOKEN=$(oc get secret vault-init -n vault -o jsonpath='{.data.root_token}' | base64 -d )\n# this policy is intentionally broad to allow to test anything in Vault. In a real life scenario this policy would be scoped down.\nvault policy write -tls-skip-verify vault-admin  ./config/local-development/vault-admin-policy.hcl\nvault auth enable -tls-skip-verify kubernetes\nvault write -tls-skip-verify auth/kubernetes/config kubernetes_host=https://kubernetes.default.svc:443\nvault write -tls-skip-verify auth/kubernetes/role/policy-admin bound_service_account_names=default bound_service_account_namespaces=vault-admin policies=vault-admin ttl=10s\n# noticed how we created a 10s TTL for the tokens created by this authentication engine\n```\n\nverify that kube authentication works:\n\n```sh\nexport token=$(oc create token default -n vault-admin) #requires oc client 4.11.x\nvault write -tls-skip-verify auth/kubernetes/login role=policy-admin jwt=${token}\n```\n\n#### Run the operator\n\n\u003e Note: this operator build process is tested with [podman](https://podman.io/), but some of the build files (Makefile specifically) use docker because they are generated automatically by operator-sdk. It is recommended [remap the docker command to the podman command](https://developers.redhat.com/blog/2020/11/19/transitioning-from-docker-to-podman#transition_to_the_podman_cli).\n\n```sh\nexport repo=raffaelespazzoli #change the organization name to your own and be sure to make the repo public\ndocker login quay.io/$repo\noc new-project vault-config-operator\noc project vault-config-operator\ntilt up\n```\n\n### Test Manually\n\nPolicy\n\n```sh\nenvsubst \u003c ./test/database-engine-admin-policy.yaml | oc apply -f - -n vault-admin\n```\n\nVault Role\n\n```sh\noc new-project test-vault-config-operator\noc label namespace test-vault-config-operator database-engine-admin=true\noc apply -f ./test/database-engine-admin-role.yaml -n vault-admin\n```\n\nSecret Engine Mount\n\n```sh\noc apply -f ./test/database-secret-engine.yaml -n test-vault-config-operator\n```\n\nDatabase secret engine connection. This will deploy a postgresql database to connect to\n\n```sh\noc create secret generic postgresql-admin-password --from-literal=postgres-password=changeit -n test-vault-config-operator\n\nhelm repo add bitnami https://charts.bitnami.com/bitnami\n\nhelm upgrade helm upgrade my-postgresql-database bitnami/postgresql -i --create-namespace -n test-vault-config-operator -f ./docs/examples/postgresql/postgresql-values.yaml  --set primary.podSecurityContext.fsGroup=null,primary.podSecurityContext.seccompProfile.type=RuntimeDefault,primary.containerSecurityContext.runAsUser=null,primary.containerSecurityContext.allowPrivilegeEscalation=false,primary.containerSecurityContext.runAsNonRoot=true,primary.containerSecurityContext.seccompProfile.type=RuntimeDefault,volumePermissions.enabled=false,shmVolume.enabled=false #For OpenShift 4.11 and higher, let set OpenShift the runAsUser and fsGroup automatically. Configure the pod and container security context to restrictive defaults and disable the volume permissions setup. See https://github.com/bitnami/charts/tree/main/bitnami/postgresql\n\noc adm policy add-scc-to-user anyuid -z default -n test-vault-config-operator\noc apply -f ./test/database-engine-config.yaml -n test-vault-config-operator\n```\n\nDatabase Secret engine role\n\n```sh\noc apply -f ./test/database-engine-read-only-role.yaml -n test-vault-config-operator\n```\n\nDatabase Secret engine static role\n\n```sh\nexport POSTGRES_PASSWORD=$(kubectl get secret --namespace test-vault-config-operator postgresql-admin-password -o jsonpath=\"{.data.postgres-password}\" | base64 -d)\noc rsh -c postgresql -n test-vault-config-operator my-postgresql-database-0\n/opt/bitnami/scripts/postgresql/entrypoint.sh /bin/bash\npsql --host 127.0.0.1 -U postgres -d postgres -p 5432\ntype $POSTGRES_PASSWORD here\nCREATE ROLE helloworld;\nexit\nexit\nexit\noc apply -f ./test/database-engine-read-only-static-role.yaml -n test-vault-config-operator\n```\n\nDatabase root password rotation. Note we are going to overwrite the previous definition\n\n```sh\noc apply -f ./test/database-engine-config-password-rotation.yaml -n test-vault-config-operator\nexport POSTGRES_PASSWORD=$(kubectl get secret --namespace test-vault-config-operator postgresql-admin-password -o jsonpath=\"{.data.postgres-password}\" | base64 -d)\noc rsh -c postgresql -n test-vault-config-operator my-postgresql-database-0\n/opt/bitnami/scripts/postgresql/entrypoint.sh /bin/bash\npsql --host 127.0.0.1 -U postgres -d postgres -p 5432\ntype $POSTGRES_PASSWORD here\n\nthis should fail now\nexit\nexit\nexit\n\n```\n\nRandomSecret\n\n```sh\noc apply -f ./test/password-policy.yaml -n vault-admin\nenvsubst \u003c ./test/kv-engine-admin-policy.yaml | oc apply -f - -n vault-admin\nenvsubst \u003c ./test/secret-writer-policy.yaml | oc apply -f - -n vault-admin\noc apply -f ./test/kv-engine-admin-role.yaml -n vault-admin\noc apply -f ./test/secret-writer-role.yaml -n vault-admin\noc apply -f ./test/kv-secret-engine.yaml -n test-vault-config-operator\noc apply -f ./test/random-secret.yaml -n test-vault-config-operator\n```\n\nVaultSecret\n\n\u003e Note: you must run the previous tests\n\n```sh\noc apply -f ./test/vaultsecret/kubernetesauthenginerole-secret-reader.yaml -n vault-admin\nenvsubst \u003c ./test/vaultsecret/policy-secret-reader.yaml | oc apply -f - -n vault-admin\noc apply -f ./test/vaultsecret/randomsecret-another-password.yaml -n test-vault-config-operator\noc apply -f ./test/vaultsecret/vaultsecret-randomsecret.yaml -n test-vault-config-operator\noc apply -f ./test/vaultsecret/vaultsecret-dynamicsecret.yaml -n test-vault-config-operator\n# test a pullsecret... Create the secret in test-vault-config-operator/kv/pullsecret using the Vault UI first\noc apply -f ./test/vaultsecret/vaultsecret-pullsecret.yaml -n test-vault-config-operator\n```\n\nVaultSecret \u0026 RandomSecret using KV Secret Engine V2\n\n```sh\n#Random Secret using v2 steps\noc apply -f ./test/randomsecret/v2/00-passwordpolicy-simple-password-policy-v2.yaml -n vault-admin\nenvsubst \u003c ./test/randomsecret/v2/01-policy-kv-engine-admin-v2.yaml | oc apply -f - -n vault-admin\nenvsubst \u003c ./test/randomsecret/v2/04-policy-secret-writer-v2.yaml | oc apply -f - -n vault-admin\nenvsubst \u003c ./test/vaultsecret/v2/00-policy-secret-reader-v2.yaml | oc apply -f - -n vault-admin\noc apply -f ./test/randomsecret/v2/02-kubernetesauthenginerole-kv-engine-admin-v2.yaml -n vault-admin\noc apply -f ./test/randomsecret/v2/05-kubernetesauthenginerole-secret-writer-v2.yaml -n vault-admin\noc apply -f ./test/vaultsecret/v2/00-kubernetesauthenginerole-secret-reader-v2.yaml -n vault-admin\noc apply -f test/randomsecret/v2/03-secretenginemount-kv-v2.yaml -n test-vault-config-operator\noc apply -f ./test/randomsecret/v2/06-randomsecret-randomsecret-password-v2.yaml -n test-vault-config-operator\noc apply -f ./test/randomsecret/v2/07-randomsecret-randomsecret-another-password-v2.yaml -n test-vault-config-operator\n\n#VaultSecret reading RandomSecret v2 steps\noc apply -f ./test/vaultsecret/v2/07-vaultsecret-randomsecret-v2.yaml -n test-vault-config-operator\n```\n\nKube auth engine mount and config and role\n\n```sh\noc apply -f ./test/kube-auth-engine-mount.yaml -n vault-admin\noc apply -f ./test/kube-auth-engine-config.yaml -n vault-admin\noc apply -f ./test/kube-auth-engine-role.yaml -n vault-admin\n```\n\nKube auth engine use vault pod OS ca bundle\n\n```sh\noc apply -f ./test/kube-auth-engine-mount.yaml -n vault-admin\noc apply -f ./test/kube-auth-engine-config-vault-pod-ca.yaml -n vault-admin\n```\n\nGithub secret engine\n\ncreate a github application following the instructions [here](https://github.com/martinbaillie/vault-plugin-secrets-github#setup-github).\nsave the ssh key in a file called: ./test/vault-secret-engine.private-key.pem and the application id\n\n```sh\nexport application_id=163698 #replace with your own\nexport org_name=raf-backstage-demo\nexport ssh_key=$(cat ./test/vault-secret-engine.private-key.pem | base64 -w 0)\nenvsubst \u003c ./test/github-secret-engine-config-secret-template.yaml | oc apply -f - -n vault-admin\noc apply -f ./test/github-secret-engine-mount.yaml -n vault-admin\nenvsubst \u003c ./test/github-secret-engine-config.yaml | oc apply -f - -n vault-admin\n#vault read -tls-skip-verify github/raf-backstage-demo/token\nvault write -tls-skip-verify github/raf-backstage-demo/token org_name=${org_name}\nenvsubst \u003c ./test/github-secret-engine-role.yaml | oc apply -f - -n vault-admin\nvault read -tls-skip-verify github/raf-backstage-demo/token/one-repo-only\n```\n\nTest groups and group aliases\n\nnote we just want to very that the group is created in vault, we are not actually setting up a complete authentication workflow. Refer to the jwtoidcauthengine for that.\n\n```sh\noc apply -f ./test/groups/group.yaml -n vault-admin\noc apply -f ./test/groups/groupalias.yaml -n vault-admin\n```\n\n### Test helm chart locally\n\n#### Run the automated helmchart test\n\n```sh\nmake helmchart-test\n```\n\nSince this will run a kind instance, you may then test creating CRs manually...\n\n```sh\nexport VAULT_TOKEN=$(kubectl get secret vault-init -n vault -o jsonpath='{.data.root_token}' | base64 -d)\nexport VAULT_ADDR=\"http://localhost\"\nkubectl create namespace vault-admin\nkubectl create namespace test-vault-config-operator\n```\n\nNext, run through the [Test Manually](#test-manually) steps.\n\n#### Manually test the helmchart\n\nDefine an image and tag. For example...\n\n```sh\nexport imageRepository=\"quay.io/redhat-cop/vault-config-operator\"\nexport imageTag=\"$(git -c 'versionsort.suffix=-' ls-remote --exit-code --refs --sort='version:refname' --tags https://github.com/redhat-cop/vault-config-operator.git '*.*.*' | tail --lines=1 | cut --delimiter='/' --fields=3)\"\n```\n\nDeploy chart using service serving certificates...\n\n```sh\nmake helmchart IMG=${imageRepository} VERSION=${imageTag}\noc new-project vault-config-operator-local\noc apply -f test/helm/configmap-ocp-service-ca.yaml -n vault-config-operator-local\nhelm upgrade -i vault-config-operator-local charts/vault-config-operator -n vault-config-operator-local --create-namespace -f test/helm/values.yaml\n```\n\nDeploy chart using cert manager certificates...\n\n```sh\nmake helmchart IMG=${imageRepository} VERSION=${imageTag}\noc new-project vault-config-operator-local\noc apply -f test/helm/configmap-ocp-service-ca.yaml -n vault-config-operator-local\nhelm upgrade -i vault-config-operator-local charts/vault-config-operator -n vault-config-operator-local --create-namespace -f test/helm/values.yaml --set enableCertManager=true\n```\n\nDelete...\n\n```sh\nhelm delete vault-config-operator-local -n vault-config-operator-local\nkubectl delete -f charts/vault-config-operator/crds/crds.yaml\n```\n\n## Building/Pushing the operator image\n\n```sh\nexport repo=raffaelespazzoli #replace with yours\ndocker login quay.io/$repo\nmake docker-build IMG=quay.io/$repo/vault-config-operator:latest\nmake docker-push IMG=quay.io/$repo/vault-config-operator:latest\n```\n\n## Deploy to OLM via bundle\n\n```sh\nmake manifests\nmake bundle IMG=quay.io/$repo/vault-config-operator:latest\noperator-sdk bundle validate ./bundle --select-optional suite=operatorframework --optional-values=k8s-version=1.25\nmake bundle-build BUNDLE_IMG=quay.io/$repo/vault-config-operator-bundle:latest\ndocker push quay.io/$repo/vault-config-operator-bundle:latest\noperator-sdk bundle validate quay.io/$repo/vault-config-operator-bundle:latest --select-optional suite=operatorframework --optional-values=k8s-version=1.25\noc new-project vault-config-operator\noc label namespace vault-config-operator openshift.io/cluster-monitoring=\"true\"\noperator-sdk cleanup vault-config-operator -n vault-config-operator\noperator-sdk run bundle --install-mode AllNamespaces -n vault-config-operator quay.io/$repo/vault-config-operator-bundle:latest\n```\n\nConfigure Subscription to use local vault for testing...\n\n```sh\noc apply -f test/olm/configmap-ocp-service-ca.yaml -n vault-config-operator\noc apply -f test/olm/subscription-vault-config-operator-v0-0-1-sub.yaml -n vault-config-operator\n```\n\n## Integration Test\n\n\u003e Note the envtest seems to only work with kind when using docker instead of podman\n\n```sh\nmake integration\n```\n\n## Releasing\n\n```sh\ngit tag -a \"\u003ctagname\u003e\" -m \"\u003ccommit message\u003e\"\ngit push upstream \u003ctagname\u003e\n```\n\nIf you need to remove a release:\n\n```sh\ngit tag -d \u003ctagname\u003e\ngit push upstream --delete \u003ctagname\u003e\n```\n\nIf you need to \"move\" a release to the current main\n\n```sh\ngit tag -f \u003ctagname\u003e\ngit push upstream -f \u003ctagname\u003e\n```\n\n### Cleaning up\n\n```sh\noperator-sdk cleanup vault-config-operator -n vault-config-operator\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fredhat-cop%2Fvault-config-operator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fredhat-cop%2Fvault-config-operator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fredhat-cop%2Fvault-config-operator/lists"}