1
<#import "/templates/guide.adoc" as tmpl>
2
<#import "/templates/kc.adoc" as kc>
3
<#import "/templates/links.adoc" as links>
6
title="FIPS 140-2 support"
7
summary="How to configure {project_name} server for FIPS compliance"
10
The Federal Information Processing Standard Publication 140-2, (FIPS 140-2), is a U.S. government computer security standard used to approve cryptographic modules. {project_name} supports running in FIPS 140-2 compliant mode. In this case, {project_name} will use only FIPS approved cryptography algorithms for its functionality.
12
To run in FIPS 140-2, {project_name} should run on a FIPS 140-2 enabled system. This requirement usually assumes RHEL or Fedora where FIPS was enabled during installation.
13
See https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/9/html-single/security_hardening/index#assembly_installing-the-system-in-fips-mode_security-hardening[RHEL documentation]
14
for the details. When the system is in FIPS mode, it makes sure that the underlying OpenJDK is in FIPS mode as well and would use only
15
https://access.redhat.com/documentation/en-us/openjdk/17/html/configuring_openjdk_17_on_rhel_with_fips/openjdk-default-fips-configuration[FIPS enabled security providers].
17
To check that the system is in FIPS mode, you can check it with the following command from the command line:
21
fips-mode-setup --check
24
If the system is not in FIPS mode, you can enable it with the following command, however it is recommended that system is in FIPS mode since the installation rather than subsequently enabling it as follows:
28
fips-mode-setup --enable
31
== BouncyCastle library
33
{project_name} internally uses the BouncyCastle library for many cryptography utilities. Please note that the default version of the BouncyCastle library that shipped with {project_name} is not FIPS compliant;
34
however, BouncyCastle also provides a FIPS validated version of its library. The FIPS validated BouncyCastle library cannot be shipped with {project_name} due to license constraints and
35
{project_name} cannot provide official support of it. Therefore, to run in FIPS compliant mode, you need to download BouncyCastle-FIPS bits and add them to the {project_name} distribution.
36
When {project_name} executes in fips mode, it will use the BCFIPS bits instead of the default BouncyCastle bits, which achieves FIPS compliance.
38
=== BouncyCastle FIPS bits
40
BouncyCastle FIPS can be downloaded from the https://www.bouncycastle.org/fips-java/[BouncyCastle official page]. Then you can add them to the directory
41
`KEYCLOAK_HOME/providers` of your distribution. Make sure to use proper versions compatible with BouncyCastle Keycloak dependencies. The supported BCFIPS bits needed are:
43
* `bc-fips-1.0.2.3.jar`
44
* `bctls-fips-1.0.16.jar`
45
* `bcpkix-fips-1.0.7.jar`
49
You can create either `pkcs12` or `bcfks` keystore to be used for the {project_name} server SSL.
53
The `p12` (or `pkcs12`) keystore (and/or truststore) works well in BCFIPS non-approved mode.
55
PKCS12 keystore can be generated with OpenJDK 17 Java on RHEL 9 in the standard way. For instance, the following command can be used to generate the keystore:
59
keytool -genkeypair -sigalg SHA512withRSA -keyalg RSA -storepass passwordpassword \
60
-keystore $KEYCLOAK_HOME/conf/server.keystore \
62
-dname CN=localhost -keypass passwordpassword
65
When the system is in FIPS mode, the default `java.security` file is changed in order to use FIPS enabled security providers, so no additional configuration is needed. Additionally, in the PKCS12 keystore, you can store PBE (password-based encryption) keys simply by using the keytool command, which makes it ideal for using it with {project_name} KeyStore Vault and/or to store configuration properties in the KeyStore Config Source. For more details, see the <@links.server id="configuration"/> and the <@links.server id="vault"/>.
69
BCFKS keystore generation requires the use of the BouncyCastle FIPS libraries and a custom security file.
71
You can start by creating a helper file, such as `/tmp/kc.keystore-create.java.security`. The content of the file needs only to have the following property:
75
securerandom.strongAlgorithms=PKCS11:SunPKCS11-NSS-FIPS
78
Next, enter a command such as the following to generate the keystore:
82
keytool -keystore $KEYCLOAK_HOME/conf/server.keystore \
84
-providername BCFIPS \
85
-providerclass org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider \
86
-provider org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider \
87
-providerpath $KEYCLOAK_HOME/providers/bc-fips-*.jar \
89
-genkeypair -sigalg SHA512withRSA -keyalg RSA -storepass passwordpassword \
90
-dname CN=localhost -keypass passwordpassword \
91
-J-Djava.security.properties=/tmp/kc.keystore-create.java.security
94
WARNING: Using self-signed certificates is for demonstration purposes only, so replace these certificates with proper certificates when you move to a production environment.
96
Similar options are needed when you are doing any other manipulation with keystore/truststore of `bcfks` type.
100
To run the server with BCFIPS in non-approved mode, enter the following command::
102
<@kc.start parameters="--features=fips --hostname=localhost --https-key-store-password=passwordpassword --log-level=INFO,org.keycloak.common.crypto:TRACE,org.keycloak.crypto:TRACE"/>
104
NOTE: In non-approved mode, the default keystore type (as well as default truststore type) is PKCS12. Hence if you generated a BCFKS keystore as described above,
105
it is also required to use the command `--https-key-store-type=bcfks`. A similar command might be needed for the truststore as well if you want to use it.
107
NOTE: You can disable logging in production if everything works as expected.
111
There is the `fips-mode` option, which is automatically set to `non-strict` when the `fips` feature is enabled. This means to run BCFIPS in the "non-approved mode".
112
The more secure alternative is to use `--features=fips --fips-mode=strict` in which case BouncyCastle FIPS will use "approved mode".
113
Using that option results in stricter security requirements on cryptography and security algorithms.
115
NOTE: In strict mode, the default keystore type (as well as default truststore type) is BCFKS. If you want to use a different keystore type
116
it is required to use the option `--https-key-store-type` with appropriate type. A similar command might be needed for the truststore as well if you want to use it.
118
When starting the server, you can check that the startup log contains `KC` provider with the note about `Approved Mode` such as the following:
122
KC(BCFIPS version 1.000203 Approved Mode, FIPS-JVM: enabled) version 1.0 - class org.keycloak.crypto.fips.KeycloakFipsSecurityProvider,
125
=== Cryptography restrictions in strict mode
127
* As mentioned in the previous section, strict mode may not work with `pkcs12` keystore. It is required to use another keystore (like `bcfks`) as mentioned earlier. Also `jks` and `pkcs12` keystores are not
128
supported in {project_name} when using strict mode. Some examples are importing or generating a keystore of an OIDC or SAML client in the Admin Console or for a `java-keystore` provider in the realm keys.
130
* User passwords must be 14 characters or longer. {project_name} uses PBKDF2 based password encoding by default. BCFIPS approved mode requires passwords to be at least 112 bits
131
(effectively 14 characters) with PBKDF2 algorithm. If you want to allow a shorter password, set the property `max-padding-length` of provider `pbkdf2-sha256` of SPI `password-hashing`
132
to value 14 to provide additional padding when verifying a hash created by this algorithm. This setting is also backwards compatible with previously stored passwords.
133
For example, if the user's database is in a non-FIPS environment and you have shorter passwords and you want to verify them now with {project_name} using BCFIPS in approved mode, the passwords should work.
134
So effectively, you can use an option such as the following when starting the server:
138
--spi-password-hashing-pbkdf2-sha256-max-padding-length=14
141
NOTE: Using the option above does not break FIPS compliance. However, note that longer passwords are good practice anyway. For example, passwords auto-generated by modern browsers match this
142
requirement as they are longer than 14 characters.
144
* RSA keys of 1024 bits do not work (2048 is the minimum). This applies for keys used by the {project_name} realm itself (Realm keys from the `Keys` tab in the admin console), but also client keys and IDP keys
146
* HMAC SHA-XXX keys must be at least 112 bits (or 14 characters long). For example if you use OIDC clients with the client authentication `Signed Jwt with Client Secret` (or `client-secret-jwt` in
147
the OIDC notation), then your client secrets should be at least 14 characters long. Note that for good security, it is recommended to use client secrets generated by the {project_name} server, which
148
always fulfils this requirement.
152
To have SAML working, make sure that a `XMLDSig` security provider is available in your security providers.
153
To have Kerberos working, make sure that a `SunJGSS` security provider is available. In FIPS enabled RHEL 9 in OpenJDK 17.0.6, these
154
security providers are not present in the `java.security`, which means that they effectively cannot work.
156
To have SAML working, you can manually add the provider into `JAVA_HOME/conf/security/java.security` into the list fips providers. For example, add the line such as the following:
160
fips.provider.7=XMLDSig
163
Adding this security provider should work well. In fact, it is FIPS compliant and likely will be added by default in the future OpenJDK 17 micro version.
164
Details are in the https://bugzilla.redhat.com/show_bug.cgi?id=1940064[bugzilla].
166
NOTE: It is recommended to look at `JAVA_HOME/conf/security/java.security` and check all configured providers here and make sure that the number matches. In other words, `fips.provider.7`
167
assumes that there are already 6 providers configured with prefix like `fips.provider.N` in this file.
169
If you prefer not to edit your `java.security` file inside java itself, you can create a custom java security file (for example named `kc.java.security`) and add only the single
170
property above for adding XMLDSig provider into that file. Then start your {project_name} server with this property file attached:
174
-Djava.security.properties=/location/to/your/file/kc.java.security
177
For Kerberos/SPNEGO, the security provider `SunJGSS` is not yet fully FIPS compliant. Hence it is not recommended to add it to your list of security providers
178
if you want to be FIPS compliant. The `KERBEROS` feature is disabled by default in {project_name} when it is executed on FIPS platform and when security provider is not
179
available. Details are in the https://bugzilla.redhat.com/show_bug.cgi?id=2051628[bugzilla].
181
== Run the CLI on the FIPS host
183
If you want to run Client Registration CLI (`kcreg.sh|bat` script) or Admin CLI (`kcadm.sh|bat` script),
184
the CLI must also use the BouncyCastle FIPS dependencies instead of plain BouncyCastle dependencies. To achieve this, you may copy the
185
jars to the CLI library folder and that is enough. CLI tool will automatically use BCFIPS dependencies instead of plain BC when
186
it detects that corresponding BCFIPS jars are present (see above for the versions used). For example, use command such as the following before running the CLI:
190
cp $KEYCLOAK_HOME/providers/bc-fips-*.jar $KEYCLOAK_HOME/bin/client/lib/
191
cp $KEYCLOAK_HOME/providers/bctls-fips-*.jar $KEYCLOAK_HOME/bin/client/lib/
194
NOTE: When trying to use BCFKS truststore/keystore with CLI, you may see issues due this truststore is not the default java keystore type. It can be good to specify it as default in java
195
security properties. For example run this command on unix based systems before doing any operation with kcadm|kcreg clients:
199
echo "keystore.type=bcfks
200
fips.keystore.type=bcfks" > /tmp/kcadm.java.security
201
export KC_OPTS="-Djava.security.properties=/tmp/kcadm.java.security"
204
== {project_name} server in FIPS mode in containers
206
When you want {project_name} in FIPS mode to be executed inside a container, your "host" must be using FIPS mode as well. The container
207
will then "inherit" FIPS mode from the parent host.
208
See https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/9/html/security_hardening/using-the-system-wide-cryptographic-policies_security-hardening#enabling-fips-mode-in-a-container_using-the-system-wide-cryptographic-policies[this section]
209
in the RHEL documentation for the details.
211
The {project_name} container image will automatically be in fips mode when executed from the host in FIPS mode.
212
However, make sure that the {project_name} container also uses BCFIPS jars (instead of BC jars) and proper options when started.
214
Regarding this, it is best to build your own container image as described in the <@links.server id="containers"/> and tweak it to use BCFIPS etc.
216
For example in the current directory, you can create sub-directory `files` and add:
218
* BC FIPS jar files as described above
219
* Custom keystore file - named for example `keycloak-fips.keystore.bcfks`
220
* Security file `kc.java.security` with added provider for SAML
222
Then create `Dockerfile` in the current directory similar to this:
225
[source,dockerfile,subs="attributes+"]
227
FROM quay.io/keycloak/keycloak:{containerlabel} as builder
232
RUN cp /tmp/files/*.jar /opt/keycloak/providers/
233
RUN cp /tmp/files/keycloak-fips.keystore.* /opt/keycloak/conf/server.keystore
234
RUN cp /tmp/files/kc.java.security /opt/keycloak/conf/
236
RUN /opt/keycloak/bin/kc.sh build --features=fips --fips-mode=strict
238
FROM quay.io/keycloak/keycloak:{containerlabel}
239
COPY --from=builder /opt/keycloak/ /opt/keycloak/
241
ENTRYPOINT ["/opt/keycloak/bin/kc.sh"]
244
Then build FIPS as an optimized Docker image and start it as described in the <@links.server id="containers"/>. These steps require that you use arguments as described above when starting the image.
246
== Migration from non-fips environment
248
If you previously used {project_name} in a non-fips environment, it is possible to migrate it to a FIPS environment including its data. However, restrictions and considerations exist as
249
mentioned in previous sections, namely:
251
* Make sure all the {project_name} functionality relying on keystores uses only supported keystore types. This differs based on whether strict or non-strict mode is used.
252
* Kerberos authentication may not work. If your authentication flow uses `Kerberos` authenticator, this authenticator will be automatically switched to `DISABLED` when migrated to FIPS
253
environment. It is recommended to remove any `Kerberos` user storage providers from your realm and disable `Kerberos` related functionality in LDAP providers before switching to FIPS environment.
255
In addition to the preceding requirements, be sure to doublecheck this before switching to FIPS strict mode:
257
* Make sure that all the {project_name} functionality relying on keys (for example, realm or client keys) use RSA keys of at least 2048 bits
259
* Make sure that clients relying on `Signed JWT with Client Secret` use at least 14 characters long secrets (ideally generated secrets)
261
* Password length restriction as described earlier. In case your users have shorter passwords, be sure to start the server with the max padding length set to 14 of PBKDF2 provider as mentioned
262
earlier. If you prefer to avoid this option, you can for instance ask all your users to reset their password (for example by the `Forgot password` link) during the first authentication in the new environment.
265
== {project_name} FIPS mode on the non-fips system
267
{project_name} is supported and tested on a FIPS enabled RHEL 8 system and `ubi8` image. It is supported with RHEL 9 (and `ubi9` image) as well. Running on
268
the non-RHEL compatible platform or on the non-FIPS enabled platform, the FIPS compliance cannot be strictly guaranteed and cannot be officially supported.
270
If you are still restricted to running {project_name} on such a system, you can at least update your security providers configured in `java.security` file. This update does not amount to FIPS compliance, but
271
at least the setup is closer to it. It can be done by providing a custom security file with only an overriden list of security providers as described earlier. For a list of recommended providers,
272
see the https://access.redhat.com/documentation/en-us/openjdk/17/html/configuring_openjdk_17_on_rhel_with_fips/openjdk-default-fips-configuration[OpenJDK 17 documentation].
274
You can check the {project_name} server log at startup to see if the correct security providers are used. TRACE logging should be enabled for crypto-related Keycloak packages as described in the Keycloak startup command earlier.