This repository explores some of the integrations with credentials and certificates providers.
- OpenShift Secured Integration
This repository demonstrates how to securely integrate an OpenShift cluster with HashiCorp Vault for managing secrets and credentials, and cert-manager for automating certificate creation and renewal. You'll find deployment guides, step-by-step instructions, and example configurations to streamline your setup. Dive in to simplify and secure your cluster's secrets and certificates management!
cert-manager is a Kubernetes add-on to automate the management and issuance of TLS certificates from various issuing sources. It will ensure certificates are valid and up to date periodically, and attempt to renew certificates at an appropriate time before expiry.
In order to split installation of the operator and post-configuration, I've split cert-manager resources in three different ArgoCD applications:
cert-manager-operatorwill install the operator as well as create aws credentials using the Cluster Credentials Operator to allow the operator to perform DNS requests to validate the URIs of the certificates. It also configures metrics retrieval so that you can configure its metrics (Prefixed bycertmanager_).cert-manager-route53application will create the actual Certificate Issuer and certificates for the API server and the Ingress and apply them to the cluster.cert-manager-self-signedis just a configuration example on how to create a self-signed certificate and use it to issue certificates for your own services. This does not have a real use-case, it is just a demonstration.
Do you want to deploy it in your cluster without ArgoCD? You can copy the following piece of code and execute it in your cluster:
# 1) Deploy the operator
oc apply -k 02-cert-manager-operator
# 2) Wait for the operator to be ready
echo -n "Waiting for cert-manager pods to be ready..."
while [[ $(oc get pods -l app.kubernetes.io/instance=cert-manager -n cert-manager -o 'jsonpath={..status.conditions[?(@.type=="Ready")].status}') != "True True True" ]]; do echo -n "." && sleep 1; done; echo -n -e " [OK]\n"
# 3) Configure the OpenShift certificates for Ingress and API
helm template 02-cert-manager-route53 --set clusterDomain=$(oc get dns.config/cluster -o jsonpath='{.spec.baseDomain}') | oc apply -f -
# 4) Configure custom certificates using self-signed
oc apply -k 02-cert-manager-self-signedcert-manager is a simple operator, but if you are just starting to play with it, you might need some guidance to better understand what is going on. Here you can find some debugging tips:
- There should be three pods in the
cert-managernamespace. If not, check the subscription status field. - Among the pods, the
cert-managerwill contain the validation information, but thecert-manager-webhookwill show you ifcert-manageris not trusting your issuer CA. - The
Certificateresource is the main object you use to request certificates, but if you want to see the issuing status, check thecertificaterequestor, more importantly, theorderresource. - If you request a cert in a secret
$NAME, there is an intermediate step in which it will create an auxiliary secret named$SECRET-suffixthat will then be deleted after proper issuing. Just relax and wait 😄
oc get certificate,certificaterequest,order -ACheck the certificate used in the connections:
echo Q | openssl s_client -connect $(oc get route console -n openshift-console --template="{{.spec.host}}"):443 -showcerts 2>/dev/null | openssl x509 -noout -subject -issuer -enddate- Docs: cert-manager Operator for Red Hat OpenShift.
- Blog: YAUB - SSL Certificate Management for OpenShift on AWS.
- Blog: YAUB - Managing Certificates using GitOps approach.
- Blog: Automatic certificate issuing with IdM and cert-manager operator for OpenShift.
- Blog: Let's Encrypt - Challenge Types: This is a summary of how challenges work for certificates.
- Git: Cert Manager Mixin is a collection of reusable and configurable Prometheus alerts, and a Grafana dashboard to help with operating cert-manager.
HashiCorp Vault is a secrets management tool that integrates seamlessly with OpenShift (OCP) to securely store and manage sensitive information like API keys, credentials, and certificates. It enables dynamic secrets generation and automated secret renewal, reducing manual overhead and improving security. When combined with OCP, Vault ensures that applications running in your cluster can securely access secrets with fine-grained access control, enhancing the overall security posture of your workloads.
To install HashiCorp Vault on OpenShift, the recommended mechanism is to deploy it with the Helm Chart. For that reason, I've created the following application with the simplest configuration to deploy on OpenShift and automatically create a Route in dev mode:
cat application-03-hashicorp-vault-server.yaml | \
CLUSTER_DOMAIN=$(oc get dns.config/cluster -o jsonpath='{.spec.baseDomain}') \
envsubst | oc apply -f -In order to access the deployed Vault server, just retrieve the route using the following command and access the UI using the token root:
oc get route hashicorp-vault-server -n vault --template="https://{{.spec.host}}"As the dev Vault instance is an in-memory instance, just by deleting the vault-0 pod, you will loose all the data stored in the Vault. For that reason, I have created a script to quickly set up the Secret store with some dummy data to consume from the applications. The only thing that you need is log in to the cluster and execute the following script:
./create_vault_secrets.shNow, you can access the HashiCorp Vault, to the secret/ Engine and you will see the demo1, demo2, and demo3 entries.
- Git: GitHub - vault-helm. Official repo of the HashiCorp Vault Helm repo.
- Blog: In-Depth HashiCorp Vault setup on OpenShift using OpenShift GitOps: This is a must read. It is an updated blog on how to customize the HashiCorp Vault deployment.
- HashiCorp Tutorial: Install Vault to Red Hat OpenShift
Managing secrets securely is a cornerstone of modern application security. OpenShift, while offering built-in support for Kubernetes secrets, benefits greatly from the advanced features and dynamic nature of HashiCorp Vault. This section explores multiple approaches to integrate Vault with OCP, evaluating their benefits, drawbacks, and integration with ArgoCD.
Here are some common methods for using secrets from HashiCorp Vault in OpenShift environments:
| Tool | Description | Advantages | Disadvantages |
|---|---|---|---|
| HashiCorp Vault API | Direct integration with applications | Dynamic secrets, centralized management | Needs integration in application code, dependency on Vault availability. |
| Vault Sidecar Agent Injector | Injects secrets into pods via a sidecar | Secrets not stored in Kubernetes Secrets. | Requires sidecar for each pod. Only works for pods. |
| Secrets Store CSI Driver | Mounts secrets as volumes in pods | Simplifies secret consumption, works across multiple backends | Secrets not dynamically refreshed, requires additional driver. Only works for pods. |
| Vault Secrets Operator (VSO) | Syncs Vault secrets to Kubernetes Secrets | Kubernetes-native integration, automates secret updates | Secrets stored in Kubernetes Secrets. |
| External Secrets Operator (ESO) | Syncs secrets from external providers | Multi-provider support, GitOps-friendly | Secrets persisted in Kubernetes Secrets, sync delays possible. |
| ArgoCD Vault Plugin | Fetches secrets during manifest rendering | Tight GitOps integration, supports encrypted secrets | Adds complexity to the pipeline setup. Plugins are not in RH support. |
Tip
The first method just implies using app framework libraries or pre-exec scripts to retrieve the Secrets from the HashiCorp Vault manually and add them to the application. For that reason, we are not going to explore that possibility.
Nice blogs that I've used to compile this comparison:
The Vault Agent Injector alters pod specifications to include Vault Agent containers that render Vault secrets to a shared memory volume using Vault Agent Templates. By rendering secrets to a shared volume, containers within the pod can consume Vault secrets without being Vault aware.
The injector is a Kubernetes Mutation Webhook Controller. The controller intercepts pod events and applies mutations to the pod if annotations exist within the request. This functionality is provided by the vault-k8s project and can be automatically installed and configured using the Vault Helm chart.
oc apply -f application-05-vault-sidecar-agent-injector.yamlWarning
If this application is not rendered correctly in your ArgoCD, consider adding the following flag to your kustomize configuration: --enable-helm.
or deploy it locally with the following command kustomize build 05-vault-sidecar-agent-injector/ --enable-helm | oc apply -f -.
- Docs: HashiCorp - Vault Agent Injector.
- Tutorial: HashiCorp - Mange secrets by injecting a Vault Agent container.
- 🔧 Easy configuration based on several annotations.
- 🔑 Authentication based on ServiceAccount Tokens.
- 🛠️ Requires modifying application deployment configurations.
- 🔒 Secrets can only be injected into containers, not OpenShift configuration.
- 📂 Secrets can only be injected as files, not environment variables.
- ❌ Not supported by Red Hat.
- ⚡ High resources consumption as each pod with secret needs a permanent sidecar container.
- 🚀 Installation does not require an operator.
The Secrets Store CSI Driver secrets-store.csi.k8s.io allows Kubernetes to mount multiple secrets, keys, and certs stored in enterprise-grade external secrets stores into their pods as a volume. Once the Volume is attached, the data in it is mounted into the container’s file system.
The following secrets store providers are available for use with the Secrets Store CSI Driver Operator:
- AWS Secrets Manager.
- AWS Systems Manager Parameter Store.
- Azure Key Vault.
- Google Secret Manager.
- HashiCorp Vault.
oc apply -f application-06-secrets-store-csi-driver.yamlor deploy it locally with the following command kustomize build 06-secrets-store-csi-driver/ --enable-helm | oc apply -f -.
- Docs: OpenShift - Installing Secrets CSI.
- Docs: OpenShift - Providing sensitive data to pods by using an external secrets store.
- Docs: Kubernetes Secrets Store CSI Driver.
- Blog: OpenShift Secrets Store CSI Driver with Vault.
- 🔑 Authentication based on ServiceAccount Tokens.
- 📂 Secrets can be injected as files and environment variables as well.
- 🔧 More complex configuration. Requires Operator, and several k8s resources.
- 🛠️ Requires specific application deployment configuration related to the CSI Driver.
- 🔒 Secrets can only be injected into containers, not OpenShift configuration.
- 📲 The Secrets Store CSI Driver operator is Tech Preview in OpenShift 4.17.
- If you try to get the k8s secret, you'll see that it doesn't exist until it is requested by a pod.
- If you plan to consume your secret data as Kubernetes Secrets only, then other solutions like External Secrets Operator may be a better fit.
The Vault Secrets Operator allows Pods to consume Vault secrets and HCP Vault Secrets Apps natively from Kubernetes Secrets. The Operator writes the source Vault secret data directly to the destination Kubernetes Secret, ensuring that any changes made to the source are replicated to the destination over its lifetime.
Which are the main features?
VaultStaticSecret: Synchronize a single Vault static Secret to a single Kubernetes Secret.VaultPKISecret: Synchronize a single Vault PKI Secret. The PKI secrets engine generates dynamic X.509 certificates. With this secrets engine, services can get certificates without going through the usual manual processVaultDynamicSecret: Use secrets engines like databases, aws, azure, gcp, etc. to generate a single Vault dynamic Secret and sync it to a single Kubernetes Secret. Use Vault dynamic secrets to create secrets when accessed and to invalidate the secrets after use.
Tip
Vault's database secrets engine provides a credential management solution so that the username and password can be dynamically generated upon request, and you can control the lifecycle of the credentials:

