1. 程式人生 > >Hashicorp Vault介紹和使用說明

Hashicorp Vault介紹和使用說明

1.概述

在本文中,我們將探索Hashicorp的Vault —— 一種用於在現代應用程式體系結構中安全地管理機密資訊的流行工具。

我們將討論的主要議題包括:

  • Vault試圖解決什麼問題
  • Vault的架構和主要概念
  • 設定一個簡單的測試環境
  • 使用命令列工具與Vault互動

2.機密資訊問題

在深入瞭解Vault之前,讓我們試著瞭解它試圖解決的問題:機密資訊管理。

大多數應用程式需要訪問機密資料才能正常工作。例如,電子商務應用程式可以在某處配置使用者名稱/密碼以便連線到其資料庫。它還可能需要API金鑰才能與其他服務提供商整合,例如支付閘道器,物流和其他業務合作伙伴。

資料庫憑證和API金鑰就是我們需要以安全的方式儲存和提供給我們的應用程式的機密資訊。

一個簡單的解決方案是將這些資訊儲存在配置檔案中,並在啟動時讀取它們。但是這種方法的問題顯而易見:有權訪問此檔案的人共享我們的應用程式具有的資料庫許可權 - 通常可以完全訪問所有儲存的資料。

我們可以嘗試通過加密這些檔案來使事情變得更加困難。但是,這種方法在整體安全性方面不會增加太多。主要是因為我們的應用程式必須能夠訪問主金鑰。當以這種方式使用時,加密僅是一種“錯誤”的安全感。

現代應用程式和雲環境往往會增加一些額外的複雜性:分散式服務,多個數據庫,訊息傳遞系統等等,所有敏感資訊都在各處傳播,從而增加了安全漏洞的風險。

所以,我們能做些什麼?來用下Vault吧!

3.什麼是Vault?

Hashicorp Vault解決了管理敏感資訊的問題 —— 在Vault的用語中使用“secret”。在這種情況下,“管理”意味著Vault控制敏感資訊的所有方面:它的生成,儲存,使用以及最後它的撤銷。

Hashicorp提供兩種版本的Vault。本文中使用的開源版本可以免費使用,即使在商業環境中也是如此。同時還提供付費版本,其中包括不同SLA的技術支援和其他功能,例如HSM(硬體安全模組)支援。

3.1 架構和主要特點

Vault的架構非常簡單。其主要組成部分是:

  • 永續性後端 —— 儲存所有機密
  • 一種API伺服器 —— 用於處理客戶端請求並對機密執行操作
  • 許多secret引擎 —— 支援不同的機密型別

通過將所有機密處理委派給Vault,我們可以緩解一些安全問題: 我們的應用程式不再需要儲存它們 ,只需在需要時詢問Vault並在使用後將其丟棄 我們可以短暫的使用機密資料,從而限制攻擊者盜取祕密的“機會之窗”

Vault會在將所有資料寫入儲存之前使用加密金鑰對所有資料進行加密。此加密金鑰由另一個金鑰加密 —— 主金鑰,主金鑰僅在啟動時使用。

Vault實現的一個關鍵點是它不會將主金鑰儲存在伺服器中。 這意味著即使Vault也無法在啟動後訪問其儲存的資料。 此時,Vault例項被稱為處於“密封”狀態。

稍後,我們將完成生成主金鑰和解封Vault例項所需的步驟。

一旦啟封,Vault就可以接受API請求了。當然,這些請求需要身份驗證,這使我們控制Vault如何對客戶端進行身份驗證並決定他們可以做什麼或不做什麼。

3.2 認證

要訪問Vault中的機密,客戶端需要使用一種受支援的方法對自身進行身份驗證。最簡單的方法使用Tokens,它只是使用特殊HTTP頭在每個API請求上傳送的字串。

最初安裝時,Vault會自動生成“根令牌”。此令牌與Linux系統中的超級使用者等效,因此應將其使用限制在最低限度。作為最佳實踐,我們應該使用此根令牌來建立具有較少許可權的其他令牌,然後撤消它。但這不是問題,因為我們以後可以使用unseal鍵生成另一個根令牌。

