Running Nexus with FIPS mode enabled (plus LDAP)

I’m running Nexus Repository Manager in Docker on a UBI8 (RedHat) base image, which uses FIPS mode when the host is also in FIPS mode.

We then get the following error in the Nexus container logs:

2022-02-11 16:26:34,368+0000 WARN  [FelixStartLevel] *SYSTEM Sisu - Problem adding: org.eclipse.sisu.inject.LazyBeanEntry@5db2efd6 to: org.sonatype.nexus.internal.event.EventManagerImpl@3c2a453a via: org.sonatype.nexus.internal.event.EventManagerImpl$EventAwareMediator@232b0e56
com.google.inject.ProvisionException: Unable to provision, see the following errors:

1) [Guice/ErrorInjectingConstructor]: FileNotFoundException: NONE (No such file or directory)
  at TrustStoreImpl.<init>(TrustStoreImpl.java:84)
  at /
      \_ installed by: NexusBundleModule -> SpaceModule
  while locating TrustStoreImpl
  while locating Object annotated with *

Learn more:
  https://github.com/google/guice/wiki/ERROR_INJECTING_CONSTRUCTOR

1 error

======================
Full classname legend:
======================
FileNotFoundException: "java.io.FileNotFoundException"
NexusBundleModule:     "org.sonatype.nexus.extender.modules.NexusBundleModule"
SpaceModule:           "org.eclipse.sisu.space.SpaceModule"
TrustStoreImpl:        "com.sonatype.nexus.ssl.plugin.internal.TrustStoreImpl"
========================
End of classname legend:
========================

	at com.google.inject.internal.InternalProvisionException.toProvisionException(InternalProvisionException.java:251)
	at com.google.inject.internal.InjectorImpl$1.get(InjectorImpl.java:1103)
	at org.eclipse.sisu.inject.LazyBeanEntry.getValue(LazyBeanEntry.java:81)
	at org.sonatype.nexus.internal.event.EventManagerImpl$EventAwareMediator.add(EventManagerImpl.java:81)
	at org.sonatype.nexus.internal.event.EventManagerImpl$EventAwareMediator.add(EventManagerImpl.java:1)
	at org.eclipse.sisu.inject.WatchedBeans.add(WatchedBeans.java:80)
	at org.eclipse.sisu.inject.InjectorBindings.publishWildcardMatches(InjectorBindings.java:185)
	at org.eclipse.sisu.inject.InjectorBindings.subscribe(InjectorBindings.java:86)
	at org.eclipse.sisu.inject.DefaultBeanLocator.watch(DefaultBeanLocator.java:80)
	at org.sonatype.nexus.internal.event.EventManagerImpl.doStart(EventManagerImpl.java:93)
	at org.sonatype.goodies.lifecycle.LifecycleSupport.start(LifecycleSupport.java:99)
	at org.sonatype.nexus.extender.NexusLifecycleManager.startComponent(NexusLifecycleManager.java:199)
	at org.sonatype.nexus.extender.NexusLifecycleManager.to(NexusLifecycleManager.java:111)
	at org.sonatype.nexus.extender.NexusContextListener.moveToPhase(NexusContextListener.java:319)
	at org.sonatype.nexus.extender.NexusContextListener.frameworkEvent(NexusContextListener.java:216)
	at org.apache.felix.framework.Felix.setActiveStartLevel(Felix.java:1597)
	at org.apache.felix.framework.FrameworkStartLevelImpl.run(FrameworkStartLevelImpl.java:308)
	at java.lang.Thread.run(Thread.java:750)
