Vault是一個基於身份的密鑰管理和資料加密系統,提供對Token、密碼、認證、API Key等常見敏感憑據的安全儲存和控制,可有效解決應用系統中對敏感資訊的寫入程式碼問題。本文介紹如何在ACK叢集中部署和使用Vault。
前提條件
已安裝Helm,且Helm為v3.6及以上版本。更多資訊,請參見Helm Release。
安裝初始化Vault
步驟一:安裝Vault
任選以下方式擷取Vault的安裝包。本文樣本中Helm的Chart版本為vault-0.24.1,Vault版本為1.3.1。
登入Git倉庫vault-helm擷取。
通過遠程倉庫擷取。執行以下命令,添加並更新倉庫。
helm repo add hashicorp https://helm.releases.hashicorp.com helm repo update
執行以下命令,配置別名(Alias)簡化操作命令。
以下指令碼代碼以ACK叢集的KubeConfig資訊放置在
$HOME/Downloads/kubeconfig檔案中為例說明,使用時KubeConfig位置資訊請根據實際位置替換。# Helm用戶端。 alias h="helm --kubeconfig $HOME/Downloads/kubeconfig" # kubectl用戶端。 alias k="kubectl --kubeconfig $HOME/Downloads/kubeconfig"安裝Vault。
生產環境建議安裝Raft版本的Vault,請勿使用Standard alone版本。
執行以下命令,建立名為vault的命名空間。
k create ns vault將Vault安裝在
vault的命名空間中,後續和K8s Namespace相關的值都為vault。執行以下命令,在名為vault的命名空間中安裝Vault。
以下StorageClass(SC)使用ACK支援的SC,可通過
k get sc查詢。儲存的Size不小於20 GiB。部署完成後,將產生三個隨用隨付的ESSD雲端硬碟,作為Vault的Pod掛載使用的PV。關於雲端硬碟的計費資訊,請參見計費。h install vault -nvault hashicorp/vault \ --set='server.ha.enabled=true' \ --set='server.ha.raft.enabled=true' \ --set='server.dataStorage.size=20Gi' \ --set='server.dataStorage.storageClass=alicloud-disk-essd'執行以下命令,查看Vault的Pod狀態。
k get po -n vault預期輸出:
NAME READY STATUS RESTARTS AGE vault-0 0/1 Running 0 45s vault-1 0/1 Running 0 45s vault-2 0/1 Running 0 44s vault-agent-injector-59fdd7cdf8-prwv7 1/1 Running 0 45s
步驟二:初始化和解鎖Vault
執行以下命令,查看Vault第一次啟動後的狀態。
k exec -nvault vault-0 -- vault status預期輸出:
Key Value --- ----- Seal Type shamir Initialized false Sealed true Total Shares 0 Threshold 0 Unseal Progress 0/0 Unseal Nonce n/a Version 1.13.1 Build Date 2023-03-23T12:51:35Z Storage Type raft HA Enabled true command terminated with exit code 2當
Initialized為false,Sealed為true時,表明Vault未進行初始化,且沒有解鎖(Unseal)。您需要進行後續的初始化和解鎖操作。執行以下命令,初始化Vault。
通過容器內的Vault二進位,產生Key。
k exec vault-0 -nvault -- vault operator init -key-shares=5 -key-threshold=3 -format=json > cluster-keys.json初始化過程中,系統產生了5個
shares,並指定解鎖次數threshold為3。在實際生產環境中,在Pod內通過POST的
vault-0.vault.vault.svc:8200/sys/init進行OpenAPI調用。此處使用了StatefulSet(sts)的DNS解析習慣,即
{$podName}.{$stsName}.{$Namespace}.svc。關於初始化Vault對應的OpenAPI,請參見Vault Start Initialization。將以上產生的檔案cluster-keys.json中
unseal_keys_b64的內容匯出,進行下一步解鎖操作。執行以下命令,解鎖Vault。關於解鎖Vault對應的OpenAPI,請參見Vault Unseal。
由於以上
unseal_threshold設定為3,所以此處需選取3個Unseal key進行解鎖,分別執行1次,共需執行3次。k exec -nvault vault-0 -- vault operator unseal Zu6EdLIFn+2****執行以下命令,查看vault-0的狀態。
k exec -it vault-0 -n vault -- vault status Key Value --- ----- Seal Type shamir Initialized true Sealed false Total Shares 5 Threshold 3 Version 1.13.1 Build Date 2023-03-23T12:51:35Z Storage Type raft Cluster Name vault-cluster-504959a1 Cluster ID d99594a5-75de-53fa-59dd-19ed024b**** HA Enabled true HA Cluster https://vault-0.vault-internal:8201 HA Mode active Active Since 2023-05-06T10:30:38.237415781Z Raft Committed Index 36 Raft Applied Index 36 k get po -n vault NAME READY STATUS RESTARTS AGE vault-0 1/1 Running 0 46m vault-1 0/1 Running 0 46m vault-2 0/1 Running 0 46m vault-agent-injector-59fdd7cdf8-prwv7 1/1 Running 0 46m預期輸出表明,
vault-0已初始化完成。(可選)如需查看Raft節點,可通過root Token登入節點進行查看。
執行以下命令,登入vault-0節點。
此處root_toke值為
hvs.5aiXKN****,其值可通過步驟3產生的檔案cluster-keys.json擷取。k exec vault-0 -n vault -- vault login hvs.5aiXKN****執行以下命令,查看Raft節點。
k exec -nvault vault-0 -- vault operator raft list-peers預期輸出:
Node Address State Voter ---- ------- ----- ----- 10285056-839a-f306-a301-5024934a794f vault-0.vault-internal:8201 leader true
步驟三:添加其他Vault節點
執行以下命令,添加Vault節點。關於添加Vault節點的OpenAPI,請參見Raft。
k exec -nvault vault-1 -- vault operator raft join http://vault-0.vault-internal:8200 Key Value --- ----- Joined true k exec -nvault vault-2 -- vault operator raft join http://vault-0.vault-internal:8200 Key Value --- ----- Joined true分別執行以下命令,解鎖添加的Vault節點。
每個節點至少要用不同的Unseal key執行3次,共需執行6次。
k exec -nvault vault-1 -- vault operator unseal Zu6EdLIF**** k exec -nvault vault-2 -- vault operator unseal Zu6EdLIF**** ... k exec -nvault vault-1 -- vault operator unseal DgYQhjo6**** k exec -nvault vault-2 -- vault operator unseal DgYQhjo6****執行以下命令,查看節點添加結果。
k exec -n vault vault-0 -- vault operator raft list-peers預期輸出:
Node Address State Voter ---- ------- ----- ----- 10285056-839a-f306-a301-5024934a794f vault-0.vault-internal:8201 leader true 71ffd98c-d6d4-a7b3-994c-9ce87f464486 vault-1.vault-internal:8201 follower true 1e9f37dc-b55b-fc46-8ca8-595428ad1d81 vault-2.vault-internal:8201 follower true k get po -n vault NAME READY STATUS RESTARTS AGE vault-0 1/1 Running 0 66m vault-1 1/1 Running 0 66m vault-2 1/1 Running 0 66m vault-agent-injector-59fdd7cdf8-prwv7 1/1 Running 0 66m預期輸出表明,
vault-1和vault-2節點已添加成功。
使用樣本
樣本一:通過Vault管理Kubernetes叢集的ServiceAccount Token
您可以通過Valut擷取rolebinding clusterrolebinding對應的Token。啟用此特性後,在Kubernetes叢集上binding時,將不會產生對應的Secret。此方式通過Vault擷取訪問APIServer的Bear Token,可避免攻擊者通過Kubernetes叢集直接擷取SA的訪問憑證。
使用以下YAML內容,分別建立ClusterRole.yaml和ClusterRoleBinding.yaml檔案。
執行以下命令,為Vault的SA綁定ClusterRole,使其能建立SA的Token。
k apply -f ClusterRole.yaml k apply -f ClusterRoleBinding.yaml執行以下命令,開啟Vault的Kubernetes的Secret特性。
k exec -nvault vault-0 -- vault secrets enable kubernetes驗證使用效果。
執行以下命令,建立名為test的命名空間。
k create ns test使用以下YAML內容,建立test.yaml檔案。
執行以下命令,部署產生測試的SA Role RoleBinding。
k apply -f test.yaml執行以下命令,擷取Token資訊。關於OpenAPI的更多資訊,請參見Kubernetes API。
k exec -nvault vault-0 -- vault write -f kubernetes/config k exec -nvault vault-0 -- vault write kubernetes/roles/my-role allowed_kubernetes_namespaces="*" service_account_name="test-service-account-with-generated-token" token_default_ttl="10m" k exec -nvault vault-0 -- vault write kubernetes/creds/my-role kubernetes_namespace=test最後一個命令輸出的一個JWT Token,可以用於請求訪問APIserver。
JWT Token即為如下代碼中的
service_account_token欄位。Key Value --- ----- lease_id kubernetes/creds/my-role/XPDLbuXJ0Bt4fF**** lease_duration 10m lease_renewable false service_account_name test-service-account-with-generated-token service_account_namespace test service_account_token eyJhbGciOiJSUzI1NiIsImtp****執行以下命令,訪問APIServer。
curl -sk https://XX.XX.XX.XX:6443/api/v1/namespaces/test/pods --header "Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtp****" "kind": "PodList", "apiVersion": "v1", "metadata": { "resourceVersion": "2861371" }, "items": [] }以上Token有效期間是10 min,如果Token到期,需要調用Write操作重新擷取Token。
k exec -nvault vault-0 -- vault write kubernetes/creds/my-role kubernetes_namespace=test
樣本二:如何在應用Pod中動態擷取RAM憑證
您可以通過Vault儲存訪問阿里雲RAM使用者的AK和SK資訊。應用通過和Vault互動動態擷取相關憑證。關於更多OpenAPI資訊,請參見AliCloud Secrets Engine。
執行以下命令,為Vault開啟
Alicloud的Secret特性。k exec -nvault vault-0 -- vault secrets enable alicloud使用阿里雲帳號登入RAM控制台。
使用以下權限原則內容,建立自訂權限原則ExampleRAMPolicyforVault。具體操作,請參見建立自訂權限原則。
該權限原則允許在RAM使用者使用任何類型的角色建立、刪除憑證或策略,並為使用者指派策略,允許取消使用者的某個策略,建立和刪除使用者、通過角色扮演來訪問資源等。
建立RAM使用者hashicorp-vault。具體操作,請參見建立RAM使用者。
為RAM使用者hashicorp-vault授予自訂權限原則ExampleRAMPolicyforVault。具體操作,請參見為RAM使用者授權。
為RAM使用者hashicorp-vault建立AccessKey。具體操作,請參見建立AccessKey。
記錄此處的AK和SK資訊。例如,此處的AccessKey為ak1,SecretKey為sk1。
執行以下命令,將已擷取的AK和SK資訊寫入Vault。
k exec -nvault vault-0 -- vault write alicloud/config access_key=ak1 secret_key=sk Success! Data written to: alicloud/configAK和SK會儲存在Vault每個節點的
/vault/data/vault.db檔案中,同時此檔案會持久化到PV中,所以節點重啟後資訊不會丟失。將Remote和Inline策略定義寫入Vault。
執行以下命令,將Remote策略寫入Vault。
Remote模式指寫入RAM中已存在的權限原則類型和名稱。此處寫入一個自訂權限原則ExampleRAMPolicyforVault,兩個系統策略AliyunOSSReadOnlyAccess和AliyunRDSReadOnlyAccess。
k exec -nvault vault-0 -- vault write alicloud/role/policy-based \ remote_policies='name:ExampleRAMPolicyforVault,type:Custom' \ remote_policies='name:AliyunOSSReadOnlyAccess,type:System' \ remote_policies='name:AliyunRDSReadOnlyAccess,type:System' Success! Data written to: alicloud/role/policy-based執行以下命令,將Inline策略寫入Vault。
Inline模式指直接在API請求中寫入原則範本。此處可將已產生的自訂權限原則ExampleRAMPolicyforVault的配置寫入Vault。
k exec -nvault vault-0 -- vault write alicloud/role/policy-based \ inline_policies=-<<EOF [ { "Statement": [ { "Action": [ "ram:CreateAccessKey", "ram:DeleteAccessKey", "ram:CreatePolicy", "ram:DeletePolicy", "ram:AttachPolicyToUser", "ram:DetachPolicyFromUser", "ram:CreateUser", "ram:DeleteUser", "sts:AssumeRole" ], "Effect": "Allow", "Resource": "*" } ], "Version": "1" } ] EOF
建立RAM角色vaultTestRole並為該RAM角色授予自訂權限原則ExampleRAMPolicyforVault。具體操作,請參見建立可信實體為阿里雲帳號的RAM角色和為RAM角色授權。
為角色授權完成後,會產生一條ARN記錄,格式如下,其中15261****為RAM使用者的ID。
vaultTestRole@role.15261****.onaliyunservice.com執行以下命令,將對應的ARN資訊寫入Vault,即將綁定關係寫入Vault,實現Vault對RAM角色vaultTestRole的扮演。
k exec -nvault vault-0 -- vault write alicloud/role/role-based \ role_arn='acs:ram::15261****:role/vaultTestRole'
驗證使用效果
執行以下命令,擷取基於策略的訪問憑證。
k exec -nvault vault-0 -- vault read alicloud/creds/policy-based Key Value --- ----- lease_id alicloud/creds/policy-based/TG1isE6uga94sRv60NK7**** lease_duration 768h lease_renewable true access_key ak1 secret_key sk1執行以下命令,擷取基於角色的訪問憑證(STS Token)。
k exec -nvault vault-0 -- vault read alicloud/creds/role-based Key Value --- ----- lease_id alicloud/creds/role-based/uJxVwNSnqzcni75kkf**** lease_duration 59m59s lease_renewable false access_key STS.NUM2e1BrC**** expiration 2023-05-09T04:16:17Z secret_key 3VmmRy**** security_token CAISiwJ1q****
角色許可權說明
如果一個角色使用不同的權限原則,就需要為角色指派不同的許可權點。
使用的權限原則 | 對應分配的許可權點 |
inline_policies | |
remote_policies |
|
role_arn |
樣本三:如何在應用Pod中通過RAM認證訪問Vault API
在K8s的應用Pod中,可通過寫代碼訪問Vault的服務,使用此方式對接阿里雲的身份認證、以及身份對應角色資訊的查詢。此應用代碼攜帶身份認證的資訊,通過訪問Vault的OpenAPI(Auth、Alicloud、Login)擷取該使用者身份對應的角色資訊,以及訪問Vault的Token。
使用此Token可對身份對應的角色進行操作,例如,查看角色詳情、角色列表、建立角色和刪除角色。關於更多操作,請參見AliCloud Auth Method (API)。
執行以下命令,為Vault開啟
Alicloud的Auth。更多OpenAPI資訊,請參見Enable Auth Method。k exec -nvault vault-0 -- vault auth enable alicloud執行以下命令,將對應的ARN寫入Vault。
k exec -nvault vault-0 -- vault write auth/alicloud/role/vaultTestRole arn='acs:ram::15261****:role/vaulttestrole'擷取調用GetCallerIdentity介面使用的URL和Header。具體操作,請參見vault-plugin。
應用代碼需先調用GetCallerIdentity介面,然後擷取調用該介面使用的URL和Header。關於GetCallerIdentity介面調用,請參見GetCallerIdentity OpenAPI。進入調用頁面,在左側搜尋方塊輸入GetCallerIdentity,在中間地區選取項目自身業務所在Region,然後在右側選擇SDK樣本,即可看到對應的代碼。
調用Login。其中
IDENTITY_REQUEST_URL_BASE_64為URL的Base64編碼,IDENTITY_REQUEST_HEADERS_BASE_64為Header的Base64編碼。更多資訊,請參見Login OpenAPI。應用程式通過上一步Login調用返回的
client_token欄位,調用Vault的Auth、Alicloud等OpenAPI,實現對應角色的訪問。
常見問題
Vault是第三方的維護的開源專案,當您遇到的問題非阿里雲或ACK官方提供支援的產品或組件,請前往Vault Communit開源專案社區諮詢處理。
如何修複Vault叢集異常?
如果Vault Pod重啟,Pod會進入0/1 Running狀態。您可以參考以下步驟對Vault叢集異常問題進行修複。
執行以下命令,查看Pod的狀態。
k exec -nvault vault-0 -- vault status預期輸出:
Key Value --- ----- Seal Type shamir Initialized true Sealed true Total Shares 5 Threshold 3 Unseal Progress 0/3 Unseal Nonce n/a Version 1.13.1 Build Date 2023-03-23T12:51:35Z Storage Type raft HA Enabled true command terminated with exit code 2預期輸出表明,Pod又處於
sealed狀態。需要重新進行解鎖操作。執行以下命令,解鎖Vault節點。
此處仍需選擇3個Unseal Key分別執行1次,共需執行3次。
k exec -nvault vault-0 -- vault operator unseal Zu6EdL****執行以下命令,通過root Token登入節點,查看Raft列表。
k exec -nvault vault-0 -- vault operator raft list-peers預期輸出:
Node Address State Voter ---- ------- ----- ----- 10285056-839a-f306-a301-5024934a794f vault-0.vault-internal:8201 follower true 71ffd98c-d6d4-a7b3-994c-9ce87f464486 vault-1.vault-internal:8201 leader true 1e9f37dc-b55b-fc46-8ca8-595428ad1d81 vault-2.vault-internal:8201 follower true預期輸出表明,
vault-0狀態變為follower正常狀態。
如何在ACK叢集中通過Service調用Vault?
Vault安裝完成後,將產生多個Service。您可以通過以下命令,查看具體Service資訊。
k get svc -n vault預期輸出:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
vault ClusterIP 172.16.193.219 <none> 8200/TCP,8201/TCP 47h
vault-active ClusterIP 172.16.177.54 <none> 8200/TCP,8201/TCP 47h
vault-internal ClusterIP None <none> 8200/TCP,8201/TCP 47h
vault-standby ClusterIP 172.16.29.54 <none> 8200/TCP,8201/TCP 47hvault和vault-internal為整個Vault叢集節點的負載平衡,其中,vault-internal為Headless的SVC。vault-active為Raft選出的leader節點。vault-standby為Raft中的follower節點。