mirror of https://github.com/shred/acme4j
Remove local certificate after it has been revoked by LE
parent
75ed708f00
commit
f44b62d3cf
|
@ -18,12 +18,6 @@ Existing code should be migrated to _acme4j_ version 2 (see the [migration guide
|
|||
|
||||
This _acme4j_ v1 branch is not actively maintained any more. It will only get bugfixes and security updates, but no new features. As soon as _Let's Encrypt_ officially ends its ACME v1 support, work on this branch will be stopped.
|
||||
|
||||
## Important
|
||||
|
||||
In order to connect to the _Let's Encrypt_ servers, _acme4j_ has used a local truststore containing their SSL certificate. Native support of IdenTrust certificates was added to Java 8u101 in July 2016. Since then, the local truststore was not necessary any more. It has been disabled in _acme4j_ v0.12.
|
||||
|
||||
**If you are still using _acme4j_ < v0.12, you must update to a later version!** The certificate in the local truststore expires in June 2018 (or maybe earlier, at the discretion of _Let's Encrypt_). After that, older _acme4j_ versions will not be able to connect to the _Let's Encrypt_ servers any more.
|
||||
|
||||
## Features
|
||||
|
||||
* Supports the "ACME v1" protocol that is used by _Let's Encrypt_
|
||||
|
|
|
@ -17,12 +17,9 @@ 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;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* An {@link AcmeProvider} for <em>Let's Encrypt</em>.
|
||||
|
@ -36,8 +33,6 @@ import org.slf4j.LoggerFactory;
|
|||
*/
|
||||
public class LetsEncryptAcmeProvider extends AbstractAcmeProvider {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(LetsEncryptAcmeProvider.class);
|
||||
|
||||
private static final String V01_DIRECTORY_URL = "https://acme-v01.api.letsencrypt.org/directory";
|
||||
private static final String STAGING_DIRECTORY_URL = "https://acme-staging.api.letsencrypt.org/directory";
|
||||
|
||||
|
@ -66,15 +61,4 @@ public class LetsEncryptAcmeProvider extends AbstractAcmeProvider {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("deprecation")
|
||||
protected HttpConnector createHttpConnector() {
|
||||
if (Boolean.getBoolean("acme4j.le.certfix")) {
|
||||
LOG.warn("Using a hardcoded Let's Encrypt certificate. It will expire by June 2018.");
|
||||
return new LetsEncryptHttpConnector();
|
||||
} else {
|
||||
return super.createHttpConnector();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,79 +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.
|
||||
*
|
||||
* @deprecated API server certificate CA is accepted by current JREs. There is no need
|
||||
* for certificate pinning any more. Hardcoded certificate will expire by June 25th, 2018.
|
||||
*/
|
||||
@Deprecated
|
||||
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,83 +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 static org.shredzone.acme4j.toolbox.TestUtils.url;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URISyntaxException;
|
||||
|
||||
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)
|
||||
@SuppressWarnings("deprecation")
|
||||
public void testCertificate() throws IOException, URISyntaxException {
|
||||
LetsEncryptHttpConnector connector = new LetsEncryptHttpConnector();
|
||||
|
||||
try {
|
||||
HttpURLConnection goodConn = connector.openConnection(
|
||||
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(
|
||||
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
|
||||
@SuppressWarnings("deprecation")
|
||||
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)));
|
||||
}
|
||||
|
||||
}
|
|
@ -10,7 +10,7 @@ Web site: [Let's Encrypt](https://letsencrypt.org)
|
|||
|
||||
## Compatibility
|
||||
|
||||
If you have to use a Java version that is older than 8u101 and does not accept the _IdenTrust_ certificates of the _Let's Encrypt_ servers, you can use a hardcoded local truststore as a workaround by setting the `acme4j.le.certfix` system property to `true`. Please note that the hardwired certificate will expire by June, 2018.
|
||||
Java 8u101 or later is required for connecting to the _Let's Encrypt_ servers.
|
||||
|
||||
## Limits
|
||||
|
||||
|
|
|
@ -14,8 +14,6 @@ In the `acme4j-client` module, the `org.shredzone.acme4j.util` package has been
|
|||
|
||||
Java support for the _IdenTrust_ certificate that is used by _Let's Encrypt_ servers was added to JRE 8u101 in July 2016. For this reason, _acme4j_ does not need to use a hardcoded local truststore anymore. It has been disabled in this version, and the standard Java truststore is used instead.
|
||||
|
||||
If you have to use an older JRE, you can re-enable the local truststore by setting the `acme4j.le.certfix` system property to `true`. Please note that the local certificate will expire by June, 2018.
|
||||
|
||||
## Migration to Version 0.10
|
||||
|
||||
Starting with version 0.10, _acme4j_ requires Java 8 or higher. This is also reflected in the API.
|
||||
|
|
Loading…
Reference in New Issue