Configure JBoss EAP 7.4 with BouncyCastle FIPS in OpenJDK 17
Configure Your Environment to use the BouncyCastle Provider
The original instructions for Java 8 are located here however, there are two changes since it was documented:
- Java 11 eliminated the
$JAVA_HOME/lib/extdirectory so it's no longer to add Bouncy Castle's jars to the classpath through this method - OpenJDK on RHEL 8 and later will autodetect that FIPS is enabled in the OS and will configure NSS instead. NSS and BouncyCastle FIPS are mutual exclusive so you need to choose which to use. Instead of using BouncyCastle FIPS consider just using NSS instead since the full solution is maintained by Red Hat.
Prerequisite:
The Bouncy Castle JARs are not provided by Red Hat, and must be obtained directly from Bouncy Castle. It's asssumed you have these jars named "bc-fips-<version>.jar" and " bctls-fips-<version>.jar".
You must also have migrated EAP to Elytron because legacy security is not supported in OpenJDK 17.
Steps:
- Create a custom java.security file. The file used in the example is called custom_java.security. You can copy the underlying JVM's java.security file and edit it to have the security providers as follows (everything else remains the same). Replace existing values with the same entry names:
security.provider.1=org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider
security.provider.2=org.bouncycastle.jsse.provider.BouncyCastleJsseProvider fips:BCFIPS
security.provider.3=SUN
security.provider.4=SunEC
security.provider.5=SunJCE
...
ssl.KeyManagerFactory.algorithm=PKIX
...
securerandom.strongAlgorithms=DEFAULT:BCFIPS
Note if you are running on RHEL using OpenJDK and have FIPS enabled, then you instead nee to use fips.provider.### instead of security.provider.###.
- Configure Java package exports for security packages by adding the following to
$JBOSS_HOME/bin/standalone.conf:
JAVA_OPTS="$JAVA_OPTS --add-exports=java.base/sun.security.provider=ALL-UNNAMED --add-opens=java.base/sun.security.util=ALL-UNNAMED --add-exports=java.base/com.sun.crypto.provider=ALL-UNNAMED"
- Start the JBoss EAP server with the custom security file:
bin/standalone.sh -Djava.security.properties==/path/to/custom_java.security
Or you can add the custom java.security to bin/standalone.conf:
JAVA_OPTS="$JAVA_OPTS -Djava.security.properties==/path/to/custom_java.security"
- Connect to the jboss-cli:
.jboss-cli.sh --connect
- Add the
BouncyCastlemodule and register it as provider in the JBoss CLI:
module add --name=org.bouncycastle.fips --resources=bc-fips-1.0.2.4.jar:bctls-fips-1.0.19.jar
/subsystem=elytron/provider-loader=BCFIPS:add(module=org.bouncycastle.fips)
/subsystem=elytron/provider-loader=SunJCE:add(class-names=[com.sun.crypto.provider.SunJCE])
/subsystem=elytron/aggregate-providers=customProviders:add(providers=[BCFIPS,SunJCE,elytron])
/subsystem=elytron:write-attribute(name=final-providers,value=customProviders)
reload
Configure Your Undertow Subsystem to use BouncyCastle
Prerequisite:
Create your server certificate and import it into a BCFKS keystore. For the purpose of this example, I'm creating a self-signed certificate with the following command:
keytool -J-Djava.security.properties=custom_java.security -genkeypair -alias jboss -keyalg RSA -keysize 4096 -keypass PASSWORD -keystore standalone/configuration/application.keystore -storetype BCFKS -storepass STORE_PASSWORD -provider org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider -providerpath bc-fips-1.0.2.4.jar -dname "cn=localhost"
Steps:
- Add the FIPS 140-2 compliant cryptography key-store, key-manager and ssl-context. When defining the keystore, the type must be BCFKS.
/subsystem=elytron/key-store=fipsKS:add(path=application.keystore,relative-to=jboss.server.config.dir,credential-reference={clear-text=STORE_PASSWORD},type="BCFKS")
/subsystem=elytron/key-manager=fipsKM:add(key-store=fipsKS,algorithm="PKIX",credential-reference={clear-text=PASSWORD})
/subsystem=elytron/server-ssl-context=fipsSSC:add(key-manager=fipsKM,protocols=["TLSv1.2"],cipher-suite-filter="TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, TLS_DHE_DSS_WITH_AES_256_CBC_SHA, TLS_DHE_DSS_WITH_AES_256_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_3DES_EDE_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA256, TLS_RSA_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA256,TLS_RSA_WITH_AES_256_CCM,TLS_RSA_WITH_AES_128_CCM")
batch
/subsystem=undertow/server=default-server/https-listener=https:undefine-attribute(name=security-realm)
/subsystem=undertow/server=default-server/https-listener=https:write-attribute(name=ssl-context,value=fipsSSC)
run-batch
- Delete the default SSL configuration. Note if you have already overriden this configuration you will need to adjust to your configuration.
/subsystem=elytron/server-ssl-context=applicationSSC:remove
/subsystem=elytron/key-manager=applicationKM:remove
/subsystem=elytron/key-store=applicationKS:remove
Setup a credential store to mask sensitive security information like passwords
Steps:
- Generate a secret key keystore. You need to pass the BC provider:
keytool -J-Djava.security.properties=custom_java.security -genseckey -keystore secretkey.bcfks -storetype BCFKS -storepass password -alias credstoreKey -keyalg AES -keysize 256 -keypass password -provider org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider -providerpath bc-fips-1.0.2.4.jar -dname "CN=localhost" -validity 365
- Connect to the jboss-cli:
bin/jboss-cli.sh --connect
- Configure the credential store:
/subsystem=elytron/credential-store=exampleFipsCredentialStore:add(credential-reference={clear-text=password},implementation-properties={keyAlias=credstoreKey,external=true, externalPath=credentialStore.bcfks, keyStoreType=BCFKS}, create=true, path=secretkey.bcfks, modifiable=true, other-providers=customProviders, relative-to=jboss.server.config.dir)
You can now add any stored secrets (i.e. passwords) with the following:
/subsystem=elytron/credential-store=exampleFipsCredentialStore:add-alias(alias=exampleAlias, secret-value=exampleValue)
For example, to configure the data source ExampleDS with a password from the credential store you could do:
/subsystem=elytron/credential-store=exampleFipsCredentialStore:add-alias(alias=exampleDbPassword, secret-value=sa)
batch
/subsystem=datasources/data-source=ExampleDS:write-attribute(name=credential-reference,value={store=exampleFipsCredentialStore, alias=exampleDbPassword})
/subsystem=datasources/data-source=ExampleDS:undefine-attribute(name=password)
run-batch
You can check that secret values have been added by running the following:
/subsystem=elytron/credential-store=exampleFipsCredentialStore:read-aliases()
{
"outcome" => "success",
"result" => [
"exampledbpassword",
"examplealias"
]
}