Image Overview: keycloak-fips
Keycloak-fips
A wolfi-based image tailored for Keycloak, incorporating the required bouncycastle FIPS modules (bcfips) to facilitate Keycloak’s operation in FIPS mode.
Both OpenJDK and Keycloak have been configured to harness the BouncyCastle FIPS API at their core. The included bcfips module meets FIPS 140-2 compliance requirements and is accredited under: FIPS certificate 4616.
Disclaimer
This image is equipped with the essential components for Keycloak to operate in FIPS mode. However, it’s important for users to ensure they use it in line with FIPS compliance standards.
This includes tasks such as keystore generation, configuration, and launching Keycloak with the correct configuration parameters. More guidance is provided in the sections below.
Keystore
Keycloak requires a bcfips-compatible keystore to manage its SSL/TLS certificates.
Although Keycloak supports various keystore types, only BCKFS offers the capability to operate in approved (strict) mode under FIPS standards, ensuring only approved ciphers are used.
BCKFS Keystore creation
Refer to the official documentation for information on how to create and configure a Keystore.
Note: The keystore needs to be generated on a seperate image, as the keytool application will not operate when bcfips is running in approved mode. Here is a snippet from our communication with the BouncyCastle maintainers:
keytool will not run if bcfips is running in approved mode. It is hard coded to pass a new SecureRandom(), which will always fail the approved RNG test.
Below is an example, using a wolfi-base container to generate a bckfs keystore:
docker run -v $(pwd):/tmp/keystore -it cgr.dev/chainguard/wolfi-base:latest sh
...
apk update && apk add curl openjdk-17-default-jvm
# Refer to Keycloak docs: 'BCFKS keystore' section for context.
echo "securerandom.strongAlgorithms=PKCS11:SunPKCS11-NSS-FIPS" > kc-keystore.java.security
# https://www.bouncycastle.org/fips-java for latest `bc-fips` version
curl https://downloads.bouncycastle.org/fips-java/bc-fips-<VERSION>.jar \
-o bc-fips.jar
keytool -v -keystore /tmp/keystore/server.keystore \
-J--add-exports=java.base/sun.security.provider=ALL-UNNAMED \
-storetype bcfks \
-providername BCFIPS \
-providerclass org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider \
-providerpath bc-fips.jar \
-alias localhost \
-genkeypair -sigalg SHA512withRSA -keyalg RSA \
-storepass '<DESIRED-KEYSTORE-PASSWORD>' \
-dname CN=localhost \
-J-Djava.security.properties=kc-keystore.java.security
Run image
This image aligns with the original upstream image regarding its entrypoint and command-line arguments. Also see the Keycloak GitHub repository, and the KeyCloak FIPS documentation.
Running in development mode
Example of launching Keycloak in development
mode, with HTTP enabled and
strict hostname resolution not enforced:
docker run -v $(pwd)/server.keystore:/usr/share/java/keycloak/conf/server.keystore \
--rm --name local-Keycloak -p 8080:8080 \
-e KEYCLOAK_ADMIN=admin \
-e KEYCLOAK_ADMIN_PASSWORD='<PASSWORD-FOR-ADMIN-USER>' \
<YOUR-REGISTRY>/keycloak-fips:latest \
start-dev \
--features=fips \
--fips-mode=strict \
--https-key-store-password='<KEYSTORE-PASSWORD>' \
--hostname=localhost \
--log-level='INFO,org.keycloak.common.crypto:TRACE,org.keycloak.crypto:TRACE'
In this example, the Keycloak UI is accessible via: http://localhost:8080.
Running in production mode
Example of running Keycloak in production
mode, enforcing the use of HTTPS
and requiring a hostname to be provided:
docker run -v /local/path/to/server.keystore:/usr/share/java/keycloak/conf/server.keystore \
--rm --name local-Keycloak -p 8443:8443 \
-e KEYCLOAK_ADMIN=admin \
-e KEYCLOAK_ADMIN_PASSWORD='<PASSWORD-FOR-ADMIN-USER>' \
cgr.dev/chainguard/Keycloak-fips:latest \
start \
--features=fips \
--fips-mode=strict \
--https-key-store-password='<KEYSTORE-PASSWORD>' \
--hostname=localhost \
--log-level='INFO,org.keycloak.common.crypto:TRACE,org.keycloak.crypto:TRACE'
In this example, the Keycloak UI is accessible via: https://localhost:8443.
FIPS validation
You’ll see debug logs such as the below if Keycloak is running in FIPS mode:
KC(BCFIPS version 1.000204 Approved Mode) version 1.0 - class org.Keycloak.crypto.fips.KeycloakFipsSecurityProvider,
BCFIPS version 1.000204 - class org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider
Additionally, you can check bcfips is enforcing minimum password lengths, by
running the container with a non-compliant admin password, such as 1234
:
Caused by: org.bouncycastle.crypto.fips.FipsUnapprovedOperationError:
password must be at least 112 bits
Customizing the image
Keycloak provides a mechanism to configure and customize the image. This process is outlined in the Keycloak image documentation.
There are subtle differences in the executable paths used in the Chainguard image. Below is the example copied from the documentation, updated with the correct paths:
FROM cgr.dev/chainguard/Keycloak-fips:latest as builder
# Enable health and metrics support
ENV KC_HEALTH_ENABLED=true
ENV KC_METRICS_ENABLED=true
# Configure a database vendor
ENV KC_DB=postgres
WORKDIR /usr/share/java/Keycloak
# for demonstration purposes only, please make sure to use proper certificates in production instead
RUN keytool -genkeypair -storepass password -storetype PKCS12 -keyalg RSA -keysize 2048 -dname "CN=server" -alias server -ext "SAN:c=DNS:localhost,IP:127.0.0.1" -keystore conf/server.keystore
RUN /usr/share/java/Keycloak/bin/kc.sh build
FROM cgr.dev/chainguard/Keycloak-fips:latest
COPY --from=builder /usr/share/java/Keycloak/ /usr/share/java/Keycloak/
# change these values to point to a running postgres instance
ENV KC_DB=postgres
ENV KC_DB_URL=<DBURL>
ENV KC_DB_USERNAME=<DBUSERNAME>
ENV KC_DB_PASSWORD=<DBPASSWORD>
ENV KC_HOSTNAME=localhost
ENTRYPOINT ["/usr/share/java/Keycloak/bin/kc.sh"]
Debugging
Invalid Keystore Format with BCFKS in production
mode
Error Message:
# kc.sh start --features=fips --hostname=localhost --https-key-store-password='**********'
ERROR: Failed to start server in (production) mode
ERROR: Unable to start HTTP server
ERROR: java.io.IOException: Invalid keystore format
Solution:
BCFKS Keystores default to strict mode, and it’s likely you omitted
--fips-mode=strict
in your arguments. If you wish to run in non-strict mode
with BCFKS, you need to include --https-key-store-type=bcfks
.
This is called out in the official documentation, but perhaps could benefit from additional clarification.
Keystore corrupted error upon launch
Error Message:
ERROR: Unable to start HTTP server
ERROR: java.io.IOException: BCFKS KeyStore corrupted: MAC calculation failed.
ERROR: BCFKS KeyStore corrupted: MAC calculation failed.
Solution:
The error indicates that a Keystore was detected, but there was an issue
parsing it. Usually this means that the password used to create the keystore
does not match what was provided as the --https-key-store-password
argument
to Keycloak.
Key material not provided error in production
mode
Error Message:
ERROR: Failed to start server in (production) mode
ERROR: Key material not provided to setup HTTPS. Please configure your
keys/certificates or start the server in development mode.
Solution:
This error usually indicates that a .keystore
was not detected in the
/usr/share/java/keycloak/conf
directory. Ensure you have created a Keystore
and it is accessible to the container in the expected directory.
Password must be at least 112 bits
Error Message:
Failed to add user '<admin-user>' to realm 'master': org.keycloak.models.ModelException:
password must be at least 112 bits
FipsUnapprovedOperationError: password must be at least 112 bits
Solution:
This is expected whenever Keycloak is running in strict
(approved) mode for
FIPS. Choose a longer admin password which is compliant. Refer to the Keycloak
FIPS documentation for more information.
Last updated: 2024-02-29 16:25