Manage secret data by kubernetes Auth Plugin with Vault

selfieblue
4 min readAug 18, 2019

--

บทความนี้ เป็ยเนื้อหาซึ่งต่อมาจาก บทความที่แล้ว เรื่องการ provision vault cluster on kubernetes เพราะฉะนั้น ผมจะอ้างอิงบางข้อความจาก บทความที่แล้ว หากใครยังไม่ได้ศึกษษแนะนำนให้เริ่มจาก บทความความที่แล้วก่อน

สำหรับบทความนี้ เราจะมาพูดถึงวิธีการจัดการกับ secret data เพื่อให้ application ที่ running บน kubernetes cluster ได้นำไปใช้งานกันนะครับ ก่อนอื่นผมขอ brief คร่าว ๆ ก่อนว่ากระบวน query secret data จาก Vault เพื่อนำมาใช้งานบน Application ของเรานั้น มีกระบวนการอย่างไร โดยใช้ภาพประกอบด้านล่างนี้

กระบวนการ query secret data นั้นจะเริ่มต้นจาก
1) Application POD จะส่ง request login ไปยัง Auth API ของ Vault โดยข้อมูลที่ส่งไปกับ Request นั้นด้วยคือ Kubernetes Service Account Token ของ Service Account ที่ชื่อว่า demo
2) Auth API ทำการตรวจสอบว่า Kubernetes Service Account Token ที่ส่งมามีอยู่จริงบน Kubernetes Cluster หรือไม่ หากมีอยู่จริง ก็จะส่ง Metadata ของ Service Account ไปให้ Core API เพื่อทำการ check policy ที่ได้สร้างไว้ ว่า service account นี้ ได้ mapping อยู่กับ policy ใดบ้าง
3) หลังจาก mapping กับ policy ได้แล้ว vault จะทำการ generate temporary client token
4) Auth API return temporary client token กลับไปให้ Application
5) Application จะนำ temporary client token ไปใช้เพื่อ request query secret data ที่อยู่ใน vault ต่อไป

จากภาพ high-level overview ด้านบน เราจะเห็นว่าก่อนที่เราจะทำการ query secret data จาก vault ได้นั้น เราจะต้องการผ่านกระบวนการที่สำคัญอยู่ 2 กระบวนการด้วยกันคือ
1) Authentication ในที่นี้คือการ Identify ว่า service account นี้มีอยู่จริง หรือไม่
2) Authorisation ในการที่นี้คือ การกำหนด permission ให้กับ service account แต่ละ service account ว่าสามารถที่จะ query secret data ได้ในขอบเขตของ secret data ใดบ้างนั่นเอง
เพราะฉะนั้น เราจะมาพูดถึง ทีละส่วนกันนะครับ

ขั้นตอนที่ 1 Authentication
ขั้นตอนสำหรับการทำ Authentication มีดังนี้
1.1) Enable Kubernetes Auth บน Vault
รัน command เพื่อ enable kubernetes auth methodโดยที่เราต้องเปิด Terminal 2 หน้าจอนะครับ terminal เพื่อทำ port forward ส่วน terminal 2 เราจะใช้เพื่อรัน vault cli

==== Terminal 1 ====
NAMESPACE="secrets"
VAULTSERVICE="ln-vault-cluster-01"
kubectl -n ${NAMESPACE} get vault ${VAULTSERVICE} -o jsonpath='{.status.vaultStatus.active}' | xargs -0 -I {} kubectl -n ${NAMESPACE} port-forward {} 8200
==== Terminal 2 ====
export VAULT_SKIP_VERIFY=1
export VAULT_TOKEN=<xxxxxxxxxxxxx>
vault auth enable -path nonprod-k8s-cluster kubernetes