Caused by: java.io.FileNotFoundException: NONE (No such file or directory)
	at java.io.FileInputStream.open0(Native Method)
	at java.io.FileInputStream.open(FileInputStream.java:195)
	at java.io.FileInputStream.<init>(FileInputStream.java:138)
	at com.sonatype.nexus.ssl.plugin.internal.TrustStoreImpl.getSystemKeyManagers(TrustStoreImpl.java:240)
	at com.sonatype.nexus.ssl.plugin.internal.TrustStoreImpl.<init>(TrustStoreImpl.java:91)
	at com.sonatype.nexus.ssl.plugin.internal.TrustStoreImpl$$FastClassByGuice$$372908699.GUICE$TRAMPOLINE(<generated>)
	at com.sonatype.nexus.ssl.plugin.internal.TrustStoreImpl$$FastClassByGuice$$372908699.apply(<generated>)
	at com.google.inject.internal.DefaultConstructionProxyFactory$FastClassProxy.newInstance(DefaultConstructionProxyFactory.java:82)
	at com.google.inject.internal.ConstructorInjector.provision(ConstructorInjector.java:114)
	at com.google.inject.internal.ConstructorInjector.construct(ConstructorInjector.java:91)
	at com.google.inject.internal.ConstructorBindingImpl$Factory.get(ConstructorBindingImpl.java:296)
	at com.google.inject.internal.ProviderToInternalFactoryAdapter.get(ProviderToInternalFactoryAdapter.java:40)
	at com.google.inject.internal.SingletonScope$1.get(SingletonScope.java:169)
	at com.google.inject.internal.InternalFactoryToProviderAdapter.get(InternalFactoryToProviderAdapter.java:45)
	at com.google.inject.internal.FactoryProxy.get(FactoryProxy.java:60)
	at com.google.inject.internal.InjectorImpl$1.get(InjectorImpl.java:1100)
	... 16 common frames omitted

This seems to be coming from this piece of code: https://github.com/sonatype/nexus-public/blob/release-3.37.3-02/plugins/nexus-ssl-plugin/src/main/java/com/sonatype/nexus/ssl/plugin/internal/TrustStoreImpl.java#L240
It seems like it cannot read the Java keystore file (It throws a FileNotFoundException).

By disabling FIPS mode in Java, everything works fine: -Dcom.redhat.fips=false.
However, we would like to have it work with FIPS mode enabled.

Here are some solutions I’ve tried but did not work.

It seems like FIPS mode uses nssdb with the modutil command. With nssdb installed, I tried setting the keystore like this: -Djavax.net.ssl.keyStore=/etc/pki/nssdb/key3.db. We still got the same error.

It’s possible additional settings may be required for a PKCS11 keystore. See comment below for a link to the docs, but I haven’t had the time to investigate.

It’s also possible a PKCS12 keystore is required (Java 8 uses JKS for the keystore by default), see comment below for link to docs.

I tried running this command like it says to convert the key to PKCS12:

keytool -importkeystore -srckeystore $JAVA_HOME/lib/security/cacerts -destkeystore $JAVA_HOME/lib/security/cacerts.p12 –deststoretype pkcs12

But get the following error, which seems to also be caused by FIPS mode:

keytool error: java.lang.ClassNotFoundException: com.rsa.jsafe.provider.JsafeJCE

I also tried the second command in those docs, but the com.rsa.jsafe.provider.JsafeJCE class doesn’t exist and I’m not sure how to install it.

keytool -importkeystore -srckeystore $JAVA_HOME/lib/security/cacerts.p12 -srcstoretype PKCS12 -srcprovidername JsafeJCE -destkeystore $JAVA_HOME/lib/security/cacerts.rsa -deststoretype PKCS12 -destprovidername JsafeJCE -providerclass com.rsa.jsafe.provider.JsafeJCE

Any guidance would be appreciated.

The image can be found here (tag 3.37.3-02): Log in to DevSecOps Collaboration Workspace

PKCS11 docs: PKCS#11 Reference Guide

PKCS12 FIPS docs: Enabling FIPS Mode

We also encountered the same issue, not in containers but as a ‘Native application’ on RHEL8 with FIPS Mode.
I opened a bug report :
https://issues.sonatype.org/browse/NEXUS-32177

You will not get Nexus (or any Java program using JKS formatted key stores for that matter) to run on a FIPS enabled environment. This is true because the FIPS standard defines the types of encryption which the system may and may not use. Unfortunately the encryption used for JKS files is not approved under FIPS.

The solution of disabling FIPS mode in Java is about all we can do, unless Nexus chooses to release a version of their software that only uses FIPS approved encryption. This seems unlikely in the near term as the standard for JKS files is long standing and using JKS files is very common. Selectively disabling FIPS for Nexus doesn’t seem unreasonable to me, but if you are being forced into this, you may need to wait a long time for Sonatype to become FIPS compliant.

Also, I wanted to point out that the “keytool” is really a Java program too. The reason why “keytool” fails is the same reason Nexus fails under FIPS and luckily the solution is the same, add the “-Dcom.redhat.fips=false” flag to the Java command line. Looking at the man page for keytool tells me that they support a “-J” option to pass things to the Java command line. So, for your keytool commands, simply add “-J-Dcom.redhat.fips=false” and the keytool commands dealing with JKS files will work for you.

Good luck!