如果你希望追蹤最新的草稿,請見鐵人賽2023
本 workshop 也接受網友的許願清單,如果有興趣的題目可於第一篇底下留言,筆者會盡力實現,但不做任何保證
整篇 Workshop 會使用的範例與原始碼,放在 Github Repository: vault-playground
在 Vault 中,策略(Policies)控制著使用者可以訪問的資源。在上一篇身份驗證中,你已經學到了身份驗證方法(authentication method)。而這一節是關於授權(Authorization),也就是合法的用戶登入後,應該能夠取得怎樣的權限。
在身份驗證方面,Vault 提供了多種啟用和使用的選項或方法。Vault 在授權和 policy 方面也使用相同的設計。所有身份驗證方法都將登入者的身份 map 回與 Vault 配置的核心 policy。
在 vault 官方網站文件中,Hashicorp 官方準備了 https://instruqt.com/的 session lab
筆者個人覺得 interactive lab 的 browser tab 很難用,也不喜歡 Terminal session 連 remote VM 的延遲,以下內容還是會使用 local dev Server 說明。
觀眾們可以自己斟酌使用。
策略(Policies)是以HCL撰寫的,但也兼容JSON格式。以下是一個範例策略:
# Dev servers have version 2 of KV secrets engine mounted by default, so will
# need these paths to grant permissions:
path "secret/data/*" {
capabilities = ["create", "update"]
}
path "secret/data/foo" {
capabilities = ["read"]
}
這個範例 policy 授予了對 KV v2 秘密管理(secrets engine)的資源的能力。如果你對於與這個秘密管理引擎相關的路徑不熟悉,可以查閱該秘密管理引擎文件中的 ACL 規則部分。
根據這個 policy,使用者可以對 secret/data/
中的任何秘密進行寫入操作,但對於 secret/data/foo
的存取僅允許讀取。policy 的預設行為是 Deny,因此不允許對未指定路徑的資源進行任何存取。
policy 格式使用 prefix 匹配系統來確定對 API 路徑的訪問控制。使用最具體的已定義策略,即精確匹配或最長 prefix 匹配。也就是存取 secret/data/foo
路徑符合上面兩條規則,但是由於第二條規則的路徑 match 最長最精確,所以最終拿到的權限是 "read"
由於 Vault 中的一切都必須通過 API 進行訪問,這使得對 Vault 的每個方面都有嚴格的控制,包括啟用秘密管理引擎、啟用身份驗證方法、身份驗證,以及存取秘密等。
有一些內建的策略無法被移除。例如,root policy 和 default policy 是必需的策略,無法被刪除。
步驟在前幾篇已經出現過數次,這邊就簡單帶過
vault server -dev -dev-no-store-token
export VAULT_ADDR='http://127.0.0.1:8200'
unset VAULT_TOKEN
vault login
你可以用下列指令列出預設的 policy
vault policy list
output
default
root
可以用以下指令讀取 default policy 的內容
vault policy read default
output 回傳許多條 policy rule,主要是給予 token 基本的操作權限
# Allow tokens to look up their own properties
path "auth/token/lookup-self" {
capabilities = ["read"]
}
# Allow tokens to renew themselves
path "auth/token/renew-self" {
capabilities = ["update"]
}
# Allow tokens to revoke themselves
path "auth/token/revoke-self" {
capabilities = ["update"]
}
...
熟悉 default policy 內容後,可以斟酌使用。或是選擇從頭編寫自己的 policy。
要撰寫 policy ,使用 vault policy write 指令。請查閱該指令的幫助文件以進一步了解用法。
vault policy write -h
Usage: vault policy write [options] NAME PATH
Uploads a policy with name NAME from the contents of a local file PATH or
stdin. If PATH is "-", the policy is read from stdin. Otherwise, it is
loaded from the file at the given path on the local disk.
# 使用 vault policy write 指令,可以從本地文件 PATH 或標準輸入(stdin)的內容上傳一個名為 NAME 的策略。如果 PATH 是 "-",則策略將從 stdin 讀取。否則,它將從本地 disk 上給定路徑的文件中載入。
Upload a policy named "my-policy" from "/tmp/policy.hcl" on the local disk:
$ vault policy write my-policy /tmp/policy.hcl
Upload a policy from stdin:
$ cat my-policy.hcl | vault policy write my-policy -
使用以下指令創建名為 "my-policy" 的 policy,並將其內容來自 stdin(標準輸入)
vault policy write my-policy - << EOF
# Dev servers have version 2 of KV secrets engine mounted by default, so will
# need these paths to grant permissions:
path "secret/data/*" {
capabilities = ["create", "update"]
}
path "secret/data/foo" {
capabilities = ["read"]
}
EOF
output
Success! Uploaded policy: my-policy
使用下列指令列出 policy
vault policy list
output
default
my-policy
root
讀取 my-policy 的內容
vault policy read my-policy
output
# Dev servers have version 2 of KV secrets engine mounted by default, so will
# need these paths to grant permissions:
path "secret/data/*" {
capabilities = ["create", "update"]
}
path "secret/data/foo" {
capabilities = ["read"]
}
你所建立的 policy ,提供對 KV-V2 秘密引擎所定義的秘密進行管理。policy 被附加到 Vault 直接生成的 otoken,或透過其各種授權方法生成的 token 上。
創建一個 token ,添加 my-policy。-field flag 設定只回傳部分 key-vault data,而不是傳整個 metadata table。-policy 設定連結 token 的 policy。
vault token create -field token -policy=my-policy
hvs.CAESIIDh...UxbUU
為了簡化,本內容使用 dev 模式伺服器,直接從 token 授權方法創建 token 。請記住,在大多數 production 環境部署中,token 將由已啟用的授權方法(ex. github auth method)創建。
可以使用 token login
vault login
output 回傳登入資訊,以及連結 token 的 policy,policy 包含 default 與 my-policy
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.CAESIIDh...UxbUU
token_accessor vY3aLwMSezlxeOn7YwcjxuhZ
token_duration 767h56m52s
token_renewable true
token_policies ["default" "my-policy"]
identity_policies []
policies ["default" "my-policy"]
你可以執行 vault token lookup,查找目前 token 的完整資訊
vault token lookup
output
Key Value
--- -----
accessor vY3aLwMSezlxeOn7YwcjxuhZ
creation_time 1694917062
creation_ttl 768h
display_name token
entity_id n/a
expire_time 2023-10-19T10:17:42.723364+08:00
explicit_max_ttl 0s
id hvs.CAESIIDh...UxbUU
issue_time 2023-09-17T10:17:42.723365+08:00
meta <nil>
num_uses 0
orphan false
path auth/token/create
policies [default my-policy]
renewable true
ttl 767h55m45s
type service
這個policy 啟用了 secret/ 秘密引擎內每個路徑的創建和更新功能,除了一個例外路徑 secret/data/foo 僅允許 read。
寫入資料到 secret/data/creds
vault kv put -mount=secret creds password="my-long-password"
output 回傳成功資訊,秘密已成功創建。
== Secret Path ==
secret/data/creds
======= Metadata =======
Key Value
--- -----
created_time 2023-09-17T02:26:44.179748Z
custom_metadata <nil>
deletion_time n/a
destroyed false
version 1
該政策僅啟用了對 secret/data/foo 路徑的讀取功能。嘗試向此路徑寫入將導致"權限拒絕"錯誤。請嘗試寫入 secret/data/foo 路徑。
vault kv put -mount=secret foo robot=beepboop
output,顯示權限錯誤。
Error writing data to secret/data/foo: Error making API request.
URL: PUT http://127.0.0.1:8200/v1/secret/data/foo
Code: 403. Errors:
* 1 error occurred:
* permission denied
此 policy 定義了一組有限的路徑和功能。如果沒有對 sys 的訪問權限,則系統相關玄線,像 vault policy list 或 vault secrets list 這樣的命令將無法運作。
當你使用 vault kv CLI 命令訪問 KV v2 秘密引擎時,我們建議使用 -mount flag 語法,來引用 KV v2 秘密引擎的路徑。
vault kv get -mount=secret foo
你也可以使用兼容 KV v1 風格的路徑 prefix 語法,在某個範圍內上是等效的,系統將自動附加 /data 到秘密路徑,可能會引起混淆。
vault kv get secret/foo
Vault 本身只有唯一的 policy 授權管理機構,不同於身份驗證,你可以啟用多個身份驗證方法。
你可以配置身份驗證方法,以自動分配一組 policy,給使用某些身份驗證方法創建的 token 。這樣做的方式取決於相關的身份驗證方法,但通常涉及將 role 映射到 policy ,或者將 identity 或 group 映射到 policy。
例如:當設定 github auth method 的 role 時,你可以使用 token policies 參數來實現這一點。
我們這邊嘗試建立另外一個 auth method,AppRole,順便在整理一次 vault -> auth method -> policy 的關係
在以下步驟中,使用權限更高的 root token 進行操作與登入
vault login
output
Token (will be hidden):
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.uCGr6...749AI
token_accessor SlAe0epU6CLngp2iclB5WN2A
token_duration ∞
token_renewable false
token_policies ["root"]
identity_policies []
policies ["root"]
啟用 approle auth method
vault auth enable approle
output
Success! Enabled approle auth method at: approle/
vault server log
2023-09-17T10:44:26.460+0800 [INFO] core: enabled credential backend: path=approle/ type=approle version=""
我們已經啟用 approle 這個 auth method,接下來要設定名為 "my-role" 的 AppRole role,配置一些基本的token 設定,並將先前定義的 "my-policy" policy,附加到所有通過該 role 創建的 token。
你可以使用下列指令,在 auth/approle/role/ 下新增 my-role,path 也代表 approle / role / my-role 的階層關係
vault write auth/approle/role/my-role \
secret_id_ttl=10m \
token_num_uses=10 \
token_ttl=20m \
token_max_ttl=30m \
secret_id_num_uses=40 \
token_policies=my-policy
output
Success! Data written to: auth/approle/role/my-role
你可以通過使用 auth 方法來驗證這個 AppRole role 是否附加了policy。
要使用 AppRole 進行身份驗證,首先需要獲取角色ID
首先先讀取目前 approle/role/my-role 的設定
v read auth/approle/role/my-role
Key Value
--- -----
bind_secret_id true
local_secret_ids false
secret_id_bound_cidrs <nil>
secret_id_num_uses 40
secret_id_ttl 10m
token_bound_cidrs []
token_explicit_max_ttl 0s
token_max_ttl 30m
token_no_default_policy false
token_num_uses 10
token_period 0s
token_policies [my-policy]
token_ttl 20m
token_type default
然後讀取 my-role 的 role-id
vault read auth/approle/role/my-role/role-id
output
Key Value
--- -----
role_id 600dce48-244c-094e-aeae-cb819ec7f5dd
接下來,獲取一個秘密ID(它類似於應用程式用於 AppRole 身份驗證的密碼),由於我們這個示範並不提供額外參數值,這先需要使用 -f | -force flag,強迫 vault 寫入一個沒有 value 的資料到 auth/approle/role/my-role/secret-id endpoint
vault write -f auth/approle/role/my-role/secret-id
可以想像是向 API server 打 POST my-role/secret-id,向 approle 註冊一個 app,server 則回傳一組 id,以辨識這個 app。
Key Value
--- -----
secret_id d80db935-9792-faf7-306d-93a2f0c3a18f
secret_id_accessor 32451384-f985-a387-175b-67140225856f
secret_id_num_uses 40
secret_id_ttl 10m
最後進行 login 取得 token,這裡使用 vault write 進行 AppRole 身份驗證,指定 role path並使用相應的選項傳遞role id和secret id
export ROLE_ID=600dce48-244c-094e-aeae-cb819ec7f5dd
export SECRET_ID=d80db935-9792-faf7-306d-93a2f0c3a18f
vault write auth/approle/login \
role_id=$ROLE_ID \
secret_id=$SECRET_ID
output,取得合法的 token,並且具有我們為 approle/my-role 配置的 my-policy 權限
Key Value
--- -----
token hvs.CAESIB9gD3aupV5X06IRIWMEvhL4QeBtizO20i2Hh2YderxpGh4KHGh2cy5BWVVWVDVFUVI3dkw5VUFUbmdoZmpnUFA
token_accessor QGrKxnHH4e9SVLqhpaqgYsCZ
token_duration 20m
token_renewable true
token_policies ["default" "my-policy"]
identity_policies []
policies ["default" "my-policy"]
token_meta_role_name my-role
實務中,這個 secret_id
會設置在 application 上,讓 application 具有合法存取 vault 的權限
我們可以重複使用設定好的 policy,綁定到 auth method 上,policy 對 auth method 是多對多的,這邊透過我們上篇 github auth method 來對照一下,解釋 auth method 與 role / policy 的關係
chechia-net 是一個組織
as a admin,我希望藉由 github auth method,讓有 github 權限的工程師,可以存取 vault
於是,透過 github auth method,自動配置 vault 權限給 chechia-net github org 下的使用者
vault auth enable -path=github-chechia github
vault write auth/github-chechia/config organization=chechia-net
as a github user,我希望藉由 github auth method,直接登入 vault,不用註冊額外的帳號
vault login -method=github -path=github-chechia
換成 approle 也是相同道理
as a admin,我希望我的 application 能夠有辦法存取 vault
vault auth enable -path=approle-golang-server approle
這個 application 可能有複數不同種類工作,所以也希望能夠配置不同的 role,給予不同的 policy 權限
更接近實務的例子,底下可能是常見的 role 用途
身為 admin,你可以使用以下命令,在 approle-golang-server 中產生一個 default role
vault write auth/approle-golang-server/role/default \
secret_id_ttl=10m \
token_num_uses=10 \
token_ttl=20m \
token_max_ttl=30m \
secret_id_num_uses=40 \
token_policies=default
增加一個 my-role
vault write auth/approle-golang-server/role/my-role \
secret_id_ttl=10m \
token_num_uses=10 \
token_ttl=20m \
token_max_ttl=30m \
secret_id_num_uses=40 \
token_policies=default,my-policy
列出在 approle-golang-server 中啟用的 role
vault list auth/approle-golang-server/role/
output
Keys
----
default
my-role
admin 配置完 role 後,記得讀取 role-id,並將 role-id 配置到 application 上
auth/approle-golang-server/role/*/role-id
,讓 application 透過 vault API 自動取得 role-idvault read auth/approle-golang-server/role/default/role-id
vault read auth/approle-golang-server/role/my-role/role-id
output
Key Value
--- -----
role_id f0340d97-a97d-85f9-30d5-65a2058baf11
Key Value
--- -----
role_id c1f3cd3e-8f0a-8b1f-91f7-a3a310b9755f
上面是 admin 需要配置的內容
現在角色換成 application,application 上線了。application 依照情境,選擇要使用那個 role,去取得 secret-id
注意,這個 role/database 與 policy/database 上面都沒有配置,請讀者自己練習,配置一個 placeholder 空的權限,或是發揮創意也可以
vault write -f auth/approle-golang-server/role/my-role/secret-id
output,vault 回覆一組短時效的 secret-id,ttl=10 min
Key Value
--- -----
secret_id ad70d84b-56a5-eec2-0a95-6aa7f2cfceef
secret_id_accessor 76a5b993-a139-9837-5990-b6adc483542a
secret_id_num_uses 40
secret_id_ttl 10m
application 可以使用 role-id + secret-id,去取得 token
vault write auth/approle-golang-server/login \
role_id=$ROLE_ID \
secret_id=$SECRET_ID
output
Key Value
--- -----
token hvs.CA...ZXRVc
token_accessor zjBhj70A6ed72zksuooxCpYt
token_duration 20m
token_renewable true
token_policies ["default" "database"]
identity_policies []
policies ["default" "database"]
token_meta_role_name database
本段部分內容使用 chatGPT-3.5 翻譯
https://developer.hashicorp.com/vault/tutorials/getting-started/getting-started-policies
https://developer.hashicorp.com/vault/docs/concepts/policies
內容,並由筆者人工校驗
base context
我希望你能充當一名繁體中文翻譯,拼寫修正者和改進者。我將用英文與程式語言與你對話,你將翻譯它,並以已糾正且改進的版本回答,以繁體中文表達。我希望你能用更美麗和優雅、高級的繁體中文詞語和句子替換我簡化的詞語和句子。保持意義不變。我只希望你回答糾正和改進,不要寫解釋。
很重要:不要使用敬語,翻譯結果中若出現"您",請用"你"取代"您"。
result correction
部分英文內容為專有名詞,產生的繁體中文翻譯結果中,這些名詞維持英文,不需要翻譯成中文:key,value,certificate,token,policy,policy rule,path,path-based,key rolling,audit,audit trail,plain text,key value,Consul,S3 bucket,Leasing,Renewal,binary,prefix,instance,metadata。
修正下列翻譯:將 "數據" 改為 "資料",將 "數據庫" 改為 "資料庫",將 "數據" 改為 "資料",將 "訪問" 改為 "存取",將 "源代碼" 改為 "原始碼",將 "信息" 改為 "資訊",將 "命令" 改為 "指令",將 "禁用" 改為 "停用",將 "默認" 改為 "預設"。