Vault還支援其他身份驗證機制,如LDAP,JWT,TLS證書等。所有這些機制都建立在基本令牌機制之上:一旦Vault驗證了我們的客戶端,它將提供一個令牌,然後我們可以使用它來訪問其他API。

令牌有一些與之相關的屬性。主要屬性是:

  • 一組關聯的策略
  • 有效期
  • 是否強制更新
  • 最大使用次數

除非另有說明,否則由Vault建立的令牌將形成父子關係。子令牌最多可以與父令牌具有相同級別的許可權。

通常的情況是,我們可以建立具有限制性策略的子令牌。關於此關係的另一個關鍵點:當我們使令牌無效時,所有子令牌及其後代也會失效。

3.3 策略

策略確切地定義了客戶端可以訪問哪些祕密以及它們可以使用它們執行哪些操作。讓我們看看一個簡單的策略是如何定義的:

path "secret/accounting"{
capabilities = [ "read"]
}

在這裡,我們使用HCL(Hashicorp的配置語言)語法來定義我們的策略。Vault還支援JSON格式,但我們將在示例中堅持使用HCL,因為它更易於閱讀。

Vault中的策略是“預設拒絕”。附加到此示例策略的令牌將訪問secret/accounting下儲存的祕密,而不是其他內容。在建立時,令牌可以附加到多個策略。這非常有用,因為它允許我們建立和測試較小的策略,然後根據需要應用它們。

策略的另一個重要方面是他們使用懶惰評估。這意味著我們可以更新給定的策略,所有令牌都會立即受到影響。

到目前為止描述的策略也稱為訪問控制列表策略或ACL策略。Vault還支援兩種其他策略型別:EGP和RGP策略。這些僅在付費版本中可用,並使用Sentinel支援擴充套件基本策略語法。

擴充套件基本策略允許我們在策略中考慮其他屬性,例如一天中的時間,多個身份驗證因素,客戶端網路來源等。例如,我們可以定義一個允許僅在工作時間訪問某指定機密的策略。

我們可以在Vault的文件中找到有關策略語法的更多詳細資訊 。

4.Secret型別

Vault支援一系列不同的祕密型別,可以解決不同的用例:

  • Key-Value: 簡單的靜態鍵值對
  • 動態生成的憑據:由Vault根據客戶端請求生成
  • 加密金鑰:用於使用客戶端資料執行加密功能

每種祕密型別由以下屬性定義:

  • 一個掛載點,定義了它的REST API字首
  • 通過相應的API公開的一組操作
  • 一組配置引數

可以通過路徑訪問給定的祕密例項 ,非常類似於檔案系統中的目錄樹。此路徑的第一個元件對應於此型別的所有機密所在的安裝點。

例如,字串 secret / my-application 對應於我們可以在其中找到my-application的鍵值對的路徑 。

4.1 Key-Value Secrets

顧名思義,鍵值Secrets是指在給定路徑下可用的簡單鍵值對。例如,我們可以在path / secret / my-application下 儲存foo = bar對 。

稍後,我們使用相同的路徑來檢索相同的一對或多對 - 多對可以儲存在同一路徑下。

Vault支援三種Key-Value機密:

  • 非版本化鍵值對,其中更新替換現有值
  • 版本化鍵值對,可保持可配置數量的舊版本
  • Cubbyhole,一種特殊型別的非版本化金鑰對,其值的範圍限定為給定的訪問令牌(稍後將詳細介紹)。

金鑰值祕密本質上是靜態的,因此沒有到期的概念與它們相關聯。這種祕密的主要使用場景是儲存憑證以訪問外部系統,例如API金鑰。

在這種情況下,憑據更新是半手動過程,通常需要有人獲取新憑據並使用Vault的命令列或其UI來輸入新值。

4.2 動態生成的Secrets

當應用程式請求時,Vault會動態生成動態機密。Vault支援多種型別的動態機密,包括以下幾種:

  • 資料庫憑證
  • SSH金鑰對
  • X.509證書
  • AWS憑證
  • Google Cloud服務帳戶
  • Active Directory帳戶

