Use GenericTokenChallenge for unknown challenge types with token

pull/17/merge
Richard Körber 2015-12-24 16:30:51 +01:00
parent 9b458fb2b6
commit fefc71b21f
8 changed files with 43 additions and 33 deletions

View File

@ -61,11 +61,11 @@ public abstract class AbstractAcmeClient implements AcmeClient {
/**
* Creates a {@link Challenge} instance for the given challenge type.
*
* @param type
* Challenge type
* @param data
* Challenge JSON data
* @return {@link Challenge} instance
*/
protected abstract Challenge createChallenge(String type);
protected abstract Challenge createChallenge(Map<String, Object> data);
/**
* Connects to the server's API.
@ -322,9 +322,7 @@ public abstract class AbstractAcmeClient implements AcmeClient {
throw new AcmeException("Provided URI is not a challenge URI");
}
T challenge = (T) createChallenge(json.get("type").toString());
challenge.unmarshall(json);
return challenge;
return (T) createChallenge(json);
}
}
@ -425,9 +423,8 @@ public abstract class AbstractAcmeClient implements AcmeClient {
(Collection<Map<String, Object>>) json.get("challenges");
List<Challenge> cr = new ArrayList<>();
for (Map<String, Object> c : challenges) {
Challenge ch = createChallenge((String) c.get("type"));
Challenge ch = createChallenge(c);
if (ch != null) {
ch.unmarshall(c);
cr.add(ch);
}
}

View File

@ -20,6 +20,8 @@ import java.util.Map;
import org.shredzone.acme4j.AcmeClient;
import org.shredzone.acme4j.challenge.Challenge;
import org.shredzone.acme4j.challenge.GenericChallenge;
import org.shredzone.acme4j.challenge.GenericTokenChallenge;
import org.shredzone.acme4j.connector.Connection;
import org.shredzone.acme4j.connector.Resource;
import org.shredzone.acme4j.exception.AcmeException;
@ -55,12 +57,22 @@ public class GenericAcmeClient extends AbstractAcmeClient {
}
@Override
protected Challenge createChallenge(String type) {
protected Challenge createChallenge(Map<String, Object> data) {
String type = (String) data.get("type");
if (type == null || type.isEmpty()) {
throw new IllegalArgumentException("type must not be empty or null");
}
return provider.createChallenge(type);
Challenge challenge = provider.createChallenge(type);
if (challenge == null) {
if (data.containsKey("token")) {
challenge = new GenericTokenChallenge();
} else {
challenge = new GenericChallenge();
}
}
challenge.unmarshall(data);
return challenge;
}
@Override

View File

@ -18,7 +18,6 @@ import java.net.URI;
import org.shredzone.acme4j.AcmeClient;
import org.shredzone.acme4j.challenge.Challenge;
import org.shredzone.acme4j.challenge.DnsChallenge;
import org.shredzone.acme4j.challenge.GenericChallenge;
import org.shredzone.acme4j.challenge.HttpChallenge;
import org.shredzone.acme4j.challenge.ProofOfPossessionChallenge;
import org.shredzone.acme4j.challenge.TlsSniChallenge;
@ -63,18 +62,17 @@ public abstract class AbstractAcmeClientProvider implements AcmeClientProvider {
}
@Override
@SuppressWarnings("unchecked")
public <T extends Challenge> T createChallenge(String type) {
public Challenge createChallenge(String type) {
if (type == null || type.isEmpty()) {
throw new IllegalArgumentException("no type given");
}
switch (type) {
case DnsChallenge.TYPE: return (T) new DnsChallenge();
case TlsSniChallenge.TYPE: return (T) new TlsSniChallenge();
case ProofOfPossessionChallenge.TYPE: return (T) new ProofOfPossessionChallenge();
case HttpChallenge.TYPE: return (T) new HttpChallenge();
default: return (T) new GenericChallenge();
case DnsChallenge.TYPE: return new DnsChallenge();
case TlsSniChallenge.TYPE: return new TlsSniChallenge();
case ProofOfPossessionChallenge.TYPE: return new ProofOfPossessionChallenge();
case HttpChallenge.TYPE: return new HttpChallenge();
default: return null;
}
}

View File

@ -56,12 +56,10 @@ public interface AcmeClientProvider {
*
* @param type
* Challenge type name
* @return Matching {@link Challenge} instance
* @throws ClassCastException
* if the expected {@link Challenge} type does not match the given type
* name.
* @return Matching {@link Challenge} instance, or {@code null} if the type is not
* known
*/
<T extends Challenge> T createChallenge(String type);
Challenge createChallenge(String type);
/**
* Creates a {@link Connection} for communication with the ACME server.

View File

@ -81,7 +81,7 @@ public class AcmeClientFactoryTest {
}
@Override
public <T extends Challenge> T createChallenge(String type) {
public Challenge createChallenge(String type) {
fail("not supposed to be invoked");
return null;
}
@ -107,7 +107,7 @@ public class AcmeClientFactoryTest {
}
@Override
public <T extends Challenge> T createChallenge(String type) {
public Challenge createChallenge(String type) {
fail("not supposed to be invoked");
return null;
}

View File

@ -482,7 +482,7 @@ public class AbstractAcmeClientTest {
/**
* Register a {@link Challenge}. For the sake of simplicity,
* {@link #createChallenge(String)} will always return the same {@link Challenge}
* {@link #createChallenge(Map)} will always return the same {@link Challenge}
* instance in this test suite.
*
* @param s
@ -507,12 +507,16 @@ public class AbstractAcmeClientTest {
}
@Override
protected Challenge createChallenge(String type) {
protected Challenge createChallenge(Map<String, Object> data) {
if (challengeMap.isEmpty()) {
fail("Unexpected invocation of createChallenge()");
}
Challenge challenge = challengeMap.get(type);
return (challenge != null ? challenge : new GenericChallenge());
Challenge challenge = challengeMap.get(data.get("type"));
if (challenge == null) {
challenge = new GenericChallenge();
}
challenge.unmarshall(data);
return challenge;
}
@Override

View File

@ -30,6 +30,7 @@ import org.shredzone.acme4j.connector.Connection;
import org.shredzone.acme4j.connector.Resource;
import org.shredzone.acme4j.exception.AcmeException;
import org.shredzone.acme4j.provider.AcmeClientProvider;
import org.shredzone.acme4j.util.ClaimBuilder;
/**
* Unit tests for {@link GenericAcmeClient}.
@ -56,7 +57,9 @@ public class GenericAcmeClientTest {
when(mockProvider.createChallenge(HttpChallenge.TYPE)).thenReturn(mockChallenge);
GenericAcmeClient client = new GenericAcmeClient(mockProvider, directoryUri);
Challenge challenge = client.createChallenge(HttpChallenge.TYPE);
Challenge challenge = client.createChallenge(new ClaimBuilder()
.put("type", HttpChallenge.TYPE)
.toMap());
assertThat(challenge, is(instanceOf(HttpChallenge.class)));
assertThat(challenge, is(sameInstance((Challenge) mockChallenge)));

View File

@ -23,7 +23,6 @@ import org.junit.Test;
import org.shredzone.acme4j.AcmeClient;
import org.shredzone.acme4j.challenge.Challenge;
import org.shredzone.acme4j.challenge.DnsChallenge;
import org.shredzone.acme4j.challenge.GenericChallenge;
import org.shredzone.acme4j.challenge.HttpChallenge;
import org.shredzone.acme4j.challenge.ProofOfPossessionChallenge;
import org.shredzone.acme4j.challenge.TlsSniChallenge;
@ -110,8 +109,7 @@ public class AbstractAcmeClientProviderTest {
assertThat(c5, instanceOf(TlsSniChallenge.class));
Challenge c6 = provider.createChallenge("foobar-01");
assertThat(c6, not(nullValue()));
assertThat(c6, instanceOf(GenericChallenge.class));
assertThat(c6, is(nullValue()));
try {
provider.createChallenge(null);