Wednesday, June 7, 2023

Vault and CoreDNS

Vault

In Kubernetes, a "vault" typically refers to HashiCorp Vault, which is an open-source tool for managing secrets and sensitive data in distributed systems. It provides a secure and centralized way to store, access, and manage secrets such as passwords, API keys, certificates, and more.

HashiCorp Vault can be integrated with Kubernetes to securely manage secrets and provide them to applications running within the cluster. When secrets are stored in Vault, they are encrypted and protected, and access to them can be controlled using fine-grained policies and access controls.

Using Vault in Kubernetes offers several advantages:

  1. Centralized Secret Management: Vault provides a central location for storing secrets, reducing the risk of secrets being exposed or leaked.

  2. Dynamic Secrets: Vault can generate short-lived secrets dynamically when requested, reducing the risk of long-lived secrets being compromised.

  3. Auditing and Access Controls: Vault logs access to secrets and provides detailed audit logs. It also allows administrators to define fine-grained access controls and policies for secret retrieval.

  4. Integration with Kubernetes: Vault can integrate with Kubernetes using the Kubernetes authentication method. This allows Kubernetes applications to authenticate with Vault and retrieve secrets specific to their needs.

By leveraging Vault in a Kubernetes environment, developers and operators can maintain a higher level of security for their applications by securely managing secrets and reducing the risk of accidental exposure or unauthorized access.

 

Vault installation on EKS using helm

Here are the step-by-step instructions, along with the real commands, to set up Scenario 1: Secure Storage of Database Credentials using Vault and Amazon EKS:

Step 1: Set up an EKS Cluster 

Follow the official AWS documentation or use the AWS Management Console to create an EKS cluster. Make sure you have the necessary permissions and credentials to create and manage the cluster.

Step 2: Install and Configure Vault on EKS

Deploy Vault as a containerized application on your EKS cluster using Kubernetes manifests. You can create a vault.yaml file with the following content:

 vault.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
name: vault
spec:
replicas: 1
selector:
matchLabels:
app: vault
template:
metadata:
labels:
app: vault
spec:
containers:
- name: vault
image: vault:latest
args:
- "server"
- "-dev"
- "-dev-root-token-id=myroot"
ports:
- containerPort: 8200

 

Create the deployment using the following command:

kubectl apply -f vault.yaml

Step 3: Enable and Configure the Kubernetes Authentication Method in Vault Enable the Kubernetes authentication method in Vault and configure it to authenticate the EKS cluster. Run the following commands: 

kubectl create serviceaccount vault-auth-sa

kubectl apply -f vault-auth-role.yaml

 

Create a file named vault-auth-role.yaml with the following contents:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: vault-auth-role
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:auth-delegator
subjects:
- kind: ServiceAccount
name: vault-auth-sa
namespace: default

 Step 4: Create a Vault Policy 

Create a Vault policy that grants read access to the path where the database credentials will be stored. For example, create a file named database-policy.hcl with the following contents:

path "secret/database/*" {
capabilities = ["read"]
}

 

Create the policy using the following command:

vault policy write database-policy database-policy.hcl

 Step 5: Store the Database Credentials in Vault 

Use the Vault CLI or API to securely store the database credentials in Vault. For example, to store the credentials for a MySQL database, run the following command:

vault kv put secret/database/mysql username="myuser" password="secretpassword"

 Step 6: Update Microservice Deployments 

Update the Kubernetes deployment manifests for each microservice to include the necessary environment variables and configurations to authenticate with Vault and retrieve the database credentials. Modify your existing microservice deployment YAML file, adding the following:

env:
- name: VAULT_ADDR
value: "http://vault:8200" # Replace 'vault' with the actual Vault address
- name: VAULT_ROLE
value: "my-role" # Replace with the Vault role created in Step 7

 Step 7: Access Database Credentials from Vault 

Modify your microservice code to retrieve the database credentials from Vault using the Vault API or a Vault client library. You can use the following code snippet as an example:

import os
import hvac

vault_addr = os.getenv("VAULT_ADDR")
vault_role = os.getenv("VAULT_ROLE")

client = hvac.Client(url=vault_addr)
client.auth_kubernetes(role=vault_role)

secrets = client.secrets.kv.v2.read_secret_version(path='database/mysql')

username = secrets['data']['data']['username']
password = secrets['data']['data']['password']

# Use the retrieved credentials to connect to the MySQL database

 

Make sure to import the necessary dependencies (such as the hvac library for Python) and handle any error conditions in your actual microservice code.

These steps provide a high-level guide to setting up Vault with Amazon EKS for secure storage and retrieval of database credentials. You can adapt them to your specific requirements and databases.

Scenario 2: Secure Management of API Keys/Secrets using Vault and Amazon EKS:

Step 1: Set up an EKS Cluster 

Follow the official AWS documentation or use the AWS Management Console to create an EKS cluster. Ensure you have the necessary permissions and credentials to create and manage the cluster.

 Step 2: Install and Configure Vault on EKS

