VaultTemplate 介紹
VaultTemplate
類位於 org.springframework.vault.core
包中,它是 Spring 的 Vault 支援的核心類,提供了豐富的功能集來與 Vault 互動。該模板提供了便捷的操作來讀取、寫入和刪除 Vault 中的資料,並提供了您的域物件與 Vault 資料之間的對映。
VaultTemplate 配置完成後是執行緒安全的,可以在多個例項中複用。 |
Vault 文件與域類之間的對映透過委託給 RestTemplate
完成。Spring Web 支援提供了對映基礎設施。
VaultTemplate
類實現了 VaultOperations
介面。VaultOperations 上的方法儘可能地沿用了 Vault API 中可用方法的命名,以便讓習慣使用 Vault 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://: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 可以使用各種工廠方法構造,例如 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
決定獲取令牌的頻率,以及關於撤銷和續訂的策略。Spring Vault 提供了兩種實現:
-
SimpleSessionManager
:僅從提供的ClientAuthentication
獲取令牌,不進行重新整理和撤銷 -
LifecycleAwareSessionManager
:如果令牌可續訂,此SessionManager
會安排令牌續訂,並在處置時撤銷登入令牌。續訂透過AsyncTaskExecutor
安排。如果使用AbstractVaultConfiguration
,則預設配置LifecycleAwareSessionManager
。
使用 EnvironmentVaultConfiguration
Spring Vault 包含 EnvironmentVaultConfiguration
,用於從 Spring 的 Environment
和一組預定義屬性鍵配置 Vault 客戶端。EnvironmentVaultConfiguration
支援常用的配置。其他配置可以透過派生自最適合的配置類來支援。使用 @Import(EnvironmentVaultConfiguration.class)
將 EnvironmentVaultConfiguration
包含到現有的基於 Java 的配置類中,並透過 Spring 的任何 PropertySource
提供配置屬性。
@PropertySource("vault.properties")
@Import(EnvironmentVaultConfiguration.class)
public class MyConfiguration{
}
vault.uri=https://: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 令牌:
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
-
元資料服務 URL:
vault.azure-msi.metadata-service
(預設為169.254.169.254/metadata/instance?api-version=2017-08-01
) -
身份令牌服務 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 令牌:
vault.token
-
Kubernetes 路徑:
vault.kubernetes.kubernetes-path
(預設為kubernetes
) -
角色:
vault.kubernetes.role
-
服務賬戶令牌檔案路徑:
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();
}
});