Skip to content

Commit

Permalink
FIPS related docs (#17196)
Browse files Browse the repository at this point in the history
* FIPS related docs
Closes #16444 #12432 #12429

Co-authored-by: andymunro <48995441+andymunro@users.noreply.github.com>
  • Loading branch information
mposolda and andymunro committed Feb 22, 2023
1 parent f91ac29 commit b9ab942
Show file tree
Hide file tree
Showing 5 changed files with 262 additions and 169 deletions.
170 changes: 4 additions & 166 deletions docs/fips.md
Original file line number Diff line number Diff line change
@@ -1,171 +1,9 @@
FIPS 140-2 Integration
======================

Environment
-----------
All the steps below were tested on RHEL 8.6 with FIPS mode enabled (See [this page](https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/security_hardening/assembly_installing-a-rhel-8-system-with-fips-mode-enabled_security-hardening#doc-wrapper)
for the details) and with OpenJDK 17.0.5 on that host.
This document is outdated and will be removed in the future. Please look at the official Keycloak documentation for FIPS integration
or at file [fips.adoc](./guides/src/main/server/fips.adoc).

Run the server with FIPS
------------------------

To run Keycloak quarkus distribution, on the FIPS enabled host and FIPS enabled OpenJDK, you need to:
- Make sure that Keycloak will use the BouncyCastle FIPS dependencies instead of the normal BouncyCastle dependencies
- Make sure to start the server with the FIPS mode.

1) Copy BCFIPS dependencies to your Keycloak distribution.
You can either download them from BouncyCastle page and add it manually to the directory `KEYCLOAK_HOME/providers`(make sure to
use proper versions compatible with BouncyCastle Keycloak dependencies).

Or you can use for example commands like this to copy the appropriate BCFIPS jars to the Keycloak distribution. Again, replace
the BCFIPS versions with the appropriate versions from pom.xml. Assumption is that you have already these BCFIPS in
your local maven repository, which can be achieved for example by building `crypto/fips1402` module (See the section for
running the unit tests below):

```
cd $KEYCLOAK_HOME/bin
export MAVEN_REPO_HOME=$HOME/.m2/repository
export BCFIPS_VERSION=1.0.2.3
export BCTLSFIPS_VERSION=1.0.14
export BCPKIXFIPS_VERSION=1.0.7
cp $MAVEN_REPO_HOME/org/bouncycastle/bc-fips/$BCFIPS_VERSION/bc-fips-$BCFIPS_VERSION.jar ../providers/
cp $MAVEN_REPO_HOME/org/bouncycastle/bctls-fips/$BCTLSFIPS_VERSION/bctls-fips-$BCTLSFIPS_VERSION.jar ../providers/
cp $MAVEN_REPO_HOME/org/bouncycastle/bcpkix-fips/$BCPKIXFIPS_VERSION/bcpkix-fips-$BCPKIXFIPS_VERSION.jar ../providers/
```

2) Now create either pkcs12 or bcfks keystore. The pkcs12 works just in BCFIPS non-approved mode.

Please choose either `bcfips` or `pkcs12` and use the appropriate value of `KEYSTORE_FILE` variable according to your choice:

Also make sure to set `KEYCLOAK_SOURCES` to the location with your Keycloak codebase.

Note that for keystore generation, it is needed to use the BouncyCastle FIPS libraries and use custom security file, which
will remove default SUN and SunPKCS11 providers as it doesn't work to create keystore with them on FIPS enabled OpenJDK11 due
the limitation described here https://access.redhat.com/solutions/6954451 and in the related bugzilla https://bugzilla.redhat.com/show_bug.cgi?id=2048582.
```
export KEYSTORE_FILE=keycloak-server.p12
#export KEYSTORE_FILE=keycloak-server.bcfks
export KEYCLOAK_SOURCES=$HOME/IdeaProjects/keycloak
export KEYSTORE_FORMAT=$(echo $KEYSTORE_FILE | cut -d. -f2)
if [ "$KEYSTORE_FORMAT" == "p12" ]; then
export KEYSTORE_FORMAT=pkcs12;
fi;
# Removing old keystore file to start from fresh
rm keycloak-server.p12
rm keycloak-server.bcfks
keytool -keystore $KEYSTORE_FILE \
-storetype $KEYSTORE_FORMAT \
-providername BCFIPS \
-providerclass org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider \
-provider org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider \
-providerpath $MAVEN_REPO_HOME/org/bouncycastle/bc-fips/1.0.2.3/bc-fips-1.0.2.3.jar \
-alias localhost \
-genkeypair -sigalg SHA512withRSA -keyalg RSA -storepass passwordpassword \
-dname CN=localhost -keypass passwordpassword \
-J-Djava.security.properties=$KEYCLOAK_SOURCES/testsuite/integration-arquillian/servers/auth-server/common/fips/kc.keystore-create.java.security
```

3) Run "build" to re-augment with `enabled` fips mode and start the server. This will run the server with BCFIPS in non-approved mode

```
./kc.sh start --fips-mode=enabled --hostname=localhost \
--https-key-store-file=$PWD/$KEYSTORE_FILE \
--https-key-store-type=$KEYSTORE_FORMAT \
--https-key-store-password=passwordpassword \
--log-level=INFO,org.keycloak.common.crypto:TRACE,org.keycloak.crypto:TRACE
```