Deploy Vault as a containerized application on your EKS cluster using Kubernetes manifests. Create a vault.yaml file with the following content:

apiVersion: apps/v1
kind: Deployment
metadata:
name: vault
spec:
replicas: 1
selector:
matchLabels:
app: vault
template:
metadata:
labels:
app: vault
spec:
containers:
- name: vault
image: vault:latest
args:
- "server"
- "-dev"
- "-dev-root-token-id=myroot"
ports:
- containerPort: 8200

 

Create the deployment using the following command:

kubectl apply -f vault.yaml

Step 3: Enable and Configure the Kubernetes Authentication Method in Vault Enable the Kubernetes authentication method in Vault and configure it to authenticate the EKS cluster. Run the following commands:

kubectl create serviceaccount vault-auth-sa

kubectl apply -f vault-auth-role.yaml

Create a file named vault-auth-role.yaml with the following contents:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: vault-auth-role
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:auth-delegator
subjects:
- kind: ServiceAccount
name: vault-auth-sa
namespace: default

Step 4: Create a Vault Policy 

Create a Vault policy that grants read access to the paths where the API keys or secrets will be stored. For example, create a file named api-keys-policy.hcl with the following contents:
 

path "secret/api-keys/*" {
capabilities = ["read"]
}

 

Create the policy using the following command:

vault policy write api-keys-policy api-keys-policy.hcl

Step 5: Store the API Keys/Secrets in Vault 

Use the Vault CLI or API to securely store the API keys/secrets in Vault. For example, to store a third-party API key, run the following command:

vault kv put secret/api-keys/third-party key="myapikey"

 

 Step 6: Update Application Deployments 

Update the Kubernetes deployment manifests for your application to include the necessary environment variables and configurations to authenticate with Vault and retrieve the API keys/secrets. Modify your existing application deployment YAML file, adding the following:

 

env:
- name: VAULT_ADDR
value: "http://vault:8200" # Replace 'vault' with the actual Vault address
- name: VAULT_ROLE
value: "my-role" # Replace with the Vault role created in Step 7

 

Step 7: Access API Keys/Secrets from Vault 

Modify your application code to retrieve the API keys/secrets from Vault using the Vault API or a Vault client library. Here's an example using Python:

 

import os
import hvac

vault_addr = os.getenv("VAULT_ADDR")
vault_role = os.getenv("VAULT_ROLE")

client = hvac.Client(url=vault_addr)
client.auth_kubernetes(role=vault_role)

secrets = client.secrets.kv.v2.read_secret_version(path='api-keys/third-party')

api_key = secrets['data']['data']['key']

# Use the retrieved API key in your application

 

Make sure to import the necessary dependencies (such as the hvac library for Python) and handle any error conditions in your actual application code.

These steps provide a high-level guide to setting up Vault with Amazon EKS for secure management of API keys/secrets. You can adapt them to your specific requirements and add more API keys/secrets as needed.

 CoreDNS

CoreDNS is a versatile, lightweight, and extensible DNS server that is commonly used as the default DNS provider in Kubernetes clusters. It is responsible for handling DNS resolution requests within the cluster.

In a Kubernetes environment, CoreDNS serves as the primary DNS server for all DNS queries made by pods, services, and other components. It provides name resolution for both internal cluster DNS and external DNS lookups.

CoreDNS can be deployed as a standalone pod or as a Deployment with multiple replicas for high availability. It integrates seamlessly with Kubernetes through the CoreDNS ConfigMap, which defines the DNS zones, forwarders, and other configuration settings.

Some key features and functionalities of CoreDNS in Kubernetes include:

  1. Service Discovery: CoreDNS dynamically discovers services and endpoints within the cluster, allowing pods and services to communicate with each other using their DNS names.

  2. DNS-Based Service Discovery: CoreDNS supports DNS-based service discovery, allowing pods to discover and connect to other services using their DNS names rather than IP addresses.

  3. DNS Forwarding: CoreDNS can forward DNS queries to external DNS servers, such as those provided by your DNS provider or configured in the cluster.

  4. Customization and Extensibility: CoreDNS supports plugins that enable custom configurations, such as zone transfers, caching, middleware integration, and more.

Overall, CoreDNS plays a crucial role in providing DNS resolution services within Kubernetes clusters, facilitating communication between various components and enabling seamless service discovery.

To set up CoreDNS in an Amazon EKS cluster with real-time examples, you can follow these steps:

 

Vault real practical 

you should have below kind of cluster
eksctl create cluster \
    --name learn-vault \
    --nodes 3 \
    --with-oidc \
    --ssh-access \
    --ssh-public-key learn-vault \
    --managed

add-on CSIDriver atleast

check these roles
eksctl-my-cluster1-nodegroup-my-n-NodeInstanceRole-1B9HIL62FL5MO
AmazonEBSCSIDriverPolicy
AmazonEC2ContainerRegistryReadOnly
AmazonEKS_CNI_Policy
AmazonEKSWorkerNodePolicy
AmazonSSMManagedInstanceCore