所有這些都遵循相同的使用模式。首先,我們使用連線到關聯服務所需的詳細資訊配置secret引擎。然後,我們定義一個或多個角色, 描述實際的secret建立。

我們以資料庫secret引擎為例。首先,我們必須使用所有使用者資料庫連線詳細資訊配置Vault,包括來自具有管理員許可權的預先存在的使用者的憑據以建立新使用者。

然後,我們建立一個或多個角色(Vault角色,而不是資料庫角色),其中包含用於建立新使用者的實際SQL語句。這些通常不僅包括使用者建立語句,還包括訪問模式物件(表,檢視等)以及所有必需的 grant語句。

當客戶端訪問相應的API時,Vault將使用提供的語句在資料庫中建立新的臨時使用者並返回其憑據。然後,客戶端可以使用這些憑據在請求角色的生存時間屬性定義的時間段內訪問資料庫。

憑證到達其到期時間後,Vault將自動撤消與此使用者關聯的任何許可權。客戶端還可以請求Vault續訂這些憑據。只有在特定資料庫驅動程式支援且相關策略允許的情況下,才會進行續訂過程。

4.3 加密金鑰

這個型別的祕密引擎處理加密,解密,簽名等加密功能。所有這些操作都使用Vault內部生成和儲存的加密金鑰。除非明確告知,否則Vault將永遠不會公開給定的加密金鑰。

關聯的API允許客戶端傳送Vault純文字資料並接收其加密版本。相反的情況也是可能的:我們可以傳送加密資料並取回原始文字。

目前,只有一種這種型別的引擎:Transit引擎。此引擎支援流行的金鑰型別,如RSA和ECDSA,還支援 Convergent Encryption。使用此模式時,給定的明文值始終會產生相同的密文結果,這種屬性在某些應用程式中非常有用。

例如,我們可以使用此模式加密事務日誌表中的信用卡號。使用收斂加密,每次插入新事務時,加密的信用卡值都是相同的,因此允許使用常規SQL查詢進行報告,搜尋等。

5.Vault設定

在本節中,我們將建立一個本地測試環境,以便測試Vault的功能。

Vault的部署很簡單:只需下載與我們的作業系統對應的軟體包,並將其可執行檔案(Windows上的vault 或vault.exe )提取到PATH上的某個目錄。此可執行檔案包含伺服器,也是標準客戶端。

Vault支援一種development 模式,適用於某些快速測試並習慣其命令列工具,但對於實際使用情況來說太簡單了:重啟時所有資料都丟失,API訪問使用普通HTTP。

相反,我們將使用基於檔案的持久儲存和設定HTTPS,以便我們可以探索一些可能導致問題的真實配置細節。

5.1 啟動Vault Server

Vault使用HCL或JSON格式的配置檔案。以下檔案定義了使用檔案儲存和自簽名證書啟動伺服器所需的所有配置:

// Enable UI
ui = true

// Filesystem storage
storage "file" {
  path    = "./vault-data"
}

// TCP Listener using a self-signed certificate
listener "tcp" {
  address     = "127.0.0.1:8200"
  tls_cert_file = "localhost.cert"
  tls_key_file = "localhost.key"
}

現在,讓我們執行Vault。開啟命令shell,轉到包含我們的配置檔案的目錄並執行以下命令:

$ vault server -config ./vault-test.hcl

Vault將啟動並顯示一些初始化訊息。它們將包括其版本,一些配置詳細資訊以及API可用的地址。就是這樣我們的Vault伺服器啟動並執行。

5.2 Vault初始化

我們的Vault伺服器現在正在執行,但由於這是它的第一次執行,我們需要初始化它。

讓我們開啟一個新的shell並執行以下命令來實現這個目的:

$ export VAULT_ADDR=https://localhost:8200
$ export VAULT_CACERT=localhost.cert
$ vault operator init

這裡我們定義了一些環境變數,因此我們不必每次都將它們作為引數傳遞給Vault:

  • VAULT_ADDR:我們的API伺服器將為其提供請求的基URI
  • VAULT_CACERT:伺服器證書公鑰的路徑

