mirror of https://github.com/shred/acme4j
Challenge constructor requires JSON data
parent
252d886b3f
commit
8923e35d21
|
@ -176,17 +176,14 @@ public class Session {
|
||||||
public Challenge createChallenge(JSON data) {
|
public Challenge createChallenge(JSON data) {
|
||||||
Objects.requireNonNull(data, "data");
|
Objects.requireNonNull(data, "data");
|
||||||
|
|
||||||
String type = data.get("type").required().asString();
|
Challenge challenge = provider().createChallenge(this, data);
|
||||||
|
|
||||||
Challenge challenge = provider().createChallenge(this, type);
|
|
||||||
if (challenge == null) {
|
if (challenge == null) {
|
||||||
if (data.contains("token")) {
|
if (data.contains("token")) {
|
||||||
challenge = new TokenChallenge(this);
|
challenge = new TokenChallenge(this, data);
|
||||||
} else {
|
} else {
|
||||||
challenge = new Challenge(this);
|
challenge = new Challenge(this, data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
challenge.setJSON(data);
|
|
||||||
return challenge;
|
return challenge;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -58,9 +58,11 @@ public class Challenge extends AcmeJsonResource {
|
||||||
*
|
*
|
||||||
* @param session
|
* @param session
|
||||||
* {@link Session} to bind to.
|
* {@link Session} to bind to.
|
||||||
|
* @param data
|
||||||
|
* {@link JSON} challenge data
|
||||||
*/
|
*/
|
||||||
public Challenge(Session session) {
|
public Challenge(Session session, JSON data) {
|
||||||
super(session);
|
super(session, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -159,16 +161,14 @@ public class Challenge extends AcmeJsonResource {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setJSON(JSON json) {
|
protected void setJSON(JSON json) {
|
||||||
String type = json.get(KEY_TYPE).asString();
|
String type = json.get(KEY_TYPE).required().asString();
|
||||||
if (type == null) {
|
|
||||||
throw new IllegalArgumentException("map does not contain a type");
|
|
||||||
}
|
|
||||||
if (!acceptable(type)) {
|
if (!acceptable(type)) {
|
||||||
throw new AcmeProtocolException("wrong type: " + type);
|
throw new AcmeProtocolException("incompatible type " + type + " for this challenge");
|
||||||
}
|
}
|
||||||
|
|
||||||
setLocation(json.get(KEY_URL).asURL());
|
setLocation(json.get(KEY_URL).required().asURL());
|
||||||
|
|
||||||
super.setJSON(json);
|
super.setJSON(json);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ package org.shredzone.acme4j.challenge;
|
||||||
import static org.shredzone.acme4j.toolbox.AcmeUtils.*;
|
import static org.shredzone.acme4j.toolbox.AcmeUtils.*;
|
||||||
|
|
||||||
import org.shredzone.acme4j.Session;
|
import org.shredzone.acme4j.Session;
|
||||||
|
import org.shredzone.acme4j.toolbox.JSON;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implements the {@value TYPE} challenge.
|
* Implements the {@value TYPE} challenge.
|
||||||
|
@ -33,9 +34,11 @@ public class Dns01Challenge extends TokenChallenge {
|
||||||
*
|
*
|
||||||
* @param session
|
* @param session
|
||||||
* {@link Session} to bind to.
|
* {@link Session} to bind to.
|
||||||
|
* @param data
|
||||||
|
* {@link JSON} challenge data
|
||||||
*/
|
*/
|
||||||
public Dns01Challenge(Session session) {
|
public Dns01Challenge(Session session, JSON data) {
|
||||||
super(session);
|
super(session, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
package org.shredzone.acme4j.challenge;
|
package org.shredzone.acme4j.challenge;
|
||||||
|
|
||||||
import org.shredzone.acme4j.Session;
|
import org.shredzone.acme4j.Session;
|
||||||
|
import org.shredzone.acme4j.toolbox.JSON;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implements the {@value TYPE} challenge.
|
* Implements the {@value TYPE} challenge.
|
||||||
|
@ -31,9 +32,11 @@ public class Http01Challenge extends TokenChallenge {
|
||||||
*
|
*
|
||||||
* @param session
|
* @param session
|
||||||
* {@link Session} to bind to.
|
* {@link Session} to bind to.
|
||||||
|
* @param data
|
||||||
|
* {@link JSON} challenge data
|
||||||
*/
|
*/
|
||||||
public Http01Challenge(Session session) {
|
public Http01Challenge(Session session, JSON data) {
|
||||||
super(session);
|
super(session, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -16,6 +16,7 @@ package org.shredzone.acme4j.challenge;
|
||||||
import static org.shredzone.acme4j.toolbox.AcmeUtils.*;
|
import static org.shredzone.acme4j.toolbox.AcmeUtils.*;
|
||||||
|
|
||||||
import org.shredzone.acme4j.Session;
|
import org.shredzone.acme4j.Session;
|
||||||
|
import org.shredzone.acme4j.toolbox.JSON;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implements the {@value TYPE} challenge.
|
* Implements the {@value TYPE} challenge.
|
||||||
|
@ -33,9 +34,11 @@ public class TlsSni02Challenge extends TokenChallenge {
|
||||||
*
|
*
|
||||||
* @param session
|
* @param session
|
||||||
* {@link Session} to bind to.
|
* {@link Session} to bind to.
|
||||||
|
* @param data
|
||||||
|
* {@link JSON} challenge data
|
||||||
*/
|
*/
|
||||||
public TlsSni02Challenge(Session session) {
|
public TlsSni02Challenge(Session session, JSON data) {
|
||||||
super(session);
|
super(session, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -21,6 +21,7 @@ import org.jose4j.jwk.PublicJsonWebKey;
|
||||||
import org.jose4j.lang.JoseException;
|
import org.jose4j.lang.JoseException;
|
||||||
import org.shredzone.acme4j.Session;
|
import org.shredzone.acme4j.Session;
|
||||||
import org.shredzone.acme4j.exception.AcmeProtocolException;
|
import org.shredzone.acme4j.exception.AcmeProtocolException;
|
||||||
|
import org.shredzone.acme4j.toolbox.JSON;
|
||||||
import org.shredzone.acme4j.toolbox.JSONBuilder;
|
import org.shredzone.acme4j.toolbox.JSONBuilder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -38,9 +39,11 @@ public class TokenChallenge extends Challenge {
|
||||||
*
|
*
|
||||||
* @param session
|
* @param session
|
||||||
* {@link Session} to bind to.
|
* {@link Session} to bind to.
|
||||||
|
* @param data
|
||||||
|
* {@link JSON} challenge data
|
||||||
*/
|
*/
|
||||||
public TokenChallenge(Session session) {
|
public TokenChallenge(Session session, JSON data) {
|
||||||
super(session);
|
super(session, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -18,7 +18,7 @@ import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.function.Function;
|
import java.util.function.BiFunction;
|
||||||
|
|
||||||
import org.shredzone.acme4j.Session;
|
import org.shredzone.acme4j.Session;
|
||||||
import org.shredzone.acme4j.challenge.Challenge;
|
import org.shredzone.acme4j.challenge.Challenge;
|
||||||
|
@ -40,7 +40,7 @@ import org.shredzone.acme4j.toolbox.JSON;
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractAcmeProvider implements AcmeProvider {
|
public abstract class AbstractAcmeProvider implements AcmeProvider {
|
||||||
|
|
||||||
private static final Map<String, Function<Session, Challenge>> CHALLENGES = challengeMap();
|
private static final Map<String, BiFunction<Session, JSON, Challenge>> CHALLENGES = challengeMap();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Connection connect() {
|
public Connection connect() {
|
||||||
|
@ -59,8 +59,8 @@ public abstract class AbstractAcmeProvider implements AcmeProvider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Map<String, Function<Session, Challenge>> challengeMap() {
|
private static Map<String, BiFunction<Session, JSON, Challenge>> challengeMap() {
|
||||||
Map<String, Function<Session, Challenge>> map = new HashMap<>();
|
Map<String, BiFunction<Session, JSON, Challenge>> map = new HashMap<>();
|
||||||
|
|
||||||
map.put(Dns01Challenge.TYPE, Dns01Challenge::new);
|
map.put(Dns01Challenge.TYPE, Dns01Challenge::new);
|
||||||
map.put(TlsSni02Challenge.TYPE, TlsSni02Challenge::new);
|
map.put(TlsSni02Challenge.TYPE, TlsSni02Challenge::new);
|
||||||
|
@ -69,17 +69,25 @@ public abstract class AbstractAcmeProvider implements AcmeProvider {
|
||||||
return Collections.unmodifiableMap(map);
|
return Collections.unmodifiableMap(map);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
* <p>
|
||||||
|
* Custom provider implementations may override this method to provide challenges that
|
||||||
|
* are unique to the provider.
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Challenge createChallenge(Session session, String type) {
|
public Challenge createChallenge(Session session, JSON data) {
|
||||||
Objects.requireNonNull(session, "session");
|
Objects.requireNonNull(session, "session");
|
||||||
Objects.requireNonNull(type, "type");
|
Objects.requireNonNull(data, "data");
|
||||||
|
|
||||||
Function<Session, Challenge> constructor = CHALLENGES.get(type);
|
String type = data.get("type").required().asString();
|
||||||
|
|
||||||
|
BiFunction<Session, JSON, Challenge> constructor = CHALLENGES.get(type);
|
||||||
if (constructor == null) {
|
if (constructor == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return constructor.apply(session);
|
return constructor.apply(session, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -75,17 +75,15 @@ public interface AcmeProvider {
|
||||||
JSON directory(Session session, URI serverUri) throws AcmeException;
|
JSON directory(Session session, URI serverUri) throws AcmeException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a {@link Challenge} instance for the given challenge type.
|
* Creates a {@link Challenge} instance for the given challenge data.
|
||||||
* <p>
|
|
||||||
* Custom provider implementations may override this method to provide challenges that
|
|
||||||
* are unique to the provider.
|
|
||||||
*
|
*
|
||||||
* @param session
|
* @param session
|
||||||
* {@link Session} to bind the challenge to
|
* {@link Session} to bind the challenge to
|
||||||
* @param type
|
* @param data
|
||||||
* Challenge type
|
* Challenge {@link JSON} data
|
||||||
* @return {@link Challenge} instance
|
* @return {@link Challenge} instance, or {@code null} if this provider is unable to
|
||||||
|
* generate a matching {@link Challenge} instance.
|
||||||
*/
|
*/
|
||||||
Challenge createChallenge(Session session, String type);
|
Challenge createChallenge(Session session, JSON data);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,6 @@ import org.jose4j.jwx.CompactSerializer;
|
||||||
import org.jose4j.lang.JoseException;
|
import org.jose4j.lang.JoseException;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.shredzone.acme4j.Account.EditableAccount;
|
import org.shredzone.acme4j.Account.EditableAccount;
|
||||||
import org.shredzone.acme4j.challenge.Challenge;
|
|
||||||
import org.shredzone.acme4j.challenge.Dns01Challenge;
|
import org.shredzone.acme4j.challenge.Dns01Challenge;
|
||||||
import org.shredzone.acme4j.challenge.Http01Challenge;
|
import org.shredzone.acme4j.challenge.Http01Challenge;
|
||||||
import org.shredzone.acme4j.connector.Resource;
|
import org.shredzone.acme4j.connector.Resource;
|
||||||
|
@ -196,12 +195,9 @@ public class AccountTest {
|
||||||
|
|
||||||
Session session = provider.createSession();
|
Session session = provider.createSession();
|
||||||
|
|
||||||
Http01Challenge httpChallenge = new Http01Challenge(session);
|
|
||||||
Dns01Challenge dnsChallenge = new Dns01Challenge(session);
|
|
||||||
|
|
||||||
provider.putTestResource(Resource.NEW_AUTHZ, resourceUrl);
|
provider.putTestResource(Resource.NEW_AUTHZ, resourceUrl);
|
||||||
provider.putTestChallenge(Http01Challenge.TYPE, httpChallenge);
|
provider.putTestChallenge(Http01Challenge.TYPE, Http01Challenge::new);
|
||||||
provider.putTestChallenge(Dns01Challenge.TYPE, dnsChallenge);
|
provider.putTestChallenge(Dns01Challenge.TYPE, Dns01Challenge::new);
|
||||||
|
|
||||||
String domainName = "example.org";
|
String domainName = "example.org";
|
||||||
|
|
||||||
|
@ -214,7 +210,8 @@ public class AccountTest {
|
||||||
assertThat(auth.getLocation(), is(locationUrl));
|
assertThat(auth.getLocation(), is(locationUrl));
|
||||||
|
|
||||||
assertThat(auth.getChallenges(), containsInAnyOrder(
|
assertThat(auth.getChallenges(), containsInAnyOrder(
|
||||||
(Challenge) httpChallenge, (Challenge) dnsChallenge));
|
provider.getChallenge(Http01Challenge.TYPE),
|
||||||
|
provider.getChallenge(Dns01Challenge.TYPE)));
|
||||||
|
|
||||||
provider.close();
|
provider.close();
|
||||||
}
|
}
|
||||||
|
|
|
@ -108,10 +108,8 @@ public class AuthorizationTest {
|
||||||
|
|
||||||
Session session = provider.createSession();
|
Session session = provider.createSession();
|
||||||
|
|
||||||
Http01Challenge httpChallenge = new Http01Challenge(session);
|
provider.putTestChallenge("http-01", Http01Challenge::new);
|
||||||
Dns01Challenge dnsChallenge = new Dns01Challenge(session);
|
provider.putTestChallenge("dns-01", Dns01Challenge::new);
|
||||||
provider.putTestChallenge("http-01", httpChallenge);
|
|
||||||
provider.putTestChallenge("dns-01", dnsChallenge);
|
|
||||||
|
|
||||||
Authorization auth = new Authorization(session, locationUrl);
|
Authorization auth = new Authorization(session, locationUrl);
|
||||||
auth.update();
|
auth.update();
|
||||||
|
@ -122,7 +120,8 @@ public class AuthorizationTest {
|
||||||
assertThat(auth.getLocation(), is(locationUrl));
|
assertThat(auth.getLocation(), is(locationUrl));
|
||||||
|
|
||||||
assertThat(auth.getChallenges(), containsInAnyOrder(
|
assertThat(auth.getChallenges(), containsInAnyOrder(
|
||||||
(Challenge) httpChallenge, (Challenge) dnsChallenge));
|
provider.getChallenge(Http01Challenge.TYPE),
|
||||||
|
provider.getChallenge(Dns01Challenge.TYPE)));
|
||||||
|
|
||||||
provider.close();
|
provider.close();
|
||||||
}
|
}
|
||||||
|
@ -154,8 +153,8 @@ public class AuthorizationTest {
|
||||||
|
|
||||||
Session session = provider.createSession();
|
Session session = provider.createSession();
|
||||||
|
|
||||||
provider.putTestChallenge("http-01", new Http01Challenge(session));
|
provider.putTestChallenge("http-01", Http01Challenge::new);
|
||||||
provider.putTestChallenge("dns-01", new Dns01Challenge(session));
|
provider.putTestChallenge("dns-01", Dns01Challenge::new);
|
||||||
|
|
||||||
Authorization auth = new Authorization(session, locationUrl);
|
Authorization auth = new Authorization(session, locationUrl);
|
||||||
|
|
||||||
|
@ -200,10 +199,8 @@ public class AuthorizationTest {
|
||||||
|
|
||||||
Session session = provider.createSession();
|
Session session = provider.createSession();
|
||||||
|
|
||||||
Http01Challenge httpChallenge = new Http01Challenge(session);
|
provider.putTestChallenge("http-01", Http01Challenge::new);
|
||||||
Dns01Challenge dnsChallenge = new Dns01Challenge(session);
|
provider.putTestChallenge("dns-01", Dns01Challenge::new);
|
||||||
provider.putTestChallenge("http-01", httpChallenge);
|
|
||||||
provider.putTestChallenge("dns-01", dnsChallenge);
|
|
||||||
|
|
||||||
Authorization auth = new Authorization(session, locationUrl);
|
Authorization auth = new Authorization(session, locationUrl);
|
||||||
|
|
||||||
|
@ -220,7 +217,8 @@ public class AuthorizationTest {
|
||||||
assertThat(auth.getLocation(), is(locationUrl));
|
assertThat(auth.getLocation(), is(locationUrl));
|
||||||
|
|
||||||
assertThat(auth.getChallenges(), containsInAnyOrder(
|
assertThat(auth.getChallenges(), containsInAnyOrder(
|
||||||
(Challenge) httpChallenge, (Challenge) dnsChallenge));
|
provider.getChallenge(Http01Challenge.TYPE),
|
||||||
|
provider.getChallenge(Dns01Challenge.TYPE)));
|
||||||
|
|
||||||
provider.close();
|
provider.close();
|
||||||
}
|
}
|
||||||
|
@ -249,10 +247,8 @@ public class AuthorizationTest {
|
||||||
|
|
||||||
Session session = provider.createSession();
|
Session session = provider.createSession();
|
||||||
|
|
||||||
Http01Challenge httpChallenge = new Http01Challenge(session);
|
provider.putTestChallenge("http-01", Http01Challenge::new);
|
||||||
Dns01Challenge dnsChallenge = new Dns01Challenge(session);
|
provider.putTestChallenge("dns-01", Dns01Challenge::new);
|
||||||
provider.putTestChallenge("http-01", httpChallenge);
|
|
||||||
provider.putTestChallenge("dns-01", dnsChallenge);
|
|
||||||
|
|
||||||
Authorization auth = new Authorization(session, locationUrl);
|
Authorization auth = new Authorization(session, locationUrl);
|
||||||
auth.deactivate();
|
auth.deactivate();
|
||||||
|
@ -267,10 +263,10 @@ public class AuthorizationTest {
|
||||||
try (TestableConnectionProvider provider = new TestableConnectionProvider()) {
|
try (TestableConnectionProvider provider = new TestableConnectionProvider()) {
|
||||||
Session session = provider.createSession();
|
Session session = provider.createSession();
|
||||||
|
|
||||||
provider.putTestChallenge(Http01Challenge.TYPE, new Http01Challenge(session));
|
provider.putTestChallenge(Http01Challenge.TYPE, Http01Challenge::new);
|
||||||
provider.putTestChallenge(Dns01Challenge.TYPE, new Dns01Challenge(session));
|
provider.putTestChallenge(Dns01Challenge.TYPE, Dns01Challenge::new);
|
||||||
provider.putTestChallenge(TlsSni02Challenge.TYPE, new TlsSni02Challenge(session));
|
provider.putTestChallenge(TlsSni02Challenge.TYPE, TlsSni02Challenge::new);
|
||||||
provider.putTestChallenge(DUPLICATE_TYPE, new Challenge(session));
|
provider.putTestChallenge(DUPLICATE_TYPE, Challenge::new);
|
||||||
|
|
||||||
Authorization authorization = new Authorization(session, locationUrl);
|
Authorization authorization = new Authorization(session, locationUrl);
|
||||||
authorization.setJSON(getJSON("authorizationChallenges"));
|
authorization.setJSON(getJSON("authorizationChallenges"));
|
||||||
|
|
|
@ -125,9 +125,11 @@ public class SessionTest {
|
||||||
KeyPair keyPair = TestUtils.createKeyPair();
|
KeyPair keyPair = TestUtils.createKeyPair();
|
||||||
URI serverUri = URI.create(TestUtils.ACME_SERVER_URI);
|
URI serverUri = URI.create(TestUtils.ACME_SERVER_URI);
|
||||||
String challengeType = Http01Challenge.TYPE;
|
String challengeType = Http01Challenge.TYPE;
|
||||||
|
URL challengeUrl = new URL("https://example.com/acme/authz/0");
|
||||||
|
|
||||||
JSON data = new JSONBuilder()
|
JSON data = new JSONBuilder()
|
||||||
.put("type", challengeType)
|
.put("type", challengeType)
|
||||||
|
.put("url", challengeUrl)
|
||||||
.toJSON();
|
.toJSON();
|
||||||
|
|
||||||
Http01Challenge mockChallenge = mock(Http01Challenge.class);
|
Http01Challenge mockChallenge = mock(Http01Challenge.class);
|
||||||
|
@ -135,7 +137,7 @@ public class SessionTest {
|
||||||
|
|
||||||
when(mockProvider.createChallenge(
|
when(mockProvider.createChallenge(
|
||||||
ArgumentMatchers.any(Session.class),
|
ArgumentMatchers.any(Session.class),
|
||||||
ArgumentMatchers.eq(challengeType)))
|
ArgumentMatchers.eq(data)))
|
||||||
.thenReturn(mockChallenge);
|
.thenReturn(mockChallenge);
|
||||||
|
|
||||||
Session session = new Session(serverUri, keyPair) {
|
Session session = new Session(serverUri, keyPair) {
|
||||||
|
@ -149,7 +151,7 @@ public class SessionTest {
|
||||||
assertThat(challenge, is(instanceOf(Http01Challenge.class)));
|
assertThat(challenge, is(instanceOf(Http01Challenge.class)));
|
||||||
assertThat(challenge, is(sameInstance((Challenge) mockChallenge)));
|
assertThat(challenge, is(sameInstance((Challenge) mockChallenge)));
|
||||||
|
|
||||||
verify(mockProvider).createChallenge(session, challengeType);
|
verify(mockProvider).createChallenge(session, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -47,7 +47,6 @@ import org.shredzone.acme4j.toolbox.TestUtils;
|
||||||
*/
|
*/
|
||||||
public class ChallengeTest {
|
public class ChallengeTest {
|
||||||
private Session session;
|
private Session session;
|
||||||
private URL resourceUrl = url("https://example.com/acme/some-resource");
|
|
||||||
private URL locationUrl = url("https://example.com/acme/some-location");
|
private URL locationUrl = url("https://example.com/acme/some-location");
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
|
@ -74,7 +73,7 @@ public class ChallengeTest {
|
||||||
|
|
||||||
Session session = provider.createSession();
|
Session session = provider.createSession();
|
||||||
|
|
||||||
provider.putTestChallenge(Http01Challenge.TYPE, new Http01Challenge(session));
|
provider.putTestChallenge(Http01Challenge.TYPE, Http01Challenge::new);
|
||||||
|
|
||||||
Http01Challenge challenge = Challenge.bind(session, locationUrl);
|
Http01Challenge challenge = Challenge.bind(session, locationUrl);
|
||||||
|
|
||||||
|
@ -91,8 +90,7 @@ public class ChallengeTest {
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testUnmarshal() throws URISyntaxException {
|
public void testUnmarshal() throws URISyntaxException {
|
||||||
Challenge challenge = new Challenge(session);
|
Challenge challenge = new Challenge(session, getJSON("genericChallenge"));
|
||||||
challenge.setJSON(getJSON("genericChallenge"));
|
|
||||||
|
|
||||||
// Test unmarshalled values
|
// Test unmarshalled values
|
||||||
assertThat(challenge.getType(), is("generic-01"));
|
assertThat(challenge.getType(), is("generic-01"));
|
||||||
|
@ -126,8 +124,7 @@ public class ChallengeTest {
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testRespond() throws JoseException {
|
public void testRespond() throws JoseException {
|
||||||
Challenge challenge = new Challenge(session);
|
Challenge challenge = new Challenge(session, getJSON("genericChallenge"));
|
||||||
challenge.setJSON(getJSON("genericChallenge"));
|
|
||||||
|
|
||||||
JSONBuilder cb = new JSONBuilder();
|
JSONBuilder cb = new JSONBuilder();
|
||||||
challenge.respond(cb);
|
challenge.respond(cb);
|
||||||
|
@ -140,8 +137,7 @@ public class ChallengeTest {
|
||||||
*/
|
*/
|
||||||
@Test(expected = AcmeProtocolException.class)
|
@Test(expected = AcmeProtocolException.class)
|
||||||
public void testNotAcceptable() throws URISyntaxException {
|
public void testNotAcceptable() throws URISyntaxException {
|
||||||
Http01Challenge challenge = new Http01Challenge(session);
|
new Http01Challenge(session, getJSON("dnsChallenge"));
|
||||||
challenge.setJSON(getJSON("dnsChallenge"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -152,7 +148,7 @@ public class ChallengeTest {
|
||||||
TestableConnectionProvider provider = new TestableConnectionProvider() {
|
TestableConnectionProvider provider = new TestableConnectionProvider() {
|
||||||
@Override
|
@Override
|
||||||
public int sendSignedRequest(URL url, JSONBuilder claims, Session session, int... httpStatus) {
|
public int sendSignedRequest(URL url, JSONBuilder claims, Session session, int... httpStatus) {
|
||||||
assertThat(url, is(resourceUrl));
|
assertThat(url, is(locationUrl));
|
||||||
assertThat(claims.toString(), sameJSONAs(getJSON("triggerHttpChallengeRequest").toString()));
|
assertThat(claims.toString(), sameJSONAs(getJSON("triggerHttpChallengeRequest").toString()));
|
||||||
assertThat(session, is(notNullValue()));
|
assertThat(session, is(notNullValue()));
|
||||||
assertThat(httpStatus, isIntArrayContainingInAnyOrder());
|
assertThat(httpStatus, isIntArrayContainingInAnyOrder());
|
||||||
|
@ -167,8 +163,7 @@ public class ChallengeTest {
|
||||||
|
|
||||||
Session session = provider.createSession();
|
Session session = provider.createSession();
|
||||||
|
|
||||||
Http01Challenge challenge = new Http01Challenge(session);
|
Http01Challenge challenge = new Http01Challenge(session, getJSON("triggerHttpChallenge"));
|
||||||
challenge.setJSON(getJSON("triggerHttpChallenge"));
|
|
||||||
|
|
||||||
challenge.trigger();
|
challenge.trigger();
|
||||||
|
|
||||||
|
@ -202,8 +197,7 @@ public class ChallengeTest {
|
||||||
|
|
||||||
Session session = provider.createSession();
|
Session session = provider.createSession();
|
||||||
|
|
||||||
Challenge challenge = new Http01Challenge(session);
|
Challenge challenge = new Http01Challenge(session, getJSON("triggerHttpChallengeResponse"));
|
||||||
challenge.setJSON(getJSON("triggerHttpChallengeResponse"));
|
|
||||||
|
|
||||||
challenge.update();
|
challenge.update();
|
||||||
|
|
||||||
|
@ -240,8 +234,7 @@ public class ChallengeTest {
|
||||||
|
|
||||||
Session session = provider.createSession();
|
Session session = provider.createSession();
|
||||||
|
|
||||||
Challenge challenge = new Http01Challenge(session);
|
Challenge challenge = new Http01Challenge(session, getJSON("triggerHttpChallengeResponse"));
|
||||||
challenge.setJSON(getJSON("triggerHttpChallengeResponse"));
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
challenge.update();
|
challenge.update();
|
||||||
|
@ -302,10 +295,9 @@ public class ChallengeTest {
|
||||||
/**
|
/**
|
||||||
* Test that unmarshalling something different like a challenge fails.
|
* Test that unmarshalling something different like a challenge fails.
|
||||||
*/
|
*/
|
||||||
@Test(expected = IllegalArgumentException.class)
|
@Test(expected = AcmeProtocolException.class)
|
||||||
public void testBadUnmarshall() {
|
public void testBadUnmarshall() {
|
||||||
Challenge challenge = new Challenge(session);
|
new Challenge(session, getJSON("updateAccountResponse"));
|
||||||
challenge.setJSON(getJSON("updateAccountResponse"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,8 +46,7 @@ public class DnsChallengeTest {
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testDnsChallenge() throws IOException {
|
public void testDnsChallenge() throws IOException {
|
||||||
Dns01Challenge challenge = new Dns01Challenge(session);
|
Dns01Challenge challenge = new Dns01Challenge(session, getJSON("dnsChallenge"));
|
||||||
challenge.setJSON(getJSON("dnsChallenge"));
|
|
||||||
|
|
||||||
assertThat(challenge.getType(), is(Dns01Challenge.TYPE));
|
assertThat(challenge.getType(), is(Dns01Challenge.TYPE));
|
||||||
assertThat(challenge.getStatus(), is(Status.PENDING));
|
assertThat(challenge.getStatus(), is(Status.PENDING));
|
||||||
|
|
|
@ -49,8 +49,7 @@ public class HttpChallengeTest {
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testHttpChallenge() throws IOException {
|
public void testHttpChallenge() throws IOException {
|
||||||
Http01Challenge challenge = new Http01Challenge(session);
|
Http01Challenge challenge = new Http01Challenge(session, getJSON("httpChallenge"));
|
||||||
challenge.setJSON(getJSON("httpChallenge"));
|
|
||||||
|
|
||||||
assertThat(challenge.getType(), is(Http01Challenge.TYPE));
|
assertThat(challenge.getType(), is(Http01Challenge.TYPE));
|
||||||
assertThat(challenge.getStatus(), is(Status.PENDING));
|
assertThat(challenge.getStatus(), is(Status.PENDING));
|
||||||
|
@ -69,8 +68,7 @@ public class HttpChallengeTest {
|
||||||
*/
|
*/
|
||||||
@Test(expected = AcmeProtocolException.class)
|
@Test(expected = AcmeProtocolException.class)
|
||||||
public void testNoTokenSet() {
|
public void testNoTokenSet() {
|
||||||
Http01Challenge challenge = new Http01Challenge(session);
|
Http01Challenge challenge = new Http01Challenge(session, getJSON("httpNoTokenChallenge"));
|
||||||
challenge.setJSON(getJSON("httpNoTokenChallenge"));
|
|
||||||
challenge.getToken();
|
challenge.getToken();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,8 +46,7 @@ public class TlsSni02ChallengeTest {
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testTlsSni02Challenge() throws IOException {
|
public void testTlsSni02Challenge() throws IOException {
|
||||||
TlsSni02Challenge challenge = new TlsSni02Challenge(session);
|
TlsSni02Challenge challenge = new TlsSni02Challenge(session, getJSON("tlsSni02Challenge"));
|
||||||
challenge.setJSON(getJSON("tlsSni02Challenge"));
|
|
||||||
|
|
||||||
assertThat(challenge.getType(), is(TlsSni02Challenge.TYPE));
|
assertThat(challenge.getType(), is(TlsSni02Challenge.TYPE));
|
||||||
assertThat(challenge.getStatus(), is(Status.PENDING));
|
assertThat(challenge.getStatus(), is(Status.PENDING));
|
||||||
|
|
|
@ -103,7 +103,7 @@ public class SessionProviderTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Challenge createChallenge(Session session, String type) {
|
public Challenge createChallenge(Session session, JSON data) {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -131,7 +131,7 @@ public class SessionProviderTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Challenge createChallenge(Session session, String type) {
|
public Challenge createChallenge(Session session, JSON data) {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,9 @@ import org.shredzone.acme4j.connector.Connection;
|
||||||
import org.shredzone.acme4j.connector.DefaultConnection;
|
import org.shredzone.acme4j.connector.DefaultConnection;
|
||||||
import org.shredzone.acme4j.connector.HttpConnector;
|
import org.shredzone.acme4j.connector.HttpConnector;
|
||||||
import org.shredzone.acme4j.exception.AcmeException;
|
import org.shredzone.acme4j.exception.AcmeException;
|
||||||
|
import org.shredzone.acme4j.exception.AcmeProtocolException;
|
||||||
import org.shredzone.acme4j.toolbox.JSON;
|
import org.shredzone.acme4j.toolbox.JSON;
|
||||||
|
import org.shredzone.acme4j.toolbox.JSONBuilder;
|
||||||
import org.shredzone.acme4j.toolbox.TestUtils;
|
import org.shredzone.acme4j.toolbox.TestUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -133,29 +135,40 @@ public class AbstractAcmeProviderTest {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Challenge c1 = provider.createChallenge(session, Http01Challenge.TYPE);
|
Challenge c1 = provider.createChallenge(session, getJSON("httpChallenge"));
|
||||||
assertThat(c1, not(nullValue()));
|
assertThat(c1, not(nullValue()));
|
||||||
assertThat(c1, instanceOf(Http01Challenge.class));
|
assertThat(c1, instanceOf(Http01Challenge.class));
|
||||||
|
|
||||||
Challenge c2 = provider.createChallenge(session, Http01Challenge.TYPE);
|
Challenge c2 = provider.createChallenge(session, getJSON("httpChallenge"));
|
||||||
assertThat(c2, not(sameInstance(c1)));
|
assertThat(c2, not(sameInstance(c1)));
|
||||||
|
|
||||||
Challenge c3 = provider.createChallenge(session, Dns01Challenge.TYPE);
|
Challenge c3 = provider.createChallenge(session, getJSON("dnsChallenge"));
|
||||||
assertThat(c3, not(nullValue()));
|
assertThat(c3, not(nullValue()));
|
||||||
assertThat(c3, instanceOf(Dns01Challenge.class));
|
assertThat(c3, instanceOf(Dns01Challenge.class));
|
||||||
|
|
||||||
Challenge c5 = provider.createChallenge(session, TlsSni02Challenge.TYPE);
|
Challenge c5 = provider.createChallenge(session, getJSON("tlsSni02Challenge"));
|
||||||
assertThat(c5, not(nullValue()));
|
assertThat(c5, not(nullValue()));
|
||||||
assertThat(c5, instanceOf(TlsSni02Challenge.class));
|
assertThat(c5, instanceOf(TlsSni02Challenge.class));
|
||||||
|
|
||||||
Challenge c6 = provider.createChallenge(session, "foobar-01");
|
JSON json6 = new JSONBuilder()
|
||||||
|
.put("type", "foobar-01")
|
||||||
|
.put("url", "https://example.com/some/challenge")
|
||||||
|
.toJSON();
|
||||||
|
Challenge c6 = provider.createChallenge(session, json6);
|
||||||
assertThat(c6, is(nullValue()));
|
assertThat(c6, is(nullValue()));
|
||||||
|
|
||||||
Challenge c7 = provider.createChallenge(session, "");
|
try {
|
||||||
assertThat(c7, is(nullValue()));
|
JSON json7 = new JSONBuilder()
|
||||||
|
.put("url", "https://example.com/some/challenge")
|
||||||
|
.toJSON();
|
||||||
|
provider.createChallenge(session, json7);
|
||||||
|
fail("Challenge without type was accepted");
|
||||||
|
} catch (AcmeProtocolException ex) {
|
||||||
|
// expected
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
provider.createChallenge(session, (String) null);
|
provider.createChallenge(session, null);
|
||||||
fail("null was accepted");
|
fail("null was accepted");
|
||||||
} catch (NullPointerException ex) {
|
} catch (NullPointerException ex) {
|
||||||
// expected
|
// expected
|
||||||
|
|
|
@ -18,6 +18,7 @@ import java.net.URI;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.function.BiFunction;
|
||||||
|
|
||||||
import org.shredzone.acme4j.Session;
|
import org.shredzone.acme4j.Session;
|
||||||
import org.shredzone.acme4j.challenge.Challenge;
|
import org.shredzone.acme4j.challenge.Challenge;
|
||||||
|
@ -34,7 +35,8 @@ import org.shredzone.acme4j.toolbox.TestUtils;
|
||||||
* of {@link Connection} that is always returned on {@link #connect()}.
|
* of {@link Connection} that is always returned on {@link #connect()}.
|
||||||
*/
|
*/
|
||||||
public class TestableConnectionProvider extends DummyConnection implements AcmeProvider {
|
public class TestableConnectionProvider extends DummyConnection implements AcmeProvider {
|
||||||
private final Map<String, Challenge> challengeMap = new HashMap<>();
|
private final Map<String, BiFunction<Session, JSON, Challenge>> creatorMap = new HashMap<>();
|
||||||
|
private final Map<String, Challenge> createdMap = new HashMap<>();
|
||||||
private final JSONBuilder directory = new JSONBuilder();
|
private final JSONBuilder directory = new JSONBuilder();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -50,17 +52,29 @@ public class TestableConnectionProvider extends DummyConnection implements AcmeP
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register a {@link Challenge}. For the sake of simplicity,
|
* Register a {@link Challenge}.
|
||||||
* {@link #createChallenge(Session, String)} will always return the same
|
|
||||||
* {@link Challenge} instance in this test suite.
|
|
||||||
*
|
*
|
||||||
* @param s
|
* @param type
|
||||||
* Challenge type
|
* Challenge type to register.
|
||||||
* @param c
|
* @param creator
|
||||||
* {@link Challenge} instance.
|
* Creator {@link BiFunction} that creates a matching {@link Challenge}
|
||||||
*/
|
*/
|
||||||
public void putTestChallenge(String s, Challenge c) {
|
public void putTestChallenge(String type, BiFunction<Session, JSON, Challenge> creator) {
|
||||||
challengeMap.put(s, c);
|
creatorMap.put(type, creator);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the {@link Challenge} instance that has been created. Fails if no such
|
||||||
|
* challenge was created.
|
||||||
|
*
|
||||||
|
* @param type Challenge type
|
||||||
|
* @return Created {@link Challenge} instance
|
||||||
|
*/
|
||||||
|
public Challenge getChallenge(String type) {
|
||||||
|
if (!createdMap.containsKey(type)) {
|
||||||
|
throw new IllegalArgumentException("No challenge of type " + type + " was created");
|
||||||
|
}
|
||||||
|
return createdMap.get(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -94,16 +108,23 @@ public class TestableConnectionProvider extends DummyConnection implements AcmeP
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Challenge createChallenge(Session session, String type) {
|
public Challenge createChallenge(Session session, JSON data) {
|
||||||
if (challengeMap.isEmpty()) {
|
if (creatorMap.isEmpty()) {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (challengeMap.containsKey(type)) {
|
Challenge created;
|
||||||
return challengeMap.get(type);
|
|
||||||
|
String type = data.get("type").asString();
|
||||||
|
if (creatorMap.containsKey(type)) {
|
||||||
|
created = creatorMap.get(type).apply(session, data);
|
||||||
} else {
|
} else {
|
||||||
return new Challenge(session);
|
created = new Challenge(session, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
createdMap.put(type, created);
|
||||||
|
|
||||||
|
return created;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"type": "http-01",
|
"type": "http-01",
|
||||||
"status": "pending",
|
"status": "pending",
|
||||||
"url": "https://example.com/acme/some-resource",
|
"url": "https://example.com/acme/some-location",
|
||||||
"token": "IlirfxKKXAsHtmzK29Pj8A"
|
"token": "IlirfxKKXAsHtmzK29Pj8A"
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,7 @@ The standard Java mechanisms are used to verify the HTTPS certificate provided b
|
||||||
|
|
||||||
If your ACME server provides challenges that are not specified in the ACME protocol, there should be an own `Challenge` implementation for each of your challenge, by extending the [`Challenge`](../apidocs/org/shredzone/acme4j/challenge/Challenge.html) class.
|
If your ACME server provides challenges that are not specified in the ACME protocol, there should be an own `Challenge` implementation for each of your challenge, by extending the [`Challenge`](../apidocs/org/shredzone/acme4j/challenge/Challenge.html) class.
|
||||||
|
|
||||||
In your `AcmeProvider` implementation, override the `createChallenge(Session, String)` method so it returns a new instance of your `Challenge` implementation when your individual challenge type is requested. All other types should be delegated to the super method.
|
In your `AcmeProvider` implementation, override the `createChallenge(Session, JSON)` method so it returns a new instance of your `Challenge` implementation when your individual challenge type is requested. All other types should be delegated to the super method.
|
||||||
|
|
||||||
## Amended Directory Service
|
## Amended Directory Service
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue