fips-mode-setup --check
联邦信息处理标准出版物 140-2 (FIPS 140-2) 是美国政府用于批准密码模块的计算机安全标准。Keycloak 支持在符合 FIPS 140-2 标准的模式下运行。在这种情况下,Keycloak 将仅使用 FIPS 批准的密码算法来实现其功能。
要在 FIPS 140-2 模式下运行,Keycloak 应在启用 FIPS 140-2 的系统上运行。此要求通常假定为 RHEL 或 Fedora,其中 FIPS 在安装期间已启用。有关详细信息,请参阅 RHEL 文档。当系统处于 FIPS 模式时,它会确保底层 OpenJDK 也处于 FIPS 模式,并且只会使用 启用 FIPS 的安全提供程序。
要检查系统是否处于 FIPS 模式,您可以从命令行使用以下命令进行检查
fips-mode-setup --check
如果系统未处于 FIPS 模式,您可以使用以下命令启用它,但建议系统自安装以来就处于 FIPS 模式,而不是像下面这样随后启用它
fips-mode-setup --enable
Keycloak 内部使用 BouncyCastle 库进行许多密码实用程序操作。请注意,Keycloak 附带的默认版本 BouncyCastle 库不符合 FIPS 标准;但是,BouncyCastle 也提供了其库的 FIPS 验证版本。FIPS 验证的 BouncyCastle 库未与 Keycloak 一起提供,因为 Keycloak 无法提供对其的官方支持。因此,要在符合 FIPS 标准的模式下运行,您需要下载 BouncyCastle-FIPS 位,并将其添加到 Keycloak 发行版中。当 Keycloak 在 fips 模式下执行时,它将使用 BCFIPS 位而不是默认的 BouncyCastle 位,从而实现 FIPS 合规性。
可以从 BouncyCastle 官方页面 下载 BouncyCastle FIPS。然后,您可以将它们添加到发行版的 KEYCLOAK_HOME/providers
目录中。请确保使用与 BouncyCastle Keycloak 依赖项兼容的正确版本。所需的受支持 BCFIPS 位是
bc-fips 版本 2.0.0。
bctls-fips 版本 2.0.19。
bcpkix-fips 版本 2.0.7。
bcutil-fips 版本 2.0.3。
您可以创建 pkcs12
或 bcfks
密钥库以用于 Keycloak 服务器 SSL。
p12
(或 pkcs12
)密钥库(和/或信任库)在 BCFIPS 非批准模式下运行良好。
可以使用 RHEL 9 上 OpenJDK 21 Java 以标准方式生成 PKCS12 密钥库。例如,可以使用以下命令生成密钥库
keytool -genkeypair -sigalg SHA512withRSA -keyalg RSA -storepass passwordpassword \
-keystore $KEYCLOAK_HOME/conf/server.keystore \
-alias localhost \
-dname CN=localhost -keypass passwordpassword
FIPS 模式下的 pkcs12
密钥库不管理密钥(对称)密钥。此限制是由 BCFIPS
提供程序施加的,该提供程序不允许 pkcs12
密钥库类型内部存在此类密钥。
当系统处于 FIPS 模式时,默认的 java.security
文件会更改为使用启用 FIPS 的安全提供程序,因此无需额外的配置。此外,在 PKCS12 密钥库中,您可以通过简单地使用 keytool 命令来存储 PBE(基于密码的加密)密钥,这使其非常适合与 Keycloak KeyStore Vault 和/或在 KeyStore Config Source 中存储配置属性一起使用。有关更多详细信息,请参阅配置 Keycloak 和 使用 vault。
BCFKS 密钥库生成需要使用 BouncyCastle FIPS 库和自定义安全文件。
您可以从创建一个辅助文件开始,例如 /tmp/kc.keystore-create.java.security
。该文件的内容只需要具有以下属性
securerandom.strongAlgorithms=PKCS11:SunPKCS11-NSS-FIPS
接下来,输入如下命令以生成密钥库
keytool -keystore $KEYCLOAK_HOME/conf/server.keystore \
-storetype bcfks \
-providername BCFIPS \
-providerclass org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider \
-provider org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider \
-providerpath $KEYCLOAK_HOME/providers/bc-fips-*.jar \
-alias localhost \
-genkeypair -sigalg SHA512withRSA -keyalg RSA -storepass passwordpassword \
-dname CN=localhost -keypass passwordpassword \
-J-Djava.security.properties=/tmp/kc.keystore-create.java.security
使用自签名证书仅用于演示目的,因此在您转移到生产环境时,请将这些证书替换为适当的证书。 |
当您对 bcfks
类型的密钥库/信任库进行任何其他操作时,也需要类似的选项。
bin/kc.[sh|bat] start --features=fips --hostname=localhost --https-key-store-password=passwordpassword --log-level=INFO,org.keycloak.common.crypto:TRACE,org.keycloak.crypto:TRACE
在非批准模式下,默认密钥库类型(以及默认信任库类型)是 PKCS12。因此,如果您如上所述生成了 BCFKS 密钥库,则还需要使用命令 --https-key-store-type=bcfks 。如果您想使用信任库,也可能需要类似的命令。 |
如果一切正常,您可以在生产环境中禁用日志记录。 |
有一个 fips-mode
选项,当启用 fips
功能时,该选项会自动设置为 non-strict
。这意味着在“非批准模式”下运行 BCFIPS。更安全的替代方案是使用 --features=fips --fips-mode=strict
,在这种情况下,BouncyCastle FIPS 将使用“批准模式”。使用该选项会对密码学和安全算法提出更严格的安全要求。
在严格模式下,默认密钥库类型(以及默认信任库类型)是 BCFKS。如果您想使用不同的密钥库类型,则需要使用带有适当类型的选项 --https-key-store-type 。如果您想使用信任库,也可能需要类似的命令。 |
启动服务器时,您可以检查启动日志是否包含 KC
提供程序,并带有关于 Approved Mode
的注释,如下所示
KC(BCFIPS version 2.0 Approved Mode, FIPS-JVM: enabled) version 1.0 - class org.keycloak.crypto.fips.KeycloakFipsSecurityProvider,
如上一节所述,严格模式可能不适用于 pkcs12
密钥库。需要使用另一个密钥库(如 bcfks
),如前所述。此外,当使用严格模式时,Keycloak 不支持 jks
和 pkcs12
密钥库。一些示例是在管理控制台中导入或生成 OIDC 或 SAML 客户端的密钥库,或者在领域密钥中使用 java-keystore
提供程序。
用户密码必须为 14 个字符或更长。Keycloak 默认使用基于 PBKDF2 的密码编码。BCFIPS 批准模式要求密码至少为 112 位(有效长度为 14 个字符),并使用 PBKDF2 算法。如果您想允许更短的密码,请将 SPI password-hashing
的提供程序 pbkdf2-sha512
的属性 max-padding-length
设置为 14,以便在验证此算法创建的哈希值时提供额外的填充。此设置也向后兼容以前存储的密码。例如,如果用户的数据库在非 FIPS 环境中,并且您有较短的密码,并且您现在想使用批准模式下的 BCFIPS 在 Keycloak 中验证它们,则密码应该有效。因此,实际上,您可以在启动服务器时使用如下选项
--spi-password-hashing-pbkdf2-sha512-max-padding-length=14
使用上述选项不会破坏 FIPS 合规性。但是,请注意,无论如何,更长的密码都是良好的做法。例如,现代浏览器自动生成的密码符合此要求,因为它们长于 14 个字符。如果您想省略 max-padding-length 的选项,您可以将您领域的密码策略设置为密码至少 14 个字符长。 |
当您从低于 24 的 Keycloak 版本迁移,或者如果您显式设置密码策略以覆盖默认哈希算法时,您的某些用户可能使用了较旧的算法,例如 pbkdf2-sha256 。在这种情况下,请考虑添加 --spi-password-hashing-pbkdf2-sha256-max-padding-length=14 选项,以确保使用较旧的 pbkdf2-sha256 哈希密码的用户可以登录,因为他们的密码可能短于 14 个字符。 |
1024 位的 RSA 密钥不起作用(最小为 2048 位)。这适用于 Keycloak 领域本身使用的密钥(管理控制台“密钥”选项卡中的领域密钥),也适用于客户端密钥和 IDP 密钥
HMAC SHA-XXX 密钥必须至少为 112 位(或 14 个字符长)。例如,如果您使用客户端身份验证为 Signed Jwt with Client Secret
(或 OIDC 表示法中的 client-secret-jwt
) 的 OIDC 客户端,则您的客户端密钥应至少为 14 个字符长。请注意,为了良好的安全性,建议使用 Keycloak 服务器生成的客户端密钥,该密钥始终满足此要求。
bc-fips 版本 1.0.2.4 处理 PKCS 1.5 RSA 加密过渡期的结束。因此,默认情况下,严格模式不允许使用算法 RSA1_5
的 JSON Web Encryption (JWE)(BC 提供系统属性 -Dorg.bouncycastle.rsa.allow_pkcs15_enc=true
作为目前的向后兼容性选项)。RSA-OAEP
和 RSA-OAEP-256
仍然像以前一样可用。
为了使 SAML 工作,请确保您的安全提供程序中提供了 XMLDSig
安全提供程序。为了使 Kerberos 工作,请确保提供了 SunJGSS
安全提供程序。在启用 FIPS 的 RHEL 9 和 OpenJDK 21 中,XMLDSig
安全提供程序可能已在 java.security
中默认启用,最新的 OpenJDK 17 也是如此。但在较旧的 OpenJDK 17 中,它可能默认未启用,这意味着 SAML 实际上无法工作。
为了使 SAML 工作,您可以手动将提供程序添加到 JAVA_HOME/conf/security/java.security
中的 fips 提供程序列表中。例如,如果您的 FIPS 安全提供程序中尚不可用,请添加如下行
fips.provider.7=XMLDSig
添加此安全提供程序应该可以正常工作。事实上,它是 FIPS 兼容的,并且已在 OpenJDK 21 和更新版本的 OpenJDK 17 中默认添加。详细信息请参阅 bugzilla。
建议查看 JAVA_HOME/conf/security/java.security 并检查此处配置的所有提供程序,并确保编号匹配。换句话说,fips.provider.7 假定此文件中已配置了 6 个带有 fips.provider.N 前缀的提供程序。 |
如果您不想编辑 java 本身内部的 java.security
文件,您可以创建一个自定义 java 安全文件(例如命名为 kc.java.security
),并在该文件中仅添加用于添加 XMLDSig 提供程序的单个属性。然后使用附加的此属性文件启动您的 Keycloak 服务器
-Djava.security.properties=/location/to/your/file/kc.java.security
对于 Kerberos/SPNEGO,安全提供程序 SunJGSS
尚未完全符合 FIPS 标准。因此,如果您想符合 FIPS 标准,不建议将其添加到您的安全提供程序列表中。当在 FIPS 平台上执行且安全提供程序不可用时,KERBEROS
功能在 Keycloak 中默认禁用。详细信息请参阅 bugzilla。
算法 EdDSA
无法在 FIPS 模式下使用。虽然当前的 BCFIPS
提供程序支持 Ed25519
和 Ed448
曲线,但生成的密钥不实现用于管理它们的标准 JDK 接口(EdECKey
、EdECPublicKey
、EdECPrivateKey
,…),并且 Keycloak 无法将它们用于签名。
如果您想运行客户端注册 CLI (kcreg.sh|bat
脚本) 或管理 CLI (kcadm.sh|bat
脚本),则 CLI 也必须使用 BouncyCastle FIPS 依赖项而不是普通的 BouncyCastle 依赖项。为了实现这一点,您可以将 jar 复制到 CLI 库文件夹中,这就足够了。当 CLI 工具检测到相应的 BCFIPS jar 存在时,它将自动使用 BCFIPS 依赖项而不是普通的 BC(请参阅上面使用的版本)。例如,在运行 CLI 之前使用如下命令
cp $KEYCLOAK_HOME/providers/bc-fips-*.jar $KEYCLOAK_HOME/bin/client/lib/
cp $KEYCLOAK_HOME/providers/bctls-fips-*.jar $KEYCLOAK_HOME/bin/client/lib/
cp $KEYCLOAK_HOME/providers/bcutil-fips-*.jar $KEYCLOAK_HOME/bin/client/lib/
当尝试将 BCFKS 信任库/密钥库与 CLI 一起使用时,您可能会看到问题,因为此信任库不是默认的 java 密钥库类型。最好将其指定为 java 安全属性中的默认值。例如,在对 kcadm|kcreg 客户端执行任何操作之前,在基于 unix 的系统上运行此命令 |
echo "keystore.type=bcfks
fips.keystore.type=bcfks" > /tmp/kcadm.java.security
export KC_OPTS="-Djava.security.properties=/tmp/kcadm.java.security"
当您希望在容器内执行 FIPS 模式下的 Keycloak 时,您的“主机”也必须使用 FIPS 模式。然后,容器将从父主机“继承” FIPS 模式。有关详细信息,请参阅 RHEL 文档中的 此部分。
当从 FIPS 模式下的主机执行时,Keycloak 容器镜像将自动处于 fips 模式。但是,请确保 Keycloak 容器也使用 BCFIPS jar(而不是 BC jar),并在启动时使用正确的选项。
关于这一点,最好构建您自己的容器镜像,如 在容器中运行 Keycloak 中所述,并对其进行调整以使用 BCFIPS 等。
例如,在当前目录中,您可以创建子目录 files
并添加
如上所述的 BC FIPS jar 文件
自定义密钥库文件 - 例如命名为 keycloak-fips.keystore.bcfks
安全文件 kc.java.security
,其中添加了 SAML 的提供程序(OpenJDK 21 或更新版本的 OpenJDK 17 不需要)
然后在当前目录中创建类似于此的 Containerfile
FROM quay.io/keycloak/keycloak:latest as builder
ADD files /tmp/files/
WORKDIR /opt/keycloak
RUN cp /tmp/files/*.jar /opt/keycloak/providers/
RUN cp /tmp/files/keycloak-fips.keystore.* /opt/keycloak/conf/server.keystore
RUN cp /tmp/files/kc.java.security /opt/keycloak/conf/
RUN /opt/keycloak/bin/kc.sh build --features=fips --fips-mode=strict
FROM quay.io/keycloak/keycloak:latest
COPY --from=builder /opt/keycloak/ /opt/keycloak/
ENTRYPOINT ["/opt/keycloak/bin/kc.sh"]
然后构建 FIPS 作为优化的 Docker 镜像,并按照 在容器中运行 Keycloak 中所述启动它。这些步骤要求您在启动镜像时使用如上所述的参数。
如果您以前在非 fips 环境中使用过 Keycloak,则可以将其(包括其数据)迁移到 FIPS 环境。但是,存在前面部分提到的限制和注意事项,即
从 Keycloak 25 开始,密码哈希的默认算法是 argon2
。但是,此算法不支持 FIPS 140-2。这意味着如果您的用户使用 argon2
哈希了他们的密码,他们在切换到 FIPS 环境后将无法登录。如果您计划迁移到 FIPS 环境,请考虑从一开始就设置您领域的密码策略(在创建任何用户之前),并覆盖默认算法,例如 pbkdf2-sha512
,它是 FIPS 兼容的。此策略有助于使迁移到 FIPS 环境的过程顺利进行。否则,如果您的用户已经使用 argon2
密码,只需在迁移到 FIPS 环境后要求用户重置密码。例如,要求用户使用“忘记密码”或向所有用户发送重置密码的电子邮件。
确保所有依赖于密钥库的 Keycloak 功能都仅使用受支持的密钥库类型。这取决于使用的是严格模式还是非严格模式。
Kerberos 身份验证可能无法工作。如果您的身份验证流程使用 Kerberos
身份验证器,则在迁移到 FIPS 环境时,此身份验证器将自动切换为 DISABLED
。建议从您的领域中删除任何 Kerberos
用户存储提供程序,并在切换到 FIPS 环境之前禁用 LDAP 提供程序中与 Kerberos
相关的功能。
除了上述要求外,在切换到 FIPS 严格模式之前,请务必仔细检查以下内容
确保所有依赖于密钥的 Keycloak 功能(例如,领域或客户端密钥)都使用至少 2048 位的 RSA 密钥
确保依赖于 Signed JWT with Client Secret
的客户端使用至少 14 个字符长的密钥(理想情况下是生成的密钥)
如前所述的密码长度限制。如果您的用户密码较短,请务必在启动服务器时将 PBKDF2 提供程序的最大填充长度设置为 14,如前所述。如果您希望避免使用此选项,您可以例如在新环境中的首次身份验证期间,要求所有用户重置其密码(例如通过“忘记密码”链接)。
Keycloak 在启用 FIPS 的 RHEL 8 系统和 ubi8
镜像上受支持和测试。它也受 RHEL 9(和 ubi9
镜像)支持。在非 RHEL 兼容平台或非 FIPS 启用平台上运行时,FIPS 合规性无法得到严格保证,也无法获得官方支持。
如果您仍然受限于在此类系统上运行 Keycloak,您至少可以更新在 java.security
文件中配置的安全提供程序。此更新并不等同于 FIPS 合规性,但至少设置更接近它。可以通过提供自定义安全文件来完成,该文件仅包含如前所述的覆盖安全提供程序列表。有关推荐的提供程序列表,请参阅 OpenJDK 21 文档。
您可以检查 Keycloak 服务器启动日志,以查看是否使用了正确的安全提供程序。应为与密码相关的 Keycloak 包启用 TRACE 日志记录,如之前的 Keycloak 启动命令中所述。