TLS 注册表参考
TLS 注册表是一个 Quarkus 扩展,可集中管理 TLS 配置,从而更轻松地管理和维护应用程序中的安全连接。通过在单个集中位置定义 TLS 配置,您可以使用 TLS 注册表从应用程序中的多个组件引用这些配置,从而确保一致性并减少配置错误的潜在可能性。
TLS 注册表整合了设置并支持多个命名配置。因此,您可以为不同的应用程序部分定制 TLS 设置。当不同的组件需要不同的安全配置时,这种灵活性特别有用。
当您使用兼容的扩展(例如 Quarkus REST、gRPC、SmallRye GraphQL Client 或 Reactive Routes)时,TLS 注册表扩展会自动包含在您的项目中。
因此,使用 TLS 注册表的应用程序可以立即处理安全通信。
TLS 注册表还提供自动证书重新加载、与 Let's Encrypt (ACME) 集成、对 Kubernetes Cert-Manager 的支持以及与各种密钥库格式(例如 PKCS12、PEM 和 JKS)的兼容性。
1. 使用 TLS 注册表
要配置 TLS 连接(包括密钥库和信任库),请使用 quarkus.tls.*
属性。这些属性是必需的
-
设置默认 TLS 配置,直接在
quarkus.tls.*
下定义 -
通过使用
quarkus.tls.<name>.*
创建单独的命名配置。通过指定quarkus.tls.<name>.*
属性,您可以为特定组件调整 TLS 设置。
默认 TLS 配置不是回退或全局配置。每个命名的 TLS 配置或“TLS 存储桶”都必须提供其自己的属性。例如, |
如此处 详细描述,Quarkus 客户端扩展(REST、GRPC 等)忽略默认(即未命名)TLS 配置中定义的属性。唯一的例外是 |
1.1. 为 HTTP 服务器配置 HTTPS
为了确保客户端-服务器安全通信,通常需要客户端验证服务器的真实性。
-
服务器必须使用包含其证书和私钥的密钥库。
-
客户端需要配置一个信任库来验证服务器的证书。
在 TLS 握手期间,服务器会出示其证书,然后客户端会对其进行验证。这样可以防止中间人攻击并确保数据传输安全。
以下部分将指导您通过使用 PEM 或 PKCS12 密钥库类型来设置 HTTPS。此外,它们还提供有关如何使用命名配置一次性指定和管理多个 TLS 设置的信息,这使您可以为每个设置定义不同的设置。
根据您的密钥库类型使用以下配置示例之一
-
通过使用 PEM 文件
quarkus.tls.key-store.pem.0.cert=server.crt quarkus.tls.key-store.pem.0.key=server.key quarkus.http.insecure-requests=disabled # Reject HTTP requests
-
通过使用
p12
(PKCS12) 密钥库quarkus.tls.key-store.p12.path=server-keystore.p12 quarkus.tls.key-store.p12.password=secret quarkus.http.insecure-requests=disabled # Reject HTTP requests
-
使用名称区分多个配置
quarkus.tls.https.key-store.p12.path=server-keystore.p12 quarkus.tls.https.key-store.p12.password=secret quarkus.http.insecure-requests=disabled quarkus.http.tls-configuration-name=https
1.2. 为客户端配置 HTTPS
以下示例配置名为“hello”的 gRPC 客户端以使用来自默认 TLS 配置的信任库的 HTTPS
quarkus.tls.trust-store.jks.path=grpc-client-truststore.jks
quarkus.tls.trust-store.jks.password=password
quarkus.grpc.clients.hello.plain-text=false
quarkus.grpc.clients.hello.use-quarkus-grpc-client=true
1.3. 配置 mTLS
要在 Quarkus 应用程序中设置相互 TLS (mTLS),请通过为每个服务器和客户端创建和管理密钥库和信任库来配置服务器和客户端
-
服务器密钥库:包含服务器的证书和私钥。
-
客户端密钥库:包含客户端的证书和私钥。
-
服务器信任库:存储客户端的证书以验证客户端的身份。
-
客户端信任库:存储服务器的证书以验证服务器的身份。
用于指定密钥库和信任库的配置示例quarkus.tls.my-server.key-store.p12.path=target/certs/grpc-keystore.p12 quarkus.tls.my-server.key-store.p12.password=password quarkus.tls.my-server.trust-store.p12.path=target/certs/grpc-server-truststore.p12 quarkus.tls.my-server.trust-store.p12.password=password quarkus.tls.my-client.trust-store.p12.path=target/certs/grpc-client-truststore.p12 quarkus.tls.my-client.trust-store.p12.password=password quarkus.tls.my-client.key-store.p12.path=target/certs/grpc-client-keystore.p12 quarkus.tls.my-client.key-store.p12.password=password quarkus.grpc.clients.hello.plain-text=false quarkus.grpc.clients.hello.tls-configuration-name=my-client quarkus.grpc.clients.hello.use-quarkus-grpc-client=true quarkus.http.ssl.client-auth=REQUIRED # Enable mTLS quarkus.http.insecure-requests=disabled quarkus.http.tls-configuration-name=my-server quarkus.grpc.server.use-separate-server=false quarkus.grpc.server.plain-text=false
此配置通过确保服务器和客户端都验证彼此的证书来启用 mTLS,从而提供额外的安全层。
2. 引用 TLS 配置
要引用通过使用 quarkus.tls.<name>.*
属性(如使用 TLS 注册表中所述)创建的示例命名配置,请使用 tls-configuration-name
属性,如以下示例所示
# Reference the named configuration
quarkus.http.tls-configuration-name=MY_TLS_CONFIGURATION
quarkus.grpc.clients.hello.tls-configuration-name=MY_TLS_CONFIGURATION
quarkus.smallrye-graphql-client.my-client.tls-configuration-name=MY_TLS_CONFIGURATION
当使用具有证书重新加载机制的 Typesafe GraphQL 客户端时(如重新加载证书部分中所述),必须将 bean 的作用域覆盖为 |
2.1. 引用 SunJSSE 的默认信任库
JDK 发行版通常在 $JAVA_HOME/lib/security/cacerts
文件中包含一个信任库。SunJSSE(Java 安全套接字扩展 (JSSE) 的默认实现)将此信任库用作默认信任库。SunJSSE 提供的 SSL/TLS 功能被各种 Java 运行时组件(例如 javax.net.ssl.HttpsURLConnection
等)所利用。
尽管 Quarkus 扩展通常不遵守 SunJSSE 的默认信任库,但在某些情况下使用它仍然是可行的。这适用于从旧技术迁移或在 Linux 发行版上运行的情况,在 Linux 发行版中,SunJSSE 信任库与操作系统 (OS) 同步。
为了简化 SunJSSE 信任库的使用,Quarkus TLS 注册表在名称 javax.net.ssl
下提供了一个 TLS 配置,该配置模拟了 SunJSSE 的默认行为
-
如果定义了
javax.net.ssl.trustStore
系统属性,则其值将被视为信任库。 -
否则,将检查路径
$JAVA_HOME/lib/security/jssecacerts
和$JAVA_HOME/lib/security/cacerts
,并将第一个现有文件用作信任库。 -
如果未满足任何条件,则会抛出
IllegalStateException
。
用于打开信任库的密码取自 javax.net.ssl.trustStorePassword
系统属性。如果未设置此属性,则使用默认密码 changeit
。
javax.net.ssl
配置可以用作各种 *.tls-configuration-name
属性的值,如下所示
quarkus.grpc.clients.hello.tls-configuration-name=javax.net.ssl
|
3. 配置 TLS
TLS 配置主要涉及管理密钥库和信任库。具体设置取决于使用的格式,例如 PEM、P12 或 JKS。
以下部分概述了可用于配置 TLS 的各种属性。
3.1. 密钥库
密钥库存储私钥和证书。它们主要在服务器端使用,但在使用 mTLS 时也可以在客户端使用。
3.1.1. PEM 密钥库
隐私增强邮件 (PEM) 密钥库由文件对列表组成
-
证书文件 -
.crt
或.pem
文件。 -
私钥文件 - 通常是
.key
文件。
要配置 PEM 密钥库
quarkus.tls.key-store.pem.a.cert=server.crt
quarkus.tls.key-store.pem.a.key=server.key
quarkus.tls.key-store.pem.b.cert=my-second-cert.crt
quarkus.tls.key-store.pem.b.key=my-second-key.key
在大多数情况下,您只需要一对由证书和私钥组成的对。即使证书是证书链的一部分,它也只包含一个与终端实体证书对应的私钥。
当配置了多个对时,选择配置的证书和私钥对之一基于服务器名称指示 (SNI)。客户端将客户端尝试连接的服务器名称发送到服务器,服务器选择适当的证书和私钥对。要使用此功能,请确保在客户端和服务器上都启用了 SNI。
当配置多个密钥对或证书对时,服务器默认按其名称的字典顺序执行配置的对,如前面的示例中 此设置在使用 SNI 时很重要,因为它使用第一个指定的对作为默认值。 |
当使用 PEM 密钥库时,支持以下格式
-
PKCS#8 私钥(未加密)
-
PKCS#1 RSA 私钥(未加密)
-
加密的 PKCS#8 私钥(使用 AES-128-CBC 加密)
在后一种情况下,必须将 quarkus.tls.key-store.pem.password
或 quarkus.tls.key-store.pem.<name>.password
属性设置为用于解密私钥的密码。
quarkus.tls.http.key-store.pem.cert=certificate.crt
quarkus.tls.http.key-store.pem.key=key.key
quarkus.tls.http.key-store.pem.password=password
3.1.2. PKCS12 密钥库
PKCS12 密钥库是包含证书和私钥的单个文件。
要配置 PKCS12 密钥库
quarkus.tls.key-store.p12.path=server-keystore.p12
quarkus.tls.key-store.p12.password=secret
.p12
文件受密码保护,因此您需要提供密码才能打开密钥库。
这些文件可以包含多个证书和私钥。如果是这种情况,请执行以下任一操作
-
提供并配置您要使用的证书和私钥的别名
quarkus.tls.key-store.p12.path=server-keystore.p12 quarkus.tls.key-store.p12.password=secret quarkus.tls.key-store.p12.alias=my-alias quarkus.tls.key-store.p12.alias-password=my-alias-password
-
或者,使用 SNI 选择适当的证书和私钥。请注意,所有密钥都必须使用相同的密码。
3.1.3. JKS 密钥库
JKS 密钥库是包含用于服务器或客户端的证书和私钥的单个文件,用于在 TLS/SSL 连接中验证身份并建立安全通信。
JKS 是一种旧的但仍被广泛使用的 Java 特定格式。但是,要使用此格式,您必须使用特定的(现在也已弃用的)Java 工具。因此,不建议将其与 Quarkus 应用程序一起使用。 此外,OpenShift cert-manager 或 Let's Encrypt 通常不提供 JKS,并且仅保留 PEM。 |
要配置 JKS 密钥库
quarkus.tls.key-store.jks.path=server-keystore.jks
quarkus.tls.key-store.jks.password=secret
.jks
文件受密码保护,因此您需要提供密码才能打开密钥库。此外,它们可以包含多个证书和私钥。如果是这种情况
-
提供并配置您要使用的证书和私钥的别名
quarkus.tls.key-store.jks.path=server-keystore.jks quarkus.tls.key-store.jks.password=secret quarkus.tls.key-store.jks.alias=my-alias quarkus.tls.key-store.jks.alias-password=my-alias-password
-
或者,使用 SNI 选择适当的证书和私钥。请注意,所有密钥都必须使用相同的密码。
3.1.4. 提供的密钥库
如果您需要更多地控制 TLS 配置中使用的密钥库,您可以提供一个实现 io.quarkus.tls.runtime.KeyStoreProvider
接口的 CDI bean。Quarkus 在最初创建 TLS 配置时以及每次重新加载配置时调用 KeyStoreProvider::getKeyStore
。然后,生成的密钥库和选项通过 TlsConfiguration::getKeyStore
和 TlsConfiguration::getKeyStoreOptions
提供。
import io.quarkus.tls.runtime.KeyStoreAndKeyCertOptions;
import io.quarkus.tls.runtime.KeyStoreProvider;
import io.smallrye.common.annotation.Identifier;
import io.vertx.core.Vertx;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.net.PemKeyCertOptions;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
@ApplicationScoped (1)
@Identifier("<name>") (2)
public class ExampleKeyStoreProvider implements KeyStoreProvider {
@Inject (3)
SecurityDatabase securityDatabase;
@Override
public KeyStoreAndKeyCertOptions getKeyStore(Vertx vertx) {
try {
var options = new PemKeyCertOptions()
.addCertValue(Buffer.buffer(securityDatabase.getEntityCertificate()))
.addKeyValue(Buffer.buffer(securityDatabase.getEntityPrivateKey()));
var keyStore = options
.loadKeyStore(vertx);
return new KeyStoreAndKeyCertOptions(keyStore, options);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
1 | 实现 KeyStoreProvider 接口的 CDI bean 可以是 @ApplicationScoped 、@Singleton 或 @Dependent 。 |
2 | 使用 @Identifier 限定符指示要为其提供密钥库选项的命名 TLS 配置。省略限定符(或显式使用 @Default )以指示默认 TLS 配置。有关更多详细信息,请参阅引用 TLS 配置。 |
3 | 可以注入其他 CDI bean 以便在运行时访问密钥库材料。 |
3.1.5. SNI
服务器名称指示 (SNI) 是一种 TLS 扩展,使客户端可以在 TLS 握手期间指定尝试连接的主机名。SNI 使服务器能够为单个 IP 地址上的多个域提供不同的 TLS 证书,从而方便虚拟主机方案的安全通信。
要启用 SNI
quarkus.tls.key-store.sni=true # Disabled by default
启用 SNI 后,客户端会在 TLS 握手期间指示服务器名称,这允许服务器选择适当的证书
-
使用 PEM 文件配置密钥库时,必须提供多个证书 (CRT) 和密钥文件。CRT 是 X.509 证书文件的常见文件扩展名,通常采用 PEM(隐私增强邮件)格式。这些文件包含公共证书。
-
使用 JKS 或 P12 文件配置密钥库时,服务器会根据客户端在 TLS 握手期间提供的 SNI 主机名选择适当的证书。服务器将 SNI 主机名与密钥库中存储的证书中配置的公用名 (CN) 或主题备用名称 (SAN) 匹配。所有密钥库和别名密码必须相同。
3.1.6. 凭据提供程序
您可以使用凭据提供程序,而不是在配置中传递密钥库密码和别名密码。
凭据提供程序提供了一种检索密钥库和别名密码的方法。请注意,仅当未在配置中设置密码或别名密码时才使用凭据提供程序。
要配置凭据提供程序
# The name of the credential bucket in the credentials provider
quarkus.tls.key-store.credentials-provider.name=my-credentials
# The name of the bean providing the credential provider (optional, using the default credential provider if not set)
quarkus.tls.key-store.credentials-provider.bean-name=my-credentials-provider
# The key used to retrieve the keystore password, `password` by default
quarkus.tls.key-store.credentials-provider.password-key=password
# The key used to retrieve the alias password, `alias-password` by default
quarkus.tls.key-store.credentials-provider.alias-password-key=alias-password
凭据提供程序只能与 PKCS12 和 JKS 密钥库一起使用。 |
3.2. 信任库
信任库用于存储受信任方的证书。在常规 TLS 中,客户端使用信任库来验证服务器的身份。使用相互 TLS (mTLS) 时,服务器和客户端都使用信任库来相互验证身份。
3.2.1. PEM 信任库
PEM 信任库由 .crt
或 .pem
文件列表组成。每个文件都包含一个证书。
要配置 PEM 信任库
quarkus.tls.trust-store.pem.certs=ca.crt,ca2.pem
3.2.2. PKCS12 信任库
PKCS12 信任库是包含证书的单个文件。当包含多个证书时,您可以使用别名来选择适当的证书。
要配置 PKCS12 信任库
quarkus.tls.trust-store.p12.path=client-truststore.p12
quarkus.tls.trust-store.p12.password=password
quarkus.tls.trust-store.p12.alias=my-alias
.p12
文件受密码保护,因此您需要提供密码才能打开信任库。但是,与密钥库不同,别名不需要密码,因为它包含公共证书,而不是私钥。
3.2.3. JKS 信任库
JKS 信任库是包含多个证书的单个文件。当存在多个证书时,您可以使用别名来选择适当的证书。但是,应避免使用 JKS 格式,因为它不如 PKCS12 安全。
要配置 JKS 信任库
quarkus.tls.trust-store.jks.path=client-truststore.jks
quarkus.tls.trust-store.jks.password=password
quarkus.tls.trust-store.jks.alias=my-alias
.jks
文件受密码保护,因此您需要提供密码才能打开信任库。但是,与密钥库不同,别名不需要密码,因为它包含公共证书,而不是私钥。
3.2.4. 提供的信任库
如果您需要更多地控制 TLS 配置中使用的信任库,您可以提供一个实现 io.quarkus.tls.runtime.TrustStoreProvider
接口的 CDI bean。Quarkus 在最初创建 TLS 配置时以及每次重新加载配置时调用 TrustStoreProvider::getTrustStore
。然后,生成的信任库和选项通过 TlsConfiguration::getTrustStore
和 TlsConfiguration::getTrustStoreOptions
提供。
import io.quarkus.tls.runtime.TrustStoreAndTrustOptions;
import io.quarkus.tls.runtime.TrustStoreProvider;
import io.smallrye.common.annotation.Identifier;
import io.vertx.core.Vertx;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.net.PemTrustOptions;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
@ApplicationScoped (1)
@Identifier("<name>") (2)
public class ExampleTrustStoreProvider implements TrustStoreProvider {
@Inject (3)
SecurityDatabase securityDatabase;
@Override
public TrustStoreAndTrustOptions getTrustStore(Vertx vertx) {
try {
var options = new PemTrustOptions()
.addCertValue(Buffer.buffer(securityDatabase.getTrustedRootCertificate()));
var trustStore = options
.loadKeyStore(vertx);
return new TrustStoreAndTrustOptions(trustStore, options);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
1 | 实现 TrustStoreProvider 接口的 CDI bean 可以是 @ApplicationScoped 、@Singleton 或 @Dependent 。 |
2 | 使用 @Identifier 限定符指示要为其提供信任库选项的命名 TLS 配置。省略限定符(或显式使用 @Default )以指示默认 TLS 配置。有关更多详细信息,请参阅引用 TLS 配置。 |
3 | 可以注入其他 CDI bean 以便在运行时访问信任库材料。 |
3.2.5. 凭据提供程序
您可以不通过在配置中传递信任库密码,而是使用凭据提供程序。凭据提供程序允许您检索密码和其他凭据。请注意,仅当未在配置中设置密码时才使用凭据提供程序。
要配置凭据提供程序
# The name of the credential bucket in the credentials provider
quarkus.tls.trust-store.credentials-provider.name=my-credentials
# The name of the bean providing the credential provider (optional, using the default credential provider if not set)
quarkus.tls.trust-store.credentials-provider.bean-name=my-credentials-provider
# The key used to retrieve the truststore password, `password` by default
quarkus.tls.trust-store.credentials-provider.password-key=password
凭据提供程序只能与 PKCS12 和 JKS 信任库一起使用。 |
3.3. 其他属性
虽然密钥库和信任库是最重要的属性,但您还可以使用其他属性来配置 TLS。
虽然以下示例使用默认配置,但您可以通过使用配置的名称作为属性的前缀来使用命名配置。 |
3.3.1. 密码套件
密码套件是在 TLS 握手期间可以使用的密码列表。您可以配置已启用密码套件的有序列表。如果未配置,则会从内置密码中选择合理的默认值。但是,当指定后,您的配置将优先于正在使用的 SSL 引擎定义的默认套件。
要配置密码套件
quarkus.tls.cipher-suites=TLS_AES_128_GCM_SHA256,TLS_AES_256_GCM_SHA384
3.3.2. TLS 协议版本
TLS 协议版本是在 TLS 握手期间可以使用的协议列表。已启用的 TLS 协议版本指定为以逗号分隔的有序列表。相关配置属性是 quarkus.tls.protocols
或 quarkus.tls.<name>.protocols
(用于命名 TLS 配置)。如果未配置,则默认为 TLSv1.3, TLSv1.2
。
可用选项为 TLSv1
、TLSv1.1
、TLSv1.2
和 TLSv1.3
。
例如,要仅启用 TLSv1.3
quarkus.tls.protocols=TLSv1.3
3.3.3. 握手超时
建立 TLS 连接时,握手阶段是第一步。在此阶段,客户端和服务器交换信息以建立连接,这通常包括密码套件、TLS 协议版本和证书验证。
要配置握手阶段的超时
quarkus.tls.handshake-timeout=10S # Default.
3.3.4. ALPN
应用层协议协商 (ALPN) 是一种 TLS 扩展,允许客户端和服务器协商它们将在 TLS 握手期间使用哪种协议进行通信。ALPN 通过允许客户端在建立 TLS 连接之前向服务器指示其首选应用协议来提高通信效率。
这有助于在 HTTP/2 等场景中,其中可能有多个协议可用,从而可以更快地选择协议。
默认情况下启用 ALPN。
-
要禁用它
quarkus.tls.alpn=false
不建议非专业人士禁用 ALPN,因为它可能会导致性能下降、协议协商问题和意外行为,特别是对于 HTTP/2 等协议。但是,禁用 ALPN 对于诊断本机不一致或在协议协商导致冲突的特定边缘情况下测试性能可能很有用。
3.3.5. 证书吊销列表 (CRL)
证书吊销列表 (CRL) 是颁发证书颁发机构 (CA) 在其预定到期日期之前吊销的证书的列表。当证书泄露、不再需要或被视为无效时,CA 会将其添加到 CRL 中,以通知依赖方不再信任它。
您可以使用 DER 或 PKCS#7 (P7B) 格式配置 CRL 以及您不再信任的证书文件列表。
-
对于 DER 格式,请传递 DER 编码的 CRL。
-
对于 PKCS#7 格式,请传递
SignedData
对象,其中唯一重要的字段是crls
。
要配置 CRL
quarkus.tls.certificate-revocation-list=ca.crl, ca2.crl
3.3.6. 信任所有证书和主机名验证
您可以配置 TLS 连接以信任所有证书并禁用主机名验证。请注意,这是两个不同的过程
-
信任所有证书会忽略证书验证,因此所有证书都受到信任。此方法对于使用自签名证书进行测试很有用,但不应在生产中使用。
-
主机名验证是验证服务器身份的过程。
它有助于防止中间人攻击,并且通常默认为 HTTPS
或 LDAPS
。
这两个属性不应在生产中使用。 |
要信任所有证书
quarkus.tls.trust-all=true
要禁用主机名验证
quarkus.tls.hostname-verification-algorithm=NONE
3.3.7. 防止客户端重新协商
客户端发起的重新协商允许客户端请求新的会话参数,例如已建立 TLS 连接期间的其他密码套件。虽然此功能可以提供灵活性,但在使用 TLS 1.2 时也会引入潜在的安全风险。
当客户端发起新的 TLS 握手时,服务器通常比客户端消耗更多的 CPU 资源。这种资源不对称性可能会被利用来发起拒绝服务 (DoS) 攻击,从而使服务器承受大量重新协商请求。
TLS 1.3 完全删除对重新协商的支持,从而有效关闭了此潜在的攻击媒介。
-
要保护 TLS 1.2 及更早版本,请将
jdk.tls.rejectClientInitiatedRenegotiation
设置为true
以防止客户端发起的重新协商。# JVM mode: java -Djdk.tls.rejectClientInitiatedRenegotiation=true -jar ... # Native mode ./application -Djdk.tls.rejectClientInitiatedRenegotiation=true
如果您在 JVM 模式下使用 Quarkus 提供的
Dockerfile
,则可以通过将属性添加到JAVA_OPTS_APPEND
环境变量来禁用重新协商ENV JAVA_OPTS_APPPEND="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager -Djdk.tls.rejectClientInitiatedRenegotiation=true"
3.4. 配置参考
下表列出了支持的属性
构建时固定的配置属性 - 所有其他配置属性都可以在运行时覆盖
配置属性 |
类型 |
默认 |
---|---|---|
设置为 环境变量: 显示更多 |
布尔值 |
|
密钥/证书文件的顺序,基于 默认情况下,Quarkus 使用字典顺序对密钥进行排序。此属性允许您指定密钥/证书文件的顺序。 环境变量: 显示更多 |
字符串列表 |
|
path |
必需 |
|
密钥库的密码。如果未设置,则必须从凭据提供程序检索密码。 环境变量: 显示更多 |
字符串 |
|
字符串 |
||
密钥库中别名的密码。如果未设置,则将从凭据提供程序检索密码。 环境变量: 显示更多 |
字符串 |
|
字符串 |
||
path |
必需 |
|
密钥库的密码。如果未设置,则必须从凭据提供程序检索密码。 环境变量: 显示更多 |
字符串 |
|
字符串 |
||
密钥库中别名的密码。如果未设置,则可以从凭据提供程序检索密码。 环境变量: 显示更多 |
字符串 |
|
字符串 |
||
启用服务器名称指示 (SNI)。 服务器名称指示 (SNI) 是一种 TLS 扩展,允许客户端在 TLS 握手期间指定其尝试连接的主机名。这使服务器能够在单个 IP 地址上为多个域提供不同的 SSL 证书,从而方便虚拟主机方案的安全通信。 启用此设置后,客户端会在 TLS 握手期间指示服务器名称,从而允许服务器选择正确的证书。 使用 PEM 文件配置密钥库时,必须提供多个 CRT/密钥。使用 JKS 或 P12 文件配置密钥库时,它会根据 SNI 主机名选择一个别名。在这种情况下,所有密钥库密码和别名密码必须相同(使用 环境变量: 显示更多 |
布尔值 |
|
要从 凭据提供程序提供了一种检索密钥库密码以及别名密码的方法。请注意,仅当未在配置中设置密码时才使用凭据提供程序。 环境变量: 显示更多 |
字符串 |
|
提供凭据提供程序的 bean 的名称。 该名称用于选择要使用的凭据提供程序。必须将凭据提供程序作为 CDI bean 公开,并将 如果未设置,则使用默认凭据提供程序。 环境变量: 显示更多 |
字符串 |
|
用于检索密钥库密码的密钥。 如果所选凭据提供程序不支持该密钥,则不会检索密码。否则,将使用检索到的值来打开密钥库。 环境变量: 显示更多 |
字符串 |
|
用于检索密钥库别名密码的密钥。 如果所选凭据提供程序不包含密钥,则不会检索别名密码。否则,将使用检索到的值来访问密钥库中的别名 环境变量: 显示更多 |
字符串 |
|
路径列表 |
||
path |
必需 |
|
信任库的密码。如果未设置,则必须从凭据提供程序检索密码。 环境变量: 显示更多 |
字符串 |
|
字符串 |
||
字符串 |
||
path |
必需 |
|
信任库的密码。如果未设置,则必须从凭据提供程序检索密码。 环境变量: 显示更多 |
字符串 |
|
字符串 |
||
字符串 |
||
强制执行证书过期。启用后,将验证证书到期日期,如果证书已过期,则将拒绝证书(或链中的任何证书)。 环境变量: 显示更多 |
|
|
要从 凭据提供程序提供了一种检索密钥库密码以及别名密码的方法。请注意,仅当未在配置中设置密码时才使用凭据提供程序。 环境变量: 显示更多 |
字符串 |
|
提供凭据提供程序的 bean 的名称。 该名称用于选择要使用的凭据提供程序。必须将凭据提供程序作为 CDI bean 公开,并将 如果未设置,则使用默认凭据提供程序。 环境变量: 显示更多 |
字符串 |
|
用于检索信任存储密码的密钥。 如果所选凭据提供程序不包含配置的密钥,则不会检索密码。否则,检索到的值将用于打开信任存储。 环境变量: 显示更多 |
字符串 |
|
设置已启用的密码套件的有序列表。 如果未给出任何内容,则将从内置密码中选择合理的默认值。 当设置套件时,它优先于正在使用的 环境变量: 显示更多 |
字符串列表 |
|
设置已启用的 TLS 协议的有序列表。 如果未设置,则默认为 请注意,设置空列表并启用 TLS 是无效的。 您必须至少有一个协议。 此外,设置此选项会替换默认协议列表。 环境变量: 显示更多 |
字符串列表 |
|
TLS 握手阶段的超时时间。 如果未设置,则默认为 10 秒。 环境变量: 显示更多 |
|
|
启用应用程序层协议协商 (ALPN)。 应用程序层协议协商是一种 TLS 扩展,允许客户端和服务器在 TLS 握手期间协商它们将用于通信的协议。 ALPN 通过允许客户端在建立 TLS 连接之前向服务器指示其首选应用程序协议,从而实现更高效的通信。 这有助于诸如 HTTP/2 之类的场景,其中可能有多个协议可用,从而加快协议选择。 环境变量: 显示更多 |
布尔值 |
|
设置吊销证书的列表(文件路径)。 证书吊销列表 (CRL) 是由颁发证书颁发机构 (CA) 在其预定到期日期之前吊销的数字证书的列表。 当证书被泄露、不再需要或因任何原因被视为无效时,CA 会将其添加到 CRL 以通知依赖方不要再信任该证书。 允许两种格式:DER 和 PKCS#7(也称为 P7B)。 使用 DER 格式时,必须传递 DER 编码的 CRL。 使用 PKCS#7 格式时,必须传递 PKCS#7 环境变量: 显示更多 |
路径列表 |
|
布尔值 |
|
|
如果应检查服务器的身份,则使用的主机名验证算法。 应为 如果设置为 如果未设置,则配置的扩展决定要使用的默认算法。 例如,对于 HTTP,它将是“HTTPS”。 对于 TCP,它可能取决于协议。 然而,建议将其设置为“HTTPS”或“LDAPS”。 环境变量: 显示更多 |
字符串 |
|
配置后,服务器将重新加载证书(例如,从文件系统),如果重新加载成功,则会触发 此属性配置重新加载证书的周期。 如果未设置,则证书不会自动重新加载。 但是,应用程序仍然可以使用 触发的事件用于通知应用程序证书已更新,从而继续进行证书的实际切换。 环境变量: 显示更多 |
||
密钥文件的路径(采用 PEM 格式:PKCS#8、PKCS#1 或加密的 PKCS#8)。 环境变量: 显示更多 |
path |
必需 |
证书文件的路径(采用 PEM 格式)。 环境变量: 显示更多 |
path |
必需 |
当密钥被加密(加密的 PKCS#8)时,用于解密它的密码。 环境变量: 显示更多 |
字符串 |
|
密钥文件的路径(采用 PEM 格式:PKCS#8、PKCS#1 或加密的 PKCS#8)。 环境变量: 显示更多 |
path |
必需 |
证书文件的路径(采用 PEM 格式)。 环境变量: 显示更多 |
path |
必需 |
当密钥被加密(加密的 PKCS#8)时,用于解密它的密码。 环境变量: 显示更多 |
字符串 |
|
密钥/证书文件的顺序,基于 默认情况下,Quarkus 使用字典顺序对密钥进行排序。此属性允许您指定密钥/证书文件的顺序。 环境变量: 显示更多 |
字符串列表 |
|
密钥库文件的路径(P12 / PFX 格式)。 环境变量: 显示更多 |
path |
必需 |
密钥库的密码。如果未设置,则必须从凭据提供程序检索密码。 环境变量: 显示更多 |
字符串 |
|
密钥库中私钥和证书的别名。 环境变量: 显示更多 |
字符串 |
|
密钥库中别名的密码。如果未设置,则将从凭据提供程序检索密码。 环境变量: 显示更多 |
字符串 |
|
密钥库的提供程序。 环境变量: 显示更多 |
字符串 |
|
密钥库文件的路径(JKS 格式)。 环境变量: 显示更多 |
path |
必需 |
密钥库的密码。如果未设置,则必须从凭据提供程序检索密码。 环境变量: 显示更多 |
字符串 |
|
密钥库中私钥和证书的别名。 环境变量: 显示更多 |
字符串 |
|
密钥库中别名的密码。如果未设置,则可以从凭据提供程序检索密码。 环境变量: 显示更多 |
字符串 |
|
密钥库的提供程序。 环境变量: 显示更多 |
字符串 |
|
启用服务器名称指示 (SNI)。 服务器名称指示 (SNI) 是一种 TLS 扩展,允许客户端在 TLS 握手期间指定其尝试连接的主机名。这使服务器能够在单个 IP 地址上为多个域提供不同的 SSL 证书,从而方便虚拟主机方案的安全通信。 启用此设置后,客户端会在 TLS 握手期间指示服务器名称,从而允许服务器选择正确的证书。 使用 PEM 文件配置密钥库时,必须提供多个 CRT/密钥。使用 JKS 或 P12 文件配置密钥库时,它会根据 SNI 主机名选择一个别名。在这种情况下,所有密钥库密码和别名密码必须相同(使用 环境变量: 显示更多 |
布尔值 |
|
要从 凭据提供程序提供了一种检索密钥库密码以及别名密码的方法。请注意,仅当未在配置中设置密码时才使用凭据提供程序。 环境变量: 显示更多 |
字符串 |
|
提供凭据提供程序的 bean 的名称。 该名称用于选择要使用的凭据提供程序。必须将凭据提供程序作为 CDI bean 公开,并将 如果未设置,则使用默认凭据提供程序。 环境变量: 显示更多 |
字符串 |
|
用于检索密钥库密码的密钥。 如果所选凭据提供程序不支持该密钥,则不会检索密码。否则,将使用检索到的值来打开密钥库。 环境变量: 显示更多 |
字符串 |
|
用于检索密钥库别名密码的密钥。 如果所选凭据提供程序不包含密钥,则不会检索别名密码。否则,将使用检索到的值来访问密钥库中的别名 环境变量: 显示更多 |
字符串 |
|
受信任证书路径列表(Pem 格式)。 环境变量: 显示更多 |
路径列表 |
|
信任库文件的路径(P12 / PFX 格式)。 环境变量: 显示更多 |
path |
必需 |
信任库的密码。如果未设置,则必须从凭据提供程序检索密码。 环境变量: 显示更多 |
字符串 |
|
信任库的别名。 环境变量: 显示更多 |
字符串 |
|
信任库的提供程序。 环境变量: 显示更多 |
字符串 |
|
信任库文件的路径(JKS 格式)。 环境变量: 显示更多 |
path |
必需 |
信任库的密码。如果未设置,则必须从凭据提供程序检索密码。 环境变量: 显示更多 |
字符串 |
|
信任库中密钥的别名。 环境变量: 显示更多 |
字符串 |
|
信任库的提供程序。 环境变量: 显示更多 |
字符串 |
|
强制执行证书过期。启用后,将验证证书到期日期,如果证书已过期,则将拒绝证书(或链中的任何证书)。 环境变量: 显示更多 |
|
|
要从 凭据提供程序提供了一种检索密钥库密码以及别名密码的方法。请注意,仅当未在配置中设置密码时才使用凭据提供程序。 环境变量: 显示更多 |
字符串 |
|
提供凭据提供程序的 bean 的名称。 该名称用于选择要使用的凭据提供程序。必须将凭据提供程序作为 CDI bean 公开,并将 如果未设置,则使用默认凭据提供程序。 环境变量: 显示更多 |
字符串 |
|
用于检索信任存储密码的密钥。 如果所选凭据提供程序不包含配置的密钥,则不会检索密码。否则,检索到的值将用于打开信任存储。 环境变量: 显示更多 |
字符串 |
|
设置已启用的密码套件的有序列表。 如果未给出任何内容,则将从内置密码中选择合理的默认值。 当设置套件时,它优先于正在使用的 环境变量: 显示更多 |
字符串列表 |
|
设置已启用的 TLS 协议的有序列表。 如果未设置,则默认为 请注意,设置空列表并启用 TLS 是无效的。 您必须至少有一个协议。 此外,设置此选项会替换默认协议列表。 环境变量: 显示更多 |
字符串列表 |
|
TLS 握手阶段的超时时间。 如果未设置,则默认为 10 秒。 环境变量: 显示更多 |
|
|
启用应用程序层协议协商 (ALPN)。 应用程序层协议协商是一种 TLS 扩展,允许客户端和服务器在 TLS 握手期间协商它们将用于通信的协议。 ALPN 通过允许客户端在建立 TLS 连接之前向服务器指示其首选应用程序协议,从而实现更高效的通信。 这有助于诸如 HTTP/2 之类的场景,其中可能有多个协议可用,从而加快协议选择。 环境变量: 显示更多 |
布尔值 |
|
设置吊销证书的列表(文件路径)。 证书吊销列表 (CRL) 是由颁发证书颁发机构 (CA) 在其预定到期日期之前吊销的数字证书的列表。 当证书被泄露、不再需要或因任何原因被视为无效时,CA 会将其添加到 CRL 以通知依赖方不要再信任该证书。 允许两种格式:DER 和 PKCS#7(也称为 P7B)。 使用 DER 格式时,必须传递 DER 编码的 CRL。 使用 PKCS#7 格式时,必须传递 PKCS#7 环境变量: 显示更多 |
路径列表 |
|
如果设置为 这对于测试很有用,但不应在生产中使用。 环境变量: 显示更多 |
布尔值 |
|
如果应检查服务器的身份,则使用的主机名验证算法。 应为 如果设置为 如果未设置,则配置的扩展决定要使用的默认算法。 例如,对于 HTTP,它将是“HTTPS”。 对于 TCP,它可能取决于协议。 然而,建议将其设置为“HTTPS”或“LDAPS”。 环境变量: 显示更多 |
字符串 |
|
配置后,服务器将重新加载证书(例如,从文件系统),如果重新加载成功,则会触发 此属性配置重新加载证书的周期。 如果未设置,则证书不会自动重新加载。 但是,应用程序仍然可以使用 触发的事件用于通知应用程序证书已更新,从而继续进行证书的实际切换。 环境变量: 显示更多 |
关于 Duration 格式
要写入持续时间值,请使用标准的 您还可以使用简化的格式,以数字开头
在其他情况下,简化格式将被转换为
|
4. 注册表 API
虽然扩展会自动使用 TLS 注册表,但您也可以通过注册表 API 以编程方式访问 TLS 配置。
要访问 TLS 配置,请注入 TlsConfigurationRegistry
bean。 您可以通过调用 get("<NAME>")
来检索命名的 TLS 配置,或者通过调用 getDefault()
来检索默认配置。
@Inject
TlsConfigurationRegistry certificates;
// ...
TlsConfiguration def = certificates.getDefault().orElseThrow();
TlsConfiguration named = certificates.get("name").orElseThrow();
//...
TlsConfiguration
对象包含密钥库、信任库、密码套件、协议和其他属性。 它还提供了一种从配置创建 SSLContext
的方法。
您还可以使用 TlsConfiguration
对象来配置 Vert.x 客户端或服务器,例如 KeyCertOptions
、TrustOptions
等。
5. 从扩展注册证书
本节仅适用于扩展开发人员。 扩展可以在 TLS 注册表中注册证书。 当扩展需要向应用程序提供证书或提供不同的格式时,这很有用。
要通过使用扩展在 TLS 注册表中注册证书,处理器 扩展必须生成由名称和 CertificateSupplier
组成的 TlsCertificateBuildItem
。
TlsCertificateBuildItem item = new TlsCertificateBuildItem("named",
new MyCertificateSupplier());
证书供应商通常是通过使用记录器方法检索的运行时对象。
public class MyCertificateSupplier implements Supplier<TlsConfiguration> {
@Override
public TlsConfiguration get() {
try {
KeyStore ks = KeyStore.getInstance("PKCS12");
ks.load(getClass().getResourceAsStream("target/certs/test-registration-keystore.p12"),
"password".toCharArray());
KeyStore ts = KeyStore.getInstance("PKCS12");
ts.load(getClass().getResourceAsStream("target/certs/test-registration-truststore.p12"),
"password".toCharArray());
return new BaseTlsConfiguration() {
@Override
public KeyStore getKeyStore() {
return ks;
}
@Override
public KeyStore getTrustStore() {
return ts;
}
};
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
6. 启动检查
当使用 TLS 扩展的应用程序启动时,TLS 注册表会执行多项检查以确保配置正确
-
密钥库和信任库是可访问的。
-
别名在密钥库和信任库中可用且可访问。
-
证书有效。
-
密码套件和协议有效。
-
证书吊销列表 (CRL) 有效。
如果任何这些检查失败,应用程序将不会启动。
7. 重新加载证书
从 TLSConfigurationRegistry
获取的 TlsConfiguration
包括一种重新加载证书的机制。 reload
方法会刷新密钥库、信任库和 CRL,通常是通过从文件系统重新加载它们。
重新加载操作不是自动的,必须手动触发。 此外,TlsConfiguration 实现必须支持重新加载,就像配置的证书一样。 |
reload
方法返回一个 boolean
,指示重新加载是否成功。 true
值表示重新加载操作成功,不一定表示证书有更新。
重新加载 TlsConfiguration
后,使用此配置的服务器和客户端可能需要执行特定操作才能应用新证书。
通知客户端和服务器有关证书重新加载的建议方法是触发 io.quarkus.tls.CertificateUpdatedEvent
类型的 CDI 事件。 为此,请注入此类型的 CDI 事件并在重新加载时触发它。
CertificateUpdatedEvent
并对其做出反应来通知组件的示例// in the class that performs the reload
@Inject
Event<CertificateUpdatedEvent> event;
@Inject
TlsConfigurationRegistry registry;
public void reload() {
TlsConfiguration config = registry.get("name").orElseThrow();
if (config.reload()) {
event.fire(new CertificateUpdatedEvent("name", config));
}
}
// In the server (or client) code
private final io.vertx.core.http.HttpServer server;
public void onCertificateUpdate(@Observes CertificateUpdatedEvent reload) {
if ("name".equals(event.getName())) {
server.updateSSLOptions(reload.tlsConfiguration().getSSLOptions());
// Or update the SSLContext.
}
}
7.1. 定期重新加载
TLS 注册表包括一个内置机制,用于定期检查文件系统中的更改并重新加载证书。 reload-period
属性指定重新加载证书的间隔,并在每次重新加载证书时发出 CertificateUpdatedEvent
。
-
要配置定期证书重新加载
quarkus.tls.reload-period=1h quarkus.tls.key-store.pem.0.cert=tls.crt quarkus.tls.key-store.pem.0.key=tls.key
-
对于每个命名的配置,您可以设置特定的重新加载周期
quarkus.tls.http.reload-period=30m quarkus.tls.http.key-store.pem.0.cert=tls.crt quarkus.tls.http.key-store.pem.0.key=tls.key
受影响的服务器和客户端可能需要侦听 |
在 Quarkus 开发模式下,当文件被触摸时,它将更频繁地触发 CertificateUpdatedEvent 。 |
8. 使用 Kubernetes 密钥或 cert-manager
在 Kubernetes 中运行时,您可以使用 Kubernetes 密钥来存储密钥库和信任库。
8.1. 使用 Kubernetes 密钥
-
通过使用以下密钥作为示例,创建一个包含密钥库和信任库的密钥以使用 Kubernetes 密钥
apiVersion: v1 data: tls.crt: ... tls.key: ... kind: Secret metadata: name: my-certs type: kubernetes.io/tls
-
将密钥作为卷挂载到 pod 中,这是使用这些证书的最简单方法
apiVersion: apps/v1 kind: Deployment metadata: labels: app.kubernetes.io/name: demo app.kubernetes.io/version: 1.0.0-SNAPSHOT app.kubernetes.io/managed-by: quarkus name: demo spec: replicas: 1 selector: matchLabels: app.kubernetes.io/name: demo app.kubernetes.io/version: 1.0.0-SNAPSHOT template: metadata: labels: app.kubernetes.io/managed-by: quarkus app.kubernetes.io/name: demo app.kubernetes.io/version: 1.0.0-SNAPSHOT spec: containers: - env: - name: KUBERNETES_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: ... imagePullPolicy: IfNotPresent name: demo ports: - containerPort: 8443 # Configure the port to be HTTPS name: http protocol: TCP volumeMounts: - mountPath: /certs name: my-volume volumes: - name: my-volume secret: defaultMode: 0666 # Set the permissions, otherwise the pod may not be able to read the files optional: false secretName: my-certs # Reference the secret
-
配置 TLS 注册表以使用证书
# ... # TLS Registry configuration %prod.quarkus.tls.http.key-store.pem.0.cert=/certs/tls.crt %prod.quarkus.tls.http.key-store.pem.0.key=/certs/tls.key # HTTP server configuration: %prod.quarkus.http.tls-configuration-name=http %prod.quarkus.http.insecure-requests=disabled
您可以将此与定期重新加载结合使用,以便在证书更改时自动重新加载证书。
8.2. 使用 cert-manager
在 Kubernetes 中运行时,您可以使用 cert-manager 自动生成和续订证书。 Cert-manager 生成一个包含密钥库和信任库的密钥。 配置 TLS 注册表与使用 Kubernetes 密钥时相同。 生成的密钥包括以下文件
-
证书的
tls.crt
-
私钥的
tls.key
-
CA 证书的
ca.crt
(如果需要)-
要配置自动证书续订,请使用定期重新加载机制
-
# ...
# TLS Registry configuration
%prod.quarkus.tls.http.key-store.pem.0.cert=/certs/tls.crt
%prod.quarkus.tls.http.key-store.pem.0.key=/certs/tls.key
%prod.quarkus.tls.http.reload-period=24h
# HTTP server configuration:
%prod.quarkus.http.tls-configuration-name=http
%prod.quarkus.http.insecure-requests=disabled
9. 使用 OpenShift 服务证书
在 OpenShift 中运行您的应用程序时,您可以使用 OpenShift 服务证书 来自动生成和续订 TLS 证书。 Quarkus TLS 注册表可以使用这些证书和证书颁发机构 (CA) 文件来处理 HTTPS 流量并安全地验证证书。
9.1. 获取证书
要让 OpenShift 生成服务证书,请注释现有的 Service 对象。 生成的证书将存储在密钥中,然后您可以将其挂载到您的 pod 中。
以下代码段使用带有用于生成 TLS 证书的注释的 Service 对象示例。
-
查看 Service 对象的配置
apiVersion: v1 kind: Service metadata: labels: app.kubernetes.io/name: ... app.kubernetes.io/version: ... app.kubernetes.io/managed-by: quarkus name: hero-service spec: ports: - name: http port: 443 protocol: TCP targetPort: 8443 selector: app.kubernetes.io/name: ... app.kubernetes.io/version: ... type: ClusterIP
-
要生成证书,请将此注释添加到您已创建的 OpenShift
service
oc annotate service hero-service \ service.beta.openshift.io/serving-cert-secret-name=my-tls-secret
注释
service.beta.openshift.io/serving-cert-secret-name
指示 OpenShift 生成证书并将其存储在名为my-tls-secret
的密钥中。 -
通过更新您的 Deployment 配置,将密钥作为卷挂载到您的 pod 中
apiVersion: apps/v1 kind: Deployment metadata: labels: app.kubernetes.io/name: ... app.kubernetes.io/version: ... name: my-service spec: replicas: 1 selector: matchLabels: app.kubernetes.io/name: ... app.kubernetes.io/version: ... template: metadata: labels: app.kubernetes.io/name: ... app.kubernetes.io/version: ... spec: volumes: - name: my-tls-secret (1) secret: secretName: my-tls-secret containers: - env: - name: KUBERNETES_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace - name: QUARKUS_TLS_KEY_STORE_PEM_ACME_CERT (2) value: /etc/tls/tls.crt - name: QUARKUS_TLS_KEY_STORE_PEM_ACME_KEY value: /etc/tls/tls.key image: ... imagePullPolicy: Always name: my-service volumeMounts: (3) - name: my-tls-secret mountPath: /etc/tls readOnly: true ports: - containerPort: 8443 (4) name: https protocol: TCP
1 定义一个卷以挂载密钥。 使用与上面声明的密钥相同的名称。 2 设置带有证书和私钥路径的密钥库。 可以通过使用环境变量或配置文件来配置它。 此示例使用环境变量。 OpenShift 服务证书始终创建 tls.crt
和tls.key
文件。3 将密钥挂载到容器中。 确保路径与配置中使用的路径匹配(此处为 /etc/tls
)。4 配置端口以提供 HTTPS。 -
部署您的应用程序以使用 OpenShift 生成的证书。 这将使该服务通过 HTTPS 可用。
通过设置 这为 Quarkus HTTP 服务器配置默认密钥库,这允许服务器使用该证书。 有关在命名的配置中使用此证书的信息,请参阅引用 TLS 配置。 |
9.2. 信任证书颁发机构 (CA)
既然您的服务使用 OpenShift 颁发的证书,请配置您的客户端应用程序以信任此证书。 为此,请创建一个保存 CA 证书的 ConfigMap,然后配置 pod 以挂载它。 以下步骤使用 Quarkus REST 客户端作为示例,但相同的方法适用于任何客户端。
-
首先定义一个空 ConfigMap,该 ConfigMap 将填充 CA 证书
apiVersion: v1 kind: ConfigMap metadata: name: client-tls-config annotations: service.beta.openshift.io/inject-cabundle: "true"
service.beta.openshift.io/inject-cabundle
注释用于将 CA 证书注入 ConfigMap 中。 请注意,ConfigMap 最初没有数据 — 它是空的。 在其处理过程中,OpenShift 将 CA 证书注入 ConfigMap 中的service-ca.crt
文件中。 -
通过添加卷并将其挂载到您的 Deployment 配置中来挂载 ConfigMap
apiVersion: apps/v1 kind: Deployment metadata: name: my-service-client labels: app.kubernetes.io/name: ... app.kubernetes.io/version: ... spec: replicas: 1 selector: matchLabels: app.kubernetes.io/name: ... app.kubernetes.io/version: ... template: metadata: labels: app.kubernetes.io/name: ... app.kubernetes.io/version: ... spec: containers: - name: my-service-client image: ... ports: - name: http containerPort: 8080 protocol: TCP volumeMounts: (1) - name: my-client-volume mountPath: /deployments/tls volumes: (2) - name: my-client-volume configMap: name: client-tls-config
1 将 ConfigMap 挂载到容器中。 确保路径与配置中使用的路径匹配(在此示例中为 /deployments/tls
)。2 定义一个卷以挂载 ConfigMap 并引用接收 CA 证书的 ConfigMap。 -
配置 REST 客户端以使用此 CA 证书。
考虑以下 REST 客户端接口
package org.acme; import jakarta.ws.rs.GET; import jakarta.ws.rs.Path; import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; @RegisterRestClient(baseUri = "https://hero-service.cescoffi-dev.svc", configKey = "hero") (1) public interface HeroClient { record Hero (Long id, String name, String otherName, int level, String picture, String powers) { } @GET @Path("/api/heroes/random") Hero getRandomHero(); }
1 配置基本 URI 和配置密钥。 名称必须采用 <service-name>.<namespace>.svc
格式。 否则,证书将不会被信任。 确保也配置了configKey
。 -
配置 REST 客户端以信任 OpenShift 生成的 CA 证书
quarkus.rest-client.hero.tls-configuration-name=my-service-tls (1) quarkus.tls.my-service-tls.trust-store.pem.certs=/deployments/tls/service-ca.crt (2)
1 使用名为 my-service-tls
的 TLS 配置来配置hero
REST 客户端。2 设置 my-service-tls
TLS 配置,特别是带有 CA 证书的信任库。 确保路径与 Kubernetes Deployment 配置中使用的路径匹配。 该文件始终命名为service-ca.crt
。
9.3. 证书续订
OpenShift 会自动续订它生成的服务证书。 当证书续订时,密钥将更新为新的证书和私钥。
为了确保您的应用程序使用新的证书,您可以使用 Quarkus TLS 注册表的定期重新加载功能。
通过设置 reload-period
属性,TLS 注册表将定期检查密钥库和信任库中的更改,并在需要时重新加载它们
quarkus.tls.reload-period=24h
-
(可选)实现自定义机制,以便在密钥更新时重新加载证书。 有关更多信息,请参阅重新加载证书。
10. Quarkus CLI 命令和开发证书颁发机构
TLS 注册表提供了 Quarkus CLI 命令,用于生成开发证书颁发机构 (CA) 和受信任的证书。 这避免了在本地使用自签名证书。
以下代码段显示了 quarkus tls
命令的描述,其中包含两个子命令
> quarkus tls
Install and Manage TLS development certificates
Usage: tls [COMMAND]
Commands:
generate-quarkus-ca Generate Quarkus Dev CA certificate and private key. (1)
generate-certificate Generate a TLS certificate with the Quarkus Dev CA if
available. (2)
1 | 这对于本地开发很有用,因为它允许 Quarkus 充当自己的证书颁发机构,该证书颁发机构可用于签署其他证书。 |
2 | 这在为开发期间应用程序与外部服务或客户端之间的安全通信创建证书时非常有用。 |
在大多数情况下,您只需生成一次 Quarkus 开发 CA,然后生成由该 CA 签名的证书。Quarkus 开发 CA 是一个证书颁发机构,可用于在本地签名证书。它仅对开发目的有效,并且仅在本地计算机上受信任。生成的 CA 位于 $HOME/.quarkus/quarkus-dev-root-ca.pem
中,并安装在系统信任库中。
10.1. 理解自签名证书与 CA 签名证书
使用 TLS 开发时,可以使用两种类型的证书
-
自签名证书:证书由使用它的同一实体签名。默认情况下不受信任。这种类型的证书通常在证书颁发机构 (CA) 不可用或需要简单设置时使用。它不适用于生产环境,仅用于开发。
-
CA 签名证书:证书由证书 CA(受信任的实体)签名。默认情况下信任此证书,并且是生产环境的标准选择。
虽然您可以将自签名证书用于本地开发,但它有局限性。浏览器和 curl
、wget
和 httpie
等工具通常不信任自签名证书,需要手动将 CA 导入到您的操作系统中。
为避免此问题,请使用开发 CA 对证书进行签名,并将 CA 安装到系统信任库中。这可确保系统信任由该 CA 签名的所有证书。Quarkus 简化了开发 CA 的生成以及由此 CA 签名的证书的生成。
10.2. 生成开发 CA
开发 CA 是一个证书颁发机构,可用于在本地签名证书。请注意,生成的 CA 仅对开发目的有效,并且只能在本地计算机上信任。
要生成开发 CA:
quarkus tls generate-quarkus-ca --install \ (1)
--renew \ (2)
--truststore (3)
1 | --install 将 CA 安装到系统信任库中。支持 Windows、Mac 和 Linux(Fedora 和 Ubuntu)。但是,根据您的浏览器,您可能需要手动导入生成的 CA。有关更多信息,请参阅浏览器的文档。生成的 CA 位于 $HOME/.quarkus/quarkus-dev-root-ca.pem 中。 |
2 | --renew 如果 CA 已存在,则续订 CA。使用此选项时,私钥会更改,因此您需要重新生成由 CA 签名的证书。如果 CA 过期,它将自动续订,而无需 --renew 选项。 |
3 | --truststore 还会生成包含 CA 证书的 PKCS12 信任库。 |
安装证书时,您的系统可能会要求您输入密码,以便在系统信任库中安装证书,或者在 Windows 上要求在对话框中进行确认。 |
在 Windows 上,从提升的终端以管理员身份运行,以将 CA 安装到系统信任库中。 |
10.3. 生成受信任的(已签名)证书
-
-
安装 Quarkus 开发 CA 后,生成受信任的证书。此证书将由 Quarkus 开发 CA 签名,并受到您的系统信任。
quarkus tls generate-certificate --name my-cert
此命令生成由 Quarkus 开发 CA 签名的证书,如果正确安装或导入,您的系统将信任该证书。
证书存储在
./.certs/
中。生成两个文件:
-
-
$NAME-keystore.p12
:包含私钥和证书。受密码保护。 -
$NAME-truststore.p12
:包含 CA 证书,您可以用作信任库,例如,用于测试。还有其他选项可用:
Usage: tls generate-certificate [-hrV] [-c=<cn>] [-d=<directory>] -n=<name> [-p=<password>] Generate a TLS certificate with the Quarkus Dev CA if available. -c, --cn=<cn> The common name of the certificate. Default is 'localhost' -d, --directory=<directory> The directory in which the certificates will be created. Default is `.certs` -n, --name=<name> Name of the certificate. It will be used as file name and alias in the keystore -p, --password=<password> The password of the keystore. Default is 'password' -r, --renew Whether existing certificates will need to be replaced
生成证书时还会生成一个
.env
文件,使 Quarkus 开发模式能够识别这些证书。-
在开发模式下运行您的应用程序以使用这些证书
./mvnw quarkus:dev ... INFO [io.quarkus] (Quarkus Main Thread) demo 1.0.0-SNAPSHOT on JVM (powered by Quarkus 999-SNAPSHOT) started in 1.286s. Listening on: https://:8080 and https://:8443
-
通过 HTTPS 打开 Dev UI:
https://:8443/q/dev
或发出curl
请求curl https://:8443/hello Hello from Quarkus REST%
如果未安装 Quarkus 开发 CA,Quarkus 会生成自签名证书。
-
10.4. 生成自签名证书
即使安装了 Quarkus 开发 CA,您也可以生成自签名证书
quarkus tls generate-certificate --name my-cert --self-signed
这将生成一个自签名证书,该证书不是由 Quarkus 开发 CA 签名的。
10.5. 卸载 Quarkus 开发 CA
从您的系统中卸载 Quarkus 开发 CA 取决于您的操作系统。
10.5.1. 在 Windows 上删除 CA 证书
-
使用具有管理员权限的 Powershell 终端列出 Windows 上的 CA 证书:
# First, we need to identify the serial number of the CA certificate > certutil -store -user Root root "Trusted Root Certification Authorities" ================ Certificate 0 ================ Serial Number: 019036d564c8 Issuer: O=Quarkus, CN=quarkus-dev-root-ca # <-That's the CA, copy the Serial Number (the line above) NotBefore: 6/19/2024 11:07 AM NotAfter: 6/20/2025 11:07 AM Subject: C=Cloud, S=world, L=home, OU=Quarkus Dev, O=Quarkus Dev, CN=quarkus-dev-root-ca Signature matches Public Key Non-root Certificate uses same Public Key as Issuer Cert Hash(sha1): 3679bc95b613a2112a3d3256fe8321b6eccce720 No key provider information Cannot find the certificate and private key for decryption. CertUtil: -store command completed successfully.
-
删除存储的 CA 证书,并将
$Serial_Number
替换为 CA 证书的序列号:> certutil -delstore -user -v Root $Serial_Number
11. 使用 Let's Encrypt 自动证书管理
Let's Encrypt 是由 Internet Security Research Group 提供的免费、自动证书颁发机构。
Let's Encrypt 使用 自动化证书管理环境 (ACME) 协议 来支持自动证书颁发和续订。要了解有关 Let's Encrypt 和 ACME 的更多信息,请参阅 Let's Encrypt 文档。
TLS 注册表扩展允许 CLI ACME 客户端颁发和续订 Let's Encrypt 证书。您的应用程序使用此 TLS 注册表扩展来解决 ACME 协议质询。
请按照以下步骤操作,使您的 Quarkus 应用程序准备就绪,并通过新的和续订的 Let's Encrypt 证书自动更新。
11.1. 前提条件
-
确保有一个完全可解析的 DNS 域名可用,您可以使用它来访问您的应用程序。您可以使用此域名创建一个 Let's Encrypt 帐户,并通过 Let's Encrypt ACME 质询来证明您拥有此域名。您可以使用 ngrok 开始试验 Quarkus Let's Encrypt ACME 功能;有关更多信息,请参阅下面的 使用 ngrok 进行测试 部分。
-
您的 Quarkus HTTPS 应用程序必须使用构建时属性来启用 Let's Encrypt ACME 质询路由
quarkus.tls.lets-encrypt.enabled=true
TLS 注册表可以从主 HTTP 接口或管理接口管理质询过程。强烈建议使用管理接口,以便 Quarkus 可以将 ACME 质询配置与主应用程序的部署和安全要求分开处理
quarkus.tls.lets-encrypt.enabled=true quarkus.management.enabled=true
端口 80
Let's Encrypt ACME 质询要求应用程序可以通过端口 我们还建议将
|
质询从主 HTTP 接口提供,该接口可以从您的 DNS 域名访问。
不要立即启动您的应用程序。 |
11.2. 应用程序准备
在您请求 Let's Encrypt 证书之前:
-
移动到应用程序的根目录。
-
运行 TLS 注册表 Let's Encrypt CLI
prepare
命令quarkus tls lets-encrypt prepare --domain=<domain-dns-name>
prepare
命令执行以下操作:-
在应用程序的根目录中创建一个
.letsencrypt
文件夹。 -
为您的应用程序创建一个自签名域名证书和私钥,该域名证书和私钥在之前的 Let's Encrypt 先决条件步骤中配置,以启动和接受 HTTPS 请求。
-
在应用程序的根目录中创建一个
.env
配置文件,并将其配置为使用自签名域名证书和私钥,直到您获得 Let's Encrypt 证书。以下代码片段显示了生成的
.env
文件的示例:quarkus.tls.key-store.pem.acme.cert=.letsencrypt/lets-encrypt.crt quarkus.tls.key-store.pem.acme.key=.letsencrypt/lets-encrypt.key
.env
文件不包含quarkus.tls.lets-encrypt.enabled
和quarkus.management.enabled
属性,因为它们是构建时属性,需要重建应用程序。
-
11.3. 启动您的应用程序
-
启动您的应用程序
java -jar quarkus-run.jar
-
使用
https://your-domain-name:8443/
访问您的应用程序端点;例如,https://your-domain-name:8443/hello
,并在浏览器中接受自签名证书。 -
保持应用程序运行,并请求您的第一个 Let's Encrypt 证书。
-
11.4. 颁发证书
-
从应用程序目录中,运行
issue-certificate
命令以获取您的第一个 Let's Encrypt 证书quarkus tls lets-encrypt issue-certificate \ --domain=<domain-dns-name> \ (1) --email=<your contact email> \ (2) --management-url=https://:9000 (3)
1 设置您的域名。 2 提供您的联系电子邮件地址,Let's Encrypt 可以使用该地址在您的 Let's Encrypt 帐户出现任何问题时与您联系。 3 设置您的应用程序管理 URL,您可以使用该 URL 来处理 ACME 质询。如果您选择不在 Let's Encrypt 先决条件步骤中启用管理路由器,请使用 https://:8443/
。 -
在处理
issue-certificate
命令期间,TLS 注册表 CLI 执行以下任务:-
检查应用程序是否已准备好服务质询。
-
创建并记录 Let's Encrypt 帐户信息。
-
颁发 Let's Encrypt 证书请求。
-
与 Quarkus 应用程序交互以解决 ACME 质询。
当 Let's Encrypt 证书链和私钥已成功获取时,它们将转换为 PEM 格式并复制到您的应用程序的
.letsencrypt
文件夹。TLS 注册表会被通知新的证书和私钥已准备就绪,并会自动重新加载它们。
-
-
再次使用
https://your-domain-name:8443/
访问您的应用程序的端点。在浏览器中确认 Let's Encrypt 证书颁发机构现在正在签名您的域名证书。请注意,目前,
issue-certificate
命令隐式创建一个 Let's Encrypt 帐户,以便用户可以轻松开始使用 ACME 协议。对 Let's Encrypt 帐户管理的支持将进一步发展。
11.5. 续订证书
续订证书与颁发第一个证书类似,但它需要一个在 使用 Let's Encrypt 颁发证书步骤中创建的现有帐户。
运行以下命令以续订您的 Let's Encrypt 证书并设置您的域名 DNS 名称:
quarkus tls lets-encrypt renew-certificate \
--domain=<domain-dns-name>
在此命令期间,TLS 注册表 CLI 会读取在 使用 Let's Encrypt 颁发证书步骤中记录的 Let's Encrypt 帐户信息,颁发 Let's Encrypt 证书请求,并与 Quarkus 应用程序通信以解决 ACME 质询。
一旦 Let's Encrypt 证书链和私钥已成功续订,它们将被转换为 PEM 格式并复制到您的应用程序的 .letsencrypt
文件夹。当新的证书和私钥准备就绪时,TLS 注册表会被通知,并会自动重新加载它们。
11.6. 使用 ngrok 进行测试
ngrok 可用于为在 localhost 上运行的应用程序提供安全的 HTTPS 隧道,并使测试基于 HTTPS 的应用程序变得容易。
ngrok 提供了一种简化的方式来开始使用 Quarkus Let's Encrypt ACME 功能。
-
通过要求 ngrok 预留一个域来启动测试:
您可以在开发模式下使用 Quarkiverse ngrok 或直接在 ngrok 仪表板中预留它。不幸的是,您无法立即使用您的 ngrok 域来测试 Quarkus Let's Encrypt ACME 功能。这是因为 ngrok 本身使用 Let's Encrypt 并拦截本应由 Quarkus 应用程序处理的 ACME 质询。
-
因此,请从您的 ngrok 域中删除 ngrok Let's Encrypt 证书策略:
ngrok api --api-key <YOUR-API-KEY> reserved-domains delete-certificate-management-policy <YOUR-RESERVED-DOMAIN-ID>
YOUR-RESERVED-DOMAIN-ID
是您的保留域的 ID,以rd_
开头,您可以在 ngrok 仪表板域部分中找到它。 -
因为 ngrok 只通过 HTTP 转发 ACME 质询,所以请使用以下命令启动 ngrok:
ngrok http --domain <YOUR-NGROK-DOMAIN> 8080 --scheme http (1)
1 8080
是您的应用程序正在侦听的 localhost HTTP 端口。请注意,该应用程序将可以从端口80
上的http://YOUR-NGROK-DOMAIN
访问,但会重定向到您本地计算机上的端口8080
。 -
从您的本地机器测试 Quarkus Let's Encrypt ACME 功能。