Skip to content

Commit

Permalink
Test with a static test cert and keystore instead of generating a new…
Browse files Browse the repository at this point in the history
… one each run
  • Loading branch information
Vlatombe committed Oct 10, 2024
1 parent bc4ba6e commit 58c5c7b
Show file tree
Hide file tree
Showing 9 changed files with 118 additions and 230 deletions.
5 changes: 0 additions & 5 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -212,11 +212,6 @@ THE SOFTWARE.
<artifactId>jmh-generator-annprocess</artifactId>
<version>${jmh.version}</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk18on</artifactId>
<version>1.78.1</version>
</dependency>
<dependency>
<groupId>org.jenkins-ci</groupId>
<artifactId>test-annotations</artifactId>
Expand Down
163 changes: 0 additions & 163 deletions src/main/java/jenkins/test/https/SelfSignedCertificates.java

This file was deleted.

This file was deleted.

47 changes: 23 additions & 24 deletions src/main/java/org/jvnet/hudson/test/RealJenkinsRule.java
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,10 @@
import java.security.KeyStoreException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
Expand Down Expand Up @@ -112,8 +111,10 @@
import io.jenkins.test.fips.FIPSTestBundleProvider;
import jenkins.model.Jenkins;
import jenkins.model.JenkinsLocationConfiguration;
import jenkins.test.https.KeyStoreManager;
import jenkins.util.Timer;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.htmlunit.WebClient;
import org.junit.AssumptionViolatedException;
import org.junit.rules.DisableOnDebug;
Expand All @@ -122,8 +123,6 @@
import org.junit.rules.Timeout;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
import jenkins.test.https.KeyStoreManager;
import jenkins.test.https.SelfSignedCertificates;
import org.jvnet.hudson.test.recipes.LocalData;
import org.kohsuke.stapler.HttpResponse;
import org.kohsuke.stapler.HttpResponses;
Expand Down Expand Up @@ -765,54 +764,54 @@ public URL getUrl() throws MalformedURLException {

/**
* Sets up HTTPS for the current instance, and disables plain HTTP.
* This generates a self-signed certificate for localhost. The corresponding root CA that needs to be trusted by HTTP client can be obtained using {@link #getRootCA()}.
* This generates a self-signed certificate for <em>localhost</em>. The corresponding root CA that needs to be trusted by HTTP client can be obtained using {@link #getRootCA()}.
*
* @return the current instance
* @see #createWebClient()
*/
public RealJenkinsRule https() {
return https("localhost");
try {
var keyStorePath = tmp.allocate().toPath().resolve("test-keystore.p12");
IOUtils.copy(getClass().getResource("/https/test-keystore.p12"), keyStorePath.toFile());
var keyStoreManager = new KeyStoreManager(keyStorePath, "changeit");
try (var is = getClass().getResourceAsStream("/https/test-cert.pem")) {
var cert = (X509Certificate) CertificateFactory.getInstance("X.509").generateCertificate(is);
https("localhost", keyStoreManager, cert);
}
} catch (CertificateException | KeyStoreException | NoSuchAlgorithmException | IOException e) {
throw new RuntimeException(e);
}
return this;
}


/**
* Sets up HTTPS for the current instance, and disables plain HTTP.
* This generates a self-signed certificate for the given host name. The corresponding root CA that needs to be trusted by HTTP client can be obtained using {@link #getRootCA()}.
* <p>
* You don't need to call {@link #withHost(String)} when calling this method.
*
* @param host the host name to use in the certificate
* @param keyStoreManager a key store manager containing the key and certificate to use for HTTPS. It needs to be valid for the given host
* @param rootCA the certificate that needs to be trusted by callers.
* @return the current instance
* @see #createWebClient()
* @see #withHost(String)
*/
public RealJenkinsRule https(@NonNull String host) {
public RealJenkinsRule https(@NonNull String host, @NonNull KeyStoreManager keyStoreManager, @NonNull X509Certificate rootCA) {
this.host = host;
this.https = true;
this.keyStoreManager = keyStoreManager;
try {
// TODO remove password once we have https://github.com/jenkinsci/winstone/pull/417
var keyStoreManager = new KeyStoreManager(createTempDirectory("keystore").resolve("keyStore.p12"), token);
var rootCAs = SelfSignedCertificates.createRootCAs();
var userCert = SelfSignedCertificates.createUserCert(host, rootCAs.intermediate());
keyStoreManager.setCertificateEntry(host, rootCAs.root().certificate());
keyStoreManager.setKeyEntry(host, userCert.keyPair().getPrivate(), new Certificate[]{
userCert.certificate(),
rootCAs.intermediate().certificate(),
rootCAs.root().certificate()
});
keyStoreManager.save();
this.rootCA = rootCAs.root().certificate();
this.keyStoreManager = keyStoreManager;
this.sslSocketFactory = keyStoreManager.buildClientSSLContext().getSocketFactory();
} catch (CertificateException | KeyStoreException | NoSuchAlgorithmException | KeyManagementException |
} catch (NoSuchAlgorithmException | KeyManagementException | CertificateException | KeyStoreException |
IOException e) {
throw new RuntimeException(e);
}
this.rootCA = rootCA;
return this;
}

/**
* @return the current autogenerated root CA or null if {@link #https(String)} has not been called.
* @return the current autogenerated root CA or null if {@link #https()} has not been called.
*/
@Nullable
public X509Certificate getRootCA() {
Expand Down
47 changes: 47 additions & 0 deletions src/main/keystore/generate_self_signed_cert.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#!/usr/bin/env bash
set -euo pipefail

cd "$(dirname "$0")/../.."

tmpDir=$(mktemp -d)
trap 'rm -rf $tmpDir' EXIT

cat > "$tmpDir/req.cnf" <<EOF
[ req ]
default_bits = 2048
prompt = no
distinguished_name = req_distinguished_name
x509_extensions = req_ext
[ req_distinguished_name ]
countryName = US
stateOrProvinceName = NY
localityName = New York
organizationName = Jenkins
organizationalUnitName = Test
commonName = Self-Signed CA
emailAddress = [email protected]
[ req_ext ]
keyUsage = digitalSignature
basicConstraints = CA:false
subjectAltName = @alternate_names
subjectKeyIdentifier = hash
[ alternate_names ]
DNS.1 = localhost
EOF

mkdir -p "$tmpDir/output"
key="$tmpDir/output/key.pem"
cert="$tmpDir/output/cert.pem"
certP12="$tmpDir/output/cert.p12"
# Generate a self-signed cert valid for 100 years
echo "Generate self-signed cert for localhost for 100 years"
openssl req -newkey rsa:2048 -nodes -keyout "$key" -x509 -days 36500 -out "$cert" -config "$tmpDir/req.cnf"
echo "Generate PKCS12 keystore"
openssl pkcs12 -inkey "$key" -in "$cert" -export -out "$certP12" -passout pass:changeit -passin pass:changeit
echo "Copying generated resources to src/main/resources"
mkdir -p src/main/resources/https
cp "$cert" src/main/resources/https/test-cert.pem
cp "$certP12" src/main/resources/https/test-keystore.p12
24 changes: 24 additions & 0 deletions src/main/resources/https/test-cert.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
-----BEGIN CERTIFICATE-----
MIID8zCCAtugAwIBAgIUOjlbXGGFXddBZvQRZT2GFs6QDEswDQYJKoZIhvcNAQEL
BQAwgYoxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJOWTERMA8GA1UEBwwITmV3IFlv
cmsxEDAOBgNVBAoMB0plbmtpbnMxDTALBgNVBAsMBFRlc3QxFzAVBgNVBAMMDlNl
bGYtU2lnbmVkIENBMSEwHwYJKoZIhvcNAQkBFhJub3JlcGx5QGplbmtpbnMuaW8w
HhcNMjQxMDEwMTE1OTU5WhcNMjUxMDEwMTE1OTU5WjCBijELMAkGA1UEBhMCVVMx
CzAJBgNVBAgMAk5ZMREwDwYDVQQHDAhOZXcgWW9yazEQMA4GA1UECgwHSmVua2lu
czENMAsGA1UECwwEVGVzdDEXMBUGA1UEAwwOU2VsZi1TaWduZWQgQ0ExITAfBgkq
hkiG9w0BCQEWEm5vcmVwbHlAamVua2lucy5pbzCCASIwDQYJKoZIhvcNAQEBBQAD
ggEPADCCAQoCggEBAJ7L6c7X/KcHpqGmh6X3ibvJfHi30bVbzu6WzYWnNxBmGby1
kH4kTRntlUqV3r82kIEImBuxVgpN3zA0HrFL10YzQuFEmq7ENGmC5rwkN2bgzwSP
3GubKkIilNtt0b8jYIhXBpTnurA6lkfRnJufIXcCJQUt1XKABk06QrgEozWNmmtF
eRT/O8ZIUYbN2SKVAJzw+eUH2jJueU3Px4JBzsCH3FIHm0hns7FzfD1ii3BIXsjc
H6t6XXpUBlfaMPogVcdznVy47NDcT/nuNCqFMtZlg6qXDiYKSM2yKVwECsEBXskS
MD3FgDMaVEv/zdW97YAO83jNMFSMf2GVfB8gFEkCAwEAAaNPME0wCwYDVR0PBAQD
AgeAMAkGA1UdEwQCMAAwFAYDVR0RBA0wC4IJbG9jYWxob3N0MB0GA1UdDgQWBBTG
aPVOHhY0gS/TqdEHVJG9mr47TzANBgkqhkiG9w0BAQsFAAOCAQEAcd/lMAhdqTnD
3NQ3nIFvxXBs/Y0938AmGNNbLix3qTYFGVAIrCXQQFgXYO+WvowL/DRPPxdjB960
5SC9AkRLi0gKS9OEio20FrVCnT1j5wjdMlb9idK/VxLJg6toGp1jUbuSFBnrhFSs
LXRSYPGNXoaGYs2/YBKlP2W7+pqin8VXbFBauhhi+xqVLBDq5zo2Lwnj4y22UmBF
QO4ucQ2K4q0wh5PcM3iUxWfgZ/HxIcBiZvyJHklcaPteRuWF/40irRo//WkGzJOZ
w6nk5TtixTKnWrHU9kvZouwtYx7K4TJ/VXy5mfuLtmM09PumgQAVdqNPplJ17fIP
W9YzDpAmwA==
-----END CERTIFICATE-----
Binary file added src/main/resources/https/test-keystore.p12
Binary file not shown.
Loading

0 comments on commit 58c5c7b

Please sign in to comment.