oc apply -f application-07-vault-secrets-operator.yamlDo you want to check the Certificate content?
oc -n test-secrets get secret vso-pki -o jsonpath='{.data.certificate}' | base64 -dDo you want to check the Certificate validity?
oc -n test-secrets exec -it vso-pki-cert-checker -- openssl x509 -in /etc/pki/certificate -noout -text | grep -E '(Subject|Issuer|Not Before|Not After ):'
Issuer: CN=my-website.com
Not Before: Mar 30 10:21:27 2025 GMT
Not After : Mar 30 10:22:57 2025 GMT
Subject: CN=www.my-website.comDo you want to check the Dynamic Feature?
Then, you need to install the MySQL DB and you can use the following chart as example:
helm upgrade --install mysql oci://registry-1.docker.io/bitnamicharts/mysql \
--namespace vault \
--version 12.3.2 \
--values 07-vault-secrets-operator/mysql-values.yaml- Blog: Vault Secrets Operator for Kubernetes now GA.
- Git: learn-vault-secrets-operator
- Tutorial: Manage Kubernetes native secrets with the Vault Secrets Operator.
- The VSO operator is a certified operator by HashiCorp.
- Integration with Vault Dynamic Secrets.
- It allows to create secrets without a pod using it, so can be used for OpenShift configuration.
- Simplified configuration compared to the previous methods.
- It supports natively Static and Dynamic Secrets.
- Documentation is poor and specially when VSO is installed using OLM.
- It looks like having smaller penetration in the market compared to other alternatives.
External Secrets Operator is a Kubernetes operator that integrates external secret management systems like AWS Secrets Manager, HashiCorp Vault, Google Secrets Manager, Azure Key Vault, IBM Cloud Secrets Manager, CyberArk Conjur, Pulumi ESC and many more. The operator reads information from external APIs and automatically injects the values into a Kubernetes Secret.
Note
On december 2024, release 0.11.0, the ESO team stopped providing updates via OLM. The reason behind it is due to the coupling nature with our helm charts, which takes precedence over OLM as our first class release mechanism. We recommend OLM users to switch to plain helm chart installs as opposed to keep using OLM helm operator. Yo can check the official statement here and here.
This operator can be installed using the following ArgoCD application, that instantiates the official Helm chart:
oc apply -f application-08-external-secrets-operator.yamlor deploy it locally with the following command:
helm repo add external-secrets https://charts.external-secrets.io
helm upgrade -i --create-namespace -n external-secrets external-secrets external-secrets/external-secrets --set "installCRDs=true"- External Secrets Main site.
- ESO - HashiCorp Vault Provider.
- ESO - GitHub repository.
- Blog: External Secrets with HashiCorp Vault.
- It allows much more interaction types with the Secret Vault, like
PushSecrets, to push secrets to Vault. - Lot's of integrations with many Secret providers.
- The provider only supports Static Secrets. For dynamic secrets you need an ESO generator.
- The OLM operator has been deprecated.
- Red Hat Tech Preview support is targeted for OpenShift Plus 4.19. See the Jira here.
- As of December 2024, the way to install it is by a Helm Chart supported by the ESO team.
- Only
ExternalSecret,SecretStore,ClusterExternalSecretandClusterSecretStorehave v1beta1 support.
The Argo CD plugin retrieves secrets from various Secret Management tools (HashiCorp Vault, IBM Cloud Secrets Manager, AWS Secrets Manager, etc.) and inject them into Kubernetes resources.
This configuration requires deploying an instance of ArgoCD and customizing it. As I don't want to bloat the configuration with unnecessary elements, I will keep it minimal and focused on essential features. Meanwhile, we can deploy a new customized instance with the following command:
oc apply -k 09-argocd-vault-plugin-deploymentAfter the new instance is deployed, we can create a new ArgoCD application with a secret in that new application:
oc apply -f application-09-avp-example.yaml- Git repo: argocd-vault-plugin.
- Docs: ArgoCD Vault Plugin.
- Blog: How to Use HashiCorp Vault and Argo CD for GitOps on OpenShift.
- GitHub: jtudelag - ArgoCD Vault Plugin (AVP).
- No need of extra deployments, operators, or deployments.
- Changes behavior of ArgoCD App, as normal
Refreshbutton does not recalculate secrets. NeedsHard Refresh. - Tight couples the CD tool and the Secrets retrieval tool.
- It adds three new containers to the ArgoCD server pod.
- Not possible to evaluate the secrets without deploying using GitOps.
- Not possible to segregate authentication with different users in the same ArgoCD instance.
- It's not supported to use
kubernetesauthentication against HashiCorp Vault using ArgoCD deployed using the OLM operator, as it does not allow setting a custom ServiceAccount or mounting the SA token.
By default, etcd data is not encrypted in OpenShift Container Platform. You can enable etcd encryption for your cluster to provide an additional layer of data security. For example, it can help protect the loss of sensitive data if an etcd backup is exposed to the incorrect parties. When you enable etcd encryption, the following OpenShift API server and Kubernetes API server resources are encrypted:
- Secrets
- Config maps
- Routes
- OAuth access tokens
- OAuth authorize tokens
To enable etcd encryption, you would set etcdEncryption.enabled: true in your values file or pass it as a parameter when installing/upgrading the Helm chart. If you deployed the cert-manager following the steps of the previous
# 3) Configure the OpenShift certificates for Ingress and API
helm template 02-cert-manager-route53 --set clusterDomain=$(oc get dns.config/cluster -o jsonpath='{.spec.baseDomain}') --set etcdEncryption.enable="true" | oc apply -f -Great! We configured that flag on the APIServer resource, but I really need to make sure that encryption is enabled on the node. That's fine! Use the following commands to check the encryption configuration for each component:
- Review the
Encryptedstatus condition for the OpenShift API server to verify that its resources were successfully encrypted:
oc get openshiftapiserver -o=jsonpath='{range .items[0].status.conditions[?(@.type=="Encrypted")]}{.reason}{"\n"}{.message}{"\n"}'
EncryptionCompleted
All resources encrypted: routes.route.openshift.io- Review the
Encryptedstatus condition for the Kubernetes API server to verify that its resources were successfully encrypted:
$ oc get kubeapiserver -o=jsonpath='{range .items[0].status.conditions[?(@.type=="Encrypted")]}{.reason}{"\n"}{.message}{"\n"}'
EncryptionCompleted
All resources encrypted: secrets, configmaps- Review the
Encryptedstatus condition for the OpenShift OAuth API server to verify that its resources were successfully encrypted:
$ oc get authentication.operator.openshift.io -o=jsonpath='{range .items[0].status.conditions[?(@.type=="Encrypted")]}{.reason}{"\n"}{.message}{"\n"}'
EncryptionCompleted
All resources encrypted: oauthaccesstokens.oauth.openshift.io, oauthauthorizetokens.oauth.openshift.io