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

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.

CheckCommandExpected result
Namespace createdkubectl get ns vault-operatorNamespace vault-operator is present in the cluster
Pod service launchedkubectl get pod -n vault-operatorThe service pod is in the Running state
ServiceAccount createdkubectl get sa -n vault-operatorThe 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 createdkubectl get secret -n vault-operatorThe 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
DataDestination
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
  1. In the cluster GUI, go to namespace vault-operator.
  2. Open the Storage section and select Secret with the name vault-secret.
  3. Copy and save the values of the ca.crt and token keys.

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:

  1. Open the Access → Auth Methods section.
  2. Click Enable new method and select the type Kubernetes.
  3. Specify the path in the Path field and click Enable method.
FieldDescriptionWhere to get the value
PathIt is recommended to use a path other than the default, such as client cluster nameManually set by the administrator when creating a Kubernetes authentication method in Vault
  1. When the method is created, on the Configuration tab, specify the parameters for connecting to the Kubernetes API:
FieldDescriptionWhere to get the value
Kubernetes CA CertificateValue ca.crtSee step 1.1
Token Reviewer JWTServiceAccount TokenSee step1.1
Kubernetes hostKubernetes API server address with port, for example https://10.11.12.13:6443In 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:

  1. Go to the Access → Auth Methods section.
  2. Open the Kubernetes authentication method you created.
  3. On the Roles tab, click Create role. For the role, be sure to fill out:
FieldDescriptionWhere to get the value
NameThe role name that will need to be specified in the kubernetes.role parameter of the VaultAuth resourceSet manually by the administrator when creating a role in Vault
Bound service account namesServiceAccount name in namespace vault-operatorReceive in the client cluster with the command kubectl get sa -n vault-operator
Bound service account namespacesName of the namespace vault-operator in which the ServiceAccount was createdUse the value vault-operator, since the service is deployed in this namespace
Generated Token's PoliciesName of the created access policyUse 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
FieldData typeDescription
kubernetes.rolestringName of the role created for the Kubernetes authentication method on the Vault side
kubernetes.serviceAccountstringServiceAccount name for authentication in Vault, created in namespace vault-operator when setting vault-secrets-operator
kubernetes.tokenExpirationSecondsintegerLifetime of the token used for authentication in Vault
methodstringVault authentication method. kubernetes must be specified
mountstringKubernetes authentication method path created on the Vault side
vaultConnectionRefstringName 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:

CheckCommandExpected result
Status VaultConnectionkubectl get vaultconnection -n vault-operator <vault-connection-name> -o yamlThere are no errors in status and valid is set to true
Status VaultAuthkubectl get vaultauth -n vault-operator <vault-auth-name> -o yamlstatus has no authentication errors and valid is set to true
Logs vault-secrets-operatorkubectl 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
FieldTypeExample valueDescription
destinationobject—Parameters for the Secret Kubernetes that will be created or updated based on data from Vault
destination.createbooleantrueCreate a Kubernetes Secret automatically if there is no such Secret yet
destination.namestringsecret-kubernetes-nameName of the Secret that will be created in the cluster
destination.overwritebooleantrueOverwrite existing Kubernetes Secret when updating data
mountstringkvSecrets Engine Path to Vault
pathstringsecret-namePath to the secret inside the specified Secrets Engine
refreshAfterstring10sThe interval at which the operator rechecks and synchronizes data from Vault
typestringkv-v2Type Secrets Engine in Vault
vaultAuthRefstringvault-auth-nameName 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:

VariableDefaultDescription
VSO_NAMESPACEvault-operatorNamespace in which vault-secrets-operator is deployed
VAULTAUTH_NAMEvault-auth-nameThe name of the created resource is VaultAuth
VAULT_ROLE—Name of the role created for the Kubernetes authentication method on the Vault side
VSO_SERVICEACCOUNTvault-secrets-operator-controller-managerName of ServiceAccount vault-secrets-operator used for Vault authentication
VAULT_AUTH_MOUNT—Kubernetes authentication method path created on the Vault side
VAULTCONNECTION_REFvault-connection-nameResource name VaultConnection
K8S_TOKEN_EXPIRATION_SECONDS600Lifetime of the token used for authentication in Vault
CHECK_DELAY_SECONDS10Delay in seconds before checking resource statuses after applying manifests
CREATE_VAULTSTATICSECRETfalseAdditionally create VaultStaticSecret to test integration
VAULTSTATICSECRET_NAMEvault-static-secretThe name of the created resource is VaultStaticSecret
DESTINATION_SECRET_NAMEsecret-kubernetes-nameName of the Kubernetes Secret that will be created by the operator
DESTINATION_OVERWRITEtrueOverwrite existing Kubernetes Secret when updating data
KV_MOUNTkvSecrets Engine Path to Vault
KV_PATHsecret-namePath to an existing secret in Secrets Engine
REFRESH_AFTER10sSecret resync interval
SECRET_ENGINE_TYPEkv-v2Type 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