mirror of https://github.com/shred/acme4j
Remove local truststore for Let's Encrypt servers
parent
e15abb0ca0
commit
148c98d673
|
@ -12,7 +12,7 @@ It is an independent open source implementation that is not affiliated with or e
|
|||
|
||||
* Fully supports the ACME v2 protocol
|
||||
* Easy to use Java API
|
||||
* Requires JRE 8 or higher
|
||||
* Requires JRE 8 (update 101) or higher
|
||||
* Built with maven, packages available at [Maven Central](http://search.maven.org/#search|ga|1|g%3A%22org.shredzone.acme4j%22)
|
||||
* Small, only requires [jose4j](https://bitbucket.org/b_c/jose4j/wiki/Home) and [slf4j](http://www.slf4j.org/) as dependencies
|
||||
* Extensive unit and integration tests
|
||||
|
|
|
@ -17,7 +17,6 @@ import java.net.MalformedURLException;
|
|||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
|
||||
import org.shredzone.acme4j.connector.HttpConnector;
|
||||
import org.shredzone.acme4j.exception.AcmeProtocolException;
|
||||
import org.shredzone.acme4j.provider.AbstractAcmeProvider;
|
||||
import org.shredzone.acme4j.provider.AcmeProvider;
|
||||
|
@ -28,8 +27,7 @@ import org.shredzone.acme4j.provider.AcmeProvider;
|
|||
* The {@code serverUri} is {@code "acme://letsencrypt.org"} for the production server,
|
||||
* and {@code "acme://letsencrypt.org/staging"} for a testing server.
|
||||
* <p>
|
||||
* If you want to use <em>Let's Encrypt</em>, always prefer to use this provider, as it
|
||||
* takes care for the correct connection and SSL certificates.
|
||||
* If you want to use <em>Let's Encrypt</em>, always prefer to use this provider.
|
||||
*
|
||||
* @see <a href="https://letsencrypt.org/">Let's Encrypt</a>
|
||||
*/
|
||||
|
@ -63,9 +61,4 @@ public class LetsEncryptAcmeProvider extends AbstractAcmeProvider {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected HttpConnector createHttpConnector() {
|
||||
return new LetsEncryptHttpConnector();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,75 +0,0 @@
|
|||
/*
|
||||
* acme4j - Java ACME client
|
||||
*
|
||||
* Copyright (C) 2015 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.letsencrypt;
|
||||
|
||||
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 Let's Encrypt. It is pinned to the Let's Encrypt
|
||||
* server certificate.
|
||||
*/
|
||||
public class LetsEncryptHttpConnector 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 Let's
|
||||
* Encrypt certificate.
|
||||
*/
|
||||
protected synchronized SSLSocketFactory createSocketFactory() throws IOException {
|
||||
if (sslSocketFactory == null) {
|
||||
try {
|
||||
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
|
||||
keystore.load(getClass().getResourceAsStream("/org/shredzone/acme4j/letsencrypt.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.
|
@ -1,80 +0,0 @@
|
|||
/*
|
||||
* acme4j - Java ACME client
|
||||
*
|
||||
* Copyright (C) 2015 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.letsencrypt;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
|
||||
import javax.net.ssl.HttpsURLConnection;
|
||||
import javax.net.ssl.SSLHandshakeException;
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.experimental.categories.Category;
|
||||
|
||||
/**
|
||||
* Unit test for {@link LetsEncryptHttpConnector}.
|
||||
*/
|
||||
public class LetsEncryptHttpConnectorTest {
|
||||
|
||||
/**
|
||||
* Test if the connector accepts only the Let's Encrypt certificate.
|
||||
* <p>
|
||||
* This test requires a network connection. It should be excluded from automated
|
||||
* builds.
|
||||
*/
|
||||
@Test
|
||||
@Category(HttpURLConnection.class)
|
||||
public void testCertificate() throws IOException {
|
||||
LetsEncryptHttpConnector connector = new LetsEncryptHttpConnector();
|
||||
|
||||
try {
|
||||
HttpURLConnection goodConn = connector.openConnection(
|
||||
new URL("https://acme-staging.api.letsencrypt.org/directory"));
|
||||
assertThat(goodConn, is(instanceOf(HttpsURLConnection.class)));
|
||||
goodConn.connect();
|
||||
} catch (SSLHandshakeException ex) {
|
||||
fail("Connection does not accept Let's Encrypt certificate");
|
||||
}
|
||||
|
||||
try {
|
||||
HttpURLConnection badConn = connector.openConnection(
|
||||
new URL("https://www.google.com"));
|
||||
assertThat(badConn, is(instanceOf(HttpsURLConnection.class)));
|
||||
badConn.connect();
|
||||
fail("Connection accepts foreign certificate");
|
||||
} catch (SSLHandshakeException ex) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that the {@link SSLSocketFactory} can be instantiated and is cached.
|
||||
*/
|
||||
@Test
|
||||
public void testCreateSocketFactory() throws IOException {
|
||||
LetsEncryptHttpConnector connector = new LetsEncryptHttpConnector();
|
||||
|
||||
SSLSocketFactory factory1 = connector.createSocketFactory();
|
||||
assertThat(factory1, is(notNullValue()));
|
||||
|
||||
SSLSocketFactory factory2 = connector.createSocketFactory();
|
||||
assertThat(factory1, is(sameInstance(factory2)));
|
||||
}
|
||||
|
||||
}
|
|
@ -7,14 +7,6 @@ Web site: [Let's Encrypt](https://letsencrypt.org)
|
|||
* `acme://letsencrypt.org` - Production server
|
||||
* `acme://letsencrypt.org/staging` - Testing server
|
||||
|
||||
## Features
|
||||
## Note
|
||||
|
||||
* Accepts the ACME server certificate of Let's Encrypt even on older Java versions
|
||||
|
||||
## Limits
|
||||
|
||||
* Registrations per IP: 10 per 3 hours
|
||||
* Certificates per Domain: 5 per 7 days
|
||||
* SANs per Certificate: 100
|
||||
|
||||
See [here](https://community.letsencrypt.org/t/public-beta-rate-limits/4772) for the current limits.
|
||||
* Java 8u101 or higher is required for connecting to the _Let's Encrypt_ servers.
|
||||
|
|
Loading…
Reference in New Issue