在我們的例子中,我們使用VAULT_CACERT, 因此我們可以使用HTTPS訪問Vault的API。我們需要這個,因為我們使用的是自簽名證書。對於我們通常可以訪問CA簽名證書的製作環境而言,這不是必需的。

發出上述命令後,我們應該看到如下訊息:

Unseal Key 1: kHcMDI6lwIfX1xdcThrDF5jR00gDOc1a7t6kr+fCXWcN
Unseal Key 2: 6xsSLornxUqfMUSoq7XPIb9PLIFnzPPMR+UMTzWP0m0o
Unseal Key 3: pgrhB6wtrnINh3SY4mS2cWjEzmuiMRWmg+SIp50/4DQs
Unseal Key 4: BpR1Lzuogn9AJYJADxXuCit5yxGYtM2qF0BxHn1g/Zw8
Unseal Key 5: Vj7W6HYcCZvtkCnjNdR+4fuw+aCmlfQ+IZMTc70cyzIh

Initial Root Token: 2HgD0nKyaDjI5TICz9pObW2T

前5行是我們稍後用於解開Vault儲存的主金鑰。 請注意,Vault僅在初始化期間顯示解封金鑰 - 以後永遠不會出現。記下並安全地儲存它們,否則在伺服器重啟時我們將無法訪問我們的機密資訊!

另外,請注意根令牌,因為我們稍後會需要它。與unseal鍵不同,root令牌可以在以後輕鬆生成,因此一旦完成所有配置任務就可以安全地銷燬它。由於我們稍後將發出需要身份驗證令牌的命令,因此我們現在將根令牌儲存在環境變數中:

$ export VAULT_TOKEN= 2HgD0nKyaDjI5TICz9pObW2T

現在讓我們看看我們的伺服器狀態,我們已經使用以下命令對其進行了初始化:

$ vault status
Key                Value
---                -----
Seal Type          shamir
Sealed             true
Total Shares       5
Threshold          3
Unseal Progress    0/3
Unseal Nonce       n/a
Version            0.11.3
HA Enabled         false

我們可以看到Vault仍然是密封的。Unseal Progress :“0/3”意味著Vault需要三個,但到目前為止還沒有開啟。

5.3 Vault Unseal

我們現在開啟Vault,以便我們可以開始使用其祕密服務。為了完成開封過程,我們需要提供五個關鍵股中的任意三個:

$ vault operator unseal kHcMDI6lwIfX1xdcThrDF5jR00gDOc1a7t6kr+fCXWcN
$ vault operator unseal 6xsSLornxUqfMUSoq7XPIb9PLIFnzPPMR+UMTzWP0m0o
$ vault operator unseal pgrhB6wtrnINh3SY4mS2cWjEzmuiMRWmg+SIp50/4DQs

發出每個命令後,Vault將列印啟封進度,包括它需要多少個共享。傳送最後一個金鑰共享後,我們會看到如下訊息:

Key             Value
---             -----
Seal Type       shamir
Initialized     true
Sealed          false
Total Shares    5
Threshold       3
Version         0.11.3
Cluster Name    vault-cluster-6c90f68f
Cluster ID      a1259a6b-aa24-b02a-1d36-b64907ea3570
HA Enabled      false

在這種情況下,“密封”屬性為“假”,這意味著Vault已準備好接受命令。

6.測試Vault

在本節中,我們將使用其支援的兩種Secret型別測試我們的Vault設定:鍵值對和資料庫。我們還將展示如何建立附加了特定策略的新令牌。

6.1 使用鍵/值Secret

首先,讓我們儲存祕密的鍵值對並將其讀回。 假設用於初始化Vault的命令shell仍處於開啟狀態,我們使用以下命令將這些鍵值對儲存在secret / fakebank路徑下:

$ vault kv put secret/fakebank api_key=abc1234 api_secret=1a2b3c4d

我們現在可以使用以下命令隨時讀取這些鍵值對:

$ vault kv get secret/fakebank
======= Data =======
Key           Value
---           -----
api_key       abc1234
api_secret    1a2b3c4d

