mirror of https://github.com/shred/acme4j
Allow custom pebble.minica.pem files
Also changes from a Java proprietary truststore file to the official Pebble PEM file.pull/168/head
parent
793bcd7ce1
commit
e589b16d98
|
@ -20,7 +20,9 @@ import java.security.KeyStore;
|
||||||
import java.security.KeyStoreException;
|
import java.security.KeyStoreException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.cert.CertificateException;
|
import java.security.cert.CertificateException;
|
||||||
|
import java.security.cert.CertificateFactory;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
import javax.net.ssl.SSLContext;
|
import javax.net.ssl.SSLContext;
|
||||||
|
@ -28,12 +30,15 @@ import javax.net.ssl.TrustManagerFactory;
|
||||||
|
|
||||||
import org.shredzone.acme4j.connector.HttpConnector;
|
import org.shredzone.acme4j.connector.HttpConnector;
|
||||||
import org.shredzone.acme4j.connector.NetworkSettings;
|
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
|
* {@link HttpConnector} to be used for Pebble. Pebble uses a static, self-signed SSL
|
||||||
* certificate.
|
* certificate.
|
||||||
*/
|
*/
|
||||||
public class PebbleHttpConnector extends HttpConnector {
|
public class PebbleHttpConnector extends HttpConnector {
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(PebbleHttpConnector.class);
|
||||||
private static final AtomicReference<SSLContext> SSL_CONTEXT_REF = new AtomicReference<>();
|
private static final AtomicReference<SSLContext> SSL_CONTEXT_REF = new AtomicReference<>();
|
||||||
|
|
||||||
public PebbleHttpConnector(NetworkSettings settings) {
|
public PebbleHttpConnector(NetworkSettings settings) {
|
||||||
|
@ -53,9 +58,11 @@ public class PebbleHttpConnector extends HttpConnector {
|
||||||
*/
|
*/
|
||||||
protected SSLContext createSSLContext() {
|
protected SSLContext createSSLContext() {
|
||||||
if (SSL_CONTEXT_REF.get() == null) {
|
if (SSL_CONTEXT_REF.get() == null) {
|
||||||
try (var in = getClass().getResourceAsStream("/org/shredzone/acme4j/provider/pebble/pebble.truststore")) {
|
try {
|
||||||
var keystore = KeyStore.getInstance(KeyStore.getDefaultType());
|
var keystore = readPemFile("/pebble.minica.pem")
|
||||||
keystore.load(in, "acme4j".toCharArray());
|
.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());
|
var tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
|
||||||
tmf.init(keystore);
|
tmf.init(keystore);
|
||||||
|
@ -63,12 +70,38 @@ public class PebbleHttpConnector extends HttpConnector {
|
||||||
var sslContext = SSLContext.getInstance("TLS");
|
var sslContext = SSLContext.getInstance("TLS");
|
||||||
sslContext.init(null, tmf.getTrustManagers(), null);
|
sslContext.init(null, tmf.getTrustManagers(), null);
|
||||||
SSL_CONTEXT_REF.set(sslContext);
|
SSL_CONTEXT_REF.set(sslContext);
|
||||||
} catch (IOException | KeyStoreException | CertificateException
|
} catch (KeyStoreException | NoSuchAlgorithmException | KeyManagementException ex) {
|
||||||
| NoSuchAlgorithmException | KeyManagementException ex) {
|
|
||||||
throw new RuntimeException("Could not create truststore", ex);
|
throw new RuntimeException("Could not create truststore", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Objects.requireNonNull(SSL_CONTEXT_REF.get());
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
Loading…
Reference in New Issue