4) For the `fips-mode` option, the more secure alternative is to use `--fips-mode=strict` in which case BouncyCastle FIPS will use "approved mode",
which means even stricter security requirements on cryptography and security algorithms. Few more points:
- As mentioned above, strict mode won't work with `pkcs12` keystore. So it is needed to use other keystore (probably `bcfks`).
- User passwords must be 14 characters or longer. Keycloak uses PBKDF2 based password encoding by default. BCFIPS approved mode requires passwords to be at least 112 bits
- (effectively 14 characters). If you want to allow shorter password, you need to set property `max-padding-length` of
provider `pbkdf2-sha256` of SPI `password-hashing` to value 14, so there will be some additional padding used when verifying hash created by this algorithm.
This is also backwards compatible with previously stored passwords (if you had your user's DB in non-FIPS environment and you have shorter passwords and you
want to verify them now with Keycloak using BCFIPS in approved mode, it should work fine). So effectively, you can use option like this when starting the server:
```
--spi-password-hashing-pbkdf2-sha256-max-padding-length=14
```
- RSA keys of 1024 bits don't work (2048 is the minimum). This applies for keys used by Keycloak realm itself (Realm keys from the `Keys` tab), but also client keys and IDP keys
- 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` (aka `client-secret-jwt`), then your client secrets should be at least 14 characters long.
But anyway, it is recommended to use client secrets generated by Keycloak server, which always matches this requirement.
- Also `jks` and `pkcs12` keystores/trustores are not supported.

When starting server at startup, you can check that startup log contains `KC` provider contains KC provider with the note about `Approved Mode` like this:
```
KC(BCFIPS version 1.000203 Approved Mode) version 1.0 - class org.keycloak.crypto.fips.KeycloakFipsSecurityProvider,
```

Other considerations
--------------------
#### SAML and Kerberos
In order to have SAML working, there is a need to have `XMLDSig` security provider to be available in your `JAVA_HOME/conf/security/java.security`.
In order to have Kerberos working, there is a need to have `SunJGSS` security provider available. In FIPS enabled RHEL 8.6 in OpenJDK 17.0.5, these
security providers are not by default in the `java.security`, which means that they effectively cannot work.

To have SAML working, you can manually add the provider into `java.security` into the list fips providers. For example add the line like:
```
fips.provider.7=XMLDSig
```
Adding this security provider should be fine as in fact it is FIPS compliant and likely will be added by default in the future OpenJDK micro version.
Details: https://bugzilla.redhat.com/show_bug.cgi?id=1940064

For Kerberos, there are few more things to be done to have security provider FIPS compliant. Hence it is not recommended to add security provider
if you want to be FIPS compliant. The `KERBEROS` feature is disabled by default in Keycloak when it is executed on this platform and when security provider is not
available. Details: https://bugzilla.redhat.com/show_bug.cgi?id=2051628

Run the CLI on the FIPS host
----------------------------
In case you want to run Client Registration CLI (`kcreg.sh/bat` script) or Admin CLI (`kcadm.sh/bat` script), it is needed
that CLI will also use the BouncyCastle FIPS dependencies instead of plain BouncyCastle dependencies. To achieve this, you may copy the
jars to the CLI library folder and that is enough. CLI tool will automatically use BCFIPS dependencies instead of plain BC when
it detects that corresponding BCFIPS jars are present (see above for the versions used):
```
cp $MAVEN_REPO_HOME/org/bouncycastle/bc-fips/$BCFIPS_VERSION/bc-fips-$BCFIPS_VERSION.jar ../bin/client/lib/
cp $MAVEN_REPO_HOME/org/bouncycastle/bctls-fips/$BCTLSFIPS_VERSION/bctls-fips-$BCTLSFIPS_VERSION.jar ../bin/client/lib/
```

Keycloak server in FIPS mode in the container
---------------------------------------------
When you want Keycloak in FIPS mode to be executed inside container, it is needed that your "host" is using FIPS mode as well. The container
will then "inherit" FIPS mode from the parent host. See this docs for the details in the RHEL documentation:
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

So keycloak container image will be just automatically in fips mode when executed from the host in FIPS mode. So only things needed is to
make sure that Keycloak container also uses BCFIPS jars (instead of BC jars) and proper options when started.

Regarding this, it is likely best to build your own container image based on the official keycloak image and tweak it to use BCFIPS etc. For
inspiration, you can take a look at the GH project https://github.com/mposolda/keycloak-fips-image, which does pretty much what is described in
this README file above, and allows to consume this in the container

#### TODO: When we convert this README into official docs, we should likely avoid using this GH project, but somehow describe it better as for example here: https://www.keycloak.org/server/containers


Run the unit tests in the FIPS environment
------------------------------------------
This instruction is about running automated tests on the FIPS enabled RHEL 8.6 system with the FIPS enabled OpenJDK 11.

So far only the unit tests inside the `crypto` module are supported. More effort is needed to have whole testsuite passing.

First it is needed to build the project (See above). Then run the tests in the `crypto` module.
```
mvn clean install -f common -DskipTests=true
mvn clean install -f core -DskipTests=true
mvn clean install -f server-spi -DskipTests=true
mvn clean install -f server-spi-private -DskipTests=true
mvn clean install -f services -DskipTests=true
mvn clean install -f crypto/fips1402
```

The tests should work also with the BouncyCastle approved mode, which is more strict in the used crypto algorithms
```
mvn clean install -f crypto/fips1402 -Dorg.bouncycastle.fips.approved_only=true
```

Run the integration tests in the FIPS environment
-------------------------------------------------
Run the unit or integration tests in the FIPS environment.
---------------------------------------------------------
See the FIPS section in the [HOW-TO-RUN.md](../testsuite/integration-arquillian/HOW-TO-RUN.md)
Loading

0 comments on commit b9ab942

Please sign in to comment.