動態

詳情 返回 返回

私密信息管理工具 Vault 快速入門 - 動態 詳情

什麼是 Vault

Vault 是一個基於身份的秘密和加密管理系統。秘密是您想要嚴格控制訪問的任何內容,例如 API 加密密鑰、密碼和證書。 Vault 提供由身份驗證和授權方法控制的加密服務。使用 Vault 的 UI、CLI 或 HTTP API,可以安全地存儲和管理、嚴格控制(限制)和審核對機密和其他敏感數據的訪問。

為什麼需要 Vault

  • 執行密碼輪換策略很痛苦
  • 掌握機密的員工離職後可能泄密或是惡意報復
  • 開發者不小心把機密信息隨着代碼上傳到公網的源碼倉庫造成泄密
  • 管理多個系統的機密非常麻煩
  • 需要將機密信息安全地加密後存儲,但又不想將密鑰暴露給應用程序,以防止應用程序被入侵後連帶密鑰一起泄漏

Vault 架構圖

Vault 只暴漏了存儲後端(Storage Backend) 和 API,其他部分都被保護起來了。Vault 並不信任後端存儲,存放的都是密文。

安裝

此處以 Mac 為例,其他平台參考官方文檔Vault 安裝嚮導

❯ brew tap hashicorp/tap
❯ brew install hashicorp/tap/vault

啓動 Vault(Dev 模式)

❯ vault server -dev
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 variables:

    $ export VAULT_ADDR='http://127.0.0.1:8200'

The unseal key and root token are displayed below in case you want to
seal/unseal the Vault or re-authenticate.

Unseal Key: QNqS6xZOnJKsbcz60PThJE2O070F2+9b7LLrGGgI7os=
Root Token: hvs.IKbh5pTGI0Qn08G5QNJb4jPY

Development mode should NOT be used in production installations!

查看服務狀態

❯ vault status
Key             Value
---             -----
Seal Type       shamir
Initialized     true
Sealed          false
Total Shares    1
Threshold       1
Version         1.12.1
Build Date      2022-10-27T12:32:05Z
Storage Type    inmem
Cluster Name    vault-cluster-c5c1f8a4
Cluster ID      60514532-959b-9540-ea21-5d9c968a21ba
HA Enabled      false

寫入第一個密碼

❯ vault write kv/infini value=infinilabs
Success! Data written to: kv/infini

如果報這個錯誤:

vault write kv/infini value=infinilabs
Error writing data to kv/cheng: Error making API request.

URL: PUT http://127.0.0.1:8200/v1/kv/cheng
Code: 404. Errors:

  • no handler for route 'kv/cheng'

是因為 kv 存儲沒有啓動(不同版本默認初始設置不同),執行:

❯ vault secrets enable kv

讀取一條數據

❯ vault read kv/infini
Key                 Value
---                 -----
refresh_interval    768h
value               labs

使用 Consul 作為數據存儲的 Backend

Vault 自身不存儲數據,需要提供存儲後台。 支持多種後台。

❯ brew tap hashicorp/tap
❯ brew install hashicorp/tap/consul

啓動 Consul

❯ consul agent -dev
==> Starting Consul agent...
              Version: '1.14.1'
           Build Date: '2022-11-21 16:56:07 +0000 UTC'
              Node ID: '6d9bcfc4-60cf-5d9b-c4fa-764127a94af6'
            Node name: 'ChengKai-MacBook.local'
           Datacenter: 'dc1' (Segment: '<all>')
               Server: true (Bootstrap: false)
          Client Addr: [127.0.0.1] (HTTP: 8500, HTTPS: -1, gRPC: 8502, gRPC-TLS: 8503, DNS: 8600)
         Cluster Addr: 127.0.0.1 (LAN: 8301, WAN: 8302)
    Gossip Encryption: false
     Auto-Encrypt-TLS: false
            HTTPS TLS: Verify Incoming: false, Verify Outgoing: false, Min Version: TLSv1_2
             gRPC TLS: Verify Incoming: false, Min Version: TLSv1_2
     Internal RPC TLS: Verify Incoming: false, Verify Outgoing: false (Verify Hostname: false), Min Version: TLSv1_2

==> Log data will now stream in as it occurs:

2022-11-30T16:34:52.604+0800 [WARN]  agent: Node name "ChengKai-MacBook.local" will not be discoverable via DNS due to invalid characters. Valid characters include all alpha-numerics and dashes.
2022-11-30T16:34:52.609+0800 [WARN]  agent.auto_config: Node name "ChengKai-MacBook.local" will not be discoverable via DNS due to invalid characters. Valid characters include all alpha-numerics and dashes.
2022-11-30T16:34:52.613+0800 [INFO]  agent.server.raft: initial configuration: index=1 servers="[{Suffrage:Voter ID:6d9bcfc4-60cf-5d9b-c4fa-764127a94af6 Address:127.0.0.1:8300}]"
2022-11-30T16:34:52.614+0800 [INFO]  agent.server.raft: entering follower state: follower="Node at 127.0.0.1:8300 [Follower]" leader-address= leader-id=

