From d2eb81eba5dd4225712d18cd0ac158b47f4a28c5 Mon Sep 17 00:00:00 2001 From: Thomas Bayer Date: Mon, 9 Dec 2024 17:28:28 +0100 Subject: [PATCH 1/3] Fixed tests --- .../validation/SOAPProxyValidationTest.java | 54 ++++++++++--------- .../util/DistributionExtractingTestcase.java | 5 -- 2 files changed, 29 insertions(+), 30 deletions(-) diff --git a/distribution/src/test/java/com/predic8/membrane/examples/tests/validation/SOAPProxyValidationTest.java b/distribution/src/test/java/com/predic8/membrane/examples/tests/validation/SOAPProxyValidationTest.java index 6db0239513..fb51db972b 100644 --- a/distribution/src/test/java/com/predic8/membrane/examples/tests/validation/SOAPProxyValidationTest.java +++ b/distribution/src/test/java/com/predic8/membrane/examples/tests/validation/SOAPProxyValidationTest.java @@ -15,46 +15,50 @@ package com.predic8.membrane.examples.tests.validation; import com.predic8.membrane.examples.util.*; -import io.restassured.RestAssured; -import io.restassured.http.ContentType; import org.junit.jupiter.api.*; -import java.io.IOException; +import java.io.*; -import static com.predic8.membrane.core.http.Header.CONTENT_TYPE; -import static com.predic8.membrane.core.http.MimeType.APPLICATION_SOAP; -import static com.predic8.membrane.test.AssertUtils.*; -import static io.restassured.RestAssured.config; -import static io.restassured.RestAssured.given; -import static io.restassured.config.EncoderConfig.encoderConfig; +import static com.predic8.membrane.core.http.MimeType.*; +import static io.restassured.RestAssured.*; import static java.io.File.*; public class SOAPProxyValidationTest extends DistributionExtractingTestcase { - @Override - protected String getExampleDirName() { - return "validation" + separator + "soap-Proxy"; - } + @Override + protected String getExampleDirName() { + return "validation" + separator + "soap-Proxy"; + } - @Test - public void testValidCitySoapRequest() throws IOException { - given().contentType(APPLICATION_SOAP) + @Test + public void testValidCitySoapRequest() throws IOException, InterruptedException { + try (Process2 ignored = startServiceProxyScript()) { + // @formatter:off + given() + .contentType(APPLICATION_SOAP) .body(readFile("city-soap.xml")) - .when() + .when() .post("http://localhost:2000/") - .then() + .then() .statusCode(200) .extract().asString(); - } + // @formatter:on + } + } - @Test - public void testInvalidCitySoapRequest() throws IOException { - given().contentType(APPLICATION_SOAP) + @Test + public void testInvalidCitySoapRequest() throws IOException, InterruptedException { + try (Process2 ignored = startServiceProxyScript()) { + // @formatter:off + given() + .contentType(APPLICATION_SOAP) .body(readFile("invalid-city-soap.xml")) - .when() + .when() .post("http://localhost:2000/") - .then() + .then() .statusCode(400) .extract().asString(); - } + // @formatter:on + } + } } diff --git a/distribution/src/test/java/com/predic8/membrane/examples/util/DistributionExtractingTestcase.java b/distribution/src/test/java/com/predic8/membrane/examples/util/DistributionExtractingTestcase.java index 827e3b7ffa..9f2f86fdac 100644 --- a/distribution/src/test/java/com/predic8/membrane/examples/util/DistributionExtractingTestcase.java +++ b/distribution/src/test/java/com/predic8/membrane/examples/util/DistributionExtractingTestcase.java @@ -35,17 +35,12 @@ public abstract class DistributionExtractingTestcase { public static final String MEMBRANE_LOG_LEVEL = "info"; - public static final String BLZ_SERVICE = "http://localhost:2000/bank/services/BLZService"; - public static final String BLZ_SERVICE_WSDL = BLZ_SERVICE + "?wsdl"; - public static final String LOCALHOST_2000 = "http://localhost:2000"; public static final String[] CONTENT_TYPE_APP_XML_HEADER = {"Content-Type", APPLICATION_XML}; public static final String[] CONTENT_TYPE_TEXT_XML_HEADER = {"Content-Type", TEXT_XML}; public static final String[] CONTENT_TYPE_APP_JSON_HEADER = {"Content-Type", APPLICATION_JSON}; - public static final String[] CONTENT_TYPE_SOAP_HEADER = {"Content-Type", APPLICATION_SOAP}; - private File unzipDir; private File membraneHome; protected File baseDir = new File(getExampleDirName()); From 634891c92f3d4ab1bf85cba6fed4c5722afde8a0 Mon Sep 17 00:00:00 2001 From: Thomas Bayer Date: Tue, 10 Dec 2024 12:25:32 +0100 Subject: [PATCH 2/3] Refactoring --- .../membrane/core/config/security/Trust.java | 20 +- .../core/config/security/TrustStore.java | 4 + .../core/transport/ssl/StaticSSLContext.java | 335 +++++++++++------- 3 files changed, 221 insertions(+), 138 deletions(-) diff --git a/core/src/main/java/com/predic8/membrane/core/config/security/Trust.java b/core/src/main/java/com/predic8/membrane/core/config/security/Trust.java index 0506874b6d..f52c291830 100644 --- a/core/src/main/java/com/predic8/membrane/core/config/security/Trust.java +++ b/core/src/main/java/com/predic8/membrane/core/config/security/Trust.java @@ -14,13 +14,9 @@ package com.predic8.membrane.core.config.security; -import com.predic8.membrane.annot.MCAttribute; -import com.predic8.membrane.annot.MCChildElement; -import com.predic8.membrane.annot.MCElement; +import com.predic8.membrane.annot.*; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; +import java.util.*; /** * @description Experimental. @@ -53,6 +49,10 @@ public List getCertificateList() { return certificateList; } + /** + * + * @param certificateList + */ @MCChildElement public void setCertificateList(List certificateList) { this.certificateList = certificateList; @@ -62,6 +62,10 @@ public String getAlgorithm() { return algorithm; } + /** + * + * @param algorithm + */ @MCAttribute public void setAlgorithm(String algorithm) { this.algorithm = algorithm; @@ -71,6 +75,10 @@ public String getCheckRevocation() { return checkRevocation; } + /** + * TODO + * @param checkRevocation + */ @MCAttribute public void setCheckRevocation(String checkRevocation) { this.checkRevocation = checkRevocation; diff --git a/core/src/main/java/com/predic8/membrane/core/config/security/TrustStore.java b/core/src/main/java/com/predic8/membrane/core/config/security/TrustStore.java index cdfbe6e9a2..14b55e41fb 100644 --- a/core/src/main/java/com/predic8/membrane/core/config/security/TrustStore.java +++ b/core/src/main/java/com/predic8/membrane/core/config/security/TrustStore.java @@ -50,6 +50,10 @@ public String getCheckRevocation() { return checkRevocation; } + /** + * TODO + * @param checkRevocation + */ @MCAttribute public void setCheckRevocation(String checkRevocation) { this.checkRevocation = checkRevocation; diff --git a/core/src/main/java/com/predic8/membrane/core/transport/ssl/StaticSSLContext.java b/core/src/main/java/com/predic8/membrane/core/transport/ssl/StaticSSLContext.java index 2f1a737d05..efdb3eac71 100644 --- a/core/src/main/java/com/predic8/membrane/core/transport/ssl/StaticSSLContext.java +++ b/core/src/main/java/com/predic8/membrane/core/transport/ssl/StaticSSLContext.java @@ -14,25 +14,21 @@ package com.predic8.membrane.core.transport.ssl; -import com.predic8.membrane.core.config.security.SSLParser; -import com.predic8.membrane.core.config.security.Store; -import com.predic8.membrane.core.resolver.ResolverMap; -import com.predic8.membrane.core.transport.TrustManagerWrapper; -import com.predic8.membrane.core.transport.http2.Http2TlsSupport; -import org.apache.commons.lang3.NotImplementedException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.annotation.Nullable; -import javax.crypto.Cipher; +import com.predic8.membrane.core.config.security.*; +import com.predic8.membrane.core.resolver.*; +import com.predic8.membrane.core.transport.*; +import com.predic8.membrane.core.transport.http2.*; +import org.slf4j.*; + +import javax.annotation.*; +import javax.crypto.*; import javax.net.ssl.*; -import javax.validation.constraints.NotNull; -import java.io.IOException; -import java.lang.reflect.InvocationTargetException; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.ServerSocket; -import java.net.Socket; +import javax.validation.constraints.*; +import java.io.*; +import java.lang.reflect.*; +import java.net.*; +import java.security.Key; +import java.security.KeyStore; import java.security.*; import java.security.cert.Certificate; import java.security.cert.*; @@ -44,8 +40,8 @@ public class StaticSSLContext extends SSLContext { private static final String DEFAULT_CERTIFICATE_SHA256 = "c7:e3:fd:97:2f:d3:b9:4f:38:87:9c:45:32:70:b3:d8:c1:9f:d1:64:39:fc:48:5f:f4:a1:6a:95:b5:ca:08:f7"; private static final Logger log = LoggerFactory.getLogger(StaticSSLContext.class.getName()); + public static final String PKCS_12 = "PKCS12"; private static boolean defaultCertificateWarned = false; - private static boolean limitedStrength; static { String dhKeySize = System.getProperty("jdk.tls.ephemeralDHKeySize"); @@ -53,8 +49,7 @@ public class StaticSSLContext extends SSLContext { System.setProperty("jdk.tls.ephemeralDHKeySize", "matched"); try { - limitedStrength = Cipher.getMaxAllowedKeyLength("AES") <= 128; - if (limitedStrength) + if (Cipher.getMaxAllowedKeyLength("AES") <= 128) log.warn("Your Java Virtual Machine does not have unlimited strength cryptography. If it is legal in your country, we strongly advise installing the Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files."); } catch (NoSuchAlgorithmException ignored) { } @@ -64,127 +59,196 @@ public class StaticSSLContext extends SSLContext { System.setProperty("jdk.tls.server.enableStatusRequestExtension", "true"); } - - private final SSLParser sslParser; + private final SSLParser sslParser; // TODO push up to super class? private List dnsNames; private javax.net.ssl.SSLContext sslc; - private long validFrom; - private long validUntil; + private Validity validity; public StaticSSLContext(SSLParser sslParser, ResolverMap resourceResolver, String baseLocation) { + if (sslParser.getTrustStore() != null && sslParser.getTrust() != null) + throw new InvalidParameterException(" may not be used together with ."); + + if (sslParser.getKeyStore() != null && sslParser.getKey() != null) + throw new InvalidParameterException(" may not be used together with ."); + this.sslParser = sslParser; try { - String algorihm = getAlgorithm(sslParser); + initializeJavaSSLContext(createTrustManagerFactory(resourceResolver, baseLocation), + createKeyManagerFactoryWithSideEffects(resourceResolver, baseLocation)); - KeyManagerFactory kmf = null; - String keyStoreType = "PKCS12"; - if (sslParser.getKeyStore() != null) { - char[] keyPass = getKeyPass(sslParser); + } catch (Exception e) { + throw new RuntimeException(e); + } - if (sslParser.getKeyStore().getType() != null) - keyStoreType = sslParser.getKeyStore().getType(); - KeyStore ks = openKeyStore(sslParser.getKeyStore(), "PKCS12", keyPass, resourceResolver, baseLocation); + init(sslParser, sslc); + } - String paramAlias = sslParser.getKeyStore().getKeyAlias(); - String keyAlias = (paramAlias != null) ? aliasOrThrow(ks, paramAlias) : firstAliasOrThrow(ks); + private @org.jetbrains.annotations.Nullable KeyManagerFactory createKeyManagerFactoryWithSideEffects( ResolverMap resourceResolver, String baseLocation) throws NoSuchAlgorithmException, CertificateException, IOException, KeyStoreException, NoSuchProviderException, UnrecoverableKeyException { + if (sslParser.getKeyStore() != null) { + char[] keyPass = getKeyPass(sslParser); - KeyStore filteredKeyStore = filterKeyStoreByAlias(ks, keyPass, keyAlias); + KeyStore ks = openKeyStore(sslParser.getKeyStore(), keyPass, resourceResolver, baseLocation); - kmf = KeyManagerFactory.getInstance(algorihm); - kmf.init(filteredKeyStore, keyPass); + String keyAlias = getKeyAlias(sslParser, ks); - dnsNames = extractDnsNames(ks.getCertificate(keyAlias)); - List certs = Arrays.asList(ks.getCertificateChain(keyAlias)); - validUntil = getMinimumValidity(certs); - validFrom = getValidFrom(certs); - } - if (sslParser.getKey() != null) { - if (kmf != null) - throw new InvalidParameterException(" may not be used together with ."); + dnsNames = extractDnsNames(ks.getCertificate(keyAlias)); + validity = getValidityPeriod(ks, keyAlias); - KeyStore ks = KeyStore.getInstance(keyStoreType); - ks.load(null, "".toCharArray()); + KeyManagerFactory kmf = KeyManagerFactory.getInstance(getAlgorithm(sslParser)); + kmf.init(filterKeyStoreByAlias(ks, keyPass, keyAlias), keyPass); + return kmf; + } + if (sslParser.getKey() != null) { + return getKeyManagerFactoryWithSideEffects(sslParser, resourceResolver, baseLocation); + } + return null; // Ok! + } - List certs = new ArrayList<>(); + private @org.jetbrains.annotations.Nullable TrustManagerFactory createTrustManagerFactory( ResolverMap resourceResolver, String baseLocation) throws NoSuchAlgorithmException, CertificateException, IOException, KeyStoreException, NoSuchProviderException, InvalidAlgorithmParameterException { + if (sslParser.getTrustStore() == null && sslParser.getTrust() == null) + return null; + + KeyStore trustStore = null; + String checkRevocation = null; + if (sslParser.getTrustStore() != null) { + trustStore = openKeyStore(sslParser.getTrustStore(), null, resourceResolver, baseLocation); + checkRevocation = sslParser.getTrustStore().getCheckRevocation(); + } else if (sslParser.getTrust() != null) { + trustStore = getStore(resourceResolver, baseLocation); + checkRevocation = sslParser.getTrust().getCheckRevocation(); + } + return createTrustManagerFactory2(trustStore, checkRevocation); + } - for (com.predic8.membrane.core.config.security.Certificate cert : sslParser.getKey().getCertificates()) - certs.add(PEMSupport.getInstance().parseCertificate(cert.get(resourceResolver, baseLocation))); - if (certs.isEmpty()) - throw new RuntimeException("At least one //ssl/key/certificate is required."); - dnsNames = extractDnsNames(certs.get(0)); + private @org.jetbrains.annotations.NotNull KeyStore getStore(ResolverMap resourceResolver, String baseLocation) throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException { + KeyStore trustStore = KeyStore.getInstance(PKCS_12); + trustStore.load(null, "".toCharArray()); - checkChainValidity(certs); - Key k = getKey(sslParser, resourceResolver, baseLocation); - checkKeyMatchesCert(k, certs); + for (int j = 0; j < sslParser.getTrust().getCertificateList().size(); j++) + trustStore.setCertificateEntry("inlinePemCertificate" + j, + PEMSupport.getInstance().parseCertificate( + sslParser.getTrust().getCertificateList().get(j).get(resourceResolver, baseLocation))); + return trustStore; + } - ks.setKeyEntry("inlinePemKeyAndCertificate", k, "".toCharArray(), certs.toArray(new Certificate[certs.size()])); + private String getTrustAlgorithm() { + if (sslParser.getTrust() != null && sslParser.getTrust().getAlgorithm() != null) + return sslParser.getTrust().getAlgorithm(); - kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); - kmf.init(ks, getKeyPassword(sslParser)); - validUntil = getMinimumValidity(certs); - validFrom = getValidFrom(certs); - } + if (sslParser.getTrustStore() != null && sslParser.getTrustStore().getAlgorithm() != null) + return sslParser.getTrustStore().getAlgorithm(); - TrustManagerFactory tmf = null; - KeyStore ts = null; - String trustAlgorithm = TrustManagerFactory.getDefaultAlgorithm(); - String checkRevocation = null; - if (sslParser.getTrustStore() != null) { - if (sslParser.getTrustStore().getAlgorithm() != null) - trustAlgorithm = sslParser.getTrustStore().getAlgorithm(); - ts = openKeyStore(sslParser.getTrustStore(), keyStoreType, null, resourceResolver, baseLocation); - checkRevocation = sslParser.getTrustStore().getCheckRevocation(); - } - if (sslParser.getTrust() != null) { - if (tmf != null) - throw new InvalidParameterException(" may not be used together with ."); - if (sslParser.getTrust().getAlgorithm() != null) - trustAlgorithm = sslParser.getTrust().getAlgorithm(); - - ts = KeyStore.getInstance(keyStoreType); - ts.load(null, "".toCharArray()); - - for (int j = 0; j < sslParser.getTrust().getCertificateList().size(); j++) - ts.setCertificateEntry("inlinePemCertificate" + j, PEMSupport.getInstance().parseCertificate(sslParser.getTrust().getCertificateList().get(j).get(resourceResolver, baseLocation))); - checkRevocation = sslParser.getTrust().getCheckRevocation(); - } - if (ts != null) { - tmf = TrustManagerFactory.getInstance(trustAlgorithm); - if (checkRevocation != null) { - CertPathBuilder cpb = CertPathBuilder.getInstance(trustAlgorithm); - PKIXBuilderParameters pkixParams = new PKIXBuilderParameters(ts, new X509CertSelector()); - PKIXRevocationChecker rc = (PKIXRevocationChecker) cpb.getRevocationChecker(); - EnumSet options = EnumSet.noneOf(PKIXRevocationChecker.Option.class); - for (String option : checkRevocation.split(",")) - options.add(PKIXRevocationChecker.Option.valueOf(option)); - pkixParams.addCertPathChecker(rc); - tmf.init( new CertPathTrustManagerParameters(pkixParams) ); - } else { - tmf.init(ts); - } + return TrustManagerFactory.getDefaultAlgorithm(); + } + + private @org.jetbrains.annotations.Nullable TrustManagerFactory createTrustManagerFactory2(KeyStore trustStore, String checkRevocation) throws NoSuchAlgorithmException, InvalidAlgorithmParameterException, KeyStoreException { + TrustManagerFactory tmf = null; + if (trustStore != null) { + tmf = TrustManagerFactory.getInstance(getTrustAlgorithm()); + if (checkRevocation != null) { + tmf.init( new CertPathTrustManagerParameters(getPkixBuilderParameters(trustStore, getTrustAlgorithm(), checkRevocation)) ); + } else { + tmf.init(trustStore); } + } + return tmf; + } - TrustManager[] tms = tmf != null ? tmf.getTrustManagers() : null /* trust anyone: new TrustManager[] { new NullTrustManager() } */; - if (sslParser.isIgnoreTimestampCheckFailure()) - tms = new TrustManager[] { new TrustManagerWrapper(tms, true) }; + private @org.jetbrains.annotations.NotNull String getTrustStoreType() { + String trustStoreType = sslParser.getTrustStore().getType(); + if (trustStoreType == null) + trustStoreType = PKCS_12; + return trustStoreType; + } - if (sslParser.getProtocol() != null) - sslc = javax.net.ssl.SSLContext.getInstance(sslParser.getProtocol()); - else - sslc = javax.net.ssl.SSLContext.getInstance("TLS"); + private static @org.jetbrains.annotations.NotNull PKIXBuilderParameters getPkixBuilderParameters(KeyStore trustStore, String trustAlgorithm, String checkRevocation) throws KeyStoreException, InvalidAlgorithmParameterException, NoSuchAlgorithmException { + PKIXBuilderParameters pkixParams = new PKIXBuilderParameters(trustStore, new X509CertSelector()); + pkixParams.addCertPathChecker(getRevocationChecker(trustAlgorithm, checkRevocation)); + return pkixParams; + } - sslc.init( - kmf != null ? kmf.getKeyManagers() : null, - tms, - null); + private static @org.jetbrains.annotations.NotNull PKIXRevocationChecker getRevocationChecker(String trustAlgorithm, String checkRevocation) throws NoSuchAlgorithmException { + PKIXRevocationChecker rc = (PKIXRevocationChecker) CertPathBuilder.getInstance(trustAlgorithm).getRevocationChecker(); + rc.setOptions(createOptions(checkRevocation)); + return rc; + } - } catch (Exception e) { - throw new RuntimeException(e); - } + private static @org.jetbrains.annotations.NotNull EnumSet createOptions(String checkRevocation) { + EnumSet options = EnumSet.noneOf(PKIXRevocationChecker.Option.class); + for (String option : checkRevocation.split(",")) + options.add(PKIXRevocationChecker.Option.valueOf(option)); + return options; + } - init(sslParser, sslc); + private void initializeJavaSSLContext(TrustManagerFactory tmf, KeyManagerFactory kmf) throws KeyManagementException, NoSuchAlgorithmException { + TrustManager[] tms = tmf != null ? tmf.getTrustManagers() : null /* trust anyone: new TrustManager[] { new NullTrustManager() } */; + if (sslParser.isIgnoreTimestampCheckFailure()) + tms = new TrustManager[] { new TrustManagerWrapper(tms, true) }; + + if (sslParser.getProtocol() != null) + sslc = javax.net.ssl.SSLContext.getInstance(sslParser.getProtocol()); + else + sslc = javax.net.ssl.SSLContext.getInstance("TLS"); + + sslc.init( + kmf != null ? kmf.getKeyManagers() : null, + tms, + null); + } + + private static String getKeyAlias(SSLParser sslParser, KeyStore ks) throws KeyStoreException { + String paramAlias = sslParser.getKeyStore().getKeyAlias(); + return (paramAlias != null) ? aliasOrThrow(ks, paramAlias) : firstAliasOrThrow(ks); + } + + record Validity(long from, long until) {}; + + private Validity getValidityPeriod(KeyStore ks, String keyAlias) throws KeyStoreException { + List certs = Arrays.asList(ks.getCertificateChain(keyAlias)); + return new Validity(getValidFrom(certs), getMinimumValidity(certs)); + } + + private @org.jetbrains.annotations.NotNull KeyManagerFactory getKeyManagerFactoryWithSideEffects(SSLParser sslParser, ResolverMap resourceResolver, String baseLocation) throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException, UnrecoverableKeyException { + + List certs = getCertificates(sslParser, resourceResolver, baseLocation); + + dnsNames = extractDnsNames(certs.get(0)); + + checkChainValidity(certs); + validity = new Validity(getValidFrom(certs),getMinimumValidity(certs)); + + return getKeyManagerFactory(sslParser, getKey(sslParser, resourceResolver, baseLocation, certs), certs); + } + + private Key getKey(SSLParser sslParser, ResolverMap resourceResolver, String baseLocation, List certs) throws IOException { + Key k = getKey(sslParser, resourceResolver, baseLocation); + checkKeyMatchesCert(k, certs); + return k; + } + + private @org.jetbrains.annotations.NotNull KeyManagerFactory getKeyManagerFactory(SSLParser sslParser, Key k, List certs) throws NoSuchAlgorithmException, KeyStoreException, UnrecoverableKeyException, IOException, CertificateException { + KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); + kmf.init(getKeyStore(k, certs), getKeyPassword(sslParser)); + return kmf; + } + + private static @org.jetbrains.annotations.NotNull List getCertificates(SSLParser sslParser, ResolverMap resourceResolver, String baseLocation) throws IOException { + List certs = new ArrayList<>(); + + for (com.predic8.membrane.core.config.security.Certificate cert : sslParser.getKey().getCertificates()) + certs.add(PEMSupport.getInstance().parseCertificate(cert.get(resourceResolver, baseLocation))); + if (certs.isEmpty()) + throw new RuntimeException("At least one //ssl/key/certificate is required."); + return certs; + } + + private static @org.jetbrains.annotations.NotNull KeyStore getKeyStore(Key k, List certs) throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException { + KeyStore ks = KeyStore.getInstance(StaticSSLContext.PKCS_12); + ks.load(null, "".toCharArray()); + ks.setKeyEntry("inlinePemKeyAndCertificate", k, "".toCharArray(), certs.toArray(new Certificate[0])); + return ks; } private static Key getKey(SSLParser sslParser, ResolverMap resourceResolver, String baseLocation) throws IOException { @@ -207,10 +271,9 @@ private static char[] getKeyPassword(SSLParser sslParser) { } private static String getAlgorithm(SSLParser sslParser) { - String algorihm = KeyManagerFactory.getDefaultAlgorithm(); if (sslParser.getAlgorithm() != null) - algorihm = sslParser.getAlgorithm(); - return algorihm; + return sslParser.getAlgorithm(); + return KeyManagerFactory.getDefaultAlgorithm(); } public StaticSSLContext(SSLParser sslParser, javax.net.ssl.SSLContext sslc) { @@ -248,19 +311,11 @@ public boolean equals(Object obj) { @Override public int hashCode() { - return java.util.Objects.hash(sslParser, dnsNames, sslc, validFrom, validUntil); + return java.util.Objects.hash(sslParser, dnsNames, sslc, validity); } - public static KeyStore openKeyStore(Store store, String defaultType, char[] keyPass, ResolverMap resourceResolver, String baseLocation) throws NoSuchAlgorithmException, CertificateException, IOException, KeyStoreException, NoSuchProviderException { - String type = store.getType(); - if (type == null) - type = defaultType; - char[] password = keyPass; - if (store.getPassword() != null) - password = store.getPassword().toCharArray(); - if (password == null) - throw new InvalidParameterException("Password for key store is not set."); - KeyStore ks = getAndLoadKeyStore(store, resourceResolver, baseLocation, type, password); + public static KeyStore openKeyStore(Store store, char[] keyPass, ResolverMap resourceResolver, String baseLocation) throws NoSuchAlgorithmException, CertificateException, IOException, KeyStoreException, NoSuchProviderException { + KeyStore ks = getAndLoadKeyStore(store, resourceResolver, baseLocation, getStoreTypeOrDefault(store), getPassword(store, keyPass)); if (!defaultCertificateWarned && ks.getCertificate("membrane") != null) { if (getDigest(ks, "membrane").equals(DEFAULT_CERTIFICATE_SHA256)) { log.warn("Using Membrane with the default certificate. This is highly discouraged! " @@ -271,6 +326,22 @@ public static KeyStore openKeyStore(Store store, String defaultType, char[] keyP return ks; } + private static char @org.jetbrains.annotations.NotNull [] getPassword(Store store, char[] keyPass) { + char[] password = keyPass; + if (store.getPassword() != null) + password = store.getPassword().toCharArray(); + if (password == null) + throw new InvalidParameterException("Password for key store is not set."); + return password; + } + + private static @org.jetbrains.annotations.NotNull String getStoreTypeOrDefault(Store store) { + String type = store.getType(); + if (type == null) + return PKCS_12; + return type; + } + public void applyCiphers(SSLServerSocket sslServerSocket) { if (ciphers != null) { SSLParameters sslParameters = sslServerSocket.getSSLParameters(); @@ -413,16 +484,16 @@ public String getPrometheusContextTypeName() { @Override public boolean hasKeyAndCertificate() { - return validUntil != 0 && validFrom != 0; + return validity.until != 0 && validity.from != 0; } @Override public long getValidFrom() { - return validFrom; + return validity.from; } @Override public long getValidUntil() { - return validUntil; + return validity.until; } } From 329ab7443d7ed0ee9cedc15a4e946fdd81a139dd Mon Sep 17 00:00:00 2001 From: Thomas Bayer Date: Tue, 10 Dec 2024 13:28:55 +0100 Subject: [PATCH 3/3] Refactoring --- .../membrane/core/config/security/Trust.java | 5 ++--- .../membrane/core/config/security/TrustStore.java | 3 +-- .../core/transport/ssl/StaticSSLContext.java | 14 +++----------- 3 files changed, 6 insertions(+), 16 deletions(-) diff --git a/core/src/main/java/com/predic8/membrane/core/config/security/Trust.java b/core/src/main/java/com/predic8/membrane/core/config/security/Trust.java index f52c291830..aca864e2dd 100644 --- a/core/src/main/java/com/predic8/membrane/core/config/security/Trust.java +++ b/core/src/main/java/com/predic8/membrane/core/config/security/Trust.java @@ -19,8 +19,7 @@ import java.util.*; /** - * @description Experimental. - *

Allows to insert one or more PEM blocks containing the certificates to be trusted directly into the proxies.xml + * @description

Allows to insert one or more PEM blocks containing the certificates to be trusted directly into the proxies.xml * file.

*

This is an alternative for {@link TrustStore}.

*/ @@ -50,7 +49,7 @@ public List getCertificateList() { } /** - * + * @description List of certificates * @param certificateList */ @MCChildElement diff --git a/core/src/main/java/com/predic8/membrane/core/config/security/TrustStore.java b/core/src/main/java/com/predic8/membrane/core/config/security/TrustStore.java index 14b55e41fb..fa8ccc68bd 100644 --- a/core/src/main/java/com/predic8/membrane/core/config/security/TrustStore.java +++ b/core/src/main/java/com/predic8/membrane/core/config/security/TrustStore.java @@ -25,9 +25,8 @@ public class TrustStore extends Store { @Override public boolean equals(Object obj) { - if (!(obj instanceof TrustStore)) + if (!(obj instanceof TrustStore other)) return false; - TrustStore other = (TrustStore) obj; return super.equals(obj) && Objects.equal(algorithm, other.algorithm); } diff --git a/core/src/main/java/com/predic8/membrane/core/transport/ssl/StaticSSLContext.java b/core/src/main/java/com/predic8/membrane/core/transport/ssl/StaticSSLContext.java index efdb3eac71..b9fa386815 100644 --- a/core/src/main/java/com/predic8/membrane/core/transport/ssl/StaticSSLContext.java +++ b/core/src/main/java/com/predic8/membrane/core/transport/ssl/StaticSSLContext.java @@ -156,13 +156,6 @@ private String getTrustAlgorithm() { return tmf; } - private @org.jetbrains.annotations.NotNull String getTrustStoreType() { - String trustStoreType = sslParser.getTrustStore().getType(); - if (trustStoreType == null) - trustStoreType = PKCS_12; - return trustStoreType; - } - private static @org.jetbrains.annotations.NotNull PKIXBuilderParameters getPkixBuilderParameters(KeyStore trustStore, String trustAlgorithm, String checkRevocation) throws KeyStoreException, InvalidAlgorithmParameterException, NoSuchAlgorithmException { PKIXBuilderParameters pkixParams = new PKIXBuilderParameters(trustStore, new X509CertSelector()); pkixParams.addCertPathChecker(getRevocationChecker(trustAlgorithm, checkRevocation)); @@ -203,7 +196,7 @@ private static String getKeyAlias(SSLParser sslParser, KeyStore ks) throws KeySt return (paramAlias != null) ? aliasOrThrow(ks, paramAlias) : firstAliasOrThrow(ks); } - record Validity(long from, long until) {}; + record Validity(long from, long until) {} private Validity getValidityPeriod(KeyStore ks, String keyAlias) throws KeyStoreException { List certs = Arrays.asList(ks.getCertificateChain(keyAlias)); @@ -253,8 +246,7 @@ private Key getKey(SSLParser sslParser, ResolverMap resourceResolver, String bas private static Key getKey(SSLParser sslParser, ResolverMap resourceResolver, String baseLocation) throws IOException { Object key = PEMSupport.getInstance().parseKey(sslParser.getKey().getPrivate().get(resourceResolver, baseLocation)); - Key k = key instanceof Key ? (Key) key : ((KeyPair)key).getPrivate(); - return k; + return key instanceof Key? (Key) key : ((KeyPair)key).getPrivate(); } private static char[] getKeyPassword(SSLParser sslParser) { @@ -377,7 +369,7 @@ public ServerSocket createServerSocket(int port, int backlog, InetAddress bindAd return sslss; } - public Socket wrapAcceptedSocket(Socket socket) throws IOException { + public Socket wrapAcceptedSocket(Socket socket) { return socket; }