HashiCorp Vault 開源密碼管理平台 Linux 安裝示範

使用下面的指令安裝 Vault:
    
wget -O - https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg

echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list

sudo apt update && sudo apt install vault
    

確認安裝完成:
    
vault --version
    

範例輸出:
    
vault --version
Vault v1.18.3 (7ae4eca5403bf574f142cd8f987b8d83bafcd1de), built 2024-12-16T14:00:53Z
    

設定開機自動啟動:
    
sudo systemctl enable vault
    

啟動 Vault 服務:
    
sudo systemctl start vault
    

確認 Vault 執行狀態:
    
sudo systemctl status vault
    

範例輸出:
    
sudo systemctl status vault
● vault.service - "HashiCorp Vault - A tool for managing secrets"
     Loaded: loaded (/usr/lib/systemd/system/vault.service; enabled; preset: enabled)
     Active: active (running) since Tue 2025-01-28 03:01:39 UTC; 3s ago
       Docs: https://developer.hashicorp.com/vault/docs
   Main PID: 7414 (vault)
      Tasks: 7 (limit: 2276)
     Memory: 102.0M (peak: 102.4M)
        CPU: 437ms
     CGroup: /system.slice/vault.service
             └─7414 /usr/bin/vault server -config=/etc/vault.d/vault.hcl

