mirror of https://github.com/shred/acme4j
Connect to Pebble via https
parent
6cfd898895
commit
4c4cf5b5cf
|
@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Binary file not shown.
|
@ -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"));
|
||||||
|
|
|
@ -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()));
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue