How To Integrate Multiple Kubernetes Clusters to Vault Server

Posted on 168 views

In case you have many clusters as part of your infrastructure and you would wish to introduce HashiCorp Vault to take care of your secrets, then worry no more. In this guide, we are going to configure Develop, Staging and Production Kubernetes Authentication methods in Vault server then proceed to add secrets, policies, roles and link them all together to our separate Kubernetes clusters (Develop, Staging and Production). If you have more clusters, you can use similar pattern that we will be using to add them.

Definition of terms

  • Policies: Policies provide a declarative way to grant or forbid access to certain paths and operations in Vault.
  • Roles: Policies are attached to tokens and roles to enforce client permissions on Vault.
  • Secrets: A secret is anything that you want to tightly control access to, such as API encryption keys, passwords, or certificates

Since we have three clusters, we are going to begin with Develop, then Staging and then complete with Production.

1. Develop cluster

Configuring Dev cluster Kubernetes Auth Method

Before we can configure Kubernetes Auth, we need to have a few things in our basket. We need JWT reviewer token, Kubernetes ca certificate, Kubernetes service account and the Kubernetes host control plane. So we shall begin by gathering these things in each of the clusters.

Get Dev Cluster control plane

Change your context to Dev Kubernetes cluster

kubectl config use-context dev-cluster

Then get the Dev control plane URL.

$ kubectl cluster-info
Kubernetes control plane is running at https://192.168.20.22

Get/Create Dev service account

This service account is going to be used to generate the JWT reviewer token as we will see very soon. So let us create a ClusterRole and ClusterRoleBinding for the service account. Note that if there is a service account with the requisite permissions in the cluster already, you can use it here. The service account can be in any namespace.

$ vim vault-sa.yaml

---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
   name: role-tokenreview-binding ##This Role!
   namespace: default
roleRef:
   apiGroup: rbac.authorization.k8s.io
   kind: ClusterRole
   name: system:auth-delegator
subjects:
- kind: ServiceAccount
  name: vault-auth
  namespace: default

Create the Service Account

kubectl create sa vault-auth
kubectl apply -f vault-sa.yaml

NOTE: The service account must have role-tokenreview-binding ClusterRoleBinding permissions.

Get Dev Reviewer JWT Token

Once we have our service account, we can now generate the reviewer JWT Token as follows

export DEV_VAULT_SA_NAME=$(kubectl -n  get sa vault-auth --output jsonpath=".secrets[*]['name']")
export DEV_SA_JWT_TOKEN=$(kubectl -n  get secret $DEV_VAULT_SA_NAME --output 'go-template= .data.token ' | base64 --decode)
echo $DEV_SA_JWT_TOKEN >> ~/dev-cluster-jwt-token

The reviewer JWT Token will be stored in “~/dev-cluster-jwt-token” file.

Get Dev CA Certificate

Lastly, let us generate the ca certificate of the Dev Cluster. Over to the terminal, run the commands below:

DEV_KUBE_CA_CERT=$(kubectl config view --raw --minify --flatten --output='jsonpath=.clusters[].cluster.certificate-authority-data' | base64 --decode)
echo $DEV_KUBE_CA_CERT >> ~/dev-ca.crt

The CA certificate will be stored in “~/dev-ca.crt” file.

Once the two files have been generated, I presume in your local machine. You will need to send them to the Vault server. Our server is in GCP in this example, and the files were transferred as follows:

$ scp ~/dev-cluster-jwt-token [email protected]:~
$ scp ~/dev-ca.crt [email protected]:~

At this point, we have everything we need to configure Dev cluster’s Kubernetes Auth Method

Configure Dev cluster’s Kubernetes Auth Method

To configure this, login to your Vault instance and run the commands below.

Create Kubernetes Dev Auth method path

vault auth enable --path=dev-cluster kubernetes

Then configure the new path with the details we created as follows

