Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 2 additions & 5 deletions avaje-jex-ssl/src/main/java/io/avaje/jex/ssl/DSslPlugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,16 @@

final class DSslPlugin implements SslPlugin {

final HttpsConfigurator sslConfigurator;
private final HttpsConfigurator sslConfigurator;

DSslPlugin(Consumer<SslConfig> consumer) {

final var config = new DSslConfig();

consumer.accept(config);
sslConfigurator = SSLConfigurator.create(config);
this.sslConfigurator = SSLConfigurator.create(config);
}

@Override
public void apply(Jex jex) {

jex.config().httpsConfig(sslConfigurator);
}
}
14 changes: 4 additions & 10 deletions avaje-jex-ssl/src/main/java/io/avaje/jex/ssl/DTrustConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,7 @@ public TrustConfig certificateFromClasspath(String certificateFile) {

@Override
public TrustConfig certificateFromInputStream(InputStream certificateInputStream) {

certificates.addAll(KeyStoreUtil.parseCertificates(certificateInputStream));

return this;
}

Expand All @@ -42,11 +40,11 @@ public TrustConfig certificateFromPath(String certificatePath) {
return this;
}

public List<Certificate> certificates() {
List<Certificate> certificates() {
return certificates;
}

public List<KeyStore> keyStores() {
List<KeyStore> keyStores() {
return keyStores;
}

Expand All @@ -62,12 +60,8 @@ public TrustConfig trustStoreFromClasspath(String trustStoreFile, String trustSt
}

@Override
public TrustConfig trustStoreFromInputStream(
InputStream trustStoreInputStream, String trustStorePassword) {

keyStores.add(
KeyStoreUtil.loadKeyStore(trustStoreInputStream, trustStorePassword.toCharArray()));

public TrustConfig trustStoreFromInputStream(InputStream trustStoreInputStream, String trustStorePassword) {
keyStores.add(KeyStoreUtil.loadKeyStore(trustStoreInputStream, trustStorePassword.toCharArray()));
return this;
}

Expand Down
15 changes: 2 additions & 13 deletions avaje-jex-ssl/src/main/java/io/avaje/jex/ssl/KeyStoreUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ final class KeyStoreUtil {
Pattern.DOTALL);

static KeyStore loadKeyStore(InputStream inputStream, char[] password) {

// Read all bytes first so we can try different formats
byte[] data;
try {
Expand All @@ -60,14 +59,12 @@ static KeyStore loadKeyStore(InputStream inputStream, char[] password) {
return keyStore;
}

throw new SslConfigException(
"Unable to load KeyStore - format not recognized or invalid password");
throw new SslConfigException("Unable to load KeyStore - format not recognized or invalid password");
}

private static KeyStore tryLoadKeyStore(byte[] data, String type, char[] password) {
try (var bis = new ByteArrayInputStream(data)) {
var keyStore = KeyStore.getInstance(type);

keyStore.load(bis, password);
return keyStore;
} catch (Exception e) {
Expand All @@ -80,16 +77,13 @@ static X509ExtendedKeyManager loadIdentityFromPem(
InputStream certificateInputStream, String privateKeyContent, char[] password) {
try {
var certificates = parseCertificates(certificateInputStream);

var privateKey = parsePrivateKey(privateKeyContent, password);

var keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null, null);

var certChain = certificates.toArray(new Certificate[0]);
var alias = "identity";
var keyPassword = password != null ? password : new char[0];

keyStore.setKeyEntry(alias, privateKey, keyPassword, certChain);

var kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
Expand All @@ -113,9 +107,8 @@ static X509ExtendedKeyManager loadIdentityFromPem(
}

static List<Certificate> parsePemCertificates(String content) {

List<Certificate> certs = new ArrayList<>();
CertificateFactory factory = null;
CertificateFactory factory;
try {
factory = CertificateFactory.getInstance("X.509");

Expand All @@ -132,11 +125,9 @@ static List<Certificate> parsePemCertificates(String content) {
} catch (Exception e) {
throw new SslConfigException("Failed to parse PEM certificate", e);
}

if (certs.isEmpty()) {
throw new SslConfigException("No valid certificate found in PEM content");
}

return certs;
}

Expand Down Expand Up @@ -182,7 +173,6 @@ static List<Certificate> parseCertificates(InputStream inputStream) {

// Try to parse as PEM first (check if it contains PEM markers)
var content = new String(data, StandardCharsets.UTF_8);

if (content.contains("-----BEGIN CERTIFICATE-----")) {
certs.addAll(parsePemCertificates(content));
} else {
Expand All @@ -195,7 +185,6 @@ static List<Certificate> parseCertificates(InputStream inputStream) {
throw new SslConfigException("Unable to load KeyStore", e);
}
}

return certs;
}

Expand Down
21 changes: 5 additions & 16 deletions avaje-jex-ssl/src/main/java/io/avaje/jex/ssl/SSLConfigurator.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ final class SSLConfigurator extends HttpsConfigurator {

private final boolean clientAuth;

public SSLConfigurator(SSLContext context, boolean clientAuth) {
SSLConfigurator(SSLContext context, boolean clientAuth) {
super(context);
this.clientAuth = clientAuth;
}
Expand All @@ -40,7 +40,6 @@ public void configure(HttpsParameters params) {
static SSLConfigurator create(DSslConfig sslConfig) throws SslConfigException {
try {
var sslContext = createContext(sslConfig);

var keyManagers = createKeyManagers(sslConfig);
var trustManagers = createTrustManagers(sslConfig);

Expand All @@ -60,7 +59,6 @@ private static SSLContext createContext(DSslConfig sslConfig) throws NoSuchAlgor
}

private static KeyManager[] createKeyManagers(DSslConfig sslConfig) throws SslConfigException {

try {
return switch (sslConfig.loadedIdentity()) {
case KEY_MANAGER -> new KeyManager[] {sslConfig.keyManager()};
Expand All @@ -81,32 +79,27 @@ private static KeyManager[] createKeyManagersFromKeyStore(DSslConfig sslConfig)
return keyManagerFactory.getKeyManagers();
}

private static KeyManagerFactory createKeyManagerFactory(DSslConfig sslConfig)
throws NoSuchAlgorithmException {
private static KeyManagerFactory createKeyManagerFactory(DSslConfig sslConfig) throws NoSuchAlgorithmException {
if (sslConfig.securityProvider() != null) {
return KeyManagerFactory.getInstance(KEY_MANAGER_ALGORITHM, sslConfig.securityProvider());
}
return KeyManagerFactory.getInstance(KEY_MANAGER_ALGORITHM);
}

private static TrustManager[] createTrustManagers(DSslConfig sslConfig)
throws SslConfigException {
private static TrustManager[] createTrustManagers(DSslConfig sslConfig) throws SslConfigException {
var trustConfig = sslConfig.trustConfig();

if (trustConfig == null) {
return null; // Use system default trust managers
}

try {
var trustStores = trustConfig.keyStores();
var certificates = trustConfig.certificates();

if (trustStores.isEmpty() && certificates.isEmpty()) {
return null; // No custom trust configuration
}

var trustStore = createCombinedTrustStore(trustStores, certificates);

var trustManagerFactory = createTrustManagerFactory(sslConfig);
trustManagerFactory.init(trustStore);

Expand All @@ -116,19 +109,15 @@ private static TrustManager[] createTrustManagers(DSslConfig sslConfig)
}
}

private static TrustManagerFactory createTrustManagerFactory(DSslConfig sslConfig)
throws NoSuchAlgorithmException {
private static TrustManagerFactory createTrustManagerFactory(DSslConfig sslConfig) throws NoSuchAlgorithmException {
if (sslConfig.securityProvider() != null) {
return TrustManagerFactory.getInstance(TRUST_MANAGER_ALGORITHM, sslConfig.securityProvider());
}
return TrustManagerFactory.getInstance(TRUST_MANAGER_ALGORITHM);
}

private static KeyStore createCombinedTrustStore(
List<KeyStore> trustStores, List<Certificate> certificates) throws Exception {

private static KeyStore createCombinedTrustStore(List<KeyStore> trustStores, List<Certificate> certificates) throws Exception {
var combinedTrustStore = KeyStore.getInstance(KeyStore.getDefaultType());

combinedTrustStore.load(null, null);

// Add certificates from existing trust stores
Expand Down
5 changes: 2 additions & 3 deletions avaje-jex-ssl/src/main/java/io/avaje/jex/ssl/SslConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,7 @@ default void pemFromClasspath(String certificateFile, String privateKeyFile) {
* @param certificateInputStream input stream to the certificate chain PEM file.
* @param privateKeyInputStream input stream to the private key PEM file.
*/
default void pemFromInputStream(
InputStream certificateInputStream, InputStream privateKeyInputStream) {
default void pemFromInputStream(InputStream certificateInputStream, InputStream privateKeyInputStream) {
pemFromInputStream(certificateInputStream, privateKeyInputStream, null);
}

Expand Down Expand Up @@ -162,7 +161,7 @@ default void pemFromString(String certificateString, String privateKeyString) {
/**
* Configure the Provider for the SSLContext.
*
* @param trustConfigConsumer consumer to configure the trust configuration.
* @param securityProvider the security provider to use.
*/
void securityProvider(Provider securityProvider);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package io.avaje.jex.ssl;

/**
* SSL Configuration exception.
*/
public class SslConfigException extends RuntimeException {

public SslConfigException(String message, Throwable t) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,7 @@ public interface TrustConfig {
* @param trustStorePassword password for the trust store.
* @return The updated TrustConfig instance for method chaining.
*/
TrustConfig trustStoreFromInputStream(
InputStream trustStoreInputStream, String trustStorePassword);
TrustConfig trustStoreFromInputStream(InputStream trustStoreInputStream, String trustStorePassword);

/**
* Load a trust store from a given path in the system. The trust store can be in JKS or PKCS12
Expand Down