Skip to content

Commit

Permalink
[JEP-237] Add new method to RealJenkinsRule to start in FIPS mode (#829)
Browse files Browse the repository at this point in the history
Signed-off-by: Olivier Lamy <[email protected]>
  • Loading branch information
olamy authored Sep 16, 2024
1 parent a9407ce commit 87a0eab
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 1 deletion.
5 changes: 5 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,11 @@ THE SOFTWARE.
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.jenkins.test.fips</groupId>
<artifactId>fips-bundle-test</artifactId>
<version>23.v76d4fd57f5b_d</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
Expand Down
40 changes: 39 additions & 1 deletion src/main/java/org/jvnet/hudson/test/RealJenkinsRule.java
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
Expand All @@ -90,6 +91,8 @@
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import io.jenkins.test.fips.FIPSTestBundleProvider;
import jenkins.model.Jenkins;
import jenkins.model.JenkinsLocationConfiguration;
import jenkins.util.Timer;
Expand Down Expand Up @@ -200,6 +203,7 @@ public final class RealJenkinsRule implements TestRule {

private boolean prepareHomeLazily;
private boolean provisioned;
private final List<File> bootClasspathFiles = new ArrayList<>();

// TODO may need to be relaxed for Gradle-based plugins

Check warning on line 208 in src/main/java/org/jvnet/hudson/test/RealJenkinsRule.java

View check run for this annotation

ci.jenkins.io / Open Tasks Scanner

TODO

NORMAL: may need to be relaxed for Gradle-based plugins
private static final Pattern SNAPSHOT_INDEX_JELLY = Pattern.compile("(file:/.+/target)/classes/index.jelly");
Expand Down Expand Up @@ -457,6 +461,36 @@ public RealJenkinsRule prepareHomeLazily(boolean prepareHomeLazily) {
return this;
}

/**
* Use {@link #withFIPSEnabled(FIPSTestBundleProvider)} with default value of {@link FIPSTestBundleProvider#get()}
*/
public RealJenkinsRule withFIPSEnabled() {
return withFIPSEnabled(FIPSTestBundleProvider.get());
}

/**
+
* @param fipsTestBundleProvider the {@link FIPSTestBundleProvider} to use for testing
*/
public RealJenkinsRule withFIPSEnabled(FIPSTestBundleProvider fipsTestBundleProvider) {
Objects.requireNonNull(fipsTestBundleProvider, "fipsTestBundleProvider must not be null");
try {
return withBootClasspath(fipsTestBundleProvider.getBootClasspathFiles().toArray(new File[0]))
.javaOptions(fipsTestBundleProvider.getJavaOptions().toArray(new String[0]));
} catch (IOException e) {
throw new RuntimeException(e);
}
}

/**
*
* @param files add some {@link File} to bootclasspath
*/
public RealJenkinsRule withBootClasspath(File...files) {
this.bootClasspathFiles.addAll(List.of(files));
return this;
}

public static List<String> getJacocoAgentOptions() {
RuntimeMXBean runtimeMxBean = ManagementFactory.getRuntimeMXBean();
List<String> arguments = runtimeMxBean.getInputArguments();
Expand Down Expand Up @@ -744,8 +778,12 @@ public void startJenkins() throws Throwable {
+ ",suspend=" + (debugSuspend ? "y" : "n")
+ (debugPort > 0 ? ",address=" + httpListenAddress + ":" + debugPort : ""));
}
argv.addAll(javaOptions);
if(!bootClasspathFiles.isEmpty()) {
String fileList = bootClasspathFiles.stream().map(File::getAbsolutePath).collect(Collectors.joining(File.pathSeparator));
argv.add("-Xbootclasspath/a:" + fileList);

}
argv.addAll(javaOptions);

argv.addAll(List.of(
"-jar", war.getAbsolutePath(),
Expand Down
73 changes: 73 additions & 0 deletions src/test/java/org/jvnet/hudson/test/RealJenkinsRuleFIPSTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* The MIT License
*
* Copyright 2024 Olivier Lamy
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

package org.jvnet.hudson.test;

import io.jenkins.test.fips.FIPSTestBundleProvider;
import jenkins.security.FIPS140;
import org.junit.Rule;
import org.junit.Test;

import javax.net.ssl.KeyManagerFactory;
import java.security.KeyStore;
import java.security.Provider;
import java.security.Security;
import java.util.Arrays;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;

public class RealJenkinsRuleFIPSTest {

@Rule public RealJenkinsRule rr = new RealJenkinsRule().prepareHomeLazily(true)
.withDebugPort(4001).withDebugServer(false)
.withFIPSEnabled(FIPSTestBundleProvider.get())
.javaOptions("-Djava.security.debug=properties");

@Test
public void fipsMode() throws Throwable {
rr.then(r -> {
Provider[] providers = Security.getProviders();
System.out.println("fipsMode providers:" + Arrays.asList(providers));

Class<?> clazz = Thread.currentThread().getContextClassLoader().loadClass("org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider");
System.out.println("BouncyCastleFipsProvider class:" + clazz);

Provider provider = Security.getProvider("BCFIPS");
assertThat(provider, notNullValue());
assertThat(provider.getClass().getName(), is("org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider"));
assertThat(providers[0].getClass().getName(), is("org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider"));
assertThat(providers[1].getClass().getName(), is("org.bouncycastle.jsse.provider.BouncyCastleJsseProvider"));
assertThat(providers[2].getClass().getName(), is("sun.security.provider.Sun"));
assertThat(KeyStore.getDefaultType(), is("BCFKS"));
assertThat(KeyManagerFactory.getDefaultAlgorithm(), is("PKIX"));

assertThat(providers.length, is(3));

assertThat(FIPS140.useCompliantAlgorithms(), is(true));
});
}

}

0 comments on commit 87a0eab

Please sign in to comment.