Jan 28 03:01:39 vault vault[7414]:                  Storage: file
Jan 28 03:01:39 vault vault[7414]:                  Version: Vault v1.18.3, built 2024-12-16T14:00:53Z
Jan 28 03:01:39 vault vault[7414]:              Version Sha: 7ae4eca5403bf574f142cd8f987b8d83bafcd1de
Jan 28 03:01:39 vault vault[7414]: ==> Vault server started! Log data will stream in below:
Jan 28 03:01:39 vault vault[7414]: 2025-01-28T03:01:39.430Z [INFO]  proxy environment: http_proxy="" https_proxy="" no_proxy=""
Jan 28 03:01:39 vault vault[7414]: 2025-01-28T03:01:39.431Z [INFO]  incrementing seal generation: generation=1
Jan 28 03:01:39 vault vault[7414]: 2025-01-28T03:01:39.431Z [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
Jan 28 03:01:39 vault vault[7414]: 2025-01-28T03:01:39.661Z [INFO]  core: Initializing version history cache for core
Jan 28 03:01:39 vault vault[7414]: 2025-01-28T03:01:39.661Z [INFO]  events: Starting event system
Jan 28 03:01:39 vault systemd[1]: Started vault.service - "HashiCorp Vault - A tool for managing secrets".
    

初始化 Vault:
    
vault operator init
    

會出現錯誤,說明憑證中缺少 IP Subject Alternative Name (SAN) 屬性,需要綁定一個 IP 或是網域:
    
vault operator init
WARNING! VAULT_ADDR and -address unset. Defaulting to https://127.0.0.1:8200.
Get "https://127.0.0.1:8200/v1/sys/seal-status": tls: failed to verify certificate: x509: cannot validate certificate for 127.0.0.1 because it doesn't contain any IP SANs
    

我們先查看 Vault 的設定檔:
    
cat /etc/vault.d/vault.hcl
    

設定檔內容:
    
# Copyright (c) HashiCorp, Inc.
# SPDX-License-Identifier: BUSL-1.1

# Full configuration options can be found at https://developer.hashicorp.com/vault/docs/configuration

ui = true

#mlock = true
#disable_mlock = true

storage "file" {
  path = "/opt/vault/data"
}

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

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

# HTTPS listener
listener "tcp" {
  address       = "0.0.0.0:8200"
  tls_cert_file = "/opt/vault/tls/tls.crt"
  tls_key_file  = "/opt/vault/tls/tls.key"
}

# Enterprise license_path
# This will be required for enterprise as of v1.8
#license_path = "/etc/vault.d/vault.hclic"

# Example AWS KMS auto unseal
#seal "awskms" {
#  region = "us-east-1"
#  kms_key_id = "REPLACE-ME"
#}

# Example HSM auto unseal
#seal "pkcs11" {
#  lib            = "/usr/vault/lib/libCryptoki2_64.so"
#  slot           = "0"
#  pin            = "AAAA-BBBB-CCCC-DDDD"
#  key_label      = "vault-hsm-key"
#  hmac_key_label = "vault-hsm-hmac-key"
#}
    

我們會發現已經有指定 HTTPS 憑證,憑證位置在 /opt/vault/tls/tls.crt 和 /opt/vault/tls/tls.key ,等一下產生完憑證後覆蓋這兩個檔案即可。

確認 IP:

ip -4 addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    altname enp2s1
    inet 192.168.0.60/24 brd 192.168.0.255 scope global ens33
       valid_lft forever preferred_lft forever
    

可以看到目前筆者示範的這台主機 IP 為 192.168.0.60 ,等一下在產生憑證時就會在憑證中設定 IP 為 192.168.0.60,這樣才可以從其他裝置中連線到這台主機。

產生憑證(記得替換 IP):
    
sudo openssl req -new -x509 -days 365 -keyout /opt/vault/tls/tls.key -out /opt/vault/tls/tls.crt -subj "/CN=192.168.0.60" -addext "subjectAltName=IP:192.168.0.60" -nodes
    

範例輸出:

sudo openssl req -new -x509 -days 365 -keyout /opt/vault/tls/tls.key -out /opt/vault/tls/tls.crt -subj "/CN=192.168.0.60" -addext "subjectAltName=IP:192.168.0.60" -nodes
.........+...+..+.+......+.......................+...+...+....+..+....+......+......+..+...+....+..............+....+...+...............+..+++++++++++++++...+...+..+......+.......+...+..............+............+....+......+........+.+.....+......+...+......+.+..............+.+........+...+....+...+...+...............+..+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
......+.....+++++++++++++++++..+...............+...+..........+.....+....+......+.........+.....+.+..+.........................+...+.+..........+...+...+.....+......+...+..........+......+......+...+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-----
    

註:也可以綁定網域,範例(假設綁定在 vault.local 網域):

sudo openssl req -new -x509 -days 365 -keyout /opt/vault/tls/tls.key -out /opt/vault/tls/tls.crt -subj "/CN=vault.local" -addext "subjectAltName=DNS:vault.local" -nodes
    

給予憑證權限:
    
sudo chmod 644 /opt/vault/tls/tls.crt
sudo chmod 600 /opt/vault/tls/tls.key
    

驗證憑證,確定包含 SAN 屬性:

sudo openssl x509 -in /opt/vault/tls/tls.crt -text
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            0a:1a:0d:b7:1e:76:9a:e6:ed:d3:fe:8f:00:ff:b4:5f:00:00:00:00
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: CN = 192.168.0.60
        Validity
            Not Before: Jan 28 03:13:55 2025 GMT
            Not After : Jan 28 03:13:55 2026 GMT
        Subject: CN = 192.168.0.60
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:9e:a3:eb:0c:49:94:c4:e8:29:5a:6f:84:c4:42:
                    fb:29:62:b5:4c:09:29:ba:86:94:85:96:73:eb:15:
                    03:87:aa:1f:14:5d:43:be:8e:76:9f:37:d5:17:f3:
                    43:bd:bb:e8:07:69:9a:6e:4a:92:fa:f5:16:3f:86:
                    56:42:6a:97:bc:d6:8d:ec:66:97:7a:2d:68:e3:77:
                    7a:33:35:59:cf:7b:39:7b:19:19:50:c8:66:73:da:
                    1a:c1
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Subject Key Identifier:
                12:EF:F7:88:65:20:A1:E5:49:3A:5D:DF:74:CB:C6:FE:00:00:00:00
            X509v3 Authority Key Identifier:
                12:EF:F7:88:65:20:A1:E5:49:3A:5D:DF:74:CB:C6:FE:00:00:00:00
            X509v3 Basic Constraints: critical
                CA:TRUE
            X509v3 Subject Alternative Name:
                IP Address:192.168.0.60
    Signature Algorithm: sha256WithRSAEncryption
    Signature Value:
        1a:75:8d:7f:8e:78:b5:e5:46:ab:51:12:99:22:5a:15:72:71:
        4f:4e:cc:6c:24:3d:01:7c:2b:40:4b:14:bd:0a:5e:49:35:45:
        f3:53:24:02:c1:87:4c:9e:6d:f6:87:8f:6c:89:97:67:9c:97:
        f5:fd:58:92:81:f5:38:9a:f4:ce:48:b4:35:89:6f:68:5a:e0:
        e1:80:f4:e9:a8:75:b6:ee:b7:0d:75:e2:6c:31:0c:48:14:01:
        66:3f:c2:a8
-----BEGIN CERTIFICATE-----
MIIDIDCCAgigAwIBAgIUChoNtx52mubt0/6PAP+0XyEY+NkwDQYJKoZIhvcNAQEL
BQAwFzEVMBMGA1UEAwwMMTkyLjE2OC4wLjYwMB4XDTI1MDEyODAzMTM1NVoXDTI2
D5qnbBhcuU375CDv7ZqUOH4dKx5eajeYoSkFjN0CPHjxX71n6UPiQw/XJWVIk9m7
DtwyOvG4F9dd4scs9VPA4X8WblBmgTQ7xjFzK2nhaEZsbEqL7bygXWCOkLf1/ViS
gfU4mvTOSLQ1iW9oWuDhgPTpqHW27rcNdeJsMQxIFAFmP8Ko
-----END CERTIFICATE-----
    

預設是使用 127.0.0.1:8200 ,我們在產生憑證時調整為 192.168.0.60:8200,需要去設定檔中增加 api_addr 參數。

修改設定檔:
    
sudo vi /etc/vault.d/vault.hcl
    

增加以下設定值(記得替換 IP):
    
api_addr = "https://192.168.0.60:8200"
    

重新啟動 Vault:
    
sudo systemctl restart vault
    

初始化 Vault(記得替換 IP):
    
vault operator init -address "https://192.168.0.60:8200"
    

範例輸出:
    
vault operator init -address "https://192.168.0.60:8200"
Get "https://192.168.0.60:8200/v1/sys/seal-status": tls: failed to verify certificate: x509: certificate signed by unknown authority
    

錯誤訊息為憑證不受信任,這是因為是自簽憑證,是不受信任的簽發單位。

將憑證複製到系統信任的憑證位置來手動讓憑證變為受信任的憑證:
    
sudo cp /opt/vault/tls/tls.crt /usr/local/share/ca-certificates/vault.crt
    

更新受信任的憑證清單
    
sudo update-ca-certificates
    

再次執行:
    
vault operator init -address "https://192.168.0.60:8200"
Unseal Key 1: /Ym5vTW8bfTTW1OWfHVDxJFvgP1sOg2K8K9ZOTc/nVV8
Unseal Key 2: 1MNKlA+ZSqsSHGGNNqSBtDiEXpOIYgGoYOfrrn/0MU00
Unseal Key 3: fQH3kVZP68QTZSEYGFsjdWbaYVxBbfXNCqwh3qtjwc25
Unseal Key 4: LpV7oyyGoZdSed73WAgV4f51/kWyaRoGxtN76POik/vs
Unseal Key 5: v+BKmlVe8UCSs6t58rnwScVpiIkpwiFc4ILaoNsy6ytc

Initial Root Token: hvs.old6nyDsbvGOoUHjeA40M8LM

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 root key. Without at least 3 keys to
reconstruct the root 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.
    

上面的 5 個 Unseal Key 和 Initial Root Token 需要儲存起來。
Unseal Key 是每次重新啟動時需要使用任意 3 個 Unseal Key 解封,Initial Root Token 則是用來登入。

查看狀態:
    
vault status -address="https://192.168.0.60:8200"
    

範例輸出:
    
vault status -address="https://192.168.0.60:8200"
Key                Value
---                -----
Seal Type          shamir
Initialized        true
Sealed             true
Total Shares       5
Threshold          3
Unseal Progress    0/3
Unseal Nonce       n/a
Version            1.18.3
Build Date         2024-12-16T14:00:53Z
Storage Type       file
HA Enabled         false
    

Vault 在一開始執行時需要使用剛剛產生出來的 5 個 key 的任意三個進行解封:
    
vault operator unseal -address="https://192.168.0.60:8200"
    

範例輸出:
    
vault operator unseal -address="https://192.168.0.60:8200"
Unseal Key (will be hidden):
Key                Value
---                -----
Seal Type          shamir
Initialized        true
Sealed             true
Total Shares       5
Threshold          3
Unseal Progress    1/3
Unseal Nonce       10d50722-62a5-4da5-c36c-bd08a5449777
Version            1.18.3
Build Date         2024-12-16T14:00:53Z
Storage Type       file
HA Enabled         false
    

上面 Unseal Progress 1/3 代表還需要再 unseal 兩次。

重複上面的動作總共執行三次後就可以登入了。

登入:
    
vault login -address "https://192.168.0.60:8200"
    

登入成功的範例輸出:
    
vault login -address "https://192.168.0.60:8200"
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.old6nyDsbvGOoUHjeA40M8LM
token_accessor       KciVoNw8e3YkG65HfWxDRzxP
token_duration       ∞
token_renewable      false
token_policies       ["root"]
identity_policies    []
policies             ["root"]
    

開啟網頁(記得替換 IP):
    
https://192.168.0.60:8200
    


就可以使用上面產生的 Initial Root Token 登入了。

參考資料:
Vault by HashiCorp
GitHub - hashicorp/vault
Vault with integrated storage deployment guide
Vault configuration parameters

留言