vault write auth/dev-cluster/config \
    token_reviewer_jwt="$(cat ~/dev-cluster-jwt-token)" \
    kubernetes_host=https://192.168.20.22 \
    kubernetes_ca_cert="$(cat ~/dev-ca.crt)" \
    issuer="https://kubernetes.default.svc.cluster.local"

Once we are at this point, our Dev auth configuration is successfully done and the only thing remaining is the configuration of secrets, policies and roles.

Create Secrets for respective applications in each cluster

First, you can create a path that will hold secrets in Dev cluster then you can add secrets therein. An example is given below

vault secrets enable -path=dev-secrets kv-v2
vault kv put dev-secrets/dev-payments-service/config username=geeks-dev password=12345

Create a policy with requisite permissions for the secrets accessibility

Once the secret is created, you need the best policy/permissions for it. Here, we will give “read” permissions only for this policy. You can have many policies for different use-cases.

vault policy write dev-app - <

You can also permit the policy to read everything under “dev-secrets” path as follows:

vault policy write dev-app - <

Create a role and attach the policy we created above

The policy is a set of permissions and a role needs access to secrets with given permissions declared in policies. As an example, we will create a role that will have “dev-app’s” policy permissions. This role will authenticate to the cluster and will only have read permissions in the given secrets. You can bind the authentication to specific Kubernetes service accounts or you can grant all namespaces and service accounts permission to authenticate.

In this case below, applications in default namespace only will be able to successfully authenticate.

vault write auth/dev-cluster/role/devweb-app \
    bound_service_account_names=default \
    bound_service_account_namespaces=default \
    policies=dev-app \
    ttl=24h

Or you can grant all namespaces and service accounts permission to authenticate as follows:

vault write auth/dev-cluster/role/devweb-app \
    bound_service_account_names=* \
    bound_service_account_namespaces=* \
    policies=dev-app \
    ttl=24h

2. Staging cluster

Configuring Staging cluster Kubernetes Auth method

Just like in our Dev cluster, before we can configure Kubernetes Auth, we need to have a few things in our plate. We need JWT reviewer token, Kubernetes ca certificate, Kubernetes service account and the Kubernetes host control plane. So we shall begin by gathering these things in each of the clusters.

Get Staging control plane

Change your context to Staging Kubernetes cluster

kubectl config use-context staging-cluster

Then get the Staging control plane URL.

$ kubectl cluster-info

Kubernetes control plane is running at https://192.168.20.23

Get/Create Staging service account

This service account is going to be used to generate the JWT reviewer token as we will see very soon. So let us create a ClusterRole and ClusterRoleBinding for the service account. Note that if there is a service account with the requisite permissions in the cluster already, you can use it here. The service account can be in any namespace.

$ vim vault-sa.yaml

---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
   name: role-tokenreview-binding  ## This!!
   namespace: default
roleRef:
   apiGroup: rbac.authorization.k8s.io
   kind: ClusterRole
   name: system:auth-delegator
subjects:
- kind: ServiceAccount
  name: vault-auth
  namespace: default

Create the Service Account

kubectl create sa vault-auth

REMEMBER: The service account must have role-tokenreview-binding ClusterRoleBinding permissions.

Get Staging Reviewer JWT Token

Once we have our service account, we can now generate the reviewer JWT Token as follows

export STAGING_VAULT_SA_NAME=$(kubectl -n  get sa vault-auth --output jsonpath=".secrets[*]['name']")
export STAGING_SA_JWT_TOKEN=$(kubectl -n  get secret $STAGING_VAULT_SA_NAME --output 'go-template= .data.token ' | base64 --decode)
echo $STAGING_SA_JWT_TOKEN >> ~/staging-cluster-jwt-token

Replace with the namespace where the service account resides.

The reviewer JWT Token will be stored in “~/staging-cluster-jwt-token” file.

Get Staging CA Certificate

Lastly, let us generate the ca certificate of the Staging Cluster. Over to the terminal, run the commands below:

STAGING_KUBE_CA_CERT=$(kubectl config view --raw --minify --flatten --output='jsonpath=.clusters[].cluster.certificate-authority-data' | base64 --decode)
echo $STAGING_KUBE_CA_CERT >> ~/staging-ca.crt

