Connect to Pebble via https

pull/55/head
Richard Körber 2017-12-06 22:55:00 +01:00
parent 6cfd898895
commit 4c4cf5b5cf
No known key found for this signature in database
GPG Key ID: AAB9FD19C78AA3E0
6 changed files with 91 additions and 8 deletions

View File

@ -19,6 +19,7 @@ import java.net.URL;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.shredzone.acme4j.connector.HttpConnector;
import org.shredzone.acme4j.provider.AbstractAcmeProvider; import org.shredzone.acme4j.provider.AbstractAcmeProvider;
import org.shredzone.acme4j.provider.AcmeProvider; import org.shredzone.acme4j.provider.AcmeProvider;
@ -47,7 +48,7 @@ public class PebbleAcmeProvider extends AbstractAcmeProvider {
try { try {
String path = serverUri.getPath(); String path = serverUri.getPath();
URL baseUrl = new URL("http://localhost:14000/dir"); URL baseUrl = new URL("https://localhost:14000/dir");
if (path != null && !path.isEmpty() && !"/".equals(path)) { if (path != null && !path.isEmpty() && !"/".equals(path)) {
baseUrl = parsePath(path); baseUrl = parsePath(path);
@ -74,10 +75,15 @@ public class PebbleAcmeProvider extends AbstractAcmeProvider {
if (m.group(2) != null) { if (m.group(2) != null) {
port = Integer.parseInt(m.group(2)); port = Integer.parseInt(m.group(2));
} }
return new URL("http", host, port, "/dir"); return new URL("https", host, port, "/dir");
} else { } else {
throw new IllegalArgumentException("Invalid Pebble host/port: " + path); throw new IllegalArgumentException("Invalid Pebble host/port: " + path);
} }
} }
@Override
protected HttpConnector createHttpConnector() {
return new PebbleHttpConnector();
}
} }

View File

@ -0,0 +1,75 @@
/*
* acme4j - Java ACME client
*
* Copyright (C) 2017 Richard "Shred" Körber
* http://acme4j.shredzone.org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
package org.shredzone.acme4j.provider.pebble;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory;
import org.shredzone.acme4j.connector.HttpConnector;
/**
* {@link HttpConnector} to be used for Pebble. Pebble uses a static, self signed SSL
* certificate.
*/
public class PebbleHttpConnector extends HttpConnector {
private static SSLSocketFactory sslSocketFactory;
@Override
public HttpURLConnection openConnection(URL url) throws IOException {
HttpURLConnection conn = super.openConnection(url);
if (conn instanceof HttpsURLConnection) {
((HttpsURLConnection) conn).setSSLSocketFactory(createSocketFactory());
}
return conn;
}
/**
* Lazily creates an {@link SSLSocketFactory} that exclusively accepts the Pebble
* certificate.
*/
protected synchronized SSLSocketFactory createSocketFactory() throws IOException {
if (sslSocketFactory == null) {
try {
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
keystore.load(getClass().getResourceAsStream("/org/shredzone/acme4j/provider/pebble/pebble.truststore"),
"acme4j".toCharArray());
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(keystore);
SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(null, tmf.getTrustManagers(), null);
sslSocketFactory = ctx.getSocketFactory();
} catch (KeyStoreException | CertificateException | NoSuchAlgorithmException
| KeyManagementException ex) {
throw new IOException("Could not create truststore", ex);
}
}
return sslSocketFactory;
}
}

View File

@ -51,15 +51,15 @@ public class PebbleAcmeProviderTest {
PebbleAcmeProvider provider = new PebbleAcmeProvider(); PebbleAcmeProvider provider = new PebbleAcmeProvider();
assertThat(provider.resolve(new URI("acme://pebble")), assertThat(provider.resolve(new URI("acme://pebble")),
is(url("http://localhost:14000/dir"))); is(url("https://localhost:14000/dir")));
assertThat(provider.resolve(new URI("acme://pebble/")), assertThat(provider.resolve(new URI("acme://pebble/")),
is(url("http://localhost:14000/dir"))); is(url("https://localhost:14000/dir")));
assertThat(provider.resolve(new URI("acme://pebble/pebble.example.com")), assertThat(provider.resolve(new URI("acme://pebble/pebble.example.com")),
is(url("http://pebble.example.com:14000/dir"))); is(url("https://pebble.example.com:14000/dir")));
assertThat(provider.resolve(new URI("acme://pebble/pebble.example.com:12345")), assertThat(provider.resolve(new URI("acme://pebble/pebble.example.com:12345")),
is(url("http://pebble.example.com:12345/dir"))); is(url("https://pebble.example.com:12345/dir")));
assertThat(provider.resolve(new URI("acme://pebble/pebble.example.com:12345/")), assertThat(provider.resolve(new URI("acme://pebble/pebble.example.com:12345/")),
is(url("http://pebble.example.com:12345/dir"))); is(url("https://pebble.example.com:12345/dir")));
try { try {
provider.resolve(new URI("acme://pebble/bad.example.com:port")); provider.resolve(new URI("acme://pebble/bad.example.com:port"));

View File

@ -76,7 +76,7 @@ public abstract class PebbleITBase {
*/ */
protected void assertIsPebbleUrl(URL url) { protected void assertIsPebbleUrl(URL url) {
assertThat(url, not(nullValue())); assertThat(url, not(nullValue()));
assertThat(url.getProtocol(), is("http")); assertThat(url.getProtocol(), is("https"));
assertThat(url.getHost(), is(pebbleHost)); assertThat(url.getHost(), is(pebbleHost));
assertThat(url.getPort(), is(pebblePort)); assertThat(url.getPort(), is(pebblePort));
assertThat(url.getPath(), not(isEmptyOrNullString())); assertThat(url.getPath(), not(isEmptyOrNullString()));

View File

@ -1,6 +1,8 @@
{ {
"pebble": { "pebble": {
"listenAddress": "0.0.0.0:14000", "listenAddress": "0.0.0.0:14000",
"certificate": "/go/src/github.com/letsencrypt/pebble/test/certs/localhost/cert.pem",
"privateKey": "/go/src/github.com/letsencrypt/pebble/test/certs/localhost/key.pem",
"httpPort": 5002, "httpPort": 5002,
"tlsPort": 5001 "tlsPort": 5001
} }