diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/Challenge.java b/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/Challenge.java index 433674f7..3e557b1f 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/Challenge.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/Challenge.java @@ -19,12 +19,14 @@ import java.time.Instant; import java.util.Objects; import org.shredzone.acme4j.AcmeResource; +import org.shredzone.acme4j.Problem; import org.shredzone.acme4j.Session; import org.shredzone.acme4j.Status; import org.shredzone.acme4j.connector.Connection; import org.shredzone.acme4j.exception.AcmeException; import org.shredzone.acme4j.exception.AcmeProtocolException; import org.shredzone.acme4j.exception.AcmeRetryAfterException; +import org.shredzone.acme4j.provider.pebble.Pebble; import org.shredzone.acme4j.util.JSON; import org.shredzone.acme4j.util.JSONBuilder; import org.slf4j.Logger; @@ -44,9 +46,10 @@ public class Challenge extends AcmeResource { private static final Logger LOG = LoggerFactory.getLogger(Challenge.class); protected static final String KEY_TYPE = "type"; + protected static final String KEY_URL = "url"; protected static final String KEY_STATUS = "status"; - protected static final String KEY_URI = "uri"; protected static final String KEY_VALIDATED = "validated"; + protected static final String KEY_ERROR = "error"; private JSON data = JSON.empty(); @@ -80,8 +83,8 @@ public class Challenge extends AcmeResource { conn.accept(HttpURLConnection.HTTP_OK); JSON json = conn.readJsonResponse(); - if (!(json.contains("type"))) { - throw new IllegalArgumentException("Provided URI is not a challenge URI"); + if (!(json.contains(KEY_TYPE))) { + throw new IllegalArgumentException("Provided URL is not a challenge URL"); } return (T) session.createChallenge(json); @@ -95,19 +98,25 @@ public class Challenge extends AcmeResource { return data.get(KEY_TYPE).asString(); } - /** - * Returns the current status of the challenge. - */ - public Status getStatus() { - return data.get(KEY_STATUS).asStatusOrElse(Status.PENDING); - } - /** * Returns the location {@link URL} of the challenge. */ @Override public URL getLocation() { - return data.get(KEY_URI).asURL(); + // TODO PEBBLE: uses "uri" instead of "url" + // https://github.com/letsencrypt/pebble/pull/25 + if (Pebble.workaround()) { + return data.get("uri").asURL(); + } else { + return data.get(KEY_URL).asURL(); + } + } + + /** + * Returns the current status of the challenge. + */ + public Status getStatus() { + return data.get(KEY_STATUS).asStatusOrElse(Status.UNKNOWN); } /** @@ -117,6 +126,13 @@ public class Challenge extends AcmeResource { return data.get(KEY_VALIDATED).asInstant(); } + /** + * Returns the reason why the challenge failed, if returned by the server. + */ + public Problem getError() { + return data.get(KEY_ERROR).asProblem(getLocation()); + } + /** * Returns the JSON representation of the challenge data. */ diff --git a/acme4j-client/src/test/java/org/shredzone/acme4j/challenge/ChallengeTest.java b/acme4j-client/src/test/java/org/shredzone/acme4j/challenge/ChallengeTest.java index 306d69bd..26603c89 100644 --- a/acme4j-client/src/test/java/org/shredzone/acme4j/challenge/ChallengeTest.java +++ b/acme4j-client/src/test/java/org/shredzone/acme4j/challenge/ChallengeTest.java @@ -21,7 +21,7 @@ import static uk.co.datumedge.hamcrest.json.SameJSONAs.sameJSONAs; import java.io.IOException; import java.net.HttpURLConnection; -import java.net.MalformedURLException; +import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.time.Duration; @@ -94,12 +94,12 @@ public class ChallengeTest { * Test that after unmarshalling, the challenge properties are set correctly. */ @Test - public void testUnmarshall() throws URISyntaxException, MalformedURLException { + public void testUnmarshall() throws URISyntaxException { Challenge challenge = new Challenge(session); // Test default values assertThat(challenge.getType(), is(nullValue())); - assertThat(challenge.getStatus(), is(Status.PENDING)); + assertThat(challenge.getStatus(), is(Status.UNKNOWN)); assertThat(challenge.getLocation(), is(nullValue())); assertThat(challenge.getValidated(), is(nullValue())); @@ -108,11 +108,15 @@ public class ChallengeTest { // Test unmarshalled values assertThat(challenge.getType(), is("generic-01")); - assertThat(challenge.getStatus(), is(Status.VALID)); + assertThat(challenge.getStatus(), is(Status.INVALID)); assertThat(challenge.getLocation(), is(url("http://example.com/challenge/123"))); assertThat(challenge.getValidated(), is(parseTimestamp("2015-12-12T17:19:36.336785823Z"))); + assertThat(challenge.getError(), is(notNullValue())); + assertThat(challenge.getError().getType(), is(URI.create("urn:ietf:params:acme:error:connection"))); + assertThat(challenge.getError().getDetail(), is("connection refused")); + assertThat(challenge.getError().getInstance(), is(URI.create("http://example.com/documents/error.html"))); assertThat(challenge.getJSON().get("type").asString(), is("generic-01")); - assertThat(challenge.getJSON().get("uri").asURL(), is(new URL("http://example.com/challenge/123"))); + assertThat(challenge.getJSON().get("url").asURL(), is(url("http://example.com/challenge/123"))); assertThat(challenge.getJSON().get("not-present").asString(), is(nullValue())); assertThat(challenge.getJSON().get("not-present-url").asURL(), is(nullValue())); } diff --git a/acme4j-client/src/test/java/org/shredzone/acme4j/challenge/OutOfBandChallengeTest.java b/acme4j-client/src/test/java/org/shredzone/acme4j/challenge/OutOfBandChallengeTest.java index 7f67a480..ff343dbe 100644 --- a/acme4j-client/src/test/java/org/shredzone/acme4j/challenge/OutOfBandChallengeTest.java +++ b/acme4j-client/src/test/java/org/shredzone/acme4j/challenge/OutOfBandChallengeTest.java @@ -48,7 +48,7 @@ public class OutOfBandChallengeTest { challenge.unmarshall(getJSON("oobChallenge")); assertThat(challenge.getType(), is(OutOfBand01Challenge.TYPE)); - assertThat(challenge.getStatus(), is(Status.PENDING)); + assertThat(challenge.getStatus(), is(Status.UNKNOWN)); assertThat(challenge.getValidationUrl(), is(new URL("https://example.com/validate/evaGxfADs6pSRb2LAv9IZ"))); diff --git a/acme4j-client/src/test/resources/json/authorizationChallenges.json b/acme4j-client/src/test/resources/json/authorizationChallenges.json index 3bc173e7..8c4a8509 100644 --- a/acme4j-client/src/test/resources/json/authorizationChallenges.json +++ b/acme4j-client/src/test/resources/json/authorizationChallenges.json @@ -2,26 +2,26 @@ "challenges": [ { "type": "http-01", - "uri": "https://example.com/authz/asdf/0", + "url": "https://example.com/authz/asdf/0", "token": "IlirfxKKXAsHtmzK29Pj8A" }, { "type": "dns-01", - "uri": "https://example.com/authz/asdf/1", + "url": "https://example.com/authz/asdf/1", "token": "DGyRejmCefe7v4NfDGDKfA" }, { "type": "tls-sni-02", - "uri": "https://example.com/authz/asdf/2", + "url": "https://example.com/authz/asdf/2", "token": "VNLBdSiZ3LppU2CRG8bilqlwq4DuApJMg3ZJowU6JhQ" }, { "type": "duplicate-01", - "uri": "https://example.com/authz/asdf/3" + "url": "https://example.com/authz/asdf/3" }, { "type": "duplicate-01", - "uri": "https://example.com/authz/asdf/4" + "url": "https://example.com/authz/asdf/4" } ] } diff --git a/acme4j-client/src/test/resources/json/genericChallenge.json b/acme4j-client/src/test/resources/json/genericChallenge.json index c2a9536b..4e4572e0 100644 --- a/acme4j-client/src/test/resources/json/genericChallenge.json +++ b/acme4j-client/src/test/resources/json/genericChallenge.json @@ -1,6 +1,11 @@ { "type": "generic-01", - "status": "valid", - "uri": "http://example.com/challenge/123", - "validated": "2015-12-12T17:19:36.336785823Z" + "status": "invalid", + "url": "http://example.com/challenge/123", + "validated": "2015-12-12T17:19:36.336785823Z", + "error": { + "type": "urn:ietf:params:acme:error:connection", + "detail": "connection refused", + "instance": "/documents/error.html" + } } diff --git a/acme4j-client/src/test/resources/json/newAuthorizationResponse.json b/acme4j-client/src/test/resources/json/newAuthorizationResponse.json index 49471166..127933a9 100644 --- a/acme4j-client/src/test/resources/json/newAuthorizationResponse.json +++ b/acme4j-client/src/test/resources/json/newAuthorizationResponse.json @@ -8,13 +8,13 @@ { "type": "http-01", "status": "pending", - "uri": "https://example.com/authz/asdf/0", + "url": "https://example.com/authz/asdf/0", "token": "IlirfxKKXAsHtmzK29Pj8A" }, { "type": "dns-01", "status": "pending", - "uri": "https://example.com/authz/asdf/1", + "url": "https://example.com/authz/asdf/1", "token": "DGyRejmCefe7v4NfDGDKfA" } ] diff --git a/acme4j-client/src/test/resources/json/triggerHttpChallenge.json b/acme4j-client/src/test/resources/json/triggerHttpChallenge.json index a4884947..d67d346a 100644 --- a/acme4j-client/src/test/resources/json/triggerHttpChallenge.json +++ b/acme4j-client/src/test/resources/json/triggerHttpChallenge.json @@ -1,6 +1,6 @@ { "type": "http-01", "status": "pending", - "uri": "https://example.com/acme/some-resource", + "url": "https://example.com/acme/some-resource", "token": "IlirfxKKXAsHtmzK29Pj8A" } diff --git a/acme4j-client/src/test/resources/json/triggerHttpChallengeResponse.json b/acme4j-client/src/test/resources/json/triggerHttpChallengeResponse.json index 9a5de2ed..6845afe5 100644 --- a/acme4j-client/src/test/resources/json/triggerHttpChallengeResponse.json +++ b/acme4j-client/src/test/resources/json/triggerHttpChallengeResponse.json @@ -1,7 +1,7 @@ { "type": "http-01", "status": "pending", - "uri": "https://example.com/acme/some-location", + "url": "https://example.com/acme/some-location", "token": "IlirfxKKXAsHtmzK29Pj8A", "keyAuthorization": "XbmEGDDc2AMDArHLt5x7GxZfIRv0aScknUKlyf5S4KU.KMH_h8aGAKlY3VQqBUczm1cfo9kaovivy59rSY1xZ0E" } diff --git a/acme4j-client/src/test/resources/json/updateAuthorizationResponse.json b/acme4j-client/src/test/resources/json/updateAuthorizationResponse.json index 54bec07b..e50c5322 100644 --- a/acme4j-client/src/test/resources/json/updateAuthorizationResponse.json +++ b/acme4j-client/src/test/resources/json/updateAuthorizationResponse.json @@ -9,13 +9,13 @@ { "type": "http-01", "status": "pending", - "uri": "https://example.com/authz/asdf/0", + "url": "https://example.com/authz/asdf/0", "token": "IlirfxKKXAsHtmzK29Pj8A" }, { "type": "dns-01", "status": "pending", - "uri": "https://example.com/authz/asdf/1", + "url": "https://example.com/authz/asdf/1", "token": "DGyRejmCefe7v4NfDGDKfA" } ], diff --git a/acme4j-client/src/test/resources/json/updateHttpChallengeResponse.json b/acme4j-client/src/test/resources/json/updateHttpChallengeResponse.json index 0e077165..d1e7cabc 100644 --- a/acme4j-client/src/test/resources/json/updateHttpChallengeResponse.json +++ b/acme4j-client/src/test/resources/json/updateHttpChallengeResponse.json @@ -1,7 +1,7 @@ { "type": "http-01", + "url": "https://example.com/acme/some-location", "status": "valid", - "uri": "https://example.com/acme/some-location", "token": "IlirfxKKXAsHtmzK29Pj8A", "keyAuthorization": "XbmEGDDc2AMDArHLt5x7GxZfIRv0aScknUKlyf5S4KU.KMH_h8aGAKlY3VQqBUczm1cfo9kaovivy59rSY1xZ0E" }