The CA certificate will be stored in “~/staging-ca.crt” file.

Once the two files have been generated, I presume in your local machine, you will need to send them to the Vault server. Our server is in GCP in this example, and the files were transferred as follows:

scp ~/staging-cluster-jwt-token  [email protected]:~
scp ~/staging-ca.crt  [email protected]:~

At this point, we have everything we need to configure Staging cluster’s Kubernetes Auth Method

Configure Staging cluster’s Kubernetes Auth Method

To configure this, login to your same Vault instance and run the commands below.

Create Kubernetes Staging Auth method path

vault auth enable --path=staging-cluster kubernetes

Then configure the new path with the details we created as follows

vault write auth/staging-cluster/config \
    token_reviewer_jwt="$(cat ~/staging-cluster-jwt-token)" \
    kubernetes_host=https://192.168.20.23 \
    kubernetes_ca_cert="$(cat ~/staging-ca.crt)" \
    issuer="https://kubernetes.default.svc.cluster.local"

Once we are at this point, our Staging Auth configuration is successfully done and the only thing remaining is the configuration of secrets, policies and roles.

Create Secrets for respective applications in each cluster

First, you can create a path that will hold secrets in Staging cluster then you can add secrets therein. An example is given below

vault secrets enable -path=staging-secrets kv-v2
vault kv put staging-secrets/staging-payments-service/config username=geeks-staging password=12345

Create a policy with requisite permissions for the secrets accessibility

Once the secret is created, you need the best policy/permissions for it. Here, we will give “read” permissions only for this policy. You can have many policies for different use-cases.

vault policy write staging-app - <

You can also permit the policy to read everything under “staging-secrets” path as follows:

vault policy write staging-app - <

Create a role and attach the policy we created above

The policy is a set of permissions and a role needs access to secrets with given permissions declared in policies. As an example, we will create a role that will have “staging-app’s” policy permissions. This role will authenticate to the cluster and will only have read permissions in the given secrets. You can bind the authentication to specific Kubernetes service accounts or you can grant all namespaces and service accounts permission to authenticate.

In this case below, applications in default namespace only will be able to successfully authenticate.

vault write auth/staging-cluster/role/staging-web-app \
    bound_service_account_names=default \
    bound_service_account_namespaces=default \
    policies=staging-app \
    ttl=24h

Or you can grant all namespaces and service accounts permission to authenticate as follows:

vault write auth/staging-cluster/role/staging-web-app \
    bound_service_account_names=* \
    bound_service_account_namespaces=* \
    policies=staging-app \
    ttl=24h

3. Production Cluster

Configuring Production cluster Kubernetes Auth method

Just like in our Dev and Staging clusters, before we can configure Kubernetes Auth, we need to have a few things in our basket. We need JWT reviewer token, Kubernetes ca certificate, Kubernetes service account and the Kubernetes host control plane. So we shall begin by gathering these things in each of the clusters.

Get Production Control Plane

Change your context to Production Kubernetes Cluster or whichever way you get access to your production cluster.

kubectl config use-context production-cluster

Then get the Production control plane URL.

$ kubectl cluster-info

Kubernetes control plane is running at https://192.168.20.24

Get/create Production service account

This service account is going to be used to generate the JWT reviewer token as we will see very soon. So let us create a ClusterRole and ClusterRoleBinding for the service account. Note that if there is a service account with the requisite permissions in the cluster already, you can use it here. The service account can be in any namespace.

$ vim vault-sa.yaml

---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
   name: role-tokenreview-binding ##This!!
   namespace: default
roleRef:
   apiGroup: rbac.authorization.k8s.io
   kind: ClusterRole
   name: system:auth-delegator
subjects:
- kind: ServiceAccount
  name: vault-auth
  namespace: default

Create the Service Account

kubectl create sa vault-auth

REMEMBER: The service account must have role-tokenreview-binding ClusterRoleBinding permissions.

Get Production Reviewer JWT Token

