This course will give you the introductory knowledge and skills you need to use HashiCorp Vault in Kubernetes.
Section 1: Vault Kubernetes Deployment | |
Section 2: Vault Kubernetes Configuration | |
Section 3: Vault Kubernetes Integration | |
Section 4: Vault Kubernetes Application |
This course will introduce you to the basics of using HashiCorp Vault in Kubernetes. You will learn how to deploy Vault in Kubernetes, configure Vault for use with Kubernetes, integrate Vault with Kubernetes, and use Vault in your Kubernetes applications.
Vault Kubernetes Deployment:
Vault can be deployed in Kubernetes using the official HashiCorp Vault Helm chart. The Helm chart allows you to deploy Vault in a variety of configurations, including a single in-memory Vault server for testing, a standalone Vault server persisting to a volume, or a highly available cluster of Vault servers.
Vault Kubernetes Configuration:
Once Vault is deployed in Kubernetes, you need to configure it for use with your applications. You will need to create a Kubernetes secret that contains the Vault token for your applications to use. You can also configure Vault to use different authentication methods, such as LDAP or Active Directory.
Vault Kubernetes Integration:
Once Vault is configured, you can integrate it with your Kubernetes applications. You can do this by using the Vault Kubernetes Auth method, which allows your applications to authenticate with Vault using a Kubernetes Service Account Token. You can also use the Vault Kubernetes Agent, which injects a Vault sidecar container into your pods that can access Vault secrets.
Vault Kubernetes Application:
Once Vault is integrated with your Kubernetes applications, you can use it to store secrets for your applications. You can store passwords, certificates, SSH keys, and other sensitive data in Vault. Vault provides a variety of secret engines that you can use to store different types of secrets.
Purpose of Vaults:
kubectl
and helm to connect to the Kubernetes cluster: https://kubernetes.io/docs/concepts/configuration/organize-cluster-access-kubeconfig/The Vault Helm chart is the recommended way to install and configure Vault on Kubernetes. In addition to running Vault itself, the Helm chart is the primary method for installing and configuring Vault to integrate with other services, such as Consul for High Availability (HA) deployments.
helm repo add hashicorp https://helm.releases.hashicorp.com && helm repo update
helm install -n vault-system --create-namespace --set ui.enabled=true vault hashicorp/vault
helm -n vault-system list
kubectl -n vault-system get all
You will need network access to the Vault cluster running on Kubernetes.
If your cluster’s ingress is already set up to allow connectivity, then feel free to modify the networking to connect to the Vault API and UI port at 8200. The path prefix will be “/
”.
kubectl proxy --port=8200
helm -n vault-system upgrade --set 'ingress.enabled=true' vault
When a Vault server is started, it starts in a sealed state. In this state, Vault is configured to know where and how to access the physical storage but doesn't know how to decrypt any of it.
Unsealing is the process of obtaining the plaintext root key necessary to read the decryption key to decrypt the data, allowing access to the Vault.
Prior to unsealing, almost no operations were possible with Vault. For example, authentication, managing the mount tables, etc., are all not possible. The only possible operations are to unseal the Vault and check the status of the seal.
The data stored by Vault is encrypted. Vault needs the encryption key in order to decrypt the data. The encryption key is also stored with the data (in the keyring) but encrypted with another encryption key known as the root key.
Therefore, to decrypt the data, Vault must decrypt the encryption key, which requires the root key. Unsealing is the process of getting access to this root key. The root key is stored alongside all other Vault data but is encrypted by yet another mechanism: the unseal key.
Upon initially visiting the UI there will be an initialization setup prompt.
Enter the following defaults:
5 key shares
Retain the unseal keys and root token for later, and then select “Continue to unseal”
Things to Note:
Enter at least three unseal keys to unseal Vault, and to access the initial authentication page
Verify Vault cluster readiness:
kubectl -n vault-system exec -ti vault-0 -- vault list secrets
You have successfully deployed a basic Vault cluster to Kubernetes.
Section 2: Vault Kubernetes Configuration
Authentication in Vault is the process by which user or machine supplied information is verified against an internal or external system.
Before a client can interact with Vault, it must authenticate against an auth method. Upon authentication, a token is generated. This token is conceptually similar to a session ID on a website. The token may have an attached policy, which is mapped at authentication time. This process is described in detail in the policies concepts documentation.
Authentication process:Tokens are the core method for authentication within Vault.
Within Vault, tokens map to information:
Root tokens are tokens that have the root policy attached to them
Root tokens are useful in development but should be extremely carefully guarded in production.
It is also good security practice for there to be multiple eyes on a terminal whenever a root token is live.
[EXERCISE]
|
The “vault-ui” Kubernetes service provides the UI at port 8200 by default
With proper ingress, forwarding, or proxying the UI can be accessed in a browser at:
/ui
” depending upon the path prefixLogin to the UI with token based authentication and the root token
Explore the interface, and note the only current secrets mount is the root user’s cubbyhole
Auth methods are the components in Vault that perform authentication and are responsible for assigning identity and a set of policies to a user
Auth methods are the components in Vault that perform authentication and are responsible for assigning identity and a set of policies to a user. Vault will enforce authentication in all cases as part of the request processing. In most cases, Vault will delegate the authentication administration and decision to the relevant configured external auth method (e.g., Amazon Web Services, GitHub, Google Cloud Platform, Kubernetes, Microsoft Azure, Okta ...).
Having multiple auth methods enables you to use an auth method that makes the most sense for your use case of Vault and your organization.
For example:
The Kubernetes auth method can be used to authenticate with Vault using a Kubernetes Service Account Token. This method of authentication makes it easy to introduce a Vault token into a Kubernetes Pod.
You can also use a Kubernetes Service Account Token to log in via JWT auth.
See the section on How to work with short-lived Kubernetes tokens for a summary of why you might want to use JWT auth instead and how it compares to Kubernetes auth.
[Exercise] Select the menu items: Access→Auth Methods→Enable new method→Infra→Kubernetes→Next Examine the Method Options
The following two items can be most easily found in your kube config
Select “Save” when you are finished. |
The kv secrets engine is used to store arbitrary secrets within the configured physical storage for Vault.
Key names must always be strings.
It honors the distinction between the create and update capabilities inside ACL policies
After the secrets engine is configured and a user/machine has a Vault token with the proper permission, then it can generate credentials
The kv secrets engine allows for writing keys with arbitrary values.
[EXERCISE]
|
Everything in Vault is path-based, and policies are no exception.
Policies provide a declarative manner to grant or forbid access to certain paths and operations in Vault.
Policy workflows and syntaxes:
Select the menu items Policies→Create ACL Policy.
Name the policy “webapp-one-read
”, and use the following content for the policy:
path "kv/data/webapps/app_one" {
capabilities = ["read"]
}
Create similar read policies for webapp-two-read, backendapp-one-read, and backendapp-two-read
These will enable read access to the previously created kv engine secrets when attached as authorization to an authentication entity
You have successfully configured a basic Vault cluster for Kubernetes authentication, configured KV2 secrets management, and authorized an authenticated Kubernetes agent to retrieve the secrets.
webapp-one-read
” and select “Add” when finished. Select “Save” when finished with the role.webapp-two
, backendapp-one
, and backendapp-two
.Bonus: Create a role for both the Bound service account names webapp-one
and webapp-two
, and a role for both the Bound service account names backendapp-one
and backendapp-two
.
webapp-one-read
and webapp-two-read
.webapps
” and “backendapps
” for the roles, and “webapp
” and “backendapp
” for the service accounts.kubectl create sa webapp-one
kubectl describe sa webapp-one
webapp-two
, backendapp-one
, and backendapp-two
webapp
and backendapp
Kubernetes service account, then create those two service accounts now as well.apiVersion: v1
kind: Secret
metadata:
name: webapp-one-configure
annotations:
kubernetes.io/service-account.name: webapp-one
type: kubernetes.io/service-account-token
kubectl create deployment webapp-one --image httpd
kubectl describe pod/webapp-one-<sha hash>
kubectl exec $(kubectl get pod -l app=webapp-one -o jsonpath="{.items[0].metadata.name}") --container httpd -- ls /vault/secrets
kubectl patch deployment/webapp-one --patch '{"spec": {"template": {"spec": {"serviceAccountName": "webapp-one"}}}}'
kubectl exec $(kubectl get pod -l app=webapp-one -o jsonpath="{.items[0].metadata.name}") --container httpd -- ls /vault/secrets
The Kubernetes Secrets Engine for Vault generates Kubernetes service account tokens.
For each lease, Vault will create a service account token attached to the defined service account, with the service account token returned to the caller.
kubectl -n vault-system exec -ti vault-0 -- /bin/sh -c 'VAULT_TOKEN=<root token> vault secrets enable kubernetes'
webapp-one
” service account and “default
” namespace:
kubectl -n vault-system exec -ti vault-0 -- /bin/sh -c 'VAULT_TOKEN=<root token> vault write kubernetes/roles/webapp-one service_account_name=webapp-one allowed_kubernetes_namespaces=default'
webapp-one
” service account in the “default
” namespace, and thereby return a service account token:
kubectl -n vault-system exec -ti vault-0 -- /bin/sh -c 'VAULT_TOKEN=<root token> vault write kubernetes/creds/webapp-one kubernetes_namespace=default'
Note that you can now view the Kubernetes secrets engine and its basic configuration in the UI; otherwise, you have no control over it.
You have successfully integrated the Vault cluster into a Kubernetes cluster for service account token authentication and workload secrets injection.
The Vault Agent Injector alters pod specifications to include Vault Agent init-containers that render Vault secrets to a shared memory volume using Vault Agent Templates.
The injector is a Kubernetes Mutation Webhook Controller.
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.
The Vault Sidecar Agent Injector leverages the sidecar pattern to alter pod specifications to include a Vault Agent container that renders Vault secrets to a shared memory volume.
The CSI Secrets Store driver enables users to create SecretProviderClass objects.
When pods requesting CSI volumes are made, the CSI Secrets Store driver sends the request to the Vault CSI provider if the provider is Vault.
Modify the “webapp-one
” deployment annotations for the associated pods to inject the Vault init-container. This will mount the secrets from “webapps/app_one
” at “/vault/secrets/mysecret
” in the pod’s container, and authenticate via the mapping between the Kubernetes service account and the Vault role through the Kubernetes authentication engine:
kubectl patch deployment/webapp-one --patch '{"spec": {"template": {"metadata": {"annotations": {"vault.hashicorp.com/agent-inject": "true", "vault.hashicorp.com/role": "webapp-one", "vault.hashicorp.com/agent-inject-secret-mysecret": "kv/data/webapps/app_one"}}}}}'
Verify the annotations and service account:
kubectl describe deployment/webapp-one
Verify the pod has a corresponding Vault init container (“vault-agent-init
”) mounting the secrets correctly:
kubectl describe pod/webapp-one-<sha hash>
Verify that the default Vault secret mount point is now accessible:
kubectl exec $(kubectl get pod -l app=webapp-one -o jsonpath="{.items[0].metadata.name}") --container httpd -- ls /vault/secrets
Add the secrets store CSI driver Helm repo:
helm repo add secrets-store-csi-driver https://kubernetes-sigs.github.io/secrets-store-csi-driver/charts
Install the driver alongside Vault:
helm -n vault-system install csi secrets-store-csi-driver/secrets-store-csi-driver --set syncSecret.enabled=true
Verify a successful driver installation by confirming the new running pod:
kubectl -n vault-system get pod
This enables the use of the CSI driver for secret storage
Additionally, the Vault installation must be configured to enable integration with this driver, and that also will be explored further at the intermediate level.
The Vault CSI plugin is also capable of mapping Vault secrets to Kubernetes secrets.
The Secrets Store CSI Driver also supports syncing to Kubernetes secret objects.
Kubernetes secrets are populated with the contents of files from your CSI volume, and their lifetime is closely tied to the lifetime of the pod for which they are created.
You have successfully provided Vault secrets for retrieval within the container as a file via Vault Agent init-container injection and installed the secrets store CSI driver as a future alternative to the Vault Agent.