This is an automated email from the ASF dual-hosted git repository.
hanicz pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/knox.git
The following commit(s) were added to refs/heads/master by this push:
new 34ba12724 KNOX-3361: Route OpenSAML off BouncyCastle in FIPS mode
(#1299)
34ba12724 is described below
commit 34ba1272412b3ed38422b4e0e5dab784bc518289
Author: hanicz <[email protected]>
AuthorDate: Thu Jul 16 06:45:06 2026 +0200
KNOX-3361: Route OpenSAML off BouncyCastle in FIPS mode (#1299)
* KNOX-3361: Route OpenSAML off BouncyCastle in FIPS mode
* KNOX-3361: Update pac4j docs
---
gateway-provider-security-pac4j/pom.xml | 10 ++
gateway-shim-opensaml-security-api/pom.xml | 110 +++++++++++++++++++++
.../FipsConfigurationPropertiesSource.java | 50 ++++++++++
.../KnoxNamedCurveRegistryInitializer.java | 37 +++++++
...nsaml.core.config.ConfigurationPropertiesSource | 16 +++
.../services/org.opensaml.core.config.Initializer | 16 +++
.../KnoxNamedCurveRegistryInitializerTest.java | 83 ++++++++++++++++
knox-site/docs/config_pac4j_provider.md | 2 +
pom.xml | 21 ++++
9 files changed, 345 insertions(+)
diff --git a/gateway-provider-security-pac4j/pom.xml
b/gateway-provider-security-pac4j/pom.xml
index ee7e55c90..ab2c64e3f 100644
--- a/gateway-provider-security-pac4j/pom.xml
+++ b/gateway-provider-security-pac4j/pom.xml
@@ -148,8 +148,18 @@
<groupId>org.apache.velocity</groupId>
<artifactId>velocity</artifactId>
</exclusion>
+ <!-- Replaced by gateway-shim-opensaml-security-api which
strips
+ the non-FIPS BouncyCastle NamedCurve SPI registration. -->
+ <exclusion>
+ <groupId>org.opensaml</groupId>
+ <artifactId>opensaml-security-api</artifactId>
+ </exclusion>
</exclusions>
</dependency>
+ <dependency>
+ <groupId>org.apache.knox</groupId>
+ <artifactId>gateway-shim-opensaml-security-api</artifactId>
+ </dependency>
<dependency>
<groupId>org.pac4j</groupId>
<artifactId>javaee-pac4j</artifactId>
diff --git a/gateway-shim-opensaml-security-api/pom.xml
b/gateway-shim-opensaml-security-api/pom.xml
new file mode 100644
index 000000000..daf43589f
--- /dev/null
+++ b/gateway-shim-opensaml-security-api/pom.xml
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.knox</groupId>
+ <artifactId>gateway</artifactId>
+ <version>3.0.0-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>gateway-shim-opensaml-security-api</artifactId>
+ <name>gateway-shim-opensaml-security-api</name>
+ <description>
+ A drop-in replacement for org.opensaml:opensaml-security-api that swaps
+ OpenSAML's GlobalNamedCurveRegistryInitializer for a Knox-owned wrapper
+ (KnoxNamedCurveRegistryInitializer). In FIPS mode the wrapper skips the
+ SPI-driven curve registration entirely so no vanilla-BouncyCastle EC
+ code executes; in non-FIPS mode it delegates to the upstream
+ initializer, giving unmodified OpenSAML behavior. Also registers a
+ FIPS-gated ConfigurationPropertiesSource to reroute OpenSAML's ECDH
+ KDF through JCE-driven PBKDF2 in FIPS mode.
+ </description>
+
+ <repositories>
+ <repository>
+ <id>shib-release</id>
+ <url>https://build.shibboleth.net/maven/releases</url>
+ <snapshots>
+ <enabled>false</enabled>
+ </snapshots>
+ <releases>
+ <enabled>true</enabled>
+ </releases>
+ </repository>
+ </repositories>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.opensaml</groupId>
+ <artifactId>opensaml-security-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opensaml</groupId>
+ <artifactId>opensaml-core-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.knox</groupId>
+ <artifactId>gateway-spi</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-shade-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>shade-opensaml-security-api</id>
+ <phase>package</phase>
+ <goals>
+ <goal>shade</goal>
+ </goals>
+ <configuration>
+
<createDependencyReducedPom>true</createDependencyReducedPom>
+
<shadedArtifactAttached>false</shadedArtifactAttached>
+
<promoteTransitiveDependencies>false</promoteTransitiveDependencies>
+ <artifactSet>
+ <includes>
+
<include>org.opensaml:opensaml-security-api</include>
+ </includes>
+ </artifactSet>
+ <filters>
+ <filter>
+
<artifact>org.opensaml:opensaml-security-api</artifact>
+ <excludes>
+
<exclude>META-INF/services/org.opensaml.core.config.Initializer</exclude>
+ </excludes>
+ </filter>
+ </filters>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git
a/gateway-shim-opensaml-security-api/src/main/java/org/apache/knox/gateway/shim/opensaml/FipsConfigurationPropertiesSource.java
b/gateway-shim-opensaml-security-api/src/main/java/org/apache/knox/gateway/shim/opensaml/FipsConfigurationPropertiesSource.java
new file mode 100644
index 000000000..ad4fac7fa
--- /dev/null
+++
b/gateway-shim-opensaml-security-api/src/main/java/org/apache/knox/gateway/shim/opensaml/FipsConfigurationPropertiesSource.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.knox.gateway.shim.opensaml;
+
+import org.apache.knox.gateway.fips.FipsUtils;
+import org.opensaml.core.config.ConfigurationProperties;
+import org.opensaml.core.config.ConfigurationPropertiesSource;
+
+import java.util.Properties;
+
+public final class FipsConfigurationPropertiesSource implements
ConfigurationPropertiesSource {
+
+ private static final ConfigurationProperties FIPS_PROPERTIES =
buildFipsProperties();
+
+ private static ConfigurationProperties buildFipsProperties() {
+ final Properties p = new Properties();
+ p.setProperty("opensaml.config.ecdh.defaultKDF", "PBKDF2");
+ return new ConfigurationProperties() {
+ @Override
+ public String getProperty(String key) {
+ return p.getProperty(key);
+ }
+
+ @Override
+ public String getProperty(String key, String defaultValue) {
+ return p.getProperty(key, defaultValue);
+ }
+ };
+ }
+
+ @Override
+ public ConfigurationProperties getProperties() {
+ return FipsUtils.isFipsEnabledWithBCProvider() ? FIPS_PROPERTIES :
null;
+ }
+}
diff --git
a/gateway-shim-opensaml-security-api/src/main/java/org/apache/knox/gateway/shim/opensaml/KnoxNamedCurveRegistryInitializer.java
b/gateway-shim-opensaml-security-api/src/main/java/org/apache/knox/gateway/shim/opensaml/KnoxNamedCurveRegistryInitializer.java
new file mode 100644
index 000000000..1e94dad66
--- /dev/null
+++
b/gateway-shim-opensaml-security-api/src/main/java/org/apache/knox/gateway/shim/opensaml/KnoxNamedCurveRegistryInitializer.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.knox.gateway.shim.opensaml;
+
+import org.apache.knox.gateway.fips.FipsUtils;
+import org.opensaml.core.config.ConfigurationService;
+import org.opensaml.core.config.InitializationException;
+import org.opensaml.core.config.Initializer;
+import org.opensaml.security.config.GlobalNamedCurveRegistryInitializer;
+import org.opensaml.security.crypto.ec.NamedCurveRegistry;
+
+public class KnoxNamedCurveRegistryInitializer implements Initializer {
+
+ @Override
+ public void init() throws InitializationException {
+ if (FipsUtils.isFipsEnabledWithBCProvider()) {
+ ConfigurationService.register(NamedCurveRegistry.class, new
NamedCurveRegistry());
+ return;
+ }
+ new GlobalNamedCurveRegistryInitializer().init();
+ }
+}
diff --git
a/gateway-shim-opensaml-security-api/src/main/resources/META-INF/services/org.opensaml.core.config.ConfigurationPropertiesSource
b/gateway-shim-opensaml-security-api/src/main/resources/META-INF/services/org.opensaml.core.config.ConfigurationPropertiesSource
new file mode 100644
index 000000000..2567527f7
--- /dev/null
+++
b/gateway-shim-opensaml-security-api/src/main/resources/META-INF/services/org.opensaml.core.config.ConfigurationPropertiesSource
@@ -0,0 +1,16 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+org.apache.knox.gateway.shim.opensaml.FipsConfigurationPropertiesSource
diff --git
a/gateway-shim-opensaml-security-api/src/main/resources/META-INF/services/org.opensaml.core.config.Initializer
b/gateway-shim-opensaml-security-api/src/main/resources/META-INF/services/org.opensaml.core.config.Initializer
new file mode 100644
index 000000000..953db2bbd
--- /dev/null
+++
b/gateway-shim-opensaml-security-api/src/main/resources/META-INF/services/org.opensaml.core.config.Initializer
@@ -0,0 +1,16 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+org.apache.knox.gateway.shim.opensaml.KnoxNamedCurveRegistryInitializer
diff --git
a/gateway-shim-opensaml-security-api/src/test/java/org/apache/knox/gateway/shim/opensaml/KnoxNamedCurveRegistryInitializerTest.java
b/gateway-shim-opensaml-security-api/src/test/java/org/apache/knox/gateway/shim/opensaml/KnoxNamedCurveRegistryInitializerTest.java
new file mode 100644
index 000000000..215fdb002
--- /dev/null
+++
b/gateway-shim-opensaml-security-api/src/test/java/org/apache/knox/gateway/shim/opensaml/KnoxNamedCurveRegistryInitializerTest.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.knox.gateway.shim.opensaml;
+
+import org.apache.knox.gateway.fips.FipsUtils;
+import org.junit.After;
+import org.junit.Test;
+import org.opensaml.core.config.ConfigurationService;
+import org.opensaml.security.crypto.ec.ECSupport;
+import org.opensaml.security.crypto.ec.NamedCurve;
+import org.opensaml.security.crypto.ec.NamedCurveRegistry;
+
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.interfaces.ECPublicKey;
+import java.security.spec.ECGenParameterSpec;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+public class KnoxNamedCurveRegistryInitializerTest {
+
+ @After
+ public void clearFipsProperty() {
+ System.clearProperty(FipsUtils.FIPS_SYSTEM_PROPERTY);
+ }
+
+ @Test
+ public void fipsModeRegistersEmptyRegistry() throws Exception {
+ System.setProperty(FipsUtils.FIPS_SYSTEM_PROPERTY, "true");
+
+ new KnoxNamedCurveRegistryInitializer().init();
+
+ NamedCurveRegistry registry =
ConfigurationService.get(NamedCurveRegistry.class);
+ assertNotNull("Wrapper must always register a NamedCurveRegistry",
registry);
+
+ NamedCurve curve = ECSupport.getNamedCurve((ECPublicKey)
generateP256KeyPair().getPublic());
+ assertNull(
+ "In FIPS mode the wrapper must short-circuit
GlobalNamedCurveRegistryInitializer "
+ + "so the registry is empty and no vanilla-BC EC code
executes.",
+ curve);
+ }
+
+ @Test
+ public void nonFipsModeDelegatesToUpstreamAndPopulatesRegistry() throws
Exception {
+ System.clearProperty(FipsUtils.FIPS_SYSTEM_PROPERTY);
+
+ new KnoxNamedCurveRegistryInitializer().init();
+
+ NamedCurveRegistry registry =
ConfigurationService.get(NamedCurveRegistry.class);
+ assertNotNull("Wrapper must always register a NamedCurveRegistry",
registry);
+
+ NamedCurve curve = ECSupport.getNamedCurve((ECPublicKey)
generateP256KeyPair().getPublic());
+ assertNotNull(
+ "In non-FIPS mode the wrapper must delegate to the upstream "
+ + "GlobalNamedCurveRegistryInitializer, populating the
registry from the "
+ + "NamedCurve SPI so ECDH-ES SAML support remains
functional.",
+ curve);
+ assertEquals("secp256r1", curve.getName());
+ }
+
+ private static KeyPair generateP256KeyPair() throws Exception {
+ KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC");
+ kpg.initialize(new ECGenParameterSpec("secp256r1"));
+ return kpg.generateKeyPair();
+ }
+}
diff --git a/knox-site/docs/config_pac4j_provider.md
b/knox-site/docs/config_pac4j_provider.md
index 7913491ed..f1ef6d0f4 100644
--- a/knox-site/docs/config_pac4j_provider.md
+++ b/knox-site/docs/config_pac4j_provider.md
@@ -187,6 +187,8 @@ This results in a URL that looks something like:
This also means that the SP Entity ID should also include this query parameter
as appropriate for your provider.
Often something like the above URL is used for both the SSO URL and SP Entity
ID.
+NOTE: ECDH-ES-encrypted SAML assertion decryption is not supported in FIPS
mode (empty NamedCurveRegistry). RSA-signed and RSA-OAEP-encrypted SAML flows
work identically in FIPS and non-FIPS.
+
##### For OpenID Connect support:
Name | Value
diff --git a/pom.xml b/pom.xml
index 94ccc793f..369e336fa 100644
--- a/pom.xml
+++ b/pom.xml
@@ -71,6 +71,7 @@
<module>gateway-i18n-logging-sl4j</module>
<module>gateway-spi</module>
<module>gateway-spi-common</module>
+ <module>gateway-shim-opensaml-security-api</module>
<module>gateway-discovery-ambari</module>
<module>gateway-discovery-cm</module>
<module>gateway-performance-test</module>
@@ -2705,11 +2706,31 @@
<artifactId>opensaml-core</artifactId>
<version>${opensaml.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.opensaml</groupId>
+ <artifactId>opensaml-core-api</artifactId>
+ <version>${opensaml.version}</version>
+ </dependency>
<dependency>
<groupId>org.opensaml</groupId>
<artifactId>opensaml-security-api</artifactId>
<version>${opensaml.version}</version>
</dependency>
+ <!-- FIPS shim: shaded opensaml-security-api with the non-FIPS
+ BouncyCastle NamedCurve SPI stripped out. Modules that need
+ opensaml-security-api on the classpath should depend on this
+ instead and exclude the upstream artifact from pac4j-saml. -->
+ <dependency>
+ <groupId>org.apache.knox</groupId>
+ <artifactId>gateway-shim-opensaml-security-api</artifactId>
+ <version>${project.version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>org.opensaml</groupId>
+ <artifactId>opensaml-security-api</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
<dependency>
<groupId>org.opensaml</groupId>
<artifactId>opensaml-security-impl</artifactId>