Skip to content

Commit

Permalink
Allow custom pebble.minica.pem files
Browse files Browse the repository at this point in the history
Also changes from a Java proprietary truststore file to the official
Pebble PEM file.
  • Loading branch information
shred committed Aug 22, 2024
1 parent 793bcd7 commit e589b16
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,20 +20,25 @@
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicReference;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;

import org.shredzone.acme4j.connector.HttpConnector;
import org.shredzone.acme4j.connector.NetworkSettings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* {@link HttpConnector} to be used for Pebble. Pebble uses a static, self-signed SSL
* certificate.
*/
public class PebbleHttpConnector extends HttpConnector {
private static final Logger LOG = LoggerFactory.getLogger(PebbleHttpConnector.class);
private static final AtomicReference<SSLContext> SSL_CONTEXT_REF = new AtomicReference<>();

public PebbleHttpConnector(NetworkSettings settings) {
Expand All @@ -53,22 +58,50 @@ public HttpClient.Builder createClientBuilder() {
*/
protected SSLContext createSSLContext() {
if (SSL_CONTEXT_REF.get() == null) {
try (var in = getClass().getResourceAsStream("/org/shredzone/acme4j/provider/pebble/pebble.truststore")) {
var keystore = KeyStore.getInstance(KeyStore.getDefaultType());
keystore.load(in, "acme4j".toCharArray());
try {
var keystore = readPemFile("/pebble.minica.pem")
.or(() -> readPemFile("/META-INF/pebble.minica.pem"))
.or(() -> readPemFile("/org/shredzone/acme4j/provider/pebble/pebble.minica.pem"))
.orElseThrow(() -> new RuntimeException("Could not find a Pebble root certificate"));

var tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(keystore);

var sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, tmf.getTrustManagers(), null);
SSL_CONTEXT_REF.set(sslContext);
} catch (IOException | KeyStoreException | CertificateException
| NoSuchAlgorithmException | KeyManagementException ex) {
} catch (KeyStoreException | NoSuchAlgorithmException | KeyManagementException ex) {
throw new RuntimeException("Could not create truststore", ex);
}
}
return Objects.requireNonNull(SSL_CONTEXT_REF.get());
}

/**
* Reads a PEM file from a resource, and returns a {@link KeyStore} that uses this
* certificate as root CA.
*
* @param resource
* Resource name
* @return A {@link KeyStore} if the resource could be read successfully, otherwise
* empty.
*/
private Optional<KeyStore> readPemFile(String resource) {
try (var in = getClass().getResourceAsStream(resource)) {
if (in == null) {
return Optional.empty();
}
var cf = CertificateFactory.getInstance("X.509");
var cert = cf.generateCertificate(in);
var keystore = KeyStore.getInstance(KeyStore.getDefaultType());
keystore.load(null, "acme4j".toCharArray());
keystore.setCertificateEntry("pebble", cert);
return Optional.of(keystore);
} catch (IOException | KeyStoreException | CertificateException
| NoSuchAlgorithmException ex) {
LOG.error("Failed to read PEM from resource '{}'", resource, ex);
return Optional.empty();
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
-----BEGIN CERTIFICATE-----
MIIDCTCCAfGgAwIBAgIIJOLbes8sTr4wDQYJKoZIhvcNAQELBQAwIDEeMBwGA1UE
AxMVbWluaWNhIHJvb3QgY2EgMjRlMmRiMCAXDTE3MTIwNjE5NDIxMFoYDzIxMTcx
MjA2MTk0MjEwWjAgMR4wHAYDVQQDExVtaW5pY2Egcm9vdCBjYSAyNGUyZGIwggEi
MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC5WgZNoVJandj43kkLyU50vzCZ
alozvdRo3OFiKoDtmqKPNWRNO2hC9AUNxTDJco51Yc42u/WV3fPbbhSznTiOOVtn
Ajm6iq4I5nZYltGGZetGDOQWr78y2gWY+SG078MuOO2hyDIiKtVc3xiXYA+8Hluu
9F8KbqSS1h55yxZ9b87eKR+B0zu2ahzBCIHKmKWgc6N13l7aDxxY3D6uq8gtJRU0
toumyLbdzGcupVvjbjDP11nl07RESDWBLG1/g3ktJvqIa4BWgU2HMh4rND6y8OD3
Hy3H8MY6CElL+MOCbFJjWqhtOxeFyZZV9q3kYnk9CAuQJKMEGuN4GU6tzhW1AgMB
AAGjRTBDMA4GA1UdDwEB/wQEAwIChDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYB
BQUHAwIwEgYDVR0TAQH/BAgwBgEB/wIBADANBgkqhkiG9w0BAQsFAAOCAQEAF85v
d40HK1ouDAtWeO1PbnWfGEmC5Xa478s9ddOd9Clvp2McYzNlAFfM7kdcj6xeiNhF
WPIfaGAi/QdURSL/6C1KsVDqlFBlTs9zYfh2g0UXGvJtj1maeih7zxFLvet+fqll
xseM4P9EVJaQxwuK/F78YBt0tCNfivC6JNZMgxKF59h0FBpH70ytUSHXdz7FKwix
Mfn3qEb9BXSk0Q3prNV5sOV3vgjEtB4THfDxSz9z3+DepVnW3vbbqwEbkXdk3j82
2muVldgOUgTwK8eT+XdofVdntzU/kzygSAtAQwLJfn51fS1GvEcYGBc1bDryIqmF
p9BI7gVKtWSZYegicA==
-----END CERTIFICATE-----
Binary file not shown.

0 comments on commit e589b16

Please sign in to comment.