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 環境中,並且您的密碼較短,而您現在想在 Keycloak 中使用 BCFIPS 在核准模式下驗證它們,則密碼應該可以運作。因此,實際上,您可以在啟動伺服器時使用類似以下的選項
--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 加密 (JWE)(BC 提供系統屬性 -Dorg.bouncycastle.rsa.allow_pkcs15_enc=true
作為目前的向後相容選項)。RSA-OAEP
和 RSA-OAEP-256
仍然與之前一樣可用。
若要使 SAML 運作,請確保您的安全提供者中提供 XMLDSig
安全提供者。若要使 Kerberos 運作,請確保提供 SunJGSS
安全提供者。在 OpenJDK 21 中啟用 FIPS 的 RHEL 9 中,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 標準,不建議將其新增到您的安全提供者清單中。當 Keycloak 在 FIPS 平台上執行且安全提供者不可用時,KERBEROS
功能預設會停用。詳細資訊請參閱 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/
當嘗試使用 CLI 時,如果遇到 BCFKS truststore/keystore 的問題,可能是因為此 truststore 不是預設的 Java keystore 類型。將其指定為 Java 安全屬性中的預設值會很有幫助。例如,在 Unix 系統上,於使用 kcadm 或 kcreg 客戶端執行任何操作之前,執行此命令: |
echo "keystore.type=bcfks
fips.keystore.type=bcfks" > /tmp/kcadm.java.security
export KC_OPTS="-Djava.security.properties=/tmp/kcadm.java.security"
當您希望 Keycloak 在容器內以 FIPS 模式執行時,您的「主機」也必須使用 FIPS 模式。容器將會從父主機「繼承」FIPS 模式。有關詳細資訊,請參閱 RHEL 文件中的此章節。
當從處於 FIPS 模式的主機執行時,Keycloak 容器映像將會自動處於 FIPS 模式。但是,請確保 Keycloak 容器在啟動時也使用 BCFIPS jar 檔案(而非 BC jar 檔案)和正確的選項。
關於這一點,最好如「在容器中執行 Keycloak」所述建立您自己的容器映像,並調整它以使用 BCFIPS 等。
例如,在當前目錄中,您可以建立子目錄 files
並加入:
如上所述的 BC FIPS jar 檔案
自訂 keystore 檔案 - 例如命名為 keycloak-fips.keystore.bcfks
包含 SAML 新增提供者的安全檔案 kc.java.security
(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"]
然後,如「在容器中執行 Keycloak」所述,將 FIPS 建置為最佳化的 Docker 映像並啟動它。這些步驟要求您在啟動映像時使用如上所述的參數。
如果您先前在非 FIPS 環境中使用 Keycloak,則可以將其連同其資料移轉到 FIPS 環境。但是,如前幾節所述,存在限制和注意事項,即:
從 Keycloak 25 開始,密碼雜湊的預設演算法為 argon2
。但是,此演算法不支援 FIPS 140-2。這表示如果您的使用者使用 argon2
雜湊其密碼,則在切換到 FIPS 環境後將無法登入。如果您計畫移轉到 FIPS 環境,請考慮從一開始就為您的領域設定密碼原則(在建立任何使用者之前),並覆寫預設演算法,例如改為 FIPS 相容的 pbkdf2-sha512
。此策略有助於使移轉到 FIPS 環境的過程順利。否則,如果您的使用者已經使用 argon2
密碼,只需要求使用者在移轉到 FIPS 環境後重設密碼即可。例如,要求使用者使用「忘記密碼」或向所有使用者發送重設密碼的電子郵件。
請確保所有依賴 keystore 的 Keycloak 功能僅使用支援的 keystore 類型。這會因使用嚴格模式還是非嚴格模式而有所不同。
Kerberos 身份驗證可能無法運作。如果您的身份驗證流程使用 Kerberos
驗證器,則當移轉到 FIPS 環境時,此驗證器將自動切換為 DISABLED
。建議在切換到 FIPS 環境之前,從您的領域中移除任何 Kerberos
使用者儲存提供者,並在 LDAP 提供者中停用與 Kerberos
相關的功能。
除了上述要求之外,在切換到 FIPS 嚴格模式之前,請務必仔細檢查:
確保所有依賴金鑰的 Keycloak 功能(例如,領域或用戶端金鑰)都使用至少 2048 位元的 RSA 金鑰
確保依賴「使用用戶端密碼簽署的 JWT」的用戶端使用至少 14 個字元長的密碼(理想情況下是產生的密碼)
如前所述的密碼長度限制。如果您的使用者密碼較短,請務必使用如前所述的 PBKDF2 提供者,將伺服器啟動時的最大填充長度設定為 14。如果您不想使用此選項,您可以例如要求所有使用者在新的環境中首次驗證期間重設他們的密碼(例如,透過「忘記密碼」連結)。
Keycloak 在已啟用 FIPS 的 RHEL 8 系統和 ubi8
映像上經過支援和測試。它也支援 RHEL 9(和 ubi9
映像)。在非 RHEL 相容平台或未啟用 FIPS 的平台上執行,無法嚴格保證 FIPS 相容性,並且無法正式支援。
如果您仍然受限於在此類系統上執行 Keycloak,則至少可以更新在 java.security
檔案中配置的安全提供者。此更新並不代表符合 FIPS 相容性,但至少設定更接近 FIPS 標準。可以透過提供自訂安全檔案來完成,其中僅包含如先前所述的覆寫安全提供者清單。有關建議的提供者清單,請參閱OpenJDK 21 文件。
您可以在啟動時檢查 Keycloak 伺服器日誌,以查看是否使用了正確的安全提供者。應該為與密碼相關的 Keycloak 套件啟用 TRACE 日誌記錄,如先前 Keycloak 啟動命令中所述。