Setting up integration with Vault in a deployed cluster
Post-deployment setup of HashiCorp Vault integration in the client cluster and on the Vault side.
When to use
Use this instruction when the client cluster has already been created with a profile from Setting up integration with HashiCorp Vault in the cluster profile, and the vault-secrets-operator service is already deployed in the vault-operator namespace.
General scheme
Setting up integration consists of the following steps:
- Step 1. Make sure the service is deployed and get the token and CA-certificate from Secret.
- Step 2. Set up integration on the Vault side
- Step 3: Create VaultAuth and test integration.
Step 1. Make sure the service is deployed
In the deployed client cluster, check that the vault-secrets-operator service has been successfully installed and the necessary resources have been created in the vault-operator namespace.
| Check | Command | Expected result |
|---|---|---|
| Namespace created | kubectl get ns vault-operator | Namespace vault-operator is present in the cluster |
| Pod service launched | kubectl get pod -n vault-operator | The service pod is in the Running state |
| ServiceAccount created | kubectl get sa -n vault-operator | The namespace vault-operator contains the ServiceAccount of the service. The ServiceAccount name will be required to configure the Kubernetes authentication method role on the Vault side |
| Secret for ServiceAccount created | kubectl get secret -n vault-operator | The namespace vault-operator contains a Secret of type kubernetes.io/service-account-token. Copy the name Secret and use it in step 1.1 |
Step 1.1. Get the token and CA certificate from Secret
After verifying the created resources, get data from Secret to configure the Kubernetes authentication method on the Vault side in the CLI or GUI.
Run the commands to obtain the Kubernetes cluster token and CA certificate:
kubectl get secret -n vault-operator <secret-name> -o jsonpath='{.data.token}' | base64 --decode
kubectl get secret -n vault-operator <secret-name> -o jsonpath="{.data.ca\.crt}" | base64 --decode
| Data | Destination |
|---|---|
ServiceAccount Token (token) | Used in the Token Reviewer JWT field when configuring the Kubernetes authentication method in Vault |
Kubernetes CA Certificate (ca.crt) | Used in the Kubernetes CA Certificate field when configuring the Kubernetes authentication method in Vault |
- In the cluster GUI, go to namespace
vault-operator. - Open the Storage section and select Secret with the name
vault-secret. - Copy and save the values of the
ca.crtandtokenkeys.
Step 2. Set up integration on the Vault side
Once you have your Kubernetes token and CA certificate, move on to setting up your Vault server-side integration. The following describes the setup scenario in the GUI. For instructions on setting up the Kubernetes authentication method via the command line interface, see the HashiCorp Vault documentation: Kubernetes auth method.
Step 2.1. Create a Kubernetes Authentication Method
Create a new Kubernetes type authentication method that allows authentication using the ServiceAccount token.
In the Vault interface:
- Open the Access → Auth Methods section.
- Click Enable new method and select the type Kubernetes.
- Specify the path in the Path field and click Enable method.
| Field | Description | Where to get the value |
|---|---|---|
Path | It is recommended to use a path other than the default, such as client cluster name | Manually set by the administrator when creating a Kubernetes authentication method in Vault |
- When the method is created, on the Configuration tab, specify the parameters for connecting to the Kubernetes API:
| Field | Description | Where to get the value |
|---|---|---|
Kubernetes CA Certificate | Value ca.crt | See step 1.1 |
Token Reviewer JWT | ServiceAccount Token | See step1.1 |
Kubernetes host | Kubernetes API server address with port, for example https://10.11.12.13:6443 | In the GUI, use the value of the “API server” field in the Description block on the client cluster dashboard. For the console, get kubeconfig and determine the API server address with the command kubectl cluster-info |
Step 2.2. Set up Secrets Engine
Create a Secrets Engine of type KV or use an existing one.
To configure the Secrets Engine in the Vault interface, go to the Secrets Engines section and click Enable new engine. Select the KV type and specify the path where the secret storage will be accessible, for example kv.
Step 2.3. Create an access policy
Create an access policy (policy) or use an existing one that allows secrets to be read in the required Secrets Engine.
To create an access policy in the Vault interface, go to the Policies section and click Create ACL policy. Provide a policy name and add Secrets Engine access rules.
Example policy for KV v2:
path "kv/data/*" { capabilities = ["read", "list"] }
Step 2.4. Create a role
For the Kubernetes authentication method you created, add a role. In the Vault interface:
- Go to the Access → Auth Methods section.
- Open the Kubernetes authentication method you created.
- On the Roles tab, click Create role. For the role, be sure to fill out:
| Field | Description | Where to get the value |
|---|---|---|
Name | The role name that will need to be specified in the kubernetes.role parameter of the VaultAuth resource | Set manually by the administrator when creating a role in Vault |
Bound service account names | ServiceAccount name in namespace vault-operator | Receive in the client cluster with the command kubectl get sa -n vault-operator |
Bound service account namespaces | Name of the namespace vault-operator in which the ServiceAccount was created | Use the value vault-operator, since the service is deployed in this namespace |
Generated Token's Policies | Name of the created access policy | Use the name of the policy created in step 2.3 |
Step 3: Create VaultAuth and basic integration testing
You can perform the creation of VaultAuth and basic integration testing via VaultStaticSecret manually or in one run using a Bash script.
Step 3.1 Create VaultAuth
After setting up authentication on the Vault side, complete the integration: create VaultAuth in the deployed client cluster.
Example VaultAuth:
apiVersion: secrets.hashicorp.com/v1beta1
kind: VaultAuth
metadata:
name: vault-auth-name
namespace: vault-operator
spec:
kubernetes:
role: role-name
serviceAccount: name-service-account
tokenExpirationSeconds: 600
method: kubernetes
mount: path-name
vaultConnectionRef: vault-connection-name
| Field | Data type | Description |
|---|---|---|
kubernetes.role | string | Name of the role created for the Kubernetes authentication method on the Vault side |
kubernetes.serviceAccount | string | ServiceAccount name for authentication in Vault, created in namespace vault-operator when setting vault-secrets-operator |
kubernetes.tokenExpirationSeconds | integer | Lifetime of the token used for authentication in Vault |
method | string | Vault authentication method. kubernetes must be specified |
mount | string | Kubernetes authentication method path created on the Vault side |
vaultConnectionRef | string | Name of VaultConnection created in the cluster during initialization |
Important: the values in spec.mount and spec.kubernetes.role must match the configuration settings of the created Kubernetes authentication method on the Vault side.
Step 3.2 Test integration
Make sure first:
| Check | Command | Expected result |
|---|---|---|
Status VaultConnection | kubectl get vaultconnection -n vault-operator <vault-connection-name> -o yaml | There are no errors in status and valid is set to true |
Status VaultAuth | kubectl get vaultauth -n vault-operator <vault-auth-name> -o yaml | status has no authentication errors and valid is set to true |
Logs vault-secrets-operator | kubectl logs -n vault-operator <vault-secrets-operator-pod> | No connection or authentication errors in Vault |
If necessary, check the configured integration withusing the test resource VaultStaticSecret. Before using the manifest, ensure that a secret exists in the specified path in Vault and that the access policy allows it to be read.
Example VaultStaticSecret:
apiVersion: secrets.hashicorp.com/v1beta1
kind: VaultStaticSecret
metadata:
name: vault-static-secret
namespace: vault-operator
spec:
destination:
create: true
name: secret-kubernetes-name
overwrite: true
mount: kv
path: secret-name
refreshAfter: 10s
type: kv-v2
vaultAuthRef: vault-auth-name
| Field | Type | Example value | Description |
|---|---|---|---|
destination | object | — | Parameters for the Secret Kubernetes that will be created or updated based on data from Vault |
destination.create | boolean | true | Create a Kubernetes Secret automatically if there is no such Secret yet |
destination.name | string | secret-kubernetes-name | Name of the Secret that will be created in the cluster |
destination.overwrite | boolean | true | Overwrite existing Kubernetes Secret when updating data |
mount | string | kv | Secrets Engine Path to Vault |
path | string | secret-name | Path to the secret inside the specified Secrets Engine |
refreshAfter | string | 10s | The interval at which the operator rechecks and synchronizes data from Vault |
type | string | kv-v2 | Type Secrets Engine in Vault |
vaultAuthRef | string | vault-auth-name | Name of the created VaultAuth used for authentication in Vault |
After applying the manifest, check that a Kubernetes Secret with the name specified in destination.name appears in the namespace vault-operator.
kubectl get secret -n vault-operator
Instead of steps 3 and 4: use a Bash script
Note: Before running the script, check the values of the variables. The script automatically creates VaultAuth, checks the status of integration resources and creates VaultStaticSecret, so an error in the parameters can lead to incorrect configuration of the connection to Vault.
Before running the script, connect to the client cluster via kubeconfig.
Variables used in the script:
| Variable | Default | Description |
|---|---|---|
VSO_NAMESPACE | vault-operator | Namespace in which vault-secrets-operator is deployed |
VAULTAUTH_NAME | vault-auth-name | The name of the created resource is VaultAuth |
VAULT_ROLE | — | Name of the role created for the Kubernetes authentication method on the Vault side |
VSO_SERVICEACCOUNT | vault-secrets-operator-controller-manager | Name of ServiceAccount vault-secrets-operator used for Vault authentication |
VAULT_AUTH_MOUNT | — | Kubernetes authentication method path created on the Vault side |
VAULTCONNECTION_REF | vault-connection-name | Resource name VaultConnection |
K8S_TOKEN_EXPIRATION_SECONDS | 600 | Lifetime of the token used for authentication in Vault |
CHECK_DELAY_SECONDS | 10 | Delay in seconds before checking resource statuses after applying manifests |
CREATE_VAULTSTATICSECRET | false | Additionally create VaultStaticSecret to test integration |
VAULTSTATICSECRET_NAME | vault-static-secret | The name of the created resource is VaultStaticSecret |
DESTINATION_SECRET_NAME | secret-kubernetes-name | Name of the Kubernetes Secret that will be created by the operator |
DESTINATION_OVERWRITE | true | Overwrite existing Kubernetes Secret when updating data |
KV_MOUNT | kv | Secrets Engine Path to Vault |
KV_PATH | secret-name | Path to an existing secret in Secrets Engine |
REFRESH_AFTER | 10s | Secret resync interval |
SECRET_ENGINE_TYPE | kv-v2 | Type Secrets Engine in Vault |
bash /dev/stdin <<'EOF'
set -euo pipefail
VSO_NAMESPACE="${VSO_NAMESPACE:-vault-operator}"
VAULTAUTH_NAME="${VAULTAUTH_NAME:-vault-auth-name}"
VAULTCONNECTION_REF="${VAULTCONNECTION_REF:-vault-connection-name}"
K8S_TOKEN_EXPIRATION_SECONDS="${K8S_TOKEN_EXPIRATION_SECONDS:-600}"
CHECK_DELAY_SECONDS="${CHECK_DELAY_SECONDS:-10}"
VSO_SERVICEACCOUNT="${VSO_SERVICEACCOUNT:-vault-secrets-operator-controller-manager}"
: "${VAULT_ROLE:?Set VAULT_ROLE, for example vault-role-name}"
: "${VAULT_AUTH_MOUNT:?Set VAULT_AUTH_MOUNT, for example cluster-name}"
CREATE_VAULTSTATICSECRET="${CREATE_VAULTSTATICSECRET:-false}"
VAULTSTATICSECRET_NAME="${VAULTSTATICSECRET_NAME:-vault-static-secret}"
DESTINATION_SECRET_NAME="${DESTINATION_SECRET_NAME:-secret-kubernetes-name}"
DESTINATION_OVERWRITE="${DESTINATION_OVERWRITE:-true}"
KV_MOUNT="${KV_MOUNT:-kv}"
KV_PATH="${KV_PATH:-secret-name}"
REFRESH_AFTER="${REFRESH_AFTER:-10s}"
SECRET_ENGINE_TYPE="${SECRET_ENGINE_TYPE:-kv-v2}"
kubectl apply -f - <<EOF2
apiVersion: secrets.hashicorp.com/v1beta1
kind: VaultAuth
metadata:
name: ${VAULTAUTH_NAME}
namespace: ${VSO_NAMESPACE}
spec:
kubernetes:
role: ${VAULT_ROLE}
serviceAccount: ${VSO_SERVICEACCOUNT}
tokenExpirationSeconds: ${K8S_TOKEN_EXPIRATION_SECONDS}
method: kubernetes
mount: ${VAULT_AUTH_MOUNT}
vaultConnectionRef: ${VAULTCONNECTION_REF}
EOF2
sleep "${CHECK_DELAY_SECONDS}"
echo "Checking VaultConnection status"
kubectl get vaultconnection -n "${VSO_NAMESPACE}" "${VAULTCONNECTION_REF}" -o yaml
echo "Checking VaultAuth status"
kubectl get vaultauth -n "${VSO_NAMESPACE}" "${VAULTAUTH_NAME}" -o yaml
if [ "${CREATE_VAULTSTATICSECRET}" = "true" ]; then
kubectl apply -f - <<EOF2
apiVersion: secrets.hashicorp.com/v1beta1
kind: VaultStaticSecret
metadata:
name: ${VAULTSTATICSECRET_NAME}
namespace: ${VSO_NAMESPACE}
spec:
destination:
create: true
name: ${DESTINATION_SECRET_NAME}
overwrite: ${DESTINATION_OVERWRITE}
mount: ${KV_MOUNT}
path: ${KV_PATH}
refreshAfter: ${REFRESH_AFTER}
type: ${SECRET_ENGINE_TYPE}
vaultAuthRef: ${VAULTAUTH_NAME}
EOF2
sleep "${CHECK_DELAY_SECONDS}"
echo "Checking the created Kubernetes Secret"
kubectl get secret -n "${VSO_NAMESPACE}" "${DESTINATION_SECRET_NAME}"
fi
EOF