mirror of https://github.com/shred/acme4j
Add method to restore a Challenge
parent
c97392236d
commit
db927300e9
|
@ -80,6 +80,19 @@ public interface AcmeClient {
|
|||
*/
|
||||
void updateChallenge(Account account, Challenge challenge) throws AcmeException;
|
||||
|
||||
/**
|
||||
* Restore a {@link Challenge} instance if only the challenge URI is known. It
|
||||
* contains the current state.
|
||||
*
|
||||
* @param account
|
||||
* {@link Account} to be used for conversation
|
||||
* @param challengeUri
|
||||
* {@link URI} of the challenge to restore
|
||||
* @throws ClassCastException
|
||||
* if the challenge does not match the desired type
|
||||
*/
|
||||
<T extends Challenge> T restoreChallenge(Account account, URI challengeUri) throws AcmeException;
|
||||
|
||||
/**
|
||||
* Request a certificate.
|
||||
*
|
||||
|
|
|
@ -39,9 +39,9 @@ public interface Challenge {
|
|||
String getType();
|
||||
|
||||
/**
|
||||
* Returns the {@link URI} of the challenge.
|
||||
* Returns the location {@link URI} of the challenge.
|
||||
*/
|
||||
URI getUri();
|
||||
URI getLocation();
|
||||
|
||||
/**
|
||||
* Returns the current status of the challenge.
|
||||
|
|
|
@ -58,7 +58,7 @@ public class GenericChallenge implements Challenge {
|
|||
}
|
||||
|
||||
@Override
|
||||
public URI getUri() {
|
||||
public URI getLocation() {
|
||||
String uri = get(KEY_URI);
|
||||
if (uri == null) {
|
||||
return null;
|
||||
|
|
|
@ -202,7 +202,7 @@ public abstract class AbstractAcmeClient implements AcmeClient {
|
|||
claims.putResource("challenge");
|
||||
challenge.marshall(claims);
|
||||
|
||||
int rc = conn.sendSignedRequest(challenge.getUri(), claims, session, account);
|
||||
int rc = conn.sendSignedRequest(challenge.getLocation(), claims, session, account);
|
||||
if (rc != HttpURLConnection.HTTP_OK && rc != HttpURLConnection.HTTP_ACCEPTED) {
|
||||
conn.throwAcmeException();
|
||||
}
|
||||
|
@ -215,7 +215,7 @@ public abstract class AbstractAcmeClient implements AcmeClient {
|
|||
public void updateChallenge(Account account, Challenge challenge) throws AcmeException {
|
||||
LOG.debug("updateChallenge");
|
||||
try (Connection conn = createConnection()) {
|
||||
int rc = conn.sendRequest(challenge.getUri());
|
||||
int rc = conn.sendRequest(challenge.getLocation());
|
||||
if (rc != HttpURLConnection.HTTP_ACCEPTED) {
|
||||
conn.throwAcmeException();
|
||||
}
|
||||
|
@ -224,6 +224,27 @@ public abstract class AbstractAcmeClient implements AcmeClient {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T extends Challenge> T restoreChallenge(Account account, URI challengeUri) throws AcmeException {
|
||||
LOG.debug("restoreChallenge");
|
||||
try (Connection conn = createConnection()) {
|
||||
int rc = conn.sendRequest(challengeUri);
|
||||
if (rc != HttpURLConnection.HTTP_ACCEPTED) {
|
||||
conn.throwAcmeException();
|
||||
}
|
||||
|
||||
Map<String, Object> json = conn.readJsonResponse();
|
||||
if (!(json.containsKey("type"))) {
|
||||
throw new AcmeException("Provided URI is not a challenge URI");
|
||||
}
|
||||
|
||||
T challenge = (T) createChallenge(json.get("type").toString());
|
||||
challenge.unmarshall(json);
|
||||
return challenge;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public URI requestCertificate(Account account, byte[] csr) throws AcmeException {
|
||||
LOG.debug("requestCertificate");
|
||||
|
|
|
@ -49,7 +49,7 @@ public class GenericChallengeTest {
|
|||
// Test default values
|
||||
assertThat(challenge.getType(), is(nullValue()));
|
||||
assertThat(challenge.getStatus(), is(Status.PENDING));
|
||||
assertThat(challenge.getUri(), is(nullValue()));
|
||||
assertThat(challenge.getLocation(), is(nullValue()));
|
||||
assertThat(challenge.getValidated(), is(nullValue()));
|
||||
|
||||
// Unmarshall a challenge JSON
|
||||
|
@ -58,7 +58,7 @@ public class GenericChallengeTest {
|
|||
// Test unmarshalled values
|
||||
assertThat(challenge.getType(), is("generic-01"));
|
||||
assertThat(challenge.getStatus(), is(Status.VALID));
|
||||
assertThat(challenge.getUri(), is(new URI("http://example.com/challenge/123")));
|
||||
assertThat(challenge.getLocation(), is(new URI("http://example.com/challenge/123")));
|
||||
assertThat(challenge.getValidated(), is("2015-12-12T17:19:36.336785823Z"));
|
||||
}
|
||||
|
||||
|
|
|
@ -224,7 +224,7 @@ public class AbstractAcmeClientTest {
|
|||
client.triggerChallenge(testAccount, challenge);
|
||||
|
||||
assertThat(challenge.getStatus(), is(Status.PENDING));
|
||||
assertThat(challenge.getUri(), is(locationUri));
|
||||
assertThat(challenge.getLocation(), is(locationUri));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -253,7 +253,31 @@ public class AbstractAcmeClientTest {
|
|||
client.updateChallenge(testAccount, challenge);
|
||||
|
||||
assertThat(challenge.getStatus(), is(Status.VALID));
|
||||
assertThat(challenge.getUri(), is(locationUri));
|
||||
assertThat(challenge.getLocation(), is(locationUri));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRestoreChallenge() throws AcmeException {
|
||||
Connection connection = new DummyConnection() {
|
||||
@Override
|
||||
public int sendRequest(URI uri) throws AcmeException {
|
||||
assertThat(uri, is(locationUri));
|
||||
return HttpURLConnection.HTTP_ACCEPTED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> readJsonResponse() throws AcmeException {
|
||||
return getJsonAsMap("updateHttpChallengeResponse");
|
||||
}
|
||||
};
|
||||
|
||||
TestableAbstractAcmeClient client = new TestableAbstractAcmeClient(connection);
|
||||
client.putTestChallenge(HttpChallenge.TYPE, new HttpChallenge());
|
||||
|
||||
Challenge challenge = client.restoreChallenge(testAccount, locationUri);
|
||||
|
||||
assertThat(challenge.getStatus(), is(Status.VALID));
|
||||
assertThat(challenge.getLocation(), is(locationUri));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -62,3 +62,23 @@ As soon as the challenge is `VALID`, you have successfully associated the domain
|
|||
If your final certificate contains further domains or subdomains, repeat the authorization run with each of them.
|
||||
|
||||
Note that wildcard certificates are not currently supported.
|
||||
|
||||
## Restore a Challenge
|
||||
|
||||
Validating a challenge can take a considerable amount of time and is a candidate for asynchronous execution. This can be a problem if you need to keep the `Challenge` object for a later time or a different Java environment.
|
||||
|
||||
To recreate a `Challenge` object at a later time, all you need is to store the original object's `location` property:
|
||||
|
||||
```java
|
||||
Challenge originalChallenge = ... // some Challenge instance
|
||||
URI challengeUri = originalChallenge.getLocation();
|
||||
```
|
||||
|
||||
Later, you pass this `challengeUri` to `recreateChallenge()`:
|
||||
|
||||
```java
|
||||
URI challengeUri = ... // challenge URI
|
||||
Challenge restoredChallenge = client.restoreChallenge(account, challengeUri);
|
||||
```
|
||||
|
||||
The `restoredChallenge` already reflects the current state of the challenge.
|
||||
|
|
Loading…
Reference in New Issue