Once we have our service account, we can now generate the reviewer JWT Token as follows

export PROD_VAULT_SA_NAME=$(kubectl -n  get sa vault-auth --output jsonpath=".secrets[*]['name']")
export PROD_SA_JWT_TOKEN=$(kubectl -n  get secret $PROD_VAULT_SA_NAME --output 'go-template= .data.token ' | base64 --decode)
echo $PROD_SA_JWT_TOKEN >> ~/prod-cluster-jwt-token

You will have to replace with the namespace where your service account can be found in.

The reviewer JWT Token will be stored in “~/prod-cluster-jwt-token” file.

Get Production CA Certificate

Lastly, let us generate the ca certificate of the Production Cluster. Over to the terminal, run the commands below:

PROD_KUBE_CA_CERT=$(kubectl config view --raw --minify --flatten --output='jsonpath=.clusters[].cluster.certificate-authority-data' | base64 --decode)
echo $PROD_KUBE_CA_CERT >> ~/prod-ca.crt

The CA certificate will be stored in “~/prod-ca.crt” file.

Once the two files have been generated, I presume in your local machine, you will need to send them to the Vault server. Our server is in GCP in this example, and the files were transferred as follows:

$ scp ~/prod-cluster-jwt-token [email protected]:~
$ scp ~/prod-ca.crt  [email protected]:~

At this point, we have everything we need to configure Production cluster’s Kubernetes Auth Method

Configure Production cluster’s Kubernetes Auth Method

To configure this, login to your same Vault instance and run the commands below.

Create Kubernetes Production Auth method path

vault auth enable --path=prod-cluster kubernetes

Then configure the new path with the details we created as follows

vault write auth/prod-cluster/config \
    token_reviewer_jwt="$(cat ~/prod-cluster-jwt-token)" \
    kubernetes_host=https://192.168.20.24 \
    kubernetes_ca_cert="$(cat ~/prod-ca.crt)" \
    issuer="https://kubernetes.default.svc.cluster.local"

Once we are at this point, our Staging Auth configuration is successfully done and the only thing remaining is the configuration of secrets, policies and roles.

Create Secrets for respective applications in each cluster

First, you can create a path that will hold secrets in Staging cluster then you can add secrets therein. An example is given below

vault secrets enable -path=prod-secrets kv-v2
vault kv put prod-secrets/prod-payments-service/config username=geeks-prod password=12345

Create a policy with requisite permissions for the secrets accessibility

Once the secret is created, you need the best policy/permissions for it. Here, we will give “read” permissions only for this policy. You can have many policies for different use-cases.

vault policy write prod-app - <

You can also permit the policy to read everything under “prod-secrets” path as follows:

vault policy write prod-app - <

Create a role and attach the policy we created above

The policy is a set of permissions and a role needs access to secrets with given permissions declared in policies. As an example, we will create a role that will have “staging-app’s” policy permissions. This role will authenticate to the cluster and will only have read permissions in the given secrets. You can bind the authentication to specific Kubernetes service accounts or you can grant all namespaces and service accounts permission to authenticate.

In this case below, applications in default namespace only will be able to successfully authenticate.

vault write auth/prod-cluster/role/prod-web-app \
    bound_service_account_names=default \
    bound_service_account_namespaces=default \
    policies=prod-app \
    ttl=24h

Or you can grant all namespaces and service accounts permission to authenticate as follows:

vault write auth/prod-cluster/role/prod-web-app \
    bound_service_account_names=* \
    bound_service_account_namespaces=* \
    policies=prod-app \
    ttl=24h

End Note

In the end, we should now be able to segregate all of the secrets in any of your working clusters and manage all of them in one place where their tokens can be easily reviewed, revoked, added and modified. Now any application in any of your Kubernetes Clusters can connect to Vault and get secrets if the details they provide are correct. Next we shall look at how applications can be configured to get secrets from the ready Vault server.

coffee

Gravatar Image
A systems engineer with excellent skills in systems administration, cloud computing, systems deployment, virtualization, containers, and a certified ethical hacker.