Wechat official account: Operation and maintenance development story, author: Jock

Vault is a central management service for processing and encrypting the secret keys of the entire infrastructure. Vault manages all of its secret keys through the Secret engine, and Vault has a secret engine available.

It mainly has the following functions:

  • Secure key store: Any key/value Secret can be stored in Vault. The Vault encrypts and persists the Secret. Back-end storage supports local disks, COSUL, and so on.

  • Dynamic Keys: Vault can dynamically generate Secret and automatically revoke them when the lease expires;

  • Data encryption: Vault can encrypt and decrypt data, and security teams can customize encryption parameters;

  • Leases and renewals: All secrets in Vault have leases associated with them. At the end of the lease, Vault will automatically revoke this confidentiality. The client can renew the lease through the built-in renewal API;

  • Revocation: Vault has built-in support for secret revocation. Vault can undo individual secrets, as well as a secret tree, such as all secrets read by a particular user or all secrets of a particular type. Revocation helps with critical rolling and locking systems in the event of an intrusion;

The installation

Install on a Linux host

Installing on a Linux host is relatively easy and requires only the following three steps:

# $sudo yum install -y yum-utils # $sudo yum-config-manager --add-repo # $sudo yum install -y yum-utils # https://rpm.releases.hashicorp.com/RHEL/hashicorp.repo # install vault $sudo yum - y install vaultCopy the code

Install in K8S

Vault provides the Helm package, which can be installed using helm.

!!!!! Version Description:

  • Helm 3.0 +

  • Kubernetes 1.9 +

$# add repo warehouse helm repo update the local warehouse add hashicorp https://helm.releases.hashicorp.com # $helm repo update # install vault $helm install vault hashicorp/vaultCopy the code

The service side

!!!!! This applies only to vault installed on the host. Vault installed using helm in a K8S cluster already has a server installed by default.

Vault is already installed on the host.

$ vault version
Vault v1.6.1 (6d2db3f033e02e70202bef9ec896360062b88b03)

Copy the code

Then run a Vault server by development default, without development mode in the formal environment.

$vault server-dev-dev-listen-address = 0.0.0.0:8200&...... WARNING! dev mode is enabled! In this mode, Vault runs entirely in-memory and starts unsealed with a single unseal key. The root token is already authenticated to the CLI, so you can immediately begin using Vault. You may need to set the following environment variable: $export VAULT_ADDR='http://0.0.0.0:8200' The unseal key and root token are displayed below in case you want to seal/unseal the Vault or re-authenticate. Unseal Key: killR+cPfTR7P7HoYRt5SsMySMDv2w9WD7ljcxpXB+Q= Root Token: s.pd4FBsC1pamE21nLv3fszdI1 Development mode should NOT be used in production installationsCopy the code

It can then be accessed at http://ip:8200/ui.

image.png

You can log in by filling in the generated Token.

image.png

Configure K8S to communicate with the Vault

To enable K8S to read Secret from Vault, K8S and Vault must communicate with each other.

!!!!! PS: I am using Kubeadm installed K8S cluster, version 1.18.9

(1) Add environment variables. Enter the IP address based on the actual situation

$export VAULT_ADDR = http://192.168.0.153:8200Copy the code

(2) Enable K8S authentication

$ vault auth enable kubernetes
Success! Enabled kubernetes auth method at: kubernetes/

Copy the code

(3) Add K8S cluster configuration information

$vault write auth/kubernetes/config \ \ kubernetes_host = https://192.168.0.153:6443 kubernetes_ca_cert=@/etc/kubernetes/pki/ca.crt Success! Data written to: auth/kubernetes/configCopy the code

(4) Create a permission policy

$ cat <<EOF | vault policy write vault-demo-policy -
> path "sys/mounts" { capabilities = ["read"] }
> path "secret/data/demo/*" { capabilities = ["read"] }
> path "secret/metadata/demo/*" { capabilities = ["list"] }
> EOF
Success! Uploaded policy: vault-demo-policy

Copy the code

Create a demo policy for the demo.

(5) Create an authentication role

$ vault write auth/kubernetes/role/vault-demo-role \
>     bound_service_account_names=vault-serviceaccount \
>     bound_service_account_namespaces=default \
>     policies=vault-demo-policy \
>     ttl=1h
Success! Data written to: auth/kubernetes/role/vault-demo-role

Copy the code

The role name is vault-demo-role, the authentication mode is RBAC authentication, the bound user is vault-ServiceAccount, and the policy is vault-Demo-policy.

(6) Create a key

$ vault kv put secret/demo/database username="coolops" password=123456 Key Value --- ----- created_time 2021-01-25T08:22:35.134166877z deletion_time N /a destroyed false version 1 # check $vault kv get secret/demo/database ====== Metadata ====== Key Value --- ----- created_time 2021-01-25T08:22:35.134166877z deletion_time N /a destroyed false  version 1 ====== Data ====== Key Value --- ----- password 123456 username coolopsCopy the code

(7) Create RBAC permission in K8S cluster

---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: vault-serviceaccount

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

---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: vault-secretadmin-role
rules:
- apiGroups: [""]
  resources: ["secrets"]
  verbs: ["*"]