啓動 Vault(生產模式)

創建配置文件,使用剛剛啓動的 Consul 作為存儲後台。
注意: 這種方式啓動,為生產模式,需要手動配置和管理秘鑰。

storage "consul"{
  address = "127.0.0.1:8500"
  path    = "vault/"
}

listener "tcp"{
  address     = "127.0.0.1:8200"
  tls_disable = 1
}

執行命令,啓動

❯ vault server -config=config.hcl
WARNING! mlock is not supported on this system! An mlockall(2)-like syscall to
prevent memory from being swapped to disk is not supported on this system. For
better security, only run Vault on systems where this call is supported. If
you are running Vault in a Docker container, provide the IPC_LOCK cap to the
container.
==> Vault server configuration:

             Api Address: http://127.0.0.1:8200
                     Cgo: disabled
         Cluster Address: https://127.0.0.1:8201
              Go Version: go1.19.2
              Listener 1: tcp (addr: "127.0.0.1:8200", cluster address: "127.0.0.1:8201", max_request_duration: "1m30s", max_request_size: "33554432", tls: "disabled")
               Log Level: info
                   Mlock: supported: false, enabled: false
           Recovery Mode: false
                 Storage: consul (HA available)
                 Version: Vault v1.12.1, built 2022-10-27T12:32:05Z
             Version Sha: e34f8a14fb7a88af4640b09f3ddbb5646b946d9c

==> Vault server started! Log data will stream in below:

2022-11-30T16:42:59.995+0800 [INFO]  proxy environment: http_proxy="" https_proxy="" no_proxy=""
2022-11-30T16:43:00.006+0800 [WARN]  no `api_addr` value specified in config or in VAULT_API_ADDR; falling back to detection if possible, but this value should be manually set

注意: 此時雖然服務啓動了,但是 Vault 處於封印狀態(sealed), 不可用。
此時我們執行操作,會看到如下提示:

❯ vault read kv/cheng
Error reading kv/cheng: Error making API request.

URL: GET http://127.0.0.1:8200/v1/kv/cheng
Code: 503. Errors:

* Vault is sealed

上面 Dev 模式啓動的 Vault 實際上幫助我們自動地把創建主密鑰、解封的步驟都完成了。生產模式,則需要手動配置後續步驟。

補充點小知識

  • Vault 保存在 Backend 中的數據都是加密的
  • Vault 密鑰稱為 Master Key 主密鑰,Vault 默認使用 Shamir 算法,把主密鑰切分成 M 份,管理員必須至少提供其中的 N 份才能還原出主密鑰(這裏的 M 和 N 都是可配置的,M>=N)理想狀態下,我們必須把這 M 份密鑰分配給公司內 M 個不同的人,只有在獲取其中 N 個人的授權後,Vault 才可以成功解密主密鑰。

Vault 初始化(生產模式)

注意看,接下來的步驟,會生成 5 個秘鑰,一個 Root 用户的 Token。真實場景下,這 5 個秘鑰會分配給 5 個不同的人員管理。 至少正確輸入 3 個秘鑰,才能解封 Vault。

熱知識: Vault 每次啓動/重啓,都會進入封印狀態,未解封時,幾乎無法執行任何操作。
> vault operator init
Unseal Key 1: IDcHr5kT7hhgYKiDxF6Qlp2g11UVXNu+f5VX51+3jpeD
Unseal Key 2: dfjqn++KcqLDIDnBcE8B0fIvicI7T9TQCxBSI7b1oE12
Unseal Key 3: DaFtgnYsm0rTQcPpLTPaDTNW338BHhyhezct+ySTT45L
Unseal Key 4: Z1vmlLm/KBydeLrmVf9ELqlJoaUgwzNvzx6ddXttc4Nk
Unseal Key 5: x2lIwJiCz3lNqzBPzkryrnatfZT9mahj3yfW4qxT3eMZ

Initial Root Token: s.o7NjzR6qXEvJEwPYpmVFOt4P

Vault initialized with 5 key shares and a key threshold of 3. Please securely
distribute the key shares printed above. When the Vault is re-sealed,
restarted, or stopped, you must supply at least 3 of these keys to unseal it
before it can start servicing requests.

Vault does not store the generated master key. Without at least 3 keys to
reconstruct the master key, Vault will remain permanently sealed!

It is possible to generate new unseal keys, provided you have a quorum of
existing unseal keys shares. See "vault operator rekey" for more information.

Vault 默認訪問 https 的地址,所以如果執行初始化報如下錯誤:

Error authenticating: error looking up token: Get "https://127.0.0.1:8200/v1/auth/token/lookup-self": http: server gave HTTP response to HTTPS client

設置一下 Vault 地址即可,執行:
export VAULT_ADDR='http://127.0.0.1:8200'

查看 Vault 狀態

此時 Vault 處於封印狀態(Sealed 為 true)

❯ 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.9.2
Storage Type       consul
HA Enabled         true

解封 Vault

使用需要 vault operator unseal 命令來執行解封。至少需要 3 個秘鑰來解封。