這個簡單的測試向我們展示了Vault正在按預期工作。我們現在可以測試一些額外的功能。

6.2 建立新令牌

到目前為止,我們已經使用了根令牌來驗證我們的請求。由於根令牌 的方式太強大了,它被認為是使用較少的特權和更短的時間生存令牌的最佳實踐。

讓我們建立一個新的令牌,我們可以像根令牌一樣使用它,但在一分鐘後過期:

$ vault token create -ttl 1m
Key                  Value
---                  -----
token                Luc1pGxZxKkNEwpCLD3Ea4VX
token_accessor       1Zzp7g1FJYW5nvqACZFQtRRx
token_duration       1m
token_renewable      true
token_policies       ["root"]
identity_policies    []
policies             ["root"]

讓我們測試一下這個令牌,用它來讀取我們之前建立的鍵/值對:

$ export VAULT_TOKEN=Luc1pGxZxKkNEwpCLD3Ea4VX
$ vault kv get secret/fakebank
======= Data =======
Key           Value
---           -----
api_key       abc1234
api_secret    1a2b3c4d

如果我們等待一分鐘並嘗試重新發出此命令,我們會收到一條錯誤訊息:

$ vault kv get secret/fakebank
Error making API request.
URL: GET https://localhost:8200/v1/sys/internal/ui/mounts/secret/fakebank
Code: 403. Errors:
* permission denied

該訊息表明我們的令牌不再有效,這正是我們所期望的。

6.3 測試策略

我們在上一節中建立的示例令牌雖是短暫存在,但仍然非常強大。現在讓我們使用策略來建立更多受限制的令牌。

例如,讓我們定義一個策略,該策略只允許對我們之前使用的secret / fakebank路徑進行讀訪問:

$ cat> sample-policy.hcl <
path "secret/fakebank"{
capabilities = ["read"]
}
EOF
$ export VAULT_TOKEN=2HgD0nKyaDjI5TICz9pObW2T
$ vault policy write fakebank-ro ./sample-policy.hcl
Success! Uploaded policy: fakebank-ro

現在,我們使用以下命令使用此策略建立令牌:

$ vault token create -policy=fakebank-ro
Key                  Value
---                  -----
token                <token value>
token_accessor       <token accessor value>
token_duration       768h
token_renewable      true
token_policies       ["default""fakebank-ro"]
identity_policies    []
policies             ["default""fakebank-ro"]

正如我們之前所做的那樣,讓我們​​使用此標記讀取我們的祕密值:

$ export VAULT_TOKEN=<token value>
$ vault kv get secret/fakebank
======= Data =======
Key           Value
---           -----
api_key       abc1234
api_secret    1a2b3c4d

到現在為止還挺好。我們可以按預期讀取資料。讓我們看看當我們嘗試更新這個祕密時會發生什麼:

$ vault kv put secret/fakebank api_key=foo api_secret=bar
Error writing data to secret/fakebank: Error making API request.
URL: PUT https://127.0.0.1:8200/v1/secret/fakebank
Code: 403. Errors:
* permission denied

由於我們的策略未授予允許寫入,因此Vault將返回403 - 拒絕訪問狀態程式碼。

6.4 使用動態資料庫憑據

作為本文的最後一個示例,讓我們使用Vault的資料庫祕密引擎來建立動態憑據。我們假設我們在本地有一個MySQL伺服器,我們可以使用“root”許可權訪問它。我們還將使用一個非常簡單的模式,該模式由一個表 - 帳戶組成。

用於建立此架構的SQL指令碼和特權使用者可在此處獲得。

--
-- Sample schema for testing vault database secrets
--
create schema fakebank;
use fakebank;
create table account( 
  id decimal(16,0), 
  name varchar(30),
  branch_id decimal(16,0),
  customer_id decimal(16,0),
  primary key (id));
  
--
-- MySQL user that will be used by Vault to create other users on demand
--
create user 'fakebank-admin'@'%' identified by 'Sup&rSecre7!';
grant all privileges on fakebank.* to 'fakebank-admin'@'%' with grant option;
grant create user on *.* to 'fakebank-admin' with grant option;