หลังจากรัน enable kubernetes auth method เรียบร้อย เราจะสามารถ เรียก vault auth method ได้จาก <VAULT_URL>/v1/auth/nonprod-k8s-cluster จะเห็นได้ว่า vault ทำการสร้าง authentication path ใหม่ ขึ้นมาตามชื่อที่เรากำหนดไว้ใน command line
1.2) Configure Connection ระหว่าง Vault กับ Kubernetes
สำหรับการ configure connection ระหว่าง Vault กับ Kubernetes นั้น ต้องการ parameters อยู่ 3 ค่าด้วยกัน นั่นคือ
- Target Kubernetes API URL (https://api.nonpord-k8s.exmaple.com)
- Target Kubernetes CA Certificate (ca.crt)
- Target Kubernetes Service Account Token (vault-authen-tokenviewer)

วิธีการ get ca.crt และ vault-authen-tokenviewer token ทำได้ โดยรัน commands

# Get
kubectl get pod -n kube-system # choose one <POD_NAME>
# Then run command to get ca.crt
kubectl -n kube-system exec <POD_NAME> cat /var/run/secrets/kubernetes.io/serviceaccount/ca.crt > ~/ca.crt
# Get
NAMESPACE="secrets"
kubectl -n ${NAMESPACE} describe secret $(kubectl -n ${NAMESPACE} get secret | grep vault-authen-tokenviewer | awk '{print $1}') | grep "token:" | awk '{print $2}' > ~/service-account-jwt.token

หลังจากที่เราเตรียม parameter ทั้ง 3 เป็นที่เรียบร้อยแล้ว เราก็จะมาทำการ apply configuration ไปที่ authentication path ที่เราสร้างขึ้นมาใน step 1.1 ที่ชื่อว่า nonprod-k8s-cluster กันเลย

KUBE_API_URL="<KUBERNETES_API_URL>"
cd ~
vault write auth/nonprod-k8s-cluster/config \
token_reviewer_jwt=@service-account-jwt.token \
kubernetes_host=${KUBE_API_URL} \
kubernetes_ca_cert=@ca.crt
rm -rf ~/ca.crt

ขั้นตอนที่ 2 Authorisation
สำหรับขั้นตอนนี้เราจะกล่าวถึง การกำหนด สิทธิ์ในการเข้าถึงข้อมูลต่าง ๆ . โดยที่เราจะทำการกำหนดสิทธิ์ต่าง ๆ ผ่าน policy หลังจากที่ได้ policy แล้ว เราจะนำ policy ต่าง ๆ ไป assign ให้กับ service account ยกตัวอย่างเช่น เราจะกำหนด สิทธิ์ให้ service account ชื่อ demo ซึ่งอยู่ใน namespace ชื่อ local สามารถที่จะ query secret data ที่อยู่ใน path secret/data/local/apps/* ได้

เรามาเริ่มจากการเตรียม policy file กันก่อน

# read-only-local.hclpath "secret/data/local/apps/*" {
capabilities = ["read", "list"]
}

ทำการ create policy ชื่อ local-read-only-policy ด้วย command

vault policy write local-read-only-policy read-only-local.hcl

พอเราสร้าง policy แล้ว เราจะนำ policy นั้นไป assign ให้กับ service account ที่ชื่อ demo ซึ่งอยู่ใน namespace ชื่อ local และ set token expiration ไว้ที่ 5 นาที

vault write auth/nonprod-k8s-cluster/role/local-read-only-role \
bound_service_account_names=demo \
bound_service_account_namespaces='local' \
policies=local-read-only-policy \
ttl=5m

สรุปง่าย ๆ คือ เมื่อ service account ชื่อ demo ซึ่งอยู่ใน namespace ชื่อ local ทำการ authen มา vault auth api เรียบร้อยแล้ว vault core engine จะทำการ สร้าง temporary client token แล้วส่งกลับไปให้ application เพื่อใช้เป็น token ในการ query secret data โดยที่ temporary client token จะมีอายุได้เพียง 5 นาที หลังจาก 5 นาที temporary client token นี้จะไม่สามารถใช้งานได้อีก

เพราะฉะนั้น การจะกำหนดสิทธิ์อะไรให้ใครสวามารถทำอะไรกับ vault ได้นั้น คือเราต้องสร้าง policy ที่เหมาะสมกับกลุ่มผู้ใช้งานเหล่านั้น อย่างเช่นเราอาจจะแบ่ง policy ตาม kubernetes namespace ดังนี้

บทความหน้า เราจะ เรียนรู้วิธีการใช้ library เพื่อ login และ query secret data แล้วเจอกันนะครับ

--

--