VaultTemplate 簡介
位於 org.springframework.vault.core
套件的 VaultTemplate
類別是 Spring Vault 支援的核心類別,提供豐富的功能集來與 Vault 互動。此樣板提供便利的操作,以在 Vault 中讀取、寫入和刪除資料,並提供您的領域物件與 Vault 資料之間的對應。
一旦設定完成,VaultTemplate 即為執行緒安全,且可在多個執行個體之間重複使用。 |
Vault 文件與領域類別之間的對應是透過委派給 RestTemplate
來完成。Spring Web 支援提供對應基礎架構。
VaultTemplate
類別實作了 VaultOperations
介面。在盡可能範圍內,VaultOperations
上的方法會以 Vault API 上可用的方法命名,使 API 對於已習慣 API 和 CLI 的現有 Vault 開發人員來說感到熟悉。例如,您會找到諸如 "write"、"delete"、"read" 和 "revoke" 等方法。設計目標是盡可能輕鬆地在 Vault API 和 VaultOperations
的使用之間進行轉換。這兩個 API 之間的主要區別在於 VaultOperations
可以傳遞領域物件,而不是 JSON 鍵值組。
參考 VaultTemplate 執行個體上的操作的首選方式是透過其介面 VaultOperations 。 |
雖然 VaultTemplate
上有許多便利方法可協助您輕鬆執行常見任務,但如果您需要直接存取 Vault API 以存取 VaultTemplate
未明確公開的功能,您可以使用數個執行回呼方法之一來存取基礎 API。執行回呼將為您提供 RestOperations
物件的參考。請參閱 執行回呼 章節以取得更多資訊。
現在讓我們看看如何在 Spring 容器的環境中使用 Vault 的範例。
註冊和設定 Spring Vault Bean
使用 Spring Vault 不需要 Spring Context。但是,在受管理容器內註冊的 VaultTemplate
和 SessionManager
執行個體將參與 Spring IoC 容器提供的 生命週期事件。這對於在應用程式關閉時處置作用中的 Vault 工作階段很有用。您還可以受益於在應用程式中重複使用相同的 VaultTemplate
執行個體。
Spring Vault 隨附一個支援組態類別,該類別提供在 Spring 容器內使用的 Bean 定義。應用程式組態類別通常從 AbstractVaultConfiguration
擴充,並且需要提供環境特定的其他詳細資訊。
從 AbstractVaultConfiguration
擴充需要實作 VaultEndpoint vaultEndpoint()
和 ClientAuthentication clientAuthentication()
方法。
@Configuration
public class AppConfig extends AbstractVaultConfiguration {
/**
* Specify an endpoint for connecting to Vault.
*/
@Override
public VaultEndpoint vaultEndpoint() {
return new VaultEndpoint(); (1)
}
/**
* Configure a client authentication.
* Please consider a more secure authentication method
* for production use.
*/
@Override
public ClientAuthentication clientAuthentication() {
return new TokenAuthentication("…"); (2)
}
}
1 | 建立一個新的 VaultEndpoint ,預設指向 https://127.0.0.1:8200 。 |
2 | 此範例使用 TokenAuthentication 快速開始使用。請參閱 [vault.core.authentication] 以取得有關支援的驗證方法的詳細資訊。 |
@Configuration
public class AppConfig extends AbstractVaultConfiguration {
@Value("${vault.uri}")
URI vaultUri;
/**
* Specify an endpoint that was injected as URI.
*/
@Override
public VaultEndpoint vaultEndpoint() {
return VaultEndpoint.from(vaultUri); (1)
}
/**
* Configure a Client Certificate authentication.
* {@link RestOperations} can be obtained from {@link #restOperations()}.
*/
@Override
public ClientAuthentication clientAuthentication() {
return new ClientCertificateAuthentication(restOperations()); (2)
}
}
1 | VaultEndpoint 可以使用各種 Factory 方法建構,例如 from(URI uri) 或 VaultEndpoint.create(String host, int port) 。 |
2 | ClientAuthentication 方法的相依性可以從 AbstractVaultConfiguration 取得,或由您的組態提供。 |
在某些情況下,建立自訂組態類別可能很麻煩。請查看 EnvironmentVaultConfiguration ,它允許使用現有屬性來源和 Spring 的 Environment 中的屬性進行組態。請在 使用 EnvironmentVaultConfiguration 中閱讀更多資訊。 |
工作階段管理
Spring Vault 需要 ClientAuthentication
才能登入和存取 Vault。請參閱 [vault.core.authentication] 以取得有關驗證的詳細資訊。Vault 登入不應在每次經過驗證的 Vault 互動時發生,而必須在整個工作階段中重複使用。此方面由 SessionManager
實作處理。SessionManager
決定取得 Token 的頻率、關於撤銷和續約。Spring Vault 隨附兩個實作
-
SimpleSessionManager
:僅從提供的ClientAuthentication
取得 Token,而無需重新整理和撤銷 -
LifecycleAwareSessionManager
:如果 Token 可續約,則此SessionManager
會排程 Token 續約,並在處置時撤銷登入 Token。續約會使用AsyncTaskExecutor
排程。如果使用AbstractVaultConfiguration
,則預設會組態LifecycleAwareSessionManager
。
使用 EnvironmentVaultConfiguration
Spring Vault 包含 EnvironmentVaultConfiguration
,可從 Spring 的 Environment
和一組預先定義的屬性鍵組態 Vault 用戶端。EnvironmentVaultConfiguration
支援常用的組態。其他組態透過從最合適的組態類別衍生來支援。將 EnvironmentVaultConfiguration
與 @Import(EnvironmentVaultConfiguration.class)
包含到現有的 Java 基礎組態類別中,並透過任何 Spring 的 PropertySource
提供組態屬性。
@PropertySource("vault.properties")
@Import(EnvironmentVaultConfiguration.class)
public class MyConfiguration{
}
vault.uri=https://127.0.0.1:8200
vault.token=00000000-0000-0000-0000-000000000000
屬性鍵
-
Vault URI:
vault.uri
-
SSL 設定
-
金鑰儲存庫資源:
vault.ssl.key-store
(選用) -
金鑰儲存庫密碼:
vault.ssl.key-store-password
(選用) -
金鑰儲存庫類型:
vault.ssl.key-store-type
(選用,通常為jks
,也支援pem
) -
信任儲存庫資源:
vault.ssl.trust-store
(選用) -
信任儲存庫密碼:
vault.ssl.trust-store-password
(選用) -
信任儲存庫類型:
vault.ssl.trust-store-type
(選用,通常為jks
,也支援pem
) -
已啟用 SSL/TLS 通訊協定:
vault.ssl.enabled-protocols
(自 2.3.2 起,選用,通訊協定以逗號分隔) -
已啟用 SSL/TLS 密碼套件:
vault.ssl.enabled-cipher-suites
(自 2.3.2 起,選用,密碼套件以逗號分隔)
-
-
驗證方法:
vault.authentication
(預設為TOKEN
,支援的驗證方法為:TOKEN
、APPID
、APPROLE
、AWS_EC2
、AWS_IAM
、AZURE
、CERT
、CUBBYHOLE
、KUBERNETES
)
驗證特定屬性鍵
-
Vault Token:
vault.token
-
AppId 路徑:
vault.app-id.app-id-path
(預設為app-id
) -
AppId:
vault.app-id.app-id
-
UserId:
vault.app-id.user-id
。MAC_ADDRESS
和IP_ADDRESS
使用MacAddressUserId
,分別為IpAddressUserId
使用者 ID 機制。任何其他值都與StaticUserId
一起使用。
-
AppRole 路徑:
vault.app-role.app-role-path
(預設為approle
) -
RoleId:
vault.app-role.role-id
-
SecretId:
vault.app-role.secret-id
(選用)
-
AWS EC2 路徑:
vault.aws-ec2.aws-ec2-path
(預設為aws-ec2
) -
角色:
vault.aws-ec2.role
-
RoleId:
vault.aws-ec2.role-id
(已棄用: 請改用vault.aws-ec2.role
) -
身分文件 URL:
vault.aws-ec2.identity-document
(預設為169.254.169.254/latest/dynamic/instance-identity/pkcs7
)
-
角色:
vault.aws-iam.role
-
Azure MSI 路徑:
vault.azure-msi.azure-path
(預設為azure
) -
角色:
vault.azure-msi.role
-
Metadata 服務 URL:
vault.azure-msi.metadata-service
(預設為169.254.169.254/metadata/instance?api-version=2017-08-01
) -
身分 TokenService URL:
vault.azure-msi.identity-token-service
(預設為169.254.169.254/metadata/identity/oauth2/token?resource=https://vault.hashicorp.com&api-version=2018-02-01
)
無設定選項。
-
初始 Vault Token:
vault.token
-
Kubernetes 路徑:
vault.kubernetes.kubernetes-path
(預設為kubernetes
) -
角色:
vault.kubernetes.role
-
服務帳戶 Token 檔案路徑:
vault.kubernetes.service-account-token-file
(預設為/var/run/secrets/kubernetes.io/serviceaccount/token
)
執行回呼
所有 Spring 樣板類別的一個常見設計特點是,所有功能都路由到樣板的執行回呼方法之一。這有助於確保例外狀況和可能需要的任何資源管理以一致的方式執行。雖然這在 JDBC 和 JMS 的情況下比 Vault 更為必要,但它仍然為存取和記錄提供單一位置。因此,使用執行回呼是存取 Vault API 以執行我們未在 VaultTemplate
上公開為方法的非常見操作的首選方式。
以下是執行回呼方法的清單。
-
<T> T
doWithVault(RestOperationsCallback<T> callback)
執行給定的RestOperationsCallback
,允許使用RestOperations
與 Vault 互動,而無需工作階段。 -
<T> T
doWithSession(RestOperationsCallback<T> callback)
執行給定的RestOperationsCallback
,允許在經過驗證的工作階段中與 Vault 互動。
以下範例使用 ClientCallback
初始化 Vault
vaultOperations.doWithVault(new RestOperationsCallback<VaultInitializationResponse>() {
@Override
public VaultInitializationResponse doWithRestOperations(RestOperations restOperations) {
ResponseEntity<VaultInitializationResponse> exchange = restOperations
.exchange("/sys/init", HttpMethod.PUT,
new HttpEntity<Object>(request),
VaultInitializationResponse.class);
return exchange.getBody();
}
});