---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: vault-secretadmin-rolebinding
subjects:
- kind: ServiceAccount
  name: vault-serviceaccount
roleRef:
  kind: Role
  name: vault-secretadmin-role
  apiGroup: rbac.authorization.k8s.io

Copy the code

Create the RBAC configuration file

$ kubectl apply -f rbac.yaml 
serviceaccount/vault-serviceaccount created
clusterrolebinding.rbac.authorization.k8s.io/vault-clusterrolebinding created
role.rbac.authorization.k8s.io/vault-secretadmin-role created
rolebinding.rbac.authorization.k8s.io/vault-secretadmin-rolebinding created

Copy the code

Use Secret in Vault in K8S

To get Secret from Vault, there are two ways:

  • Use the Vault Agent to extract secret from initContainer

  • Get it in the program using the Vault SDK

Use initContainer

!!!!! Here is an official demo.

The flow chart is as follows:

image

(1) Create ConfigMap

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 = "vault-demo-role"
            }
        }

        sink "file" {
            config = {
                path = "/home/vault/.vault-token"
            }
        }
    }

    template {
    destination = "/etc/secrets/index.html"
    contents = <<EOT
    <html>
    <body>
    <p>Some secrets:</p>
    {{- with secret "secret/demo/database" }}
    <ul>
    <li><pre>username: {{ .Data.data.username }}</pre></li>
    <li><pre>password: {{ .Data.data.password }}</pre></li>
    </ul>
    {{ end }}
    </body>
    </html>
    EOT
    }
kind: ConfigMap
metadata:
  name: example-vault-agent-config
  namespace: default

Copy the code

Template allows you to save Secret stored in Vault to a file.

Create a pod

apiVersion: v1
kind: Pod
metadata:
  name: vault-agent-example
  namespace: default
spec:
  serviceAccountName: vault-serviceaccount 

  volumes:
  - configMap:
      items:
      - key: vault-agent-config.hcl
        path: vault-agent-config.hcl
      name: example-vault-agent-config
    name: config
  - emptyDir: {}
    name: shared-data

  initContainers:
  - args:
    - agent
    - -config=/etc/vault/vault-agent-config.hcl
    - -log-level=debug
    env:
    - name: VAULT_ADDR
      value: http://192.168.0.153:8200
    image: registry.cn-hangzhou.aliyuncs.com/rookieops/vault:1.6.1 
    name: vault-agent
    volumeMounts:
    - mountPath: /etc/vault
      name: config
    - mountPath: /etc/secrets
      name: shared-data

  containers:
  - image: nginx
    name: nginx-container
    ports:
    - containerPort: 80
    volumeMounts:
    - mountPath: /usr/share/nginx/html
      name: shared-data

Copy the code

!!!!! Notice The serviceAccountName value must be the same as that previously configured

After POD runs, Secret in vault can be obtained as follows:

$ kubectl get po -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES Nfs-client-prosioner - 598D477FF6-fmgwF 1/1 Running 8 65D 172.16.7.140 ECS-968F-0005 <none> <none> Traefik-5b8BB6787-dn96j 1/1 Running 0 65D 172.16.7.138 ECS-968F-0005 <none> <none> vault-agent-example 1/1 Running 0 106s 172.16.235.231 K8s-master <none> <none> $curl 172.16.235.231 < HTML >< body> <p>Some secrets:</p> <ul> <li><pre>username: coolops</pre></li> <li><pre>password: 123456</pre></li> </ul> </body> </html>Copy the code

Using the SDK

package main import ( "fmt" "io/ioutil" vaultApi "github.com/hashicorp/vault/api" ) var ( vaultHost string vaultCAPath String vaultServiceAccount String vaultJWTPath string) func main() {// K8S token vaultJWTPath = "/ var/run/secrets/kubernetes. IO/serviceaccount/token" vaultServiceAccount / / sa name = "vault - serviceaccount" tlsConfig: = &vaultApi.TLSConfig{ CACert: vaultCAPath, Insecure: False,} config := vaultapi.defaultconfig () // Vaultapi.sprintf ("https://%s", vaultHost) config.ConfigureTLS(tlsConfig) client, _ := vaultApi.NewClient(config) buf, _ := ioutil.ReadFile(vaultJWTPath) jwt := string(buf) options := map[string]interface{}{ "jwt": jwt, "role": vaultServiceAccount, } loginSecret, _ := client.Logical().Write("auth/kubernetes/login", The options) client. SetToken (loginSecret. Auth. ClientToken) / / secret secret address, _ := client.Logical().Read("database/creds/tx") fmt.Println(secret) }Copy the code

The last

Vault is a good tool that can manage some sensitive information in a relatively secure way. However, it can be seen from the above steps that the configuration is relatively complex and the maintenance cost is relatively high. However, the integration of Kubernetes and Vault is still a good solution.

Reference:

  • Github.com/hashicorp/v…

  • Github.com/hashicorp/v…

  • www.vaultproject.io/docs/agent

  • www.vaultproject.io/docs/agent/…

  • Learn.hashicorp.com/tutorials/v…

  • Medium.com/getamis/vau…

Public account: Operation and maintenance development story

Making:Github.com/orgs/sunsha…

Love life, love operation