❯ vault operator unseal IDcHr5kT7hhgYKiDxF6Qlp2g11UVXNu+f5VX51+3jpeD
Key                Value
---                -----
Seal Type          shamir
Initialized        true
Sealed             true
Total Shares       5
Threshold          3
Unseal Progress    1/3
Unseal Nonce       9eeaaa92-d673-51d3-b993-d3affe68b5a3
Version            1.9.2
Storage Type       consul
HA Enabled         true

注意: 每次輸入一個秘鑰,會看到如上提示"Unseal Progress 1/3"。 但是,這裏僅僅表示已經輸入多少個秘鑰,並不代表輸入的秘鑰都是正確的!!

如何使用 Vault 保存秘密

進入下一步之前,先來看看 Vault 提供了哪些措施,用來保護我們的秘密?

  • 秘鑰的保護機制: 秘鑰被拆分成 5 份,至少正確輸入 3 個才能解封。
  • 策略控制(權限控制): 可以針對每個 Path 設置策略。
  • 有效期: Vault 生成的每個令牌(Token)都有有效期。

開始前,我們先寫入 2 條測試數據:

❯ vault write kv/infini value=infinilabs
Success! Data written to: kv/infini

❯ vault write kv/ck value=chengkai
Success! Data written to: kv/ck

熱知識:
"kv/infini" 是一個 Path(路徑), 可以簡單理解為數據庫中的一個表。並不是 kv 數據庫 當中的 key。你可以試試這樣存數據並讀取:

❯ vault write kv/infini ck=chengkai c=cheng k=kai
Success! Data written to: kv/infini

❯ vault read kv/infini
Key                 Value
---                 -----
refresh_interval    768h
c                   cheng
ck                  chengkai
k                   kai

制定策略

新建策略文件

輸入以下內容

path "kv/infini" {
     capabilities = ["read"]
}

解釋: 以上策略,是指在 infini 這個路徑(path)下,具有隻讀權限。

創建策略

先登錄已經解封的 Vault(使用初始化生成的 root token 登錄)

❯ vault login s.o7NjzR6qXEvJEwPYpmVFOt4P
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                s.o7NjzR6qXEvJEwPYpmVFOt4P
token_accessor       tKZyxkkFvrmhQeTsoDOogcoV
token_duration       ∞
token_renewable      false
token_policies       ["root"]
identity_policies    []
policies             ["root"]
❯ vault policy write infini-readonly policy.hcl
Success! Uploaded policy: infini-readonly

"infini-readonly" 是策略的名稱,這個可以自定義

生成 Token 並指定策略

生成對"kv/infini"具有隻讀權限的 Token, 執行:

❯ vault token create -policy="infini-readonly"
Key                  Value
---                  -----
token                s.bHzsfREs9MGirYO8yZ2TbAzq
token_accessor       nPuAQzNTn28vMMUKcDu0mN8g
token_duration       768h
token_renewable      true
token_policies       ["infini-readonly" "default"]
identity_policies    []
policies             ["infini-readonly" "default"]

此處生成了新的 Token: s.bHzsfREs9MGirYO8yZ2TbAzq, 有效期 768 小時(別拿計算器了,我算過了,32 天)

使用新生成的 Token 登錄(別找退出操作了,直接再執行 login 即可):

❯ vault login s.bHzsfREs9MGirYO8yZ2TbAzq
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                s.bHzsfREs9MGirYO8yZ2TbAzq
token_accessor       nPuAQzNTn28vMMUKcDu0mN8g
token_duration       767h56m19s
token_renewable      true
token_policies       ["infini-readonly" "default"]
identity_policies    []
policies             ["infini-readonly" "default"]

驗證新生成的 Token

嘗試讀 kv/infini 的秘密:

❯ vault read kv/infini
Key                 Value
---                 -----
refresh_interval    768h
value               infinilabs

Wow!成功讀取!

試試寫入操作

❯ vault write kv/infini value=c1
Error writing data to kv/cheng: Error making API request.

URL: PUT http://127.0.0.1:8200/v1/kv/infini
Code: 403. Errors:

* 1 error occurred:
    * permission denied

有個疑問,你説當前這個 Token,可以讀取 kv/ck 的秘密嗎?

❯ vault read kv/ck
Error reading kv/ck: Error making API request.

URL: GET http://127.0.0.1:8200/v1/kv/ck
Code: 403. Errors:

* 1 error occurred:
    * permission denied

啊歐! 不行~

OK, 到這裏了,簡單的對 Vault 做了個入門。 Vault 的功能點還有很多,去看看下面的文檔吧~~

參考文檔

  • [1]: Vault 官方文檔
  • [2]: Vault 教程(中文)
  • [3]: How To Securely Manage Secrets with HashiCorp Vault on Ubuntu 20.04
user avatar zhoumo_62382eba4b454 頭像 greasql 頭像 smalike 頭像 zhaoqianglaoshi 頭像 doge_king 頭像 zhaodaoweb 頭像 karuru 頭像 changlina 頭像 wdllmh 頭像
點贊 9 用戶, 點贊了這篇動態!
點贊

Add a new 評論

Some HTML is okay.