Kubernetes integration vault with Java application

Dmytro Vedetskyi
DevOops World … and the Universe
7 min readNov 29, 2021

Overview:

Secrets management based to the tools and methods for credentials, keys, passwords, APIs and other tokens for use in applications, services, privileged accounts and other sensitive parts of the IT ecosystem.

While secrets management is applicable across an entire enterprise, the terms “secrets” and “secrets management” are referred to more commonly in IT with regard to DevOps environments, tools, and processes.

Projects need to use secrets management methods for making app secure and avoid storing secrets/vulnerable properties such as API keys, passwords, etc in the wrong places like source control, yaml files, etc.

Kubernetes and vault have simple integration to achieve secrets management approach and close your secretes from unauthorized access. Next topic will show how to do it in the easier way and make you happy!

Minikube installation

Minikube can be installed everywhere, here is URL with official guide https://kubernetes.io/docs/tasks/tools/. I will show the example of the MacOS installation on the Intel CPU using brew.

Install with Homebrew on macOS

If you are on macOS and using Homebrew package manager, you can install kubectl with Homebrew.

  1. Run the installation command:
brew install kubectl

2. Test to ensure the version you installed is up-to-date:

kubectl version --client

3. Start minikube

minikube start --driver=hyperkit

4. Enabling dashboard for checking status of kubernetes cluster and easier managing services

# minikube dashboard
🔌 Enabling dashboard ...
▪ Using image kubernetesui/dashboard:v2.3.1
▪ Using image kubernetesui/metrics-scraper:v1.0.7
🤔 Verifying dashboard health ...
🚀 Launching proxy ...
🤔 Verifying proxy health ...
🎉 Opening http://127.0.0.1:50435/api/v1/namespaces/kubernetes-dashboard/services/http:kubernetes-dashboard:/proxy/ in your default browser...

Vault deployment in Kubernetes

Install the Consul Helm chart

Consul is a service mesh solution that launches with a key-value store. Vault requires a storage backend like Consul to manage its configuration and secrets when it is run in high-availability.

The recommended way to run Consul on Kubernetes is via the Helm chart. Helm is a package manager that installs and configures all the necessary components to run Consul in several different modes. A Helm chart includes templates that enable conditional and parameterized execution. These parameters can be set through command-line arguments or defined in YAML.

Consul’s Helm chart by default starts more services than required to act as Vault’s storage backend.

Show the parameters in helm-consul-values.yml.

global:
datacenter: vault-kubernetes-tutorial
client:
enabled: true
server:
replicas: 1
bootstrapExpect: 1
disruptionBudget:
maxUnavailable: 0

Add the HashiCorp Helm repository, update and install the latest version of the Consul Helm chart with parameters

$ helm repo add hashicorp 
$ helm repo update
$ helm install consul hashicorp/consul --values helm-consul-values.yml

The installation of the Helm chart displays the name, namespace, status, and resources created. The server and client pods are deployed in the default namespace because no namespace was specified or configured as the default.

Install the Vault Helm chart

The recommended way to run Vault on Kubernetes is via the Helm chart. This installs and configures all the necessary components to run Vault in several different modes.

Vault’s Helm chart by default launches with a file storage backend. To utilize the Consul cluster as a storage backend requires Vault to be run in high-availability mode.

Create the parameters in helm-vault-values.yml.

$ cat helm-vault-values.yml
server:
affinity: ""
ha:
enabled: true

Install the latest version of the Vault Helm chart with parameters helm-vault-values.yml applied.

$ helm install vault hashicorp/vault --values helm-vault-values.yml

The Vault pods and Vault Agent Injector pod are deployed in the default namespace.

Configuring Vault Agent

Create a service account

  1. In Kubernetes, a service account provides an identity for processes that run in a Pod so that the processes can contact the API server. Open the provided vault-auth-service-account.yaml file in your preferred text editor and examine its content for the service account definition to be used for this tutorial.
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: role-tokenreview-binding
namespace: default
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:auth-delegator
subjects:
- kind: ServiceAccount
name: vault-auth
namespace: default

2. Create a Kubernetes service account named vault-auth.

$ kubectl create serviceaccount vault-auth
$ kubectl apply --filename vault-auth-service-account.yaml

Configure Kubernetes auth method

  1. Create a read-only policy, myapp-kv-ro in Vault.
vault policy write myapp-kv-ro - <<EOF
path "secret/data/myapp/*" {
capabilities = ["read", "list"]
}
EOF

2. Create some test data at the secret/myapp path.

vault kv put secret/myapp/config \
username='UserFromVault1' \
password='passwordFromVault1' \
othersecret='othersecretFromVault1'

3. Set the environment variables to point to the running Minikube environment.

Set the VAULT_SA_NAME environment variable value to the vault-auth service account.

export VAULT_SA_NAME=$(kubectl get sa vault-auth \
--output jsonpath="{.secrets[*]['name']}")

Set the SA_JWT_TOKEN environment variable value to the service account JWT used to access the TokenReview API

