Remove pre-draft-15 compatibility code

pull/81/head
Richard Körber 2018-11-01 12:50:31 +01:00
parent b6390c6d75
commit 0c7aa2be1b
No known key found for this signature in database
GPG Key ID: AAB9FD19C78AA3E0
7 changed files with 9 additions and 263 deletions

View File

@ -1,55 +0,0 @@
/*
* acme4j - Java ACME client
*
* Copyright (C) 2018 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.connector;
import java.net.URL;
import org.shredzone.acme4j.Login;
import org.shredzone.acme4j.exception.AcmeException;
import org.shredzone.acme4j.toolbox.JSONBuilder;
/**
* This {@link Connection} is used for servers that do not implement the POST-as-GET
* feature that was introduced in ACME draft-15.
*
* @since 2.4
* @deprecated Only meant for compatibility purposes. If your server needs this
* connection, it should be fixed soon.
*/
@Deprecated
public class PreDraft15Connection extends DefaultConnection {
private static final String MIME_JSON = "application/json";
private static final String MIME_CERTIFICATE_CHAIN = "application/pem-certificate-chain";
public PreDraft15Connection(HttpConnector httpConnector) {
super(httpConnector);
}
@Override
public int sendCertificateRequest(URL url, Login login) throws AcmeException {
return sendRequest(url, login.getSession(), MIME_CERTIFICATE_CHAIN);
}
@Override
public int sendSignedPostAsGetRequest(URL url, Login login) throws AcmeException {
// Account resources must be updated by a signed POST request with empty JSON body
if (login.getAccountLocation().toExternalForm().equals(url.toExternalForm())) {
return sendSignedRequest(url, new JSONBuilder(), login);
}
return sendRequest(url, login.getSession(), MIME_JSON);
}
}

View File

@ -16,12 +16,9 @@ package org.shredzone.acme4j.provider;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.util.regex.Pattern;
import javax.annotation.ParametersAreNonnullByDefault;
import org.shredzone.acme4j.connector.Connection;
/**
* A generic {@link AcmeProvider}. It should be working for all ACME servers complying to
* the ACME specifications.
@ -31,9 +28,6 @@ import org.shredzone.acme4j.connector.Connection;
@ParametersAreNonnullByDefault
public class GenericAcmeProvider extends AbstractAcmeProvider {
private static final Pattern PARAM_POST_AS_GET =
Pattern.compile("(^|.*?&)postasget=false(&.*|$)");
@Override
public boolean accepts(URI serverUri) {
return "http".equals(serverUri.getScheme())
@ -49,15 +43,4 @@ public class GenericAcmeProvider extends AbstractAcmeProvider {
}
}
@Override
@SuppressWarnings("deprecation")
public Connection connect(URI serverUri) {
String query = serverUri.getQuery();
if (query != null && PARAM_POST_AS_GET.matcher(query).matches()) {
return new org.shredzone.acme4j.connector.PreDraft15Connection(createHttpConnector());
} else {
return super.connect(serverUri);
}
}
}

View File

@ -19,7 +19,6 @@ import java.net.URL;
import javax.annotation.ParametersAreNonnullByDefault;
import org.shredzone.acme4j.connector.Connection;
import org.shredzone.acme4j.exception.AcmeProtocolException;
import org.shredzone.acme4j.provider.AbstractAcmeProvider;
import org.shredzone.acme4j.provider.AcmeProvider;
@ -65,10 +64,4 @@ public class LetsEncryptAcmeProvider extends AbstractAcmeProvider {
}
}
@Override
@SuppressWarnings("deprecation")
public Connection connect(URI serverUri) {
return new org.shredzone.acme4j.connector.PreDraft15Connection(createHttpConnector());
}
}

View File

@ -1,153 +0,0 @@
/*
* acme4j - Java ACME client
*
* Copyright (C) 2018 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.connector;
import static org.hamcrest.CoreMatchers.sameInstance;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.*;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.Proxy;
import java.net.URI;
import java.net.URL;
import java.security.KeyPair;
import java.util.Locale;
import java.util.concurrent.atomic.AtomicBoolean;
import org.jose4j.base64url.Base64Url;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentMatchers;
import org.shredzone.acme4j.Login;
import org.shredzone.acme4j.Session;
import org.shredzone.acme4j.exception.AcmeException;
import org.shredzone.acme4j.provider.AcmeProvider;
import org.shredzone.acme4j.toolbox.JSONBuilder;
import org.shredzone.acme4j.toolbox.TestUtils;
/**
* Unit tests for {@link PreDraft15Connection}.
*/
@SuppressWarnings("deprecation")
public class PreDraft15ConnectionTest {
private URL requestUrl = TestUtils.url("http://example.com/acme/");
private URL accountUrl = TestUtils.url(TestUtils.ACCOUNT_URL);
private HttpURLConnection mockUrlConnection;
private HttpConnector mockHttpConnection;
private Session session;
private Login login;
private KeyPair keyPair;
@Before
public void setup() throws AcmeException, IOException {
mockUrlConnection = mock(HttpURLConnection.class);
mockHttpConnection = mock(HttpConnector.class);
when(mockHttpConnection.openConnection(requestUrl, Proxy.NO_PROXY)).thenReturn(mockUrlConnection);
final AcmeProvider mockProvider = mock(AcmeProvider.class);
when(mockProvider.directory(
ArgumentMatchers.any(Session.class),
ArgumentMatchers.eq(URI.create(TestUtils.ACME_SERVER_URI))))
.thenReturn(TestUtils.getJSON("directory"));
session = TestUtils.session(mockProvider);
session.setLocale(Locale.JAPAN);
keyPair = TestUtils.createKeyPair();
login = session.login(accountUrl, keyPair);
}
/**
* Test signed POST-as-GET requests in compatibility mode.
*/
@Test
public void testSendSignedPostAsGetRequest() throws Exception {
when(mockUrlConnection.getResponseCode()).thenReturn(HttpURLConnection.HTTP_OK);
try (PreDraft15Connection conn = new PreDraft15Connection(mockHttpConnection) {
@Override
public String getNonce() {
return Base64Url.encode("foo-nonce-1-foo".getBytes());
}
}) {
conn.sendSignedPostAsGetRequest(requestUrl, login);
}
verify(mockUrlConnection).setRequestMethod("GET");
verify(mockUrlConnection).setRequestProperty("Accept", "application/json");
verify(mockUrlConnection).setRequestProperty("Accept-Charset", "utf-8");
verify(mockUrlConnection).setRequestProperty("Accept-Language", "ja-JP");
verify(mockUrlConnection).setDoOutput(false);
verify(mockUrlConnection).connect();
verify(mockUrlConnection).getResponseCode();
verify(mockUrlConnection, atLeast(0)).getHeaderFields();
verifyNoMoreInteractions(mockUrlConnection);
}
/**
* Test update requests to Account in compatibility mode.
*/
@Test
public void testUpdateAccountRequest() throws Exception {
final AtomicBoolean wasInvoked = new AtomicBoolean();
try (PreDraft15Connection conn = new PreDraft15Connection(mockHttpConnection) {
@Override
public int sendSignedRequest(URL url, JSONBuilder claims, Login login) throws AcmeException {
assertThat(url, is(accountUrl));
assertThat(claims.toString(), is("{}"));
assertThat(login, is(sameInstance(PreDraft15ConnectionTest.this.login)));
wasInvoked.set(true);
return HttpURLConnection.HTTP_OK;
};
}) {
conn.sendSignedPostAsGetRequest(accountUrl, login);
}
assertThat(wasInvoked.get(), is(true));
}
/**
* Test certificate POST-as-GET requests in compatibility mode.
*/
@Test
public void testSendCertificateRequest() throws Exception {
when(mockUrlConnection.getResponseCode()).thenReturn(HttpURLConnection.HTTP_OK);
try (PreDraft15Connection conn = new PreDraft15Connection(mockHttpConnection) {
@Override
public String getNonce() {
return Base64Url.encode("foo-nonce-1-foo".getBytes());
}
}) {
conn.sendCertificateRequest(requestUrl, login);
}
verify(mockUrlConnection).setRequestMethod("GET");
verify(mockUrlConnection).setRequestProperty("Accept", "application/pem-certificate-chain");
verify(mockUrlConnection).setRequestProperty("Accept-Charset", "utf-8");
verify(mockUrlConnection).setRequestProperty("Accept-Language", "ja-JP");
verify(mockUrlConnection).setDoOutput(false);
verify(mockUrlConnection).connect();
verify(mockUrlConnection).getResponseCode();
verify(mockUrlConnection, atLeast(0)).getHeaderFields();
verifyNoMoreInteractions(mockUrlConnection);
}
}