helm install mysql bitnami/mysql
helm install vault hashicorp/vault


kubectl exec vault-0 -- vault status

Initialize Vault with one key share and one key threshold.
kubectl exec vault-0 -- vault operator init \
    -key-shares=1 \
    -key-threshold=1 \
    -format=json > cluster-keys.json

Display the unseal key found in cluster-keys.json.
cat cluster-keys.json | jq -r ".unseal_keys_b64[]"

Create a variable named VAULT_UNSEAL_KEY to capture the Vault unseal key.
VAULT_UNSEAL_KEY=$(cat cluster-keys.json | jq -r ".unseal_keys_b64[]")

Unseal Vault running on the vault-0 pod.
kubectl exec vault-0 -- vault operator unseal $VAULT_UNSEAL_KEY

kubectl exec vault-0 -- vault status

Display the root token found in cluster-keys.json.
cat cluster-keys.json | jq -r ".root_token"

Create a variable named CLUSTER_ROOT_TOKEN to capture the Vault unseal key.
CLUSTER_ROOT_TOKEN=$(cat cluster-keys.json | jq -r ".root_token")

Login with the root token on the vault-0 pod.
kubectl exec vault-0 -- vault login $CLUSTER_ROOT_TOKEN


Create a Vault database role

Enable database secrets at the path database.
kubectl exec vault-0 -- vault secrets enable database

Configure the database secrets engine with the connection credentials for the MySQL database.
kubectl exec vault-0 -- vault write database/config/mysql \
    plugin_name=mysql-database-plugin \
    connection_url="{{username}}:{{password}}@tcp(mysql.default.svc.cluster.local:3306)/" \
    allowed_roles="readonly" \
    username="root" \
    password="$ROOT_PASSWORD"


Create a database secrets engine role named readonly.
kubectl exec vault-0 -- vault write database/roles/readonly \
    db_name=mysql \
    creation_statements="CREATE USER '{{name}}'@'%' IDENTIFIED BY '{{password}}';GRANT SELECT ON *.* TO '{{name}}'@'%';" \
    default_ttl="1h" \
    max_ttl="24h"


Read credentials from the readonly database role.
kubectl exec vault-0 -- vault read database/creds/readonly

Configure Vault Kubernetes authentication


Start an interactive shell session on the vault-0 pod.
kubectl exec --stdin=true --tty=true vault-0 -- /bin/sh

Enable the Kubernetes authentication method.
#$ vault auth enable kubernetes

Configure the Kubernetes authentication method to use the location of the Kubernetes API.
#$ vault write auth/kubernetes/config \
    kubernetes_host="https://$KUBERNETES_PORT_443_TCP_ADDR:443"

Write out the policy named devwebapp that enables the read capability for secrets at path database/creds/readonly
#$ vault policy write devwebapp - <<EOF
path "database/creds/readonly" {
  capabilities = ["read"]
}
EOF


Create a Kubernetes authentication role named devweb-app.
#$ vault write auth/kubernetes/role/devweb-app \
      bound_service_account_names=internal-app \
      bound_service_account_namespaces=default \
      policies=devwebapp \
      ttl=24h

exit


Deploy web application

Define a Kubernetes service account named internal-app.
cat > internal-app.yaml <<EOF
apiVersion: v1
kind: ServiceAccount
metadata:
  name: internal-app
EOF

Create the internal-app service account.
kubectl apply --filename internal-app.yaml

Define a pod named devwebapp with the web application.
cat > devwebapp.yaml <<EOF
---
apiVersion: v1
kind: Pod
metadata:
  name: devwebapp
  labels:
    app: devwebapp
  annotations:
    vault.hashicorp.com/agent-inject: "true"
  
  vault.hashicorp.com/agent-cache-enable: "true"
   
vault.hashicorp.com/role: "devweb-app"
   
vault.hashicorp.com/agent-inject-secret-database-connect.sh: "database/creds/readonly"
   
vault.hashicorp.com/agent-inject-template-database-connect.sh: |
      {{- with secret "database/creds/readonly" -}}
      mysql -h my-release-mysql.default.svc.cluster.local --user={{ .Data.username }} --password={{ .Data.password }} my_database

      {{- end -}}

spec:
  serviceAccountName: internal-app
  containers:
    - name: devwebapp
      image: jweissig/app:0.0.1
EOF

Create the devwebapp pod.
kubectl apply --filename devwebapp.yaml


Get all the pods within the default namespace.
kubectl get pods


Display the secrets written to the file /vault/secrets/database-connect.sh on the devwebapp pod.
kubectl exec --stdin=true \
    --tty=true devwebapp \
    --container devwebapp \
    -- cat /vault/secrets/database-connect.sh

 https://developer.hashicorp.com/vault/tutorials/kubernetes/kubernetes-amazon-eks

No comments:

Post a Comment