export SA_JWT_TOKEN=$(kubectl get secret $VAULT_SA_NAME \
--output 'go-template={{ .data.token }}' | base64 --decode)

Set the SA_CA_CRT environment variable value to the PEM encoded CA cert used to talk to Kubernetes API.

export SA_CA_CRT=$(kubectl config view --raw --minify --flatten \
--output 'jsonpath={.clusters[].cluster.certificate-authority-data}' | base64 --decode)

Set the K8S_HOST environment variable value to minikube IP address.

export K8S_HOST=$(kubectl config view --raw --minify --flatten \    --output 'jsonpath={.clusters[].cluster.server}')

4. Now, enable and configure the Kubernetes auth method.

Enable the Kubernetes auth method at the default path (“auth/kubernetes”).

vault auth enable kubernetes

Tell Vault how to communicate with the Kubernetes (Minikube) cluster.

$ vault write auth/kubernetes/config \        token_reviewer_jwt="$SA_JWT_TOKEN" \        kubernetes_host="$K8S_HOST" \        
kubernetes_ca_cert="$SA_CA_CRT" \ issuer="https://kubernetes.default.svc.cluster.local"

5. Create a role named, example, that maps the Kubernetes Service Account to Vault policies and default token TTL.

vault write auth/kubernetes/role/example \
bound_service_account_names=vault-auth \
bound_service_account_namespaces=default \
policies=myapp-kv-ro \
ttl=24h

Start Vault Agent with Auto-Auth

Now that you have verified that the Kubernetes auth method has been configured on the Vault server, it is time to spin up a client Pod which leverages Vault Agent to automatically authenticate with Vault and retrieve a client token.

apiVersion: v1
data:
vault-agent-config.hcl: |
# Comment this out if running as sidecar instead of initContainer
exit_after_auth = true
pid_file = "/home/vault/pidfile"
auto_auth {
method "kubernetes" {
mount_path = "auth/kubernetes"
config = {
role = "example"
}
}
sink "file" {
config = {
path = "/home/vault/.vault-token"
}
}
}
template {
destination = "/etc/secrets/filename"
contents = <<EOT
{{- with secret "secret/data/myapp/config" }}
username: {{ .Data.data.username }}
password: {{ .Data.data.password }}
EOT
}
kind: ConfigMap
metadata:
name: example-vault-agent-config
namespace: default
  1. This creates a Vault Agent configuration file, vault-agent-config.hcl. Notice that the Vault Agent Auto-Auth (auto_auth block) is configured to use the kubernetes auth method enabled at the auth/kubernetes path on the Vault server. The Vault Agent will use the example role which you created in before
  2. The sink block specifies the location on disk where to write tokens. Vault Agent Auto-Auth sink can be configured multiple times if you want Vault Agent to place the token into multiple locations. In this example, the sink is set to /home/vault/.vault-token.
  3. Finally, the template block creates a templated file which retrieves username and password values at the secret/data/myapp/config path.
  4. The diagram shows how vault-agent works and manages the secrets, generates the proper config using vault secrets. Here is example with index.html. On the next section you will see the example how to run java springboot app with vault profiles.

Deploy Java application

Java hello-vault app is here https://github.com/helli0n/k8s-vault. The example shows how easy secrets pull from vault and start app with dynamic java profiles. Here are a several steps how to deploy app

  1. Pull https://github.com/helli0n/k8s-vault
  2. Build the project using gradlew
./gradlew build

3. Switch env to minikube as by default minikube hasn’t access to local Docker images

eval $(minikube docker-env)

4. Build docker image with java app

docker build -t hello-vault:1 .

5. Deploy configmaps, deployment and service for exposing service

kubectl create -f k8s/configmap-hello.yaml
kubectl create -f k8s/configmap-hello-vault.yaml
kubectl create -f k8s/deployment-example-k8s.yaml
kubectl create -f k8s/service-hello-vault.yaml

6. Expose service to the localhost

kubectl port-forward service/hello-vault 8889:8889

7. In a web browser, go to http://127.0.0.1:8889/

Screenshot returned the examples with secrets that were pulled from Vault. Vault agent generate two different application profiles and start app using them.

Summary:

Based on the information with examples described above everybody can understand how easy and fast your project can use secrets management methods using Kubernetes and Vault for every application, especially java application like showed in the https://github.com/helli0n/k8s-vault.

URLs:

https://learn.hashicorp.com/tutorials/vault/kubernetes-minikube?in=vault/kubernetes
https://learn.hashicorp.com/tutorials/vault/agent-kubernetes?in=vault/kubernetes
https://github.com/helli0n/k8s-vault
https://helm.sh/docs/helm/

https://kubernetes.io/docs/tutorials/hello-minikube/
https://kubernetes.io/docs/tasks/tools/
https://kubernetes.io/docs/tasks/tools/install-kubectl-macos/
https://www.beyondtrust.com/resources/glossary/secrets-management

--

--