View File

@ -57,22 +57,4 @@ public class GenericAcmeProviderTest {
assertThat(connection, is(instanceOf(DefaultConnection.class)));
}
/**
* Test if the postasget parameter is accepted.
*/
@Test
@SuppressWarnings("deprecation")
public void testPostAsGet() throws URISyntaxException {
URI serverUri = new URI("http://example.com/acme?postasget=false");
URI serverUriWithoutQuery = new URI("http://example.com/acme");
GenericAcmeProvider provider = new GenericAcmeProvider();
URL resolvedUrl = provider.resolve(serverUri);
assertThat(resolvedUrl.toString(), is(equalTo(serverUriWithoutQuery.toString())));
Connection connection = provider.connect(serverUri);
assertThat(connection, is(instanceOf(org.shredzone.acme4j.connector.PreDraft15Connection.class)));
}
}

View File

@ -13,7 +13,6 @@
*/
package org.shredzone.acme4j.provider.letsencrypt;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.*;
import static org.shredzone.acme4j.toolbox.TestUtils.url;
@ -22,7 +21,6 @@ import java.net.URI;
import java.net.URISyntaxException;
import org.junit.Test;
import org.shredzone.acme4j.connector.Connection;
/**
* Unit tests for {@link LetsEncryptAcmeProvider}.
@ -68,15 +66,4 @@ public class LetsEncryptAcmeProviderTest {
}
}
/**
* Test that Boulder is still having pre draft-15 connections.
*/
@Test
@SuppressWarnings("deprecation")
public void testConnect() {
LetsEncryptAcmeProvider provider = new LetsEncryptAcmeProvider();
Connection connection = provider.connect(URI.create("acme://letsencrypt.org"));
assertThat(connection, is(instanceOf(org.shredzone.acme4j.connector.PreDraft15Connection.class)));
}
}

View File

@ -2,6 +2,15 @@
This document will help you migrate your code to the latest _acme4j_ version.
## Migration to Version 2.5
- The GET compatibility mode has been removed. It also means that the `postasget=false` parameter is ignored from now on. If you need it to connect to your ACME server, do not update to this version until your ACME server has been fixed to support ACME draft 15.
<div class="alert alert-info" role="alert">
I recommend to update to this _acme4j_ version as soon as possible! _Let's Encrypt_ has [announced a sunset date for GET requests](https://community.letsencrypt.org/t/acme-v2-scheduled-deprecation-of-unauthenticated-resource-gets/74380) on November 1st, 2019. _acme4j_ v2.4 and older will break after that date!
</div>
## Migration to Version 2.4
- There was a major change in ACME draft 15. If you use _acme4j_ in a common way, it will transparently take care of everything in the background, so you won't even notice the change.