甲方中的KMS密钥管理以及vault的使用笔记(下) 2024-09-30 11:34:23 Steven Xeldax > 本篇为《甲方中的KMS密钥管理以及vault的使用笔记(下)》,上半部分地址:https://xeldax.top/article/kms_with_vault_note_part1 [TOC] ### vault 使用场景 #### 代码中集成vault ##### python example xsoar 使用证书认证 ``` import json import requests import dateparser # Disable insecure warnings requests.packages.urllib3.disable_warnings() ''' CONSTANTS ''' DATE_FORMAT = '%Y-%m-%dT%H:%M:%SZ' proxy = {"http":"","https":""} class Client: """ Client will implement the service API, and should not contain any Demisto logic. Should only do requests and return data. """ def __init__(self, url, cacert, cert, key, kv2,tls_name): self.url = url self.tls_name = tls_name self.cacert_location = './vault-ca.pem' self.cert_location = './cert.pem' self.key_location = './key.pem' with open(self.cacert_location,'w') as f1: f1.write(cacert) with open(self.cert_location,'w') as f2: f2.write(cert) with open(self.key_location,'w') as f3: f3.write(key) self.kv = kv2 def get_token(self): url = urljoin(self.url,'/v1/auth/cert/login') # print(open('cert.pem').read()) # print(open('key.pem').read()) req = requests.post(url=url, json={"name": self.tls_name}, cert=('cert.pem', 'key.pem'), verify=False, proxies=proxy) result = req.json() # print(req.content,req.status_code) self.token = result.get('auth',{}).get('client_token', 'hvs.9Ited1R2gp1lid72agP8jRt9') # print(self.token) def get_key_list(self): headers = { "X-Vault-Token": self.token } url = urljoin(self.url, f'/v1/{self.kv}/metadata/?list=true') req = requests.get(url=url, headers=headers, verify=False, proxies=proxy) result = req.json() return result def create_key(self, key, data): headers = { "X-Vault-Token": self.token } url = urljoin(self.url, f'/v1/{self.kv}/data/{key}') req = requests.post(url=url, headers=headers, verify=False, proxies=proxy, json={ "data": data }) result = req.text return result def delete_key(self, key): headers = { "X-Vault-Token": self.token } url = urljoin(self.url, f'/v1/{self.kv}/metadata/{key}') req = requests.delete(url=url, headers=headers, verify=False, proxies=proxy) result = req.text return result def get_kv2_data(self,key): headers = { "X-Vault-Token": self.token } url = urljoin(self.url, f'/v1/{self.kv}/data/{key}') req = requests.get(url=url, headers=headers, verify=False, proxies=proxy) result = req.json() return result def test_module(url): try: requests.get(url,verify=False) return 'ok' except: return traceback.format_exc() def fetch_credentials(client): credentials = [] result = client.get_key_list() for key in result.get("data",{}).get("keys",[]): data = client.get_kv2_data(key) data = data.get("data", {}).get("data", {}) username = data.get("username","") password = data.get("password","") if username or password: credentials.append({ "name": key, "user": username, "password": password }) demisto.credentials(credentials) def main(): """ PARSE AND VALIDATE INTEGRATION PARAMS """ cert_pem = demisto.params().get('cert_pem') key_pem = demisto.params().get('key_pem') kv2 = demisto.params().get('kv2') tls_name = demisto.params().get('tls_name') # get the service API url base_url = demisto.params().get('url') LOG(f'Command being called is {demisto.command()}') try: client = Client( url=base_url, cert=cert_pem, key=key_pem, kv2=kv2, cacert='', tls_name=tls_name ) client.get_token() if demisto.command() == 'test-module': test_module(url=base_url) elif demisto.command() == 'fetch-credentials': fetch_credentials(client) elif demisto.command() == 'vault-kms-create-secrets': key = demisto.args().get('key') data = demisto.args().get('data') data_json = json.loads(data) ret = client.create_key(data=data_json, key=key) print(ret) elif demisto.command() == 'vault-kms-get-secrets': key = demisto.args().get('key') ret = client.get_kv2_data(key=key) return_results(CommandResults( outputs_prefix='vault-kms', outputs=ret )) elif demisto.command() == 'vault-kms-get-key-list': ret = client.get_key_list() print(ret) return_results(CommandResults( outputs_prefix='vault-kms-key-list', outputs=ret )) elif demisto.command() == 'vault-kms-delete-secrets': key = demisto.args().get('key') ret = client.delete_key(key) print(ret) # Log exceptions except Exception as e: traceback.print_exc() return_error(f'Failed to execute {demisto.command()} command. Error: {str(e)}') main() ``` ##### golang example kv read ``` package main import ( "fmt" "github.com/hashicorp/vault/api" "log" ) func main() { // 创建一个新的Vault客户端 config := &api.Config{ Address: "http://127.0.0.1:8200", } client, err := api.NewClient(config) if err != nil { log.Fatal(err) } // 使用App Role登录Vault roleID := "YOUR_APPROLE_ROLE_ID" secretID := "YOUR_APPROLE_SECRET_ID" secret := map[string]interface{}{ "role_id": roleID, "secret_id": secretID, } resp, err := client.Logical().Write("auth/approle/login", secret) if err != nil { log.Fatal(err) } if resp.Auth == nil { log.Fatal("authentication failed") } client.SetToken(resp.Auth.ClientToken) // 从Vault中读取KV secretPath := "secret/data/myapp/config" secretData, err := client.Logical().Read(secretPath) if err != nil { log.Fatal(err) } if secretData == nil || secretData.Data == nil { log.Fatal("secret not found") } // 处理获取到的KV数据 data := secretData.Data["data"].(map[string]interface{}) for key, value := range data { fmt.Printf("%s: %v\n", key, value) } } ``` #### k8s中集成vault ##### 将kube API Server访问Token托管到Vault CICD团队 和K8S通信进行应用部署的时候可以使用vault中的serviceAcccount进行K8S API 调用,vault可以定期轮转token从而避免了K8S管理员token的泄露。 Vault 的 Kubernetes 机密引擎负责管理客户应用程序的凭据。它生成并管理服务帐户令牌,而这些令牌又被分配了特定的功能。借助可配置的 TTL,一旦 Vault 租约到期,令牌就会自动撤销。这样做的好处是,只在需要时授予所需的访问权限。 https://developer.hashicorp.com/vault/tutorials/kubernetes/kubernetes-secrets-engine#kubernetes-secrets-engine git clone https://github.com/hashicorp-education/learn-vault-kubernetes.git ``` root@terraform-auto-host-0:~/vault/learn-vault-kubernetes/secrets-engine# ls bindings.yaml roles.yaml serviceAccounts.yaml values.yaml root@terraform-auto-host-0:~/vault/learn-vault-kubernetes/secrets-engine# cat bindings.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: k8s-secrets-abilities-binding roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: k8s-secrets-abilities subjects: - kind: ServiceAccount name: vault namespace: vault --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: demo-clusterrole-abilities roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: demo-cluster-role-list-pods subjects: - kind: ServiceAccount name: vault namespace: vault --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: demo-role-abilities namespace: demo roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: demo-role-list-pods subjects: - kind: ServiceAccount name: sample-app namespace: demo root@terraform-auto-host-0:~/vault/learn-vault-kubernetes/secrets-engine# cat roles.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: k8s-secrets-abilities rules: - apiGroups: - "" resources: - serviceaccounts/token verbs: - create - apiGroups: [""] resources: - serviceaccounts verbs: - create - delete - apiGroups: - rbac.authorization.k8s.io resources: - roles - rolebindings - clusterroles - clusterrolebindings verbs: - create - delete --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: demo-role-list-pods namespace: demo rules: - apiGroups: [""] resources: ["pods"] verbs: ["list"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: demo-cluster-role-list-pods rules: - apiGroups: [""] resources: ["pods"] verbs: ["list","get","delete"] root@terraform-auto-host-0:~/vault/learn-vault-kubernetes/secrets-engine# cat serviceAccounts.yaml apiVersion: v1 kind: ServiceAccount metadata: name: sample-app namespace: demo root@terraform-auto-host-0:~/vault/learn-vault-kubernetes/secrets-engine# cat bindings.yaml roles.yaml serviceAccounts.yaml values.yaml root@terraform-auto-host-0:~/vault/learn-vault-kubernetes/secrets-engine# cat values.yaml global: enabled: false server: enabled: true dev: enabled: true logLevel: debug ``` minikube start helm install vault hashicorp/vault -n vault -f values.yaml --create-namespace helm status vault helm get manifest vault 需要将vault部署到k8s中,这样vault才能访问k8s 的API ``` root@terraform-auto-host-0:~/vault/learn-vault-kubernetes/secrets-engine# helm install vault hashicorp/vault -n vault -f vaules.yaml --create-namespace Error: INSTALLATION FAILED: repo hashicorp not found root@terraform-auto-host-0:~/vault/learn-vault-kubernetes/secrets-engine# helm repo add hashicorp https://helm.releases.hashicorp.com helm repo update "hashicorp" has been added to your repositories Hang tight while we grab the latest from your chart repositories... ...Successfully got an update from the "hashicorp" chart repository ...Successfully got an update from the "stable" chart repository Update Complete. ⎈Happy Helming!⎈ root@terraform-auto-host-0:~/vault/learn-vault-kubernetes/secrets-engine# root@terraform-auto-host-0:~/vault/learn-vault-kubernetes/secrets-engine# helm install vault hashicorp/vault -n vault -f values.yaml --create-namespace NAME: vault LAST DEPLOYED: Mon Sep 30 18:37:48 2024 NAMESPACE: vault STATUS: deployed REVISION: 1 NOTES: Thank you for installing HashiCorp Vault! Now that you have deployed Vault, you should look over the docs on using Vault with Kubernetes available here: https://developer.hashicorp.com/vault/docs Your release is named vault. To learn more about the release, try: $ helm status vault $ helm get manifest vault ``` minikube kubectl -- get pods -A  minikube kubectl -- port-forward -n vault service/vault 8200:8200 1> /dev/null ``` root@terraform-auto-host-0:~/vault/learn-vault-kubernetes/secrets-engine# kubectl create namespace demo namespace/demo created root@terraform-auto-host-0:~/vault/learn-vault-kubernetes/secrets-engine# root@terraform-auto-host-0:~/vault/learn-vault-kubernetes/secrets-engine# kubectl apply -f roles.yaml,serviceAccounts.yaml,bindings.yaml clusterrole.rbac.authorization.k8s.io/k8s-secrets-abilities created role.rbac.authorization.k8s.io/demo-role-list-pods created clusterrole.rbac.authorization.k8s.io/demo-cluster-role-list-pods created serviceaccount/sample-app created clusterrolebinding.rbac.authorization.k8s.io/k8s-secrets-abilities-binding created clusterrolebinding.rbac.authorization.k8s.io/demo-clusterrole-abilities created rolebinding.rbac.authorization.k8s.io/demo-role-abilities created ```  vault操作 ``` root@terraform-auto-host-0:~/vault/learn-vault-kubernetes/secrets-engine# vault secrets enable kubernetes WARNING! VAULT_ADDR and -address unset. Defaulting to https://127.0.0.1:8200. Error enabling: Post "https://127.0.0.1:8200/v1/sys/mounts/kubernetes": http: server gave HTTP response to HTTPS client root@terraform-auto-host-0:~/vault/learn-vault-kubernetes/secrets-engine# export VAULT_DEV_ROOT_TOKEN_ID="root" \ VAULT_TOKEN="root" \ VAULT_ADDR="http://127.0.0.1:8200" \ KUBE_HOST=$(kubectl config view --minify \ -o 'jsonpath={.clusters[].cluster.server}') root@terraform-auto-host-0:~/vault/learn-vault-kubernetes/secrets-engine# vault secrets enable kubernetes Success! Enabled the kubernetes secrets engine at: kubernetes/ root@terraform-auto-host-0:~/vault/learn-vault-kubernetes/secrets-engine# vault write -f kubernetes/config Success! Data written to: kubernetes/config root@terraform-auto-host-0:~/vault/learn-vault-kubernetes/secrets-engine# vault write kubernetes/roles/sample-app \ service_account_name=sample-app \ allowed_kubernetes_namespaces=demo \ token_max_ttl=80h \ token_default_ttl=1h Success! Data written to: kubernetes/roles/sample-app root@terraform-auto-host-0:~/vault/learn-vault-kubernetes/secrets-engine# vault write kubernetes/creds/sample-app kubernetes_namespace=demo Key Value --- ----- lease_id kubernetes/creds/sample-app/i7fXlm2a23fFOwQuCuU17KE8 lease_duration 1h lease_renewable false service_account_name sample-app service_account_namespace demo service_account_token eyJhbGciOiJSUzI1NiIsImtpZCI6IkRuQzFUZkg0T1JWcjFlNFBHZXB5V3VtQXpPMUFpMl9Mb0U0MDRrMUVxUXMifQ.eyJhdWQiOlsiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWwiXSwiZXhwIjoxNzI3Njk2NzkyLCJpYXQiOjE3Mjc2OTMxOTIsImlzcyI6Imh0dHBzOi8va3ViZXJuZXRlcy5kZWZhdWx0LnN2Yy5jbHVzdGVyLmxvY2FsIiwianRpIjoiNjFkY2UzYWEtYTFjOS00MmY1LTg4MTAtMDY0YTg0NmNhNTE5Iiwia3ViZXJuZXRlcy5pbyI6eyJuYW1lc3BhY2UiOiJkZW1vIiwic2VydmljZWFjY291bnQiOnsibmFtZSI6InNhbXBsZS1hcHAiLCJ1aWQiOiIwNzY4ZGM0Yi04NjExLTRmYzMtOTk4YS1lNDZhNDE5MDcyMWUifX0sIm5iZiI6MTcyNzY5MzE5Miwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50OmRlbW86c2FtcGxlLWFwcCJ9.qnhFIujSeHgBAuLoNNMZ4U9AYcuG4PGbRgQPmJ8RYR_K8BgNxtIK3NYGAbdiUzCJU1_ruKCU9jzT6FUldUwiXmDdiwtnBZ3ORYlWJ-ygW6CQIvCA_sAzV9nS60Cq8PfijlIPDGOfvQbjuaImuV_ZT-OrzFueUVovWo_T1lE2QAtwO-frhV4dHywLS4WSBZa4BuqxftcslJIiFfDjfNScpZ2tS2Uk3oIbfFaEBBtSGWxSUWmI_CL6B5YI_cRNyEppE5GSGRJ4Tq9j2JNhXwOKcYEv8MBA77AFoYJevPsRAn6oSyAYKQYSzg402epkZ2AqsJ8ZpuA5v8RjJ7Eh-YBi1g root@terraform-auto-host-0:~/vault/learn-vault-kubernetes/secrets-engine# kubectl run nginx --image=nginx --namespace demo pod/nginx created root@terraform-auto-host-0:~/vault/learn-vault-kubernetes/secrets-engine# root@terraform-auto-host-0:~/vault/learn-vault-kubernetes/secrets-engine# export TEST_TOKEN=eyJhbGciOiJSUzI1NiIsImtpZCI6IkRuQzFUZkg0T1JWcjFlNFBHZXB5V3VtQXpPMUFpMl9Mb0U0MDRrMUVxUXMifQ.eyJhdWQiOlsiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWwiXSwiZXhwIjoxNzI3Njk2NzkyLCJpYXQiOjE3Mjc2OTMxOTIsImlzcyI6Imh0dHBzOi8va3ViZXJuZXRlcy5kZWZhdWx0LnN2Yy5jbHVzdGVyLmxvY2FsIiwianRpIjoiNjFkY2UzYWEtYTFjOS00MmY1LTg4MTAtMDY0YTg0NmNhNTE5Iiwia3ViZXJuZXRlcy5pbyI6eyJuYW1lc3BhY2UiOiJkZW1vIiwic2VydmljZWFjY291bnQiOnsibmFtZSI6InNhbXBsZS1hcHAiLCJ1aWQiOiIwNzY4ZGM0Yi04NjExLTRmYzMtOTk4YS1lNDZhNDE5MDcyMWUifX0sIm5iZiI6MTcyNzY5MzE5Miwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50OmRlbW86c2FtcGxlLWFwcCJ9.qnhFIujSeHgBAuLoNNMZ4U9AYcuG4PGbRgQPmJ8RYR_K8BgNxtIK3NYGAbdiUzCJU1_ruKCU9jzT6FUldUwiXmDdiwtnBZ3ORYlWJ-ygW6CQIvCA_sAzV9nS60Cq8PfijlIPDGOfvQbjuaImuV_ZT-OrzFueUVovWo_T1lE2QAtwO-frhV4dHywLS4WSBZa4BuqxftcslJIiFfDjfNScpZ2tS2Uk3oIbfFaEBBtSGWxSUWmI_CL6B5YI_cRNyEppE5GSGRJ4Tq9j2JNhXwOKcYEv8MBA77AFoYJevPsRAn6oSyAYKQYSzg402epkZ2AqsJ8ZpuA5v8RjJ7Eh-YBi1gexport TEST_TOKEN=eyJhbGciOiJSUzI1NiIsImtpZCI6IkRuQzFUZkg0T1JWcjFlNFBHZXB5V3VtQXpPMUFpMl9Mb0U0MDRrMUVxUXMifQ.eyJhdWQiOlsiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWwiXSwiZXhwIjoxNzI3Njk2NzkyLCJpYXQiOjE3Mjc2OTMxOTIsImlzcyI6Imh0dHBzOi8va3ViZXJuZXRlcy5kZWZhdWx0LnN2Yy5jbHVzdGVyLmxvY2FsIiwianRpIjoiNjFkY2UzYWEtYTFjOS00MmY1LTg4MTAtMDY0YTg0NmNhNTE5Iiwia3ViZXJuZXRlcy5pbyI6eyJuYW1lc3BhY2UiOiJkZW1vIiwic2VydmljZWFjY291bnQiOnsibmFtZSI6InNhbXBsZS1hcHAiLCJ1aWQiOiIwNzY4ZGM0Yi04NjExLTRmYzMtOTk4YS1lNDZhNDE5MDcyMWUifX0sIm5iZiI6MTcyNzY5MzE5Miwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50OmRlbW86c2FtcGxlLWFwcCJ9.qnhFIujSeHgBAuLoNNMZ4U9AYcuG4PGbRgQPmJ8RYR_K8BgNxtIK3NYGAbdiUzCJU1_ruKCU9jzT6FUldUwiXmDdiwtnBZ3ORYlWJ-ygW6CQIvCA_sAzV9nS60Cq8PfijlIPDGOfvQbjuaImuV_ZT-OrzFueUVovWo_T1lE2QAtwO-frhV4dHywLS4WSBZa4BuqxftcslJIiFfDjfNScpZ2tS2Uk3oIbfFaEBBtSGWxSUWmI_CL6B5YI_cRNyEppE5GSGRJ4Tq9j2JNhXwOKcYEv8MBA77AFoYJevPsRAn6oSyAYKQYSzg402epkZ2AqsJ8ZpuA5v8RjJ7Eh-YBi1gexport TEST_TOKEN=eyJhbGciOiJSUzI1NiIsImtpZCI6IkRuQzFUZkg0T1JWcjFlNFBHZXB5V3VtQXpPMUFpMl9Mb0U0MDRrMUVxUXMifQ.eyJhdWQiOlsiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWwiXSwiZXhwIjoxNzI3Njk2NzkyLCJpYXQiOjE3Mjc2OTMxOTIsImlzcyI6Imh0dHBzOi8va3ViZXJuZXRlcy5kZWZhdWx0LnN2Yy5jbHVzdGVyLmxvY2FsIiwianRpIjoiNjFkY2UzYWEtYTFjOS00MmY1LTg4MTAtMDY0YTg0NmNhNTE5Iiwia3ViZXJuZXRlcy5pbyI6eyJuYW1lc3BhY2UiOiJkZW1vIiwic2VydmljZWFjY291bnQiOnsibmFtZSI6InNhbXBsZS1hcHAiLCJ1aWQiOiIwNzY4ZGM0Yi04NjExLTRmYzMtOTk4YS1lNDZhNDE5MDcyMWUifX0sIm5iZiI6MTcyNzY5MzE5Miwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50OmRlbW86c2FtcGxlLWFwcCJ9.qnhFIujSeHgBAuLoNNMZ4U9AYcuG4PGbRgQPmJ8RYR_K8BgNxtIK3NYGAbdiUzCJU1_ruKCU9jzT6FUldUwiXmDdiwtnBZ3ORYlWJ-ygW6CQIvCA_sAzV9nS60Cq8PfijlIPDGOfvQbjuaImuV_ZT-OrzFueUVovWo_T1lE2QAtwO-frhV4dHywLS4WSBZa4BuqxftcslJIiFfDjfNScpZ2tS2Uk3oIbfFaEBBtSGWxSUWmI_CL6B5YI_cRNyEppE5GSGRJ4Tq9j2JNhXwOKcYEv8MBA77AFoYJevPsRAn6oSyAYKQYSzg402epkZ2AqsJ8ZpuA5v8RjJ7Eh-YBi1g root@terraform-auto-host-0:~/vault/learn-vault-kubernetes/secrets-engine# curl -k $KUBE_HOST/api/v1/namespaces/demo/pods --header "Authorization: Bearer $TEST_TOKEN" { "kind": "PodList", "apiVersion": "v1", "metadata": { "resourceVersion": "22082" }, "items": [ { "metadata": { "name": "nginx", "namespace": "demo", "uid": "3147c36c-a10a-49bf-b36d-00a62dbe8d55", "resourceVersion": "21801", "creationTimestamp": "2024-09-30T10:48:08Z", "labels": { "run": "nginx" }, "managedFields": [ { "manager": "kubectl-run", "operation": "Update", "apiVersion": "v1", "time": "2024-09-30T10:48:08Z", "fieldsType": "FieldsV1", "fieldsV1": { ```  几个关键点: 1.vault需要能够有权限访问K8S API Server进行操作,因此kubectl apply -f 那些role和sa就是给vault赋权的 2.vault需要进行配置几个命令 创建权限 ``` vault secrets enable kubernetes vault write -f kubernetes/config vault write kubernetes/roles/sample-app \ service_account_name=sample-app \ allowed_kubernetes_namespaces=demo \ token_max_ttl=80h \ token_default_ttl=1h vault write kubernetes/creds/sample-app kubernetes_namespace=demo ``` 创建集群权限 ``` vault write kubernetes/roles/rules \ allowed_kubernetes_namespaces=default \ allowed_kubernetes_namespaces=demo \ kubernetes_role_type=ClusterRole \ token_max_ttl=80h \ token_default_ttl=1h \ generated_role_rules='{"rules":[{"apiGroups":[""],"resources":["pods"],"verbs":["list","get"]}]}' export TEST_TOKEN=$(vault write -field=service_account_token kubernetes/creds/rules kubernetes_namespace=demo cluster_role_binding=true) export TEST_TOKEN=$(vault write -field=service_account_token kubernetes/creds/rules kubernetes_namespace=demo cluster_role_binding=false) ``` 删除权限 ``` vault lease revoke -prefix kubernetes/creds/existing-role ``` ##### 将K8S Secrets托管到Vault 这章节主要是实验将k8s的secrets托管到vault中,这样的好处就是有助于vault管理k8s secrets的生命周期  可以参考这篇文章 https://developer.hashicorp.com/vault/tutorials/kubernetes/vault-secrets-operator  git clone https://github.com/hashicorp-education/learn-vault-secrets-operator.git minikube start --force  安装vault helm repo add hashicorp https://helm.releases.hashicorp.com helm repo update helm install vault hashicorp/vault -n vault --create-namespace --values vault/vault-values.yaml  kubectl exec --stdin=true --tty=true vault-0 -n vault -- /bin/sh cd tmp vault auth enable -path demo-auth-mount kubernetes vault write auth/demo-auth-mount/config \ kubernetes_host="https://$KUBERNETES_PORT_443_TCP_ADDR:443" vault secrets enable -path=kvv2 kv-v2 tee webapp.json <<EOF path "kvv2/data/webapp/config" { capabilities = ["read", "list"] } EOF vault policy write webapp webapp.json vault write auth/demo-auth-mount/role/role1 \ bound_service_account_names=demo-static-app \ bound_service_account_namespaces=app \ policies=webapp \ audience=vault \ ttl=24h vault kv put kvv2/webapp/config username="static-user" password="static-password" exit  安装 Vault Secrets Operator helm install vault-secrets-operator hashicorp/vault-secrets-operator -n vault-secrets-operator-system --create-namespace --values vault/vault-operator-values.yaml  部署并同步机密 kubectl create ns app kubectl apply -f vault/vault-auth-static.yaml kubectl apply -f vault/static-secret.yaml  查看secrets kubectl get secrets app -n secretkv -o yaml  成功将vault密码映射到k8s #### vault 自动轮转密钥 Vault支持多种类型的密钥进行自动轮转,其中一些常见的包括: 1. AWS密钥:Vault可以与AWS集成,自动轮转AWS访问密钥和密钥对。 2. 数据库凭证:Vault可以管理数据库凭证并自动轮转数据库密码,如MySQL、PostgreSQL等。 3. TLS证书:Vault可以生成和管理TLS证书,并在到期前自动轮转。 4. SSH密钥:Vault可以管理SSH密钥,并自动轮转这些密钥以增强安全性。 5. Token:Vault中的访问令牌(token)也可以进行自动轮转,以确保安全性。 这些是Vault中一些常见支持自动轮转的密钥类型,Vault还支持自定义插件来实现其他类型密钥的自动轮转。 plugin参考: https://developer.hashicorp.com/vault/tutorials/secrets-management/plugin-backends #### vault userpass登录集成TOTP MFA二次认证 ``` root@terraform-auto-host-0:~# vault write -field=id identity/entity name="admin" 0816cdd0-53f5-94d2-0f86-c3853ed6a6dc root@terraform-auto-host-0:~# vault auth list Path Type Accessor Description Version ---- ---- -------- ----------- ------- approle/ approle auth_approle_0b6572ae n/a n/a token/ token auth_token_ddf29ab1 token based credentials n/a userpass/ userpass auth_userpass_b7a61790 n/a n/a root@terraform-auto-host-0:~# vault write identity/entity-alias \ name="admin" \ canonical_id="0816cdd0-53f5-94d2-0f86-c3853ed6a6dc" \ mount_accessor="auth_userpass_b7a61790" Key Value --- ----- canonical_id 0816cdd0-53f5-94d2-0f86-c3853ed6a6dc id 6fe0aa72-4aed-50f7-f638-f1bb8f2c08a3 root@terraform-auto-host-0:~# vault write -field=method_id identity/mfa/method/totp issuer=HCP-Vault period=30 key_size=30 qr_size=200 algorithm=SHA256 digits=6 name=admin 0563a8b2-30a4-eb75-d0e6-5dc0b5601a3a root@terraform-auto-host-0:~# vault read identity/mfa/method/totp/0563a8b2-30a4-eb75-d0e6-5dc0b5601a3a Key Value --- ----- algorithm SHA256 digits 6 id 0563a8b2-30a4-eb75-d0e6-5dc0b5601a3a issuer HCP-Vault key_size 30 max_validation_attempts 5 name n/a namespace_id root namespace_path n/a period 30s qr_size 200 skew 1 type totp root@terraform-auto-host-0:~# vault write identity/mfa/method/totp/generate method_id=0563a8b2-30a4-eb75-d0e6-5dc0b5601a3a Error writing data to identity/mfa/method/totp/generate: Error making API request. URL: PUT https://127.0.0.1/v1/identity/mfa/method/totp/generate Code: 400. Errors: * missing entityID root@terraform-auto-host-0:~# vault write identity/mfa/method/totp/admin-generate method_id=0563a8b2-30a4-eb75-d0e6-5dc0b5601a3a entity_id=0816cdd0-53f5-94d2-0f86-c3853ed6a6dc Key Value --- ----- barcode iVBORw0KGgoAAAANSUhEUgAAAMgAAADIEAAAAADYoy0BAAAGn0lEQVR4nOydwW4zNwyEm+J//1dOD76oIMh+JLXu2JjvFKx3JSUDEhQ1G//5/f3LCPH3/70A828siBgWRAwLIoYFEcOCiGFBxLAgYlgQMSyIGBZEDAsihgURw4KIYUHEsCBiWBAxLIgYFkSMP/TGnx96Jz+lP8c8n4rXX1eyn+Ps2cjZ7Nlc551xnCf+Jo4QMSyIGDhlvahDrw5hHuDnXFliiffE6+e82cqzWXji2vxNIo4QMSyIGM2U9aJOI+c9Wc0TP60TwjlCNnJdWdWVUpYGsysR8jchOELEsCBijFLWjLo6IpvEesxIXV+Rp+pk+wSOEDEsiBhvSVm8H1X3qepPn175eeU5HCFiWBAxRilr32CvG918LrIh5YluU0HdSmWOEDEsiBjNlLVvoZOeEvk5e7ZeAzlz5Os8r9zCESKGBREDp6xNFUHsAWSTWCclsobuOMRQcRdHiBgWRIwfGnZ8e5UZA7o10qwhz1dF7q+tDpujgQxHiBgWRAycsv5jmGbayT7dpKPs2a5BNH7Kf4t4T7c/5ggRw4KI0UxZszB/Qeoc3r+qVzWbPbs/PkW8966yvgILIkZzY1hz69WYOFqdLkiVla1nVqHVo8VPXWV9LBZEjGb7nVcv9Ysts25YvaosXWwSTvf+vYPLESKGBRHjkpW0+ypx/apObTyoRyN0t5xxrnrkDY4QMSyIGIuNIfc48UoszsiNB2Qj2bVbdGuzvRHCESKGBRFjcWK433BxC8G+41RDUtzGBMtxhIhhQcRYnBiSftTeSMAb7084qbotfW8Mvw4LIsboX/yRaqf7Ygt/NaZu7GdrjndmqYzMUqfBzfbQESKGBRFj5H7PPiXwSqn+tPvzOVq28o37a785feEIEcOCiLE+MeQ9KzICqXCI3WJzNFBXhrzDNjM8OELEsCBijP6TQ5YcsjonS0FkezU7v+MVF6+LbtV1NY4QMSyIGKP2e6Rbq/BzN7IG3t7nG0PeB7uLI0QMCyLGemOYhTnpbnW7THwL1q1/ui19XnF1cYSIYUHEWFtJ6/s3nqtZdcTXPHN5PecNe+EIEcOCiDH6UjBeTZFTtvjz2RmL4xBTQVztrHPFqStAt98/Fgsixui1aLKN6lZN8anZ5oucP8bxs98iG4f8vtz4ceIIEcOCiLGosoj5k3jO66dmI8RP6/XwzhVZeT1mjSNEDAsiRtP93j0HjBCXVLbxrOul7EqdWEhLP1sbSdreGH44FkSM9T9SJtufbmjP2ubxfn4iWc/VnT0bjeAIEcOCiHHp6ypIg32Wpm5t4rJnuyebGfX201XWx2JBxFhbSUmvKcJnnSXAbLXdtc1mscnhi7AgYrzxf7/zwK+vd88NybO81R/HzHCV9RVYEDEu/b8sbhA92ZtFsxVmc9Xjb2a8VXc5QsSwIGIsXtjpbqDO6zU8CdQVV/e07hyn2xmbGTwijhAxLIgYI5MDt3dygwHvWZGRs/Wfdz5hUTjHnz3rCBHDgoixaL8T6yaBnBjWKTFbDznZ5CeYfP0+MfwiLIgYV7+ugqcI0lSPI5BZ+ApJLcQrpVlNFXGEiGFBxHjgewzJdq+bIsgGkzTz620p2bSekN/X7vcPx4KIsehlZfd0R6hb1mffqV5DnYJm9Q/Z/HbNqzWOEDEsiBhrk8PeT/6EPXXjq595xrKVdHGEiGFBxHjj/8uqt0h1GslGi/dkIxO6J4a3zBUnjhAxLIgYI/c7d4/va7DsnlkFla2EHCVk43drzhpHiBgWRIyrXwpGwpY3pbv9rnoN2Xqy+2e2Cn5PhiNEDAsixgO+rPPOWergWy3+FDc8nPD+W3xqhiNEDAsixmO+rL1DiTimMrqpptvvqtn0tRwhYlgQMS69YxivEFNEXduQMCdG03qF3dXW89pK+nVYEDGaviwCSTh1I71bC5F+VByZ9LLq9dxyzp84QsSwIGKMTA4ZxPdeP3Xr/tjwj3dmZlTuCuPzchwhYlgQMUYbQ55kuC0hm4VYCLJ54zg1dXLrvsLjlPUVWBAxLr1j+ARZ+HfPBOt0WkMc8mR76/b7x2JBxHhLyiJOqng9Pht/nnWrun25+qmZESLDESKGBRFjlLK6m6w6jZC0Q6yk3EWfXa8TVJaISMrlOELEsCBiXP26ihcbWyYxD3T7SKQP1nXUcxtqF0eIGBZEjPVXr5q7OELEsCBiWBAxLIgYFkQMCyKGBRHDgohhQcSwIGJYEDEsiBgWRAwLIoYFEcOCiGFBxLAgYlgQMSyIGP8EAAD//+ojPaPUgK/BAAAAAElFTkSuQmCC url otpauth://totp/HCP-Vault:0816cdd0-53f5-94d2-0f86-c3853ed6a6dc?algorithm=SHA256&digits=6&issuer=HCP-Vault&period=30&secret=XVTGOQIHYAXN3FGGFV77DV42RTIYBPLJ2GGXZGATUVVTOVDU root@terraform-auto-host-0:~# vault write identity/mfa/login-enforcement/mylogin \ mfa_method_ids="0563a8b2-30a4-eb75-d0e6-5dc0b5601a3a" \ auth_method_accessors="auth_userpass_b7a61790" Success! Data written to: identity/mfa/login-enforcement/mylogin root@terraform-auto-host-0:~# vault secrets enable totp Success! Enabled the totp secrets engine at: totp/ root@terraform-auto-host-0:~# vault write totp/keys/hcp-vault url="otpauth://totp/HCP-Vault:0816cdd0-53f5-94d2-0f86-c3853ed6a6dc?algorithm=SHA256&digits=6&issuer=HCP-Vault&period=30&secret=XVTGOQIHYAXN3FGGFV77DV42RTIYBPLJ2GGXZGATUVVTOVDU" Success! Data written to: totp/keys/hcp-vault root@terraform-auto-host-0:~# vault read totp/code/hcp-vault Key Value --- ----- code 796103 root@terraform-auto-host-0:~# root@terraform-auto-host-0:~# vault read totp/code/hcp-vault Key Value --- ----- code 796103 ``` 将 otpauth....输入到二维码生成器  用户登录成功开启OTP认证  #### vault配置IP白名单 ``` vault write auth/userpass/users/ipwhitelist \ password=XXXXX \ policies=jenkins \ token_bound_cidrs=172.17.0.1/32 ``` 使用token_bound_cidrs这个参数可以指定我们的IP地址,建议在所有正式环境都需要限制先每个用户可以访问过来的IP地址,以防攻击者在通过数据泄露拿到密钥以后可以获取vault中的数据。  如果配置在nginx后面可能取不到IP,这个时候需要额外配置 要在Nginx后面传递真实IP地址给Vault,您可以使用X-Forwarded-For头字段。这样Vault就能够识别请求的真实来源IP地址。以下是一些步骤来配置Nginx以传递真实IP地址: 1. 在Nginx配置中添加以下行以启用X-Forwarded-For头字段: ```nginx proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; ``` 2. 确保Vault服务器配置中允许接受和识别X-Forwarded-For头字段。您可以在Vault的配置文件中添加以下内容: ```hcl listener "tcp" { address = "0.0.0.0:8200" proxy_protocol_behavior = "use_always" } ``` 3. 重新加载Nginx配置以使更改生效: ```bash sudo systemctl reload nginx ``` 通过这些步骤,您就可以配置Nginx以在代理请求时传递真实IP地址给Vault。请确保您的网络架构和安全策略允许使用X-Forwarded-For头字段传递IP地址。  ### vault 审计audit https://developer.hashicorp.com/vault/docs/audit#tutorial  开启vault 审计 ``` vault audit enable file file_path=/var/log/vault_audit.log ```  ### vault trouble shoot #### Error initializing listener of type tcp: listen tcp 127.0.0.1:8200: bind: address already in use 运行时遇到这个错误 ``` root@terraform-auto-host-0:/etc/vault.d# vault server -dev -config ./vault.hcl Error parsing listener configuration. Error initializing listener of type tcp: listen tcp 127.0.0.1:8200: bind: address already in use 2024-09-22T11:54:00.870Z [INFO] proxy environment: http_proxy="" https_proxy="" no_proxy="" 2024-09-22T11:54:00.892Z [INFO] incrementing seal generation: generation=1 2024-09-22T11:54:00.893Z [INFO] core: Initializing version history cache for core 2024-09-22T11:54:00.893Z [INFO] events: Starting event system ```  看配置文件: ``` ui = true cluster_addr = "https://127.0.0.1:8201" api_addr = "https://127.0.0.1:8200" disable_mlock = true storage "raft" { path = "/opt/vault/data" node_id = "127.0.0.1" } listener "tcp" { address = "127.0.0.1:8200" tls_cert_file = "/etc/vault.d/certificate.crt" tls_key_file = "/etc/vault.d/private.key" # tls_disable = 1 } ``` TCP address listen不能写127.0.0.1,换成别的网卡的IP,或者物理网卡的IP 修正后如下:  #### Unable to establish TLS Connection with self signed certificate #837 解决办法,不要使用CN的证书,要使用subjectAltName SAN创建 #### MFA secret for method name "" not present in entity "b7c0c1a4-7adf-bdae-3c5f-7334c178046b" root@terraform-auto-host-0:~# vault login -method userpass username=ipwhitelist password=1qaz@WSX Initiating Interactive MFA Validation... Enter the passphrase for methodID "0563a8b2-30a4-eb75-d0e6-5dc0b5601a3a" of type "totp": Error making API request. URL: POST https://127.0.0.1/v1/sys/mfa/validate Code: 403. Errors: * failed to satisfy enforcement mylogin. error: 2 errors occurred: * MFA secret for method name "" not present in entity "b7c0c1a4-7adf-bdae-3c5f-7334c178046b" * login MFA validation failed for methodID 是一一和: [0563a8b2-30a4-eb75-d0e6-5dc0b5601a3a] MFA 的methodID 是一一和entity id绑定的,上述我们建立的是admin的entiy id,自然不能使用ipwhitelist这个用户。 只能使用admin用户登录 ``` root@terraform-auto-host-0:~# vault write auth/userpass/users/admin \ password=1qaz@WSX \ policies=jenkins Success! Data written to: auth/userpass/users/admin root@terraform-auto-host-0:~# vault login -method userpass username=admin password=1qaz@WSX Initiating Interactive MFA Validation... Enter the passphrase for methodID "0563a8b2-30a4-eb75-d0e6-5dc0b5601a3a" of type "totp": Success! You are now authenticated. The token information displayed below is already stored in the token helper. You do NOT need to run "vault login" again. Future Vault requests will automatically use this token. Key Value --- ----- token hvs.CAESILx2ZZky7wJc8weeg7UnSXVl8sHWH8W0T8OomRPDi0qhGh4KHGh2cy4zUDBhY1ZaWnNZbVNBeHM3RnFYTTRXNHo token_accessor RC0TZoLTskBzz794JKRFjjpJ token_duration 768h token_renewable true token_policies ["default" "jenkins"] identity_policies [] policies ["default" "jenkins"] token_meta_username admin ``` #### 使用nginx后端无法进行mtls证书认证 ``` root@terraform-auto-host-0:~# vault login -method=cert -ca-cert=/opt/ca.crt -client-cert=/root/vault/client.crt -client-key=/root/vault/client.key name=jenkins Error authenticating: Error making API request. URL: PUT https://127.0.0.1/v1/auth/cert/login Code: 400. Errors: * tls connection required ```  issue 同https://github.com/hashicorp/vault/issues/3006 nginx proxy暂无法将mtls透传,可以使用AWS NLB,或者使用nginx 代理tcp stream https://nginx.org/en/docs/stream/ngx_stream_core_module.html ## 参考资料 https://m.freebuf.com/articles/es/229311.html https://pandaychen.github.io/2021/07/10/A-KMS-STUDY/ https://www.secrss.com/articles/8141 https://www.cnblogs.com/sealio/p/16664999.html https://blog.fleeto.us/post/secret-to-vault-k8s/ vault gitbook https://blog.csdn.net/WEARE001/article/details/131413961