Using a Credentials Provider
与数据存储器交互通常意味着首先使用凭据进行连接。这些凭据将允许对客户端进行识别、验证和最终授权。基于用户名/密码的验证非常常见,但这绝不是唯一的一种。此类凭据信息可能出现在应用程序配置中,但将此类敏感信息存储在安全存储中(如 HashiCorp Vault、Azure Key Vault 或 AWS Secrets Manager,仅举几例)正变得越来越普遍。
Interacting with a datastore typically implies first connecting using credentials. Those credentials will allow the client to be identified, authenticated and eventually authorized. Username/password based authentication is very common, but that is not by any means the only one. Such credentials information may appear in the application configuration, but it is becoming increasingly popular to store this type of sensitive information in secure stores, such as HashiCorp Vault, Azure Key Vault or the AWS Secrets Manager to name just a few.
为了桥接消耗不同形式的凭据的数据存储和提供这些凭据的安全存储,Quarkus 引入了名为 Credentials Provider
的中间抽象,一些扩展可能支持以消耗凭据(例如,agroal
),而其他一些可能实现以生成凭据(例如,vault
)。
To bridge datastores that consume credentials, which can take different forms,
and secure stores that provide those credentials,
Quarkus introduces an intermediate abstraction called Credentials Provider
,
that some extensions may support to consume credentials (e.g. agroal
),
and some others may implement to produce credentials (e.g. vault
).
该服务编程接口 (SPI) 也可被希望支持 Quarkus 中尚未实现的自定义提供程序(例如,Azure Key Vault)的实现者使用。
This Service Programming Interface (SPI) may also be used by implementers that want to support custom providers not yet implemented in Quarkus (e.g. Azure Key Vault).
目前,Credentials Provider
接口由 vault
扩展实现,并由以下凭据使用者扩展支持:
Currently, the Credentials Provider
interface is implemented by the vault
extension, and is supported
by the following credentials consumer extensions:
-
agroal
-
reactive-db2-client
-
reactive-mysql-client
-
reactive-mssql-client
-
reactive-oracle-client
-
reactive-pg-client
-
oidc
-
oidc-client
-
messaging-rabbitmq
所有依赖于用户名/密码身份验证的扩展也允许将配置属性设置为 application.properties
的替代。但是,如果生成凭据(例如,Vault Dynamic DB Credentials
)或需要自定义凭据提供程序,则 Credentials Provider
是唯一选项。
All extensions that rely on username/password authentication also allow setting configuration
properties in the application.properties
as an alternative. But the Credentials Provider
is the only option
if credentials are generated (e.g. Vault Dynamic DB Credentials
) or if a custom credentials provider is required.
本指南将展示如何使用 vault
扩展中提供的 Credentials Provider
,然后我们将研究如何实现自定义 Credentials Provider
,最后我们将讨论有关在新扩展中实现 Credentials Provider
的其他注意事项。
This guide will show how to use the Credentials Provider
provided in the vault
extension,
then we will look at implementing a custom Credentials Provider
, and finally we will talk about additional
considerations regarding implementing a Credentials Provider
in a new extension.
Unresolved directive in credentials-provider.adoc - include::{includes}/extension-status.adoc[]
Vault Credentials Provider
要配置 Vault Credentials Provider
,你需要提供以下属性:
To configure a Vault Credentials Provider
you need to provide the following properties:
quarkus.vault.credentials-provider.<name>.<property>=<value>
<name>
将在使用者中用于引用此提供程序。<property>
和 <value>
字段特定于 Vault Credentials Provider
。有关完整详细信息,请参阅 {vault-datasource-guide}。
The <name>
will be used in the consumer to refer to this provider. The <property>
and <value>
fields are specific to the Vault Credentials Provider
. For complete details, please refer to the {vault-datasource-guide}.
例如:
For instance:
quarkus.vault.credentials-provider.mydatabase.kv-path=myapps/vault-quickstart/db
一旦定义,mydatabase
提供程序即可在任何支持 Credentials Provider
接口的扩展中使用。例如,在 agroal
中:
Once defined, the mydatabase
provider can be used in any extension that supports the Credentials Provider
interface. For instance in agroal
:
# configure your datasource
quarkus.datasource.db-kind = postgresql
quarkus.datasource.username = sarah
quarkus.datasource.credentials-provider = mydatabase
quarkus.datasource.jdbc.url = jdbc:postgresql://localhost:5432/mydatabase
请注意,quarkus.datasource.username
是原始 agroal
属性,而 password
属性未包含,因为值将来自我们刚刚定义的 mydatabase
凭据提供程序。另一种方法是在 Vault 中定义用户名和密码,并从配置中删除 quarkus.datasource.username
属性。所有正在使用的扩展都支持从提供程序获取用户名和密码,或仅获取密码。
Note that quarkus.datasource.username
is the original agroal
property, whereas the password
property
is not included because the value will come from the mydatabase
credentials provider we just defined.
An alternative is to define both username and password in Vault and drop the quarkus.datasource.username
property from configuration. All consuming extensions do support the ability to fetch both the username
and password from the provider, or just the password.
Time Limited Credentials
凭据提供程序可能会提供有限时凭据。例如,vault
扩展。在使用有限时凭据时,重要的是要了解凭据提供程序不会自动刷新正在使用的扩展的凭据。必须对每个扩展进行配置,以便在凭据到期之前回收其连接。
A Credentials Provider may provide time limited credentials. For instance, the vault
extension. When using
time limited credentials, it is important to understand that consuming extensions will not have their
credentials refreshed automatically by the Credentials Provider. Each extension must be configured to recycle its
connections before the credentials expire.
Datasources
数据存储连接通常是池化的。在使用有限时凭据提供程序时,必须将连接池配置为在每个连接的凭据到期之前回收连接。JDBC 和 Reactive 数据源都包含一个 max-lifetime
配置属性,可用于实现此目的。
Datastore connections are typically pooled. When using a time limited credentials provider, the pool must be
configured to recycle connections before each connection’s credentials expire. Both JDBC and Reactive datasources
have a max-lifetime
configuration property that can be used to achieve this.
quarkus.datasource.jdbc.max-lifetime=60m
quarkus.datasource.reactive.max-lifetime=60m
由开发人员负责确保数据源的 |
It is the developer’s responsibility to ensure that the configuration of the datasource’s |
RabbitMQ
在使用 messaging-rabbitmq
扩展时,不需要配置。该扩展将根据凭据提供程序提供的到期时间戳在凭据到期之前自动回收连接。
When using the messaging-rabbitmq
extension there is no configuration needed. The
extension will automatically recycle connections before their credentials expire based on the expiration
timestamp provided by the Credentials Provider.
Custom Credentials Provider
在 Quarkus 中尚未支持保险箱产品或者需要从自定义存储中检索凭据时,实现自定义凭据提供程序是唯一选择。
Implementing a custom credentials provider is the only option when a vault product is not yet supported in Quarkus, or if credentials need to be retrieved from a custom store.
需要实现的唯一界面是:
The only interface to implement is:
public interface CredentialsProvider {
String USER_PROPERTY_NAME = "user";
String PASSWORD_PROPERTY_NAME = "password";
Map<String, String> getCredentials(String credentialsProviderName);
}
`USER_PROPERTY_NAME`和`PASSWORD_PROPERTY_NAME`是标准属性,任何支持基于用户名/密码进行认证的扩展都可以识别这两个属性。
USER_PROPERTY_NAME
and PASSWORD_PROPERTY_NAME
are standard properties that should be recognized by any consuming extension that support username/password based authentication.
需要实现为有效的`@ApplicationScoped`CDI bean。
It is required that implementations be valid @ApplicationScoped
CDI beans.
这是一个简单的示例:
Here is a simple example:
@ApplicationScoped
@Unremovable
public class MyCredentialsProvider implements CredentialsProvider {
@Override
public Map<String, String> getCredentials(String credentialsProviderName) {
Map<String, String> properties = new HashMap<>();
properties.put(USER_PROPERTY_NAME, "hibernate_orm_test");
properties.put(PASSWORD_PROPERTY_NAME, "hibernate_orm_test");
return properties;
}
}
请注意,我们决定同时返回用户名和密码。
Note that we decided here to return both the username and the password.
此提供程序可以在数据源定义中像这样使用:
This provider may be used in a datasource definition like this:
quarkus.datasource.db-kind=postgresql
quarkus.datasource.credentials-provider=custom
quarkus.datasource.jdbc.url=jdbc:postgresql://localhost:5431/hibernate_orm_test
也可以使用标准 MicroProfile 配置注入的方式向提供程序传递配置属性:
It is also possible to pass configuration properties to the provider using standard MicroProfile Config injection:
custom.foo=bar
并且在提供程序实现中:
And in the provider implementation:
@Inject
Config config;
@Override
public Map<String, String> getCredentials(String credentialsProviderName) {
System.out.println("MyCredentialsProvider called with foo=" + config.getValue(credentialsProviderName + ".foo", String.class));
...
}
New Credentials Provider extension
在新的扩展中创建自定义凭据提供程序时,还有几项其他注意事项。
When creating a custom credentials provider in a new extension, there are a few additional considerations.
首先,您需要为其命名以避免在项目中存在多个凭据提供程序时发生冲突:
First, you need to name it to avoid collisions in case multiple credentials providers are available in the project:
@ApplicationScoped
@Unremovable
@Named("my-credentials-provider")
public class MyCredentialsProvider implements CredentialsProvider {
用户的责任是允许有`credentials-provider-name`属性:
It is the responsibility of the consumer to allow a credentials-provider-name
property:
quarkus.datasource.credentials-provider = custom
quarkus.datasource.credentials-provider-name = my-credentials-provider
扩展应该允许运行时配置,例如允许来自`vault`扩展的`CredentialsProviderConfig`配置提供程序中的任何自定义属性。对于 AWS Secrets Manager 扩展,可以如下配置:
The extension should allow runtime config, such as the CredentialsProviderConfig
from the vault
extension
to configure any custom property in the provider. For an AWS Secrets Manager extension, this could be:
-
region
-
credentials-type
-
secrets-id
还要注意,一些用户(例如 agroal
)会将其连接配置添加到凭据提供程序返回的任何属性中,而不仅仅是用户名和密码。因此,在设计新的凭据提供程序时,将属性限制为用户可以理解的属性,或者提供适当的配置选项以支持不同的模式。
Note also that some consumers such as agroal
will add to their connection configuration any properties returned
by the credentials provider, not just the username and password. So when you design the new credentials provider
limit the properties to what would be understood by consumers, or provide appropriate configuration options to
support different modes.