flush privileges;

現在,讓我們配置Vault以使用此資料庫。預設情況下未啟用資料庫金鑰引擎,因此我們必須先解決此問題,然後才能繼續:

$ vault secrets enable database
Success! Enabled the database secrets engine at: database/

我們現在建立一個數據庫配置資源:

$ vault write database/config/mysql-fakebank plugin_name=mysql-legacy-database-plugin connection_url="{{username}}:{{password}}@tcp(127.0.0.1:3306)/fakebank" allowed_roles="*" username="fakebank-admin" password="Sup&rSecre7!"

路徑字首database / config是必須儲存所有資料庫配置的地方。我們選擇名稱 mysql-fakebank, 以便我們可以輕鬆找出此配置所指的資料庫。至於配置鍵:

  • plugin_name:定義將使用哪個資料庫外掛。Vault的文件中描述了可用的外掛名稱
  • connection_url:這是外掛在連線資料庫時使用的模板。請注意{{username}}和{{password}}模板佔位符。連線到資料庫時,Vault將按實際值替換這些佔位符
  • allowed_roles:定義哪些Vault角色(上面討論過)可以使用此配置。在我們的例子中,我們使用“*”,因此它可用於所有角色
  • 使用者名稱和密碼:這是Vault用於執行資料庫操作的帳戶,例如建立新使用者和撤消其許可權

Vault資料庫角色設定

最終配置任務是建立包含建立使用者所需的SQL命令的Vault資料庫角色資源。根據我們的安全要求,我們可以根據需要建立任意數量的角色。

在這裡,我們建立一個角色,授予對fakebank模式的所有表的只讀訪問許可權:

$ vault write database/roles/fakebank-accounts-ro db_name=mysql-fakebank creation_statements="CREATE USER '{{name}}'@'%' IDENTIFIED BY '{{password}}';GRANT SELECT ON fakebank.* TO '{{name}}'@'%';"

資料庫引擎將路徑字首資料庫/角色 定義為儲存角色的位置。 fakebank-accounts-ro是我們稍後在建立動態憑據時使用的角色名稱。我們還提供以下屬性:

  • db_name:現有資料庫配置的名稱。對應於我們在建立配置資源時使用的路徑的最後部分
  • creation_statements: Vault將用於建立新使用者的SQL語句模板列表

建立動態憑據

一旦我們準備好資料庫角色及其相應的配置,我們就會使用以下命令生成新的動態憑據:

$ vault read database/creds/fakebank-accounts-ro
Key                Value
---                -----
lease_id           database/creds/fakebank-accounts-ro/t4RQeXdyAVq75jNmbaQfPM6n
lease_duration     768h
lease_renewable    true
password           A1a-24NNCeaazWCp2EE7
username           v-fake-60fSchsFo       

該資料庫/ creds字首用於生成可用角色憑據。由於我們使用了 fakebank-accounts-ro 角色,因此返回的使用者名稱/密碼將僅限於選擇操作。有效期為1個小時。

我們可以通過使用提供的憑據連線到資料庫然後執行一些SQL命令來驗證這一點:

$ mysql -h 127.0.0.1 -u v-fake-60fSchsFo -p fakebank
Enter password:
mysql> select * from account;
Empty set (0.00 sec)

mysql> delete from account;
ERROR 1142 (42000): DELETE command denied to user 'v-fake-60fSchsFo'@'localhost' for table 'account'

我們可以看到第一個select成功完成,但是我們無法執行delete語句。最後,如果我們等待一個小時並嘗試使用相同的憑據進行連線,我們將無法再連線到資料庫。Vault已自動撤消此使用者的所有許可權

7.結論

在本文中,我們探討了Hashicorp Vault的基礎知識,包括它試圖解決的問題的一些背景,它的架構和基本用法。

在此過程中,我們建立了一個簡單但功能齊全的測試環境,我們將在後續文章中使用它。

下一篇文章將介紹Vault的一個非常具體的用例:在Spring Boot應用程式的上下文中使用它。敬請關注!