mirror of https://github.com/shred/acme4j
parent
1289e2f5e8
commit
04a40c83e0
|
|
@ -14,7 +14,7 @@
|
||||||
package org.shredzone.acme4j;
|
package org.shredzone.acme4j;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.net.URI;
|
import java.net.URL;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -24,7 +24,7 @@ public abstract class AcmeResource implements Serializable {
|
||||||
private static final long serialVersionUID = -7930580802257379731L;
|
private static final long serialVersionUID = -7930580802257379731L;
|
||||||
|
|
||||||
private transient Session session;
|
private transient Session session;
|
||||||
private URI location;
|
private URL location;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new {@link AcmeResource}.
|
* Create a new {@link AcmeResource}.
|
||||||
|
|
@ -57,7 +57,7 @@ public abstract class AcmeResource implements Serializable {
|
||||||
/**
|
/**
|
||||||
* Sets the resource's location.
|
* Sets the resource's location.
|
||||||
*/
|
*/
|
||||||
protected void setLocation(URI location) {
|
protected void setLocation(URL location) {
|
||||||
this.location = Objects.requireNonNull(location, "location");
|
this.location = Objects.requireNonNull(location, "location");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -81,7 +81,7 @@ public abstract class AcmeResource implements Serializable {
|
||||||
/**
|
/**
|
||||||
* Gets the resource's location.
|
* Gets the resource's location.
|
||||||
*/
|
*/
|
||||||
public URI getLocation() {
|
public URL getLocation() {
|
||||||
return location;
|
return location;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ import static java.util.stream.Collectors.toList;
|
||||||
import static org.shredzone.acme4j.toolbox.AcmeUtils.parseTimestamp;
|
import static org.shredzone.acme4j.toolbox.AcmeUtils.parseTimestamp;
|
||||||
|
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
import java.net.URI;
|
import java.net.URL;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
@ -49,7 +49,7 @@ public class Authorization extends AcmeResource {
|
||||||
private List<List<Challenge>> combinations;
|
private List<List<Challenge>> combinations;
|
||||||
private boolean loaded = false;
|
private boolean loaded = false;
|
||||||
|
|
||||||
protected Authorization(Session session, URI location) {
|
protected Authorization(Session session, URL location) {
|
||||||
super(session);
|
super(session);
|
||||||
setLocation(location);
|
setLocation(location);
|
||||||
}
|
}
|
||||||
|
|
@ -64,7 +64,7 @@ public class Authorization extends AcmeResource {
|
||||||
* Location of the Authorization
|
* Location of the Authorization
|
||||||
* @return {@link Authorization} bound to the session and location
|
* @return {@link Authorization} bound to the session and location
|
||||||
*/
|
*/
|
||||||
public static Authorization bind(Session session, URI location) {
|
public static Authorization bind(Session session, URL location) {
|
||||||
return new Authorization(session, location);
|
return new Authorization(session, location);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,8 @@
|
||||||
package org.shredzone.acme4j;
|
package org.shredzone.acme4j;
|
||||||
|
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
import java.net.URI;
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
import java.security.cert.CertificateEncodingException;
|
import java.security.cert.CertificateEncodingException;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
@ -37,19 +38,19 @@ public class Certificate extends AcmeResource {
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(Certificate.class);
|
private static final Logger LOG = LoggerFactory.getLogger(Certificate.class);
|
||||||
private static final int MAX_CHAIN_LENGTH = 10;
|
private static final int MAX_CHAIN_LENGTH = 10;
|
||||||
|
|
||||||
private URI chainCertUri;
|
private URL chainCertUrl;
|
||||||
private X509Certificate cert = null;
|
private X509Certificate cert = null;
|
||||||
private X509Certificate[] chain = null;
|
private X509Certificate[] chain = null;
|
||||||
|
|
||||||
protected Certificate(Session session, URI certUri) {
|
protected Certificate(Session session, URL certUrl) {
|
||||||
super(session);
|
super(session);
|
||||||
setLocation(certUri);
|
setLocation(certUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Certificate(Session session, URI certUri, URI chainUri, X509Certificate cert) {
|
protected Certificate(Session session, URL certUrl, URL chainUrl, X509Certificate cert) {
|
||||||
super(session);
|
super(session);
|
||||||
setLocation(certUri);
|
setLocation(certUrl);
|
||||||
this.chainCertUri = chainUri;
|
this.chainCertUrl = chainUrl;
|
||||||
this.cert = cert;
|
this.cert = cert;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -62,16 +63,16 @@ public class Certificate extends AcmeResource {
|
||||||
* Location of the Certificate
|
* Location of the Certificate
|
||||||
* @return {@link Certificate} bound to the session and location
|
* @return {@link Certificate} bound to the session and location
|
||||||
*/
|
*/
|
||||||
public static Certificate bind(Session session, URI location) {
|
public static Certificate bind(Session session, URL location) {
|
||||||
return new Certificate(session, location);
|
return new Certificate(session, location);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the URI of the certificate chain. {@code null} if not known or not
|
* Returns the URL of the certificate chain. {@code null} if not known or not
|
||||||
* available.
|
* available.
|
||||||
*/
|
*/
|
||||||
public URI getChainLocation() {
|
public URL getChainLocation() {
|
||||||
return chainCertUri;
|
return chainCertUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -92,7 +93,7 @@ public class Certificate extends AcmeResource {
|
||||||
conn.accept(HttpURLConnection.HTTP_OK, HttpURLConnection.HTTP_ACCEPTED);
|
conn.accept(HttpURLConnection.HTTP_OK, HttpURLConnection.HTTP_ACCEPTED);
|
||||||
conn.handleRetryAfter("certificate is not available for download yet");
|
conn.handleRetryAfter("certificate is not available for download yet");
|
||||||
|
|
||||||
chainCertUri = conn.getLink("up");
|
chainCertUrl = conn.getLink("up");
|
||||||
cert = conn.readCertificate();
|
cert = conn.readCertificate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -111,21 +112,21 @@ public class Certificate extends AcmeResource {
|
||||||
*/
|
*/
|
||||||
public X509Certificate[] downloadChain() throws AcmeException {
|
public X509Certificate[] downloadChain() throws AcmeException {
|
||||||
if (chain == null) {
|
if (chain == null) {
|
||||||
if (chainCertUri == null) {
|
if (chainCertUrl == null) {
|
||||||
download();
|
download();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (chainCertUri == null) {
|
if (chainCertUrl == null) {
|
||||||
throw new AcmeProtocolException("No certificate chain provided");
|
throw new AcmeProtocolException("No certificate chain provided");
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG.debug("downloadChain");
|
LOG.debug("downloadChain");
|
||||||
|
|
||||||
List<X509Certificate> certChain = new ArrayList<>();
|
List<X509Certificate> certChain = new ArrayList<>();
|
||||||
URI link = chainCertUri;
|
URL link = chainCertUrl;
|
||||||
while (link != null && certChain.size() < MAX_CHAIN_LENGTH) {
|
while (link != null && certChain.size() < MAX_CHAIN_LENGTH) {
|
||||||
try (Connection conn = getSession().provider().connect()) {
|
try (Connection conn = getSession().provider().connect()) {
|
||||||
conn.sendRequest(chainCertUri, getSession());
|
conn.sendRequest(chainCertUrl, getSession());
|
||||||
conn.accept(HttpURLConnection.HTTP_OK);
|
conn.accept(HttpURLConnection.HTTP_OK);
|
||||||
|
|
||||||
certChain.add(conn.readCertificate());
|
certChain.add(conn.readCertificate());
|
||||||
|
|
@ -159,8 +160,8 @@ public class Certificate extends AcmeResource {
|
||||||
*/
|
*/
|
||||||
public void revoke(RevocationReason reason) throws AcmeException {
|
public void revoke(RevocationReason reason) throws AcmeException {
|
||||||
LOG.debug("revoke");
|
LOG.debug("revoke");
|
||||||
URI resUri = getSession().resourceUri(Resource.REVOKE_CERT);
|
URL resUrl = getSession().resourceUrl(Resource.REVOKE_CERT);
|
||||||
if (resUri == null) {
|
if (resUrl == null) {
|
||||||
throw new AcmeProtocolException("CA does not support certificate revocation");
|
throw new AcmeProtocolException("CA does not support certificate revocation");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -176,7 +177,7 @@ public class Certificate extends AcmeResource {
|
||||||
claims.put("reason", reason.getReasonCode());
|
claims.put("reason", reason.getReasonCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
conn.sendSignedRequest(resUri, claims, getSession());
|
conn.sendSignedRequest(resUrl, claims, getSession());
|
||||||
conn.accept(HttpURLConnection.HTTP_OK);
|
conn.accept(HttpURLConnection.HTTP_OK);
|
||||||
} catch (CertificateEncodingException ex) {
|
} catch (CertificateEncodingException ex) {
|
||||||
throw new AcmeProtocolException("Invalid certificate", ex);
|
throw new AcmeProtocolException("Invalid certificate", ex);
|
||||||
|
|
@ -199,7 +200,12 @@ public class Certificate extends AcmeResource {
|
||||||
*/
|
*/
|
||||||
public static void revoke(Session session, X509Certificate cert,
|
public static void revoke(Session session, X509Certificate cert,
|
||||||
RevocationReason reason) throws AcmeException {
|
RevocationReason reason) throws AcmeException {
|
||||||
new Certificate(session, URI.create(""), null, cert).revoke(reason);
|
try {
|
||||||
|
URL dummyUrl = new URL("http://");
|
||||||
|
new Certificate(session, dummyUrl, null, cert).revoke(reason);
|
||||||
|
} catch (MalformedURLException ex) {
|
||||||
|
throw new InternalError(ex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ import static org.shredzone.acme4j.toolbox.AcmeUtils.*;
|
||||||
|
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
import java.net.URL;
|
||||||
import java.security.KeyPair;
|
import java.security.KeyPair;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
|
|
@ -56,17 +57,17 @@ public class Registration extends AcmeResource {
|
||||||
|
|
||||||
private final List<URI> contacts = new ArrayList<>();
|
private final List<URI> contacts = new ArrayList<>();
|
||||||
private URI agreement;
|
private URI agreement;
|
||||||
private URI authorizations;
|
private URL authorizations;
|
||||||
private URI certificates;
|
private URL certificates;
|
||||||
private Status status;
|
private Status status;
|
||||||
private boolean loaded = false;
|
private boolean loaded = false;
|
||||||
|
|
||||||
protected Registration(Session session, URI location) {
|
protected Registration(Session session, URL location) {
|
||||||
super(session);
|
super(session);
|
||||||
setLocation(location);
|
setLocation(location);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Registration(Session session, URI location, URI agreement) {
|
protected Registration(Session session, URL location, URI agreement) {
|
||||||
super(session);
|
super(session);
|
||||||
setLocation(location);
|
setLocation(location);
|
||||||
this.agreement = agreement;
|
this.agreement = agreement;
|
||||||
|
|
@ -78,10 +79,10 @@ public class Registration extends AcmeResource {
|
||||||
* @param session
|
* @param session
|
||||||
* {@link Session} to be used
|
* {@link Session} to be used
|
||||||
* @param location
|
* @param location
|
||||||
* Location URI of the registration
|
* Location URL of the registration
|
||||||
* @return {@link Registration} bound to the session and location
|
* @return {@link Registration} bound to the session and location
|
||||||
*/
|
*/
|
||||||
public static Registration bind(Session session, URI location) {
|
public static Registration bind(Session session, URL location) {
|
||||||
return new Registration(session, location);
|
return new Registration(session, location);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -185,7 +186,7 @@ public class Registration extends AcmeResource {
|
||||||
.put("type", "dns")
|
.put("type", "dns")
|
||||||
.put("value", toAce(domain));
|
.put("value", toAce(domain));
|
||||||
|
|
||||||
conn.sendSignedRequest(getSession().resourceUri(Resource.NEW_AUTHZ), claims, getSession());
|
conn.sendSignedRequest(getSession().resourceUrl(Resource.NEW_AUTHZ), claims, getSession());
|
||||||
conn.accept(HttpURLConnection.HTTP_CREATED);
|
conn.accept(HttpURLConnection.HTTP_CREATED);
|
||||||
|
|
||||||
JSON json = conn.readJsonResponse();
|
JSON json = conn.readJsonResponse();
|
||||||
|
|
@ -240,7 +241,7 @@ public class Registration extends AcmeResource {
|
||||||
claims.put("notAfter", notAfter);
|
claims.put("notAfter", notAfter);
|
||||||
}
|
}
|
||||||
|
|
||||||
conn.sendSignedRequest(getSession().resourceUri(Resource.NEW_CERT), claims, getSession());
|
conn.sendSignedRequest(getSession().resourceUrl(Resource.NEW_CERT), claims, getSession());
|
||||||
int rc = conn.accept(HttpURLConnection.HTTP_CREATED, HttpURLConnection.HTTP_ACCEPTED);
|
int rc = conn.accept(HttpURLConnection.HTTP_CREATED, HttpURLConnection.HTTP_ACCEPTED);
|
||||||
|
|
||||||
X509Certificate cert = null;
|
X509Certificate cert = null;
|
||||||
|
|
@ -252,9 +253,9 @@ public class Registration extends AcmeResource {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
URI chainCertUri = conn.getLink("up");
|
URL chainCertUrl = conn.getLink("up");
|
||||||
|
|
||||||
return new Certificate(getSession(), conn.getLocation(), chainCertUri, cert);
|
return new Certificate(getSession(), conn.getLocation(), chainCertUrl, cert);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -277,7 +278,7 @@ public class Registration extends AcmeResource {
|
||||||
LOG.debug("key-change");
|
LOG.debug("key-change");
|
||||||
|
|
||||||
try (Connection conn = getSession().provider().connect()) {
|
try (Connection conn = getSession().provider().connect()) {
|
||||||
URI keyChangeUri = getSession().resourceUri(Resource.KEY_CHANGE);
|
URL keyChangeUrl = getSession().resourceUrl(Resource.KEY_CHANGE);
|
||||||
PublicJsonWebKey newKeyJwk = PublicJsonWebKey.Factory.newPublicJwk(newKeyPair.getPublic());
|
PublicJsonWebKey newKeyJwk = PublicJsonWebKey.Factory.newPublicJwk(newKeyPair.getPublic());
|
||||||
|
|
||||||
JSONBuilder payloadClaim = new JSONBuilder();
|
JSONBuilder payloadClaim = new JSONBuilder();
|
||||||
|
|
@ -286,7 +287,7 @@ public class Registration extends AcmeResource {
|
||||||
|
|
||||||
JsonWebSignature innerJws = new JsonWebSignature();
|
JsonWebSignature innerJws = new JsonWebSignature();
|
||||||
innerJws.setPayload(payloadClaim.toString());
|
innerJws.setPayload(payloadClaim.toString());
|
||||||
innerJws.getHeaders().setObjectHeaderValue("url", keyChangeUri);
|
innerJws.getHeaders().setObjectHeaderValue("url", keyChangeUrl);
|
||||||
innerJws.getHeaders().setJwkHeaderValue("jwk", newKeyJwk);
|
innerJws.getHeaders().setJwkHeaderValue("jwk", newKeyJwk);
|
||||||
innerJws.setAlgorithmHeaderValue(keyAlgorithm(newKeyJwk));
|
innerJws.setAlgorithmHeaderValue(keyAlgorithm(newKeyJwk));
|
||||||
innerJws.setKey(newKeyPair.getPrivate());
|
innerJws.setKey(newKeyPair.getPrivate());
|
||||||
|
|
@ -298,7 +299,7 @@ public class Registration extends AcmeResource {
|
||||||
outerClaim.put("signature", innerJws.getEncodedSignature());
|
outerClaim.put("signature", innerJws.getEncodedSignature());
|
||||||
outerClaim.put("payload", innerJws.getEncodedPayload());
|
outerClaim.put("payload", innerJws.getEncodedPayload());
|
||||||
|
|
||||||
conn.sendSignedRequest(keyChangeUri, outerClaim, getSession());
|
conn.sendSignedRequest(keyChangeUrl, outerClaim, getSession());
|
||||||
conn.accept(HttpURLConnection.HTTP_OK);
|
conn.accept(HttpURLConnection.HTTP_OK);
|
||||||
|
|
||||||
getSession().setKeyPair(newKeyPair);
|
getSession().setKeyPair(newKeyPair);
|
||||||
|
|
@ -361,19 +362,19 @@ public class Registration extends AcmeResource {
|
||||||
.forEach(contacts::add);
|
.forEach(contacts::add);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.authorizations = json.get(KEY_AUTHORIZATIONS).asURI();
|
this.authorizations = json.get(KEY_AUTHORIZATIONS).asURL();
|
||||||
this.certificates = json.get(KEY_CERTIFICATES).asURI();
|
this.certificates = json.get(KEY_CERTIFICATES).asURL();
|
||||||
|
|
||||||
if (json.contains(KEY_STATUS)) {
|
if (json.contains(KEY_STATUS)) {
|
||||||
this.status = Status.parse(json.get(KEY_STATUS).asString());
|
this.status = Status.parse(json.get(KEY_STATUS).asString());
|
||||||
}
|
}
|
||||||
|
|
||||||
URI location = conn.getLocation();
|
URL location = conn.getLocation();
|
||||||
if (location != null) {
|
if (location != null) {
|
||||||
setLocation(location);
|
setLocation(location);
|
||||||
}
|
}
|
||||||
|
|
||||||
URI tos = conn.getLink("terms-of-service");
|
URI tos = conn.getLinkAsURI("terms-of-service");
|
||||||
if (tos != null) {
|
if (tos != null) {
|
||||||
this.agreement = tos;
|
this.agreement = tos;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ package org.shredzone.acme4j;
|
||||||
|
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
import java.net.URL;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
|
@ -83,11 +84,11 @@ public class RegistrationBuilder {
|
||||||
claims.put("contact", contacts);
|
claims.put("contact", contacts);
|
||||||
}
|
}
|
||||||
|
|
||||||
conn.sendSignedRequest(session.resourceUri(Resource.NEW_REG), claims, session);
|
conn.sendSignedRequest(session.resourceUrl(Resource.NEW_REG), claims, session);
|
||||||
conn.accept(HttpURLConnection.HTTP_CREATED);
|
conn.accept(HttpURLConnection.HTTP_CREATED);
|
||||||
|
|
||||||
URI location = conn.getLocation();
|
URL location = conn.getLocation();
|
||||||
URI tos = conn.getLink("terms-of-service");
|
URI tos = conn.getLinkAsURI("terms-of-service");
|
||||||
|
|
||||||
return new Registration(session, location, tos);
|
return new Registration(session, location, tos);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@
|
||||||
package org.shredzone.acme4j;
|
package org.shredzone.acme4j;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
import java.net.URL;
|
||||||
import java.security.KeyPair;
|
import java.security.KeyPair;
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
|
|
@ -40,7 +41,7 @@ import org.shredzone.acme4j.toolbox.JSON;
|
||||||
* volatile data.
|
* volatile data.
|
||||||
*/
|
*/
|
||||||
public class Session {
|
public class Session {
|
||||||
private final AtomicReference<Map<Resource, URI>> resourceMap = new AtomicReference<>();
|
private final AtomicReference<Map<Resource, URL>> resourceMap = new AtomicReference<>();
|
||||||
private final AtomicReference<Metadata> metadata = new AtomicReference<>();
|
private final AtomicReference<Metadata> metadata = new AtomicReference<>();
|
||||||
private final URI serverUri;
|
private final URI serverUri;
|
||||||
private final AcmeProvider provider;
|
private final AcmeProvider provider;
|
||||||
|
|
@ -175,14 +176,14 @@ public class Session {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the {@link URI} of the given {@link Resource}. This may involve connecting to
|
* Gets the {@link URL} of the given {@link Resource}. This may involve connecting to
|
||||||
* the server and getting a directory. The result is cached.
|
* the server and getting a directory. The result is cached.
|
||||||
*
|
*
|
||||||
* @param resource
|
* @param resource
|
||||||
* {@link Resource} to get the {@link URI} of
|
* {@link Resource} to get the {@link URL} of
|
||||||
* @return {@link URI}, or {@code null} if the server does not offer that resource
|
* @return {@link URL}, or {@code null} if the server does not offer that resource
|
||||||
*/
|
*/
|
||||||
public URI resourceUri(Resource resource) throws AcmeException {
|
public URL resourceUrl(Resource resource) throws AcmeException {
|
||||||
readDirectory();
|
readDirectory();
|
||||||
return resourceMap.get().get(Objects.requireNonNull(resource, "resource"));
|
return resourceMap.get().get(Objects.requireNonNull(resource, "resource"));
|
||||||
}
|
}
|
||||||
|
|
@ -219,11 +220,11 @@ public class Session {
|
||||||
metadata.set(new Metadata(JSON.empty()));
|
metadata.set(new Metadata(JSON.empty()));
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<Resource, URI> map = new EnumMap<>(Resource.class);
|
Map<Resource, URL> map = new EnumMap<>(Resource.class);
|
||||||
for (Resource res : Resource.values()) {
|
for (Resource res : Resource.values()) {
|
||||||
URI uri = directoryJson.get(res.path()).asURI();
|
URL url = directoryJson.get(res.path()).asURL();
|
||||||
if (uri != null) {
|
if (url != null) {
|
||||||
map.put(res, uri);
|
map.put(res, url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
resourceMap.set(map);
|
resourceMap.set(map);
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
package org.shredzone.acme4j.challenge;
|
package org.shredzone.acme4j.challenge;
|
||||||
|
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
import java.net.URI;
|
import java.net.URL;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
|
|
@ -72,7 +72,7 @@ public class Challenge extends AcmeResource {
|
||||||
* @return {@link Challenge} bound to this session and location
|
* @return {@link Challenge} bound to this session and location
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public static <T extends Challenge> T bind(Session session, URI location) throws AcmeException {
|
public static <T extends Challenge> T bind(Session session, URL location) throws AcmeException {
|
||||||
Objects.requireNonNull(session, "session");
|
Objects.requireNonNull(session, "session");
|
||||||
Objects.requireNonNull(location, "location");
|
Objects.requireNonNull(location, "location");
|
||||||
|
|
||||||
|
|
@ -105,11 +105,11 @@ public class Challenge extends AcmeResource {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the location {@link URI} of the challenge.
|
* Returns the location {@link URL} of the challenge.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public URI getLocation() {
|
public URL getLocation() {
|
||||||
return data.get(KEY_URI).asURI();
|
return data.get(KEY_URI).asURL();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -14,8 +14,8 @@
|
||||||
package org.shredzone.acme4j.connector;
|
package org.shredzone.acme4j.connector;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
import java.net.URL;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
import java.util.Collection;
|
|
||||||
|
|
||||||
import org.shredzone.acme4j.Session;
|
import org.shredzone.acme4j.Session;
|
||||||
import org.shredzone.acme4j.exception.AcmeException;
|
import org.shredzone.acme4j.exception.AcmeException;
|
||||||
|
|
@ -31,24 +31,24 @@ public interface Connection extends AutoCloseable {
|
||||||
/**
|
/**
|
||||||
* Sends a simple GET request.
|
* Sends a simple GET request.
|
||||||
*
|
*
|
||||||
* @param uri
|
* @param url
|
||||||
* {@link URI} to send the request to.
|
* {@link URL} to send the request to.
|
||||||
* @param session
|
* @param session
|
||||||
* {@link Session} instance to be used for tracking
|
* {@link Session} instance to be used for tracking
|
||||||
*/
|
*/
|
||||||
void sendRequest(URI uri, Session session) throws AcmeException;
|
void sendRequest(URL url, Session session) throws AcmeException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends a signed POST request.
|
* Sends a signed POST request.
|
||||||
*
|
*
|
||||||
* @param uri
|
* @param url
|
||||||
* {@link URI} to send the request to.
|
* {@link URL} to send the request to.
|
||||||
* @param claims
|
* @param claims
|
||||||
* {@link JSONBuilder} containing claims. Must not be {@code null}.
|
* {@link JSONBuilder} containing claims. Must not be {@code null}.
|
||||||
* @param session
|
* @param session
|
||||||
* {@link Session} instance to be used for signing and tracking
|
* {@link Session} instance to be used for signing and tracking
|
||||||
*/
|
*/
|
||||||
void sendSignedRequest(URI uri, JSONBuilder claims, Session session) throws AcmeException;
|
void sendSignedRequest(URL url, JSONBuilder claims, Session session) throws AcmeException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the HTTP response status is in the given list of acceptable HTTP states,
|
* Checks if the HTTP response status is in the given list of acceptable HTTP states,
|
||||||
|
|
@ -96,9 +96,9 @@ public interface Connection extends AutoCloseable {
|
||||||
* <p>
|
* <p>
|
||||||
* Relative links are resolved against the last request's URL.
|
* Relative links are resolved against the last request's URL.
|
||||||
*
|
*
|
||||||
* @return Location {@link URI}, or {@code null} if no Location header was set
|
* @return Location {@link URL}, or {@code null} if no Location header was set
|
||||||
*/
|
*/
|
||||||
URI getLocation();
|
URL getLocation();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a relation link from the header.
|
* Gets a relation link from the header.
|
||||||
|
|
@ -108,20 +108,21 @@ public interface Connection extends AutoCloseable {
|
||||||
*
|
*
|
||||||
* @param relation
|
* @param relation
|
||||||
* Link relation
|
* Link relation
|
||||||
* @return Link, or {@code null} if there was no such relation link
|
* @return Link {@link URL}, or {@code null} if there was no such relation link
|
||||||
*/
|
*/
|
||||||
URI getLink(String relation);
|
URL getLink(String relation);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets one or more relation link from the header.
|
* Gets a relation link from the header.
|
||||||
* <p>
|
* <p>
|
||||||
* Relative links are resolved against the last request's URL.
|
* Relative links are resolved against the last request's URL. If there is more than
|
||||||
|
* one relation, the first one is returned.
|
||||||
*
|
*
|
||||||
* @param relation
|
* @param relation
|
||||||
* Link relation
|
* Link relation
|
||||||
* @return Collection of links, or {@code null} if there was no such relation link
|
* @return Link {@link URI}, or {@code null} if there was no such relation link
|
||||||
*/
|
*/
|
||||||
Collection<URI> getLinks(String relation);
|
URI getLinkAsURI(String relation);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Closes the {@link Connection}, releasing all resources.
|
* Closes the {@link Connection}, releasing all resources.
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
*/
|
*/
|
||||||
package org.shredzone.acme4j.connector;
|
package org.shredzone.acme4j.connector;
|
||||||
|
|
||||||
|
import static java.util.stream.Collectors.toList;
|
||||||
import static org.shredzone.acme4j.toolbox.AcmeUtils.keyAlgorithm;
|
import static org.shredzone.acme4j.toolbox.AcmeUtils.keyAlgorithm;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
@ -91,15 +92,15 @@ public class DefaultConnection implements Connection {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendRequest(URI uri, Session session) throws AcmeException {
|
public void sendRequest(URL url, Session session) throws AcmeException {
|
||||||
Objects.requireNonNull(uri, "uri");
|
Objects.requireNonNull(url, "url");
|
||||||
Objects.requireNonNull(session, "session");
|
Objects.requireNonNull(session, "session");
|
||||||
assertConnectionIsClosed();
|
assertConnectionIsClosed();
|
||||||
|
|
||||||
LOG.debug("GET {}", uri);
|
LOG.debug("GET {}", url);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
conn = httpConnector.openConnection(uri);
|
conn = httpConnector.openConnection(url);
|
||||||
conn.setRequestMethod("GET");
|
conn.setRequestMethod("GET");
|
||||||
conn.setRequestProperty(ACCEPT_CHARSET_HEADER, DEFAULT_CHARSET);
|
conn.setRequestProperty(ACCEPT_CHARSET_HEADER, DEFAULT_CHARSET);
|
||||||
conn.setRequestProperty(ACCEPT_LANGUAGE_HEADER, session.getLocale().toLanguageTag());
|
conn.setRequestProperty(ACCEPT_LANGUAGE_HEADER, session.getLocale().toLanguageTag());
|
||||||
|
|
@ -114,8 +115,8 @@ public class DefaultConnection implements Connection {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendSignedRequest(URI uri, JSONBuilder claims, Session session) throws AcmeException {
|
public void sendSignedRequest(URL url, JSONBuilder claims, Session session) throws AcmeException {
|
||||||
Objects.requireNonNull(uri, "uri");
|
Objects.requireNonNull(url, "url");
|
||||||
Objects.requireNonNull(claims, "claims");
|
Objects.requireNonNull(claims, "claims");
|
||||||
Objects.requireNonNull(session, "session");
|
Objects.requireNonNull(session, "session");
|
||||||
assertConnectionIsClosed();
|
assertConnectionIsClosed();
|
||||||
|
|
@ -124,8 +125,8 @@ public class DefaultConnection implements Connection {
|
||||||
KeyPair keypair = session.getKeyPair();
|
KeyPair keypair = session.getKeyPair();
|
||||||
|
|
||||||
if (session.getNonce() == null) {
|
if (session.getNonce() == null) {
|
||||||
LOG.debug("Getting initial nonce, HEAD {}", uri);
|
LOG.debug("Getting initial nonce, HEAD {}", url);
|
||||||
conn = httpConnector.openConnection(uri);
|
conn = httpConnector.openConnection(url);
|
||||||
conn.setRequestMethod("HEAD");
|
conn.setRequestMethod("HEAD");
|
||||||
conn.setRequestProperty(ACCEPT_LANGUAGE_HEADER, session.getLocale().toLanguageTag());
|
conn.setRequestProperty(ACCEPT_LANGUAGE_HEADER, session.getLocale().toLanguageTag());
|
||||||
conn.connect();
|
conn.connect();
|
||||||
|
|
@ -137,9 +138,9 @@ public class DefaultConnection implements Connection {
|
||||||
throw new AcmeProtocolException("Server did not provide a nonce");
|
throw new AcmeProtocolException("Server did not provide a nonce");
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG.debug("POST {} with claims: {}", uri, claims);
|
LOG.debug("POST {} with claims: {}", url, claims);
|
||||||
|
|
||||||
conn = httpConnector.openConnection(uri);
|
conn = httpConnector.openConnection(url);
|
||||||
conn.setRequestMethod("POST");
|
conn.setRequestMethod("POST");
|
||||||
conn.setRequestProperty(ACCEPT_HEADER, "application/json");
|
conn.setRequestProperty(ACCEPT_HEADER, "application/json");
|
||||||
conn.setRequestProperty(ACCEPT_CHARSET_HEADER, DEFAULT_CHARSET);
|
conn.setRequestProperty(ACCEPT_CHARSET_HEADER, DEFAULT_CHARSET);
|
||||||
|
|
@ -152,7 +153,7 @@ public class DefaultConnection implements Connection {
|
||||||
JsonWebSignature jws = new JsonWebSignature();
|
JsonWebSignature jws = new JsonWebSignature();
|
||||||
jws.setPayload(claims.toString());
|
jws.setPayload(claims.toString());
|
||||||
jws.getHeaders().setObjectHeaderValue("nonce", Base64Url.encode(session.getNonce()));
|
jws.getHeaders().setObjectHeaderValue("nonce", Base64Url.encode(session.getNonce()));
|
||||||
jws.getHeaders().setObjectHeaderValue("url", uri);
|
jws.getHeaders().setObjectHeaderValue("url", url);
|
||||||
jws.getHeaders().setJwkHeaderValue("jwk", jwk);
|
jws.getHeaders().setJwkHeaderValue("jwk", jwk);
|
||||||
jws.setAlgorithmHeaderValue(keyAlgorithm(jwk));
|
jws.setAlgorithmHeaderValue(keyAlgorithm(jwk));
|
||||||
jws.setKey(keypair.getPrivate());
|
jws.setKey(keypair.getPrivate());
|
||||||
|
|
@ -289,7 +290,7 @@ public class DefaultConnection implements Connection {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public URI getLocation() {
|
public URL getLocation() {
|
||||||
assertConnectionIsOpen();
|
assertConnectionIsOpen();
|
||||||
|
|
||||||
String location = conn.getHeaderField(LOCATION_HEADER);
|
String location = conn.getHeaderField(LOCATION_HEADER);
|
||||||
|
|
@ -302,24 +303,37 @@ public class DefaultConnection implements Connection {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public URI getLink(String relation) {
|
public URL getLink(String relation) {
|
||||||
Collection<URI> links = getLinks(relation);
|
return getLinks(relation).stream()
|
||||||
if (links == null) {
|
.findFirst()
|
||||||
return null;
|
.map(this::resolveRelative)
|
||||||
}
|
.orElse(null);
|
||||||
|
|
||||||
if (links.size() > 1) {
|
|
||||||
LOG.debug("Link: {} - using the first of {}", relation, links.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
return links.iterator().next();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<URI> getLinks(String relation) {
|
public URI getLinkAsURI(String relation) {
|
||||||
|
return getLinks(relation).stream()
|
||||||
|
.findFirst()
|
||||||
|
.map(this::resolveRelativeAsURI)
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
conn = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the link headers of the given relation. The link URIs are unresolved.
|
||||||
|
*
|
||||||
|
* @param relation
|
||||||
|
* Relation name
|
||||||
|
* @return Link headers
|
||||||
|
*/
|
||||||
|
private Collection<String> getLinks(String relation) {
|
||||||
assertConnectionIsOpen();
|
assertConnectionIsOpen();
|
||||||
|
|
||||||
List<URI> result = new ArrayList<>();
|
List<String> result = new ArrayList<>();
|
||||||
|
|
||||||
List<String> links = conn.getHeaderFields().get(LINK_HEADER);
|
List<String> links = conn.getHeaderFields().get(LINK_HEADER);
|
||||||
if (links != null) {
|
if (links != null) {
|
||||||
|
|
@ -329,17 +343,12 @@ public class DefaultConnection implements Connection {
|
||||||
if (m.matches()) {
|
if (m.matches()) {
|
||||||
String location = m.group(1);
|
String location = m.group(1);
|
||||||
LOG.debug("Link: {} -> {}", relation, location);
|
LOG.debug("Link: {} -> {}", relation, location);
|
||||||
result.add(resolveRelative(location));
|
result.add(location);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return !result.isEmpty() ? result : null;
|
return result;
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void close() {
|
|
||||||
conn = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -389,14 +398,16 @@ public class DefaultConnection implements Connection {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ("agreementRequired".equals(error)) {
|
if ("agreementRequired".equals(error)) {
|
||||||
URI instance = resolveRelative(json.get("instance").asString());
|
URI instance = resolveRelativeAsURI(json.get("instance").asString());
|
||||||
URI tos = getLink("terms-of-service");
|
URI tos = getLinkAsURI("terms-of-service");
|
||||||
return new AcmeAgreementRequiredException(type, detail, tos, instance);
|
return new AcmeAgreementRequiredException(type, detail, tos, instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ("rateLimited".equals(error)) {
|
if ("rateLimited".equals(error)) {
|
||||||
Optional<Instant> retryAfter = getRetryAfterHeader();
|
Optional<Instant> retryAfter = getRetryAfterHeader();
|
||||||
Collection<URI> rateLimits = getLinks("rate-limit");
|
Collection<URI> rateLimits = getLinks("rate-limit").stream()
|
||||||
|
.map(this::resolveRelativeAsURI)
|
||||||
|
.collect(toList());
|
||||||
return new AcmeRateLimitExceededException(type, detail, retryAfter.orElse(null), rateLimits);
|
return new AcmeRateLimitExceededException(type, detail, retryAfter.orElse(null), rateLimits);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -437,7 +448,29 @@ public class DefaultConnection implements Connection {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolves a relative link against the connection's last URI.
|
* Resolves a relative link against the connection's last URL.
|
||||||
|
*
|
||||||
|
* @param link
|
||||||
|
* Link to resolve. Absolute links are just converted to an URL. May be
|
||||||
|
* {@code null}.
|
||||||
|
* @return Absolute URL of the given link, or {@code null} if the link was
|
||||||
|
* {@code null}.
|
||||||
|
*/
|
||||||
|
private URL resolveRelative(String link) {
|
||||||
|
if (link == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
assertConnectionIsOpen();
|
||||||
|
try {
|
||||||
|
return new URL(conn.getURL(), link);
|
||||||
|
} catch (MalformedURLException ex) {
|
||||||
|
throw new AcmeProtocolException("Cannot resolve relative link: " + link, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves a relative link against the connection's last URL.
|
||||||
*
|
*
|
||||||
* @param link
|
* @param link
|
||||||
* Link to resolve. Absolute links are just converted to an URI. May be
|
* Link to resolve. Absolute links are just converted to an URI. May be
|
||||||
|
|
@ -445,15 +478,15 @@ public class DefaultConnection implements Connection {
|
||||||
* @return Absolute URI of the given link, or {@code null} if the link was
|
* @return Absolute URI of the given link, or {@code null} if the link was
|
||||||
* {@code null}.
|
* {@code null}.
|
||||||
*/
|
*/
|
||||||
private URI resolveRelative(String link) {
|
private URI resolveRelativeAsURI(String link) {
|
||||||
if (link == null) {
|
if (link == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
assertConnectionIsOpen();
|
assertConnectionIsOpen();
|
||||||
try {
|
try {
|
||||||
return new URL(conn.getURL(), link).toURI();
|
return conn.getURL().toURI().resolve(link);
|
||||||
} catch (MalformedURLException | URISyntaxException ex) {
|
} catch (URISyntaxException ex) {
|
||||||
throw new AcmeProtocolException("Cannot resolve relative link: " + link, ex);
|
throw new AcmeProtocolException("Cannot resolve relative link: " + link, ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ package org.shredzone.acme4j.connector;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
import java.net.URI;
|
import java.net.URL;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
@ -59,14 +59,14 @@ public class HttpConnector {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Opens a {@link HttpURLConnection} to the given {@link URI}.
|
* Opens a {@link HttpURLConnection} to the given {@link URL}.
|
||||||
*
|
*
|
||||||
* @param uri
|
* @param url
|
||||||
* {@link URI} to connect to
|
* {@link URL} to connect to
|
||||||
* @return {@link HttpURLConnection} connected to the {@link URI}
|
* @return {@link HttpURLConnection} connected to the {@link URL}
|
||||||
*/
|
*/
|
||||||
public HttpURLConnection openConnection(URI uri) throws IOException {
|
public HttpURLConnection openConnection(URL url) throws IOException {
|
||||||
HttpURLConnection conn = (HttpURLConnection) uri.toURL().openConnection();
|
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
||||||
configure(conn);
|
configure(conn);
|
||||||
return conn;
|
return conn;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
package org.shredzone.acme4j.connector;
|
package org.shredzone.acme4j.connector;
|
||||||
|
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
import java.net.URI;
|
import java.net.URL;
|
||||||
import java.util.ArrayDeque;
|
import java.util.ArrayDeque;
|
||||||
import java.util.Deque;
|
import java.util.Deque;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
|
@ -29,7 +29,7 @@ import org.shredzone.acme4j.exception.AcmeProtocolException;
|
||||||
import org.shredzone.acme4j.toolbox.JSON;
|
import org.shredzone.acme4j.toolbox.JSON;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An {@link Iterator} that fetches a batch of URIs from the ACME server, and generates
|
* An {@link Iterator} that fetches a batch of URLs from the ACME server, and generates
|
||||||
* {@link AcmeResource} instances.
|
* {@link AcmeResource} instances.
|
||||||
*
|
*
|
||||||
* @param <T>
|
* @param <T>
|
||||||
|
|
@ -39,10 +39,10 @@ public class ResourceIterator<T extends AcmeResource> implements Iterator<T> {
|
||||||
|
|
||||||
private final Session session;
|
private final Session session;
|
||||||
private final String field;
|
private final String field;
|
||||||
private final Deque<URI> uriList = new ArrayDeque<>();
|
private final Deque<URL> urlList = new ArrayDeque<>();
|
||||||
private final BiFunction<Session, URI, T> creator;
|
private final BiFunction<Session, URL, T> creator;
|
||||||
private boolean eol = false;
|
private boolean eol = false;
|
||||||
private URI nextUri;
|
private URL nextUrl;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new {@link ResourceIterator}.
|
* Creates a new {@link ResourceIterator}.
|
||||||
|
|
@ -52,15 +52,15 @@ public class ResourceIterator<T extends AcmeResource> implements Iterator<T> {
|
||||||
* @param field
|
* @param field
|
||||||
* Field name to be used in the JSON response
|
* Field name to be used in the JSON response
|
||||||
* @param start
|
* @param start
|
||||||
* URI of the first JSON array, may be {@code null} for an empty iterator
|
* URL of the first JSON array, may be {@code null} for an empty iterator
|
||||||
* @param creator
|
* @param creator
|
||||||
* Creator for an {@link AcmeResource} that is bound to the given
|
* Creator for an {@link AcmeResource} that is bound to the given
|
||||||
* {@link Session} and {@link URI}.
|
* {@link Session} and {@link URL}.
|
||||||
*/
|
*/
|
||||||
public ResourceIterator(Session session, String field, URI start, BiFunction<Session, URI, T> creator) {
|
public ResourceIterator(Session session, String field, URL start, BiFunction<Session, URL, T> creator) {
|
||||||
this.session = Objects.requireNonNull(session, "session");
|
this.session = Objects.requireNonNull(session, "session");
|
||||||
this.field = Objects.requireNonNull(field, "field");
|
this.field = Objects.requireNonNull(field, "field");
|
||||||
this.nextUri = start;
|
this.nextUrl = start;
|
||||||
this.creator = Objects.requireNonNull(creator, "creator");
|
this.creator = Objects.requireNonNull(creator, "creator");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -68,7 +68,7 @@ public class ResourceIterator<T extends AcmeResource> implements Iterator<T> {
|
||||||
* Checks if there is another object in the result.
|
* Checks if there is another object in the result.
|
||||||
*
|
*
|
||||||
* @throws AcmeProtocolException
|
* @throws AcmeProtocolException
|
||||||
* if the next batch of URIs could not be fetched from the server
|
* if the next batch of URLs could not be fetched from the server
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean hasNext() {
|
public boolean hasNext() {
|
||||||
|
|
@ -76,32 +76,32 @@ public class ResourceIterator<T extends AcmeResource> implements Iterator<T> {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (uriList.isEmpty()) {
|
if (urlList.isEmpty()) {
|
||||||
fetch();
|
fetch();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (uriList.isEmpty()) {
|
if (urlList.isEmpty()) {
|
||||||
eol = true;
|
eol = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return !uriList.isEmpty();
|
return !urlList.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the next object of the result.
|
* Returns the next object of the result.
|
||||||
*
|
*
|
||||||
* @throws AcmeProtocolException
|
* @throws AcmeProtocolException
|
||||||
* if the next batch of URIs could not be fetched from the server
|
* if the next batch of URLs could not be fetched from the server
|
||||||
* @throws NoSuchElementException
|
* @throws NoSuchElementException
|
||||||
* if there are no more entries
|
* if there are no more entries
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public T next() {
|
public T next() {
|
||||||
if (!eol && uriList.isEmpty()) {
|
if (!eol && urlList.isEmpty()) {
|
||||||
fetch();
|
fetch();
|
||||||
}
|
}
|
||||||
|
|
||||||
URI next = uriList.poll();
|
URL next = urlList.poll();
|
||||||
if (next == null) {
|
if (next == null) {
|
||||||
eol = true;
|
eol = true;
|
||||||
throw new NoSuchElementException("no more " + field);
|
throw new NoSuchElementException("no more " + field);
|
||||||
|
|
@ -119,11 +119,11 @@ public class ResourceIterator<T extends AcmeResource> implements Iterator<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetches the next batch of URIs. Handles exceptions. Does nothing if there is no
|
* Fetches the next batch of URLs. Handles exceptions. Does nothing if there is no
|
||||||
* URI of the next batch.
|
* URL of the next batch.
|
||||||
*/
|
*/
|
||||||
private void fetch() {
|
private void fetch() {
|
||||||
if (nextUri == null) {
|
if (nextUrl == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -135,34 +135,34 @@ public class ResourceIterator<T extends AcmeResource> implements Iterator<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads the next batch of URIs from the server, and fills the queue with the URIs. If
|
* Reads the next batch of URLs from the server, and fills the queue with the URLs. If
|
||||||
* there is a "next" header, it is used for the next batch of URIs.
|
* there is a "next" header, it is used for the next batch of URLs.
|
||||||
*/
|
*/
|
||||||
private void readAndQueue() throws AcmeException {
|
private void readAndQueue() throws AcmeException {
|
||||||
try (Connection conn = session.provider().connect()) {
|
try (Connection conn = session.provider().connect()) {
|
||||||
conn.sendRequest(nextUri, session);
|
conn.sendRequest(nextUrl, session);
|
||||||
conn.accept(HttpURLConnection.HTTP_OK);
|
conn.accept(HttpURLConnection.HTTP_OK);
|
||||||
|
|
||||||
JSON json = conn.readJsonResponse();
|
JSON json = conn.readJsonResponse();
|
||||||
fillUriList(json);
|
fillUrlList(json);
|
||||||
|
|
||||||
nextUri = conn.getLink("next");
|
nextUrl = conn.getLink("next");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fills the uri list with the URIs found in the desired field.
|
* Fills the url list with the URLs found in the desired field.
|
||||||
*
|
*
|
||||||
* @param json
|
* @param json
|
||||||
* JSON map to read from
|
* JSON map to read from
|
||||||
*/
|
*/
|
||||||
private void fillUriList(JSON json) {
|
private void fillUrlList(JSON json) {
|
||||||
JSON.Array array = json.get(field).asArray();
|
JSON.Array array = json.get(field).asArray();
|
||||||
if (array == null) {
|
if (array == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
array.stream().map(JSON.Value::asURI).forEach(uriList::add);
|
array.stream().map(JSON.Value::asURL).forEach(urlList::add);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@
|
||||||
*/
|
*/
|
||||||
package org.shredzone.acme4j.exception;
|
package org.shredzone.acme4j.exception;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URL;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -23,7 +23,7 @@ import java.util.Objects;
|
||||||
public class AcmeConflictException extends AcmeException {
|
public class AcmeConflictException extends AcmeException {
|
||||||
private static final long serialVersionUID = 7454201988845449591L;
|
private static final long serialVersionUID = 7454201988845449591L;
|
||||||
|
|
||||||
private final URI location;
|
private final URL location;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new {@link AcmeConflictException}.
|
* Creates a new {@link AcmeConflictException}.
|
||||||
|
|
@ -31,9 +31,9 @@ public class AcmeConflictException extends AcmeException {
|
||||||
* @param msg
|
* @param msg
|
||||||
* Details about the conflicting resource
|
* Details about the conflicting resource
|
||||||
* @param location
|
* @param location
|
||||||
* {@link URI} of the conflicting resource
|
* {@link URL} of the conflicting resource
|
||||||
*/
|
*/
|
||||||
public AcmeConflictException(String msg, URI location) {
|
public AcmeConflictException(String msg, URL location) {
|
||||||
super(msg);
|
super(msg);
|
||||||
this.location = Objects.requireNonNull(location, "location");
|
this.location = Objects.requireNonNull(location, "location");
|
||||||
}
|
}
|
||||||
|
|
@ -41,7 +41,7 @@ public class AcmeConflictException extends AcmeException {
|
||||||
/**
|
/**
|
||||||
* Location of the conflicting resource.
|
* Location of the conflicting resource.
|
||||||
*/
|
*/
|
||||||
public URI getLocation() {
|
public URL getLocation() {
|
||||||
return location;
|
return location;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@
|
||||||
package org.shredzone.acme4j.provider;
|
package org.shredzone.acme4j.provider;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
import java.net.URL;
|
||||||
import java.util.ServiceLoader;
|
import java.util.ServiceLoader;
|
||||||
|
|
||||||
import org.shredzone.acme4j.Session;
|
import org.shredzone.acme4j.Session;
|
||||||
|
|
@ -41,15 +42,15 @@ public interface AcmeProvider {
|
||||||
boolean accepts(URI serverUri);
|
boolean accepts(URI serverUri);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolves the server URI and returns the matching directory URI.
|
* Resolves the server URI and returns the matching directory URL.
|
||||||
*
|
*
|
||||||
* @param serverUri
|
* @param serverUri
|
||||||
* Server {@link URI}
|
* Server {@link URI}
|
||||||
* @return Resolved directory {@link URI}
|
* @return Resolved directory {@link URL}
|
||||||
* @throws IllegalArgumentException
|
* @throws IllegalArgumentException
|
||||||
* if the server {@link URI} is not accepted
|
* if the server {@link URI} is not accepted
|
||||||
*/
|
*/
|
||||||
URI resolve(URI serverUri);
|
URL resolve(URI serverUri);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a {@link Connection} for communication with the ACME server.
|
* Creates a {@link Connection} for communication with the ACME server.
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,9 @@
|
||||||
*/
|
*/
|
||||||
package org.shredzone.acme4j.provider;
|
package org.shredzone.acme4j.provider;
|
||||||
|
|
||||||
|
import java.net.MalformedURLException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A generic {@link AcmeProvider}. It should be working for all ACME servers complying to
|
* A generic {@link AcmeProvider}. It should be working for all ACME servers complying to
|
||||||
|
|
@ -30,8 +32,12 @@ public class GenericAcmeProvider extends AbstractAcmeProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public URI resolve(URI serverUri) {
|
public URL resolve(URI serverUri) {
|
||||||
return serverUri;
|
try {
|
||||||
|
return serverUri.toURL();
|
||||||
|
} catch (MalformedURLException ex) {
|
||||||
|
throw new IllegalArgumentException("Invalid server URI", ex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,8 +13,9 @@
|
||||||
*/
|
*/
|
||||||
package org.shredzone.acme4j.provider.letsencrypt;
|
package org.shredzone.acme4j.provider.letsencrypt;
|
||||||
|
|
||||||
|
import java.net.MalformedURLException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URL;
|
||||||
|
|
||||||
import org.shredzone.acme4j.connector.HttpConnector;
|
import org.shredzone.acme4j.connector.HttpConnector;
|
||||||
import org.shredzone.acme4j.exception.AcmeProtocolException;
|
import org.shredzone.acme4j.exception.AcmeProtocolException;
|
||||||
|
|
@ -37,8 +38,8 @@ public class LetsEncryptAcmeProvider extends AbstractAcmeProvider {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(LetsEncryptAcmeProvider.class);
|
private static final Logger LOG = LoggerFactory.getLogger(LetsEncryptAcmeProvider.class);
|
||||||
|
|
||||||
private static final String V01_DIRECTORY_URI = "https://acme-v01.api.letsencrypt.org/directory";
|
private static final String V01_DIRECTORY_URL = "https://acme-v01.api.letsencrypt.org/directory";
|
||||||
private static final String STAGING_DIRECTORY_URI = "https://acme-staging.api.letsencrypt.org/directory";
|
private static final String STAGING_DIRECTORY_URL = "https://acme-staging.api.letsencrypt.org/directory";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean accepts(URI serverUri) {
|
public boolean accepts(URI serverUri) {
|
||||||
|
|
@ -47,21 +48,21 @@ public class LetsEncryptAcmeProvider extends AbstractAcmeProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public URI resolve(URI serverUri) {
|
public URL resolve(URI serverUri) {
|
||||||
String path = serverUri.getPath();
|
String path = serverUri.getPath();
|
||||||
String directoryUri;
|
String directoryUrl;
|
||||||
if (path == null || "".equals(path) || "/".equals(path) || "/v01".equals(path)) {
|
if (path == null || "".equals(path) || "/".equals(path) || "/v01".equals(path)) {
|
||||||
directoryUri = V01_DIRECTORY_URI;
|
directoryUrl = V01_DIRECTORY_URL;
|
||||||
} else if ("/staging".equals(path)) {
|
} else if ("/staging".equals(path)) {
|
||||||
directoryUri = STAGING_DIRECTORY_URI;
|
directoryUrl = STAGING_DIRECTORY_URL;
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalArgumentException("Unknown URI " + serverUri);
|
throw new IllegalArgumentException("Unknown URI " + serverUri);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return new URI(directoryUri);
|
return new URL(directoryUrl);
|
||||||
} catch (URISyntaxException ex) {
|
} catch (MalformedURLException ex) {
|
||||||
throw new AcmeProtocolException(directoryUri, ex);
|
throw new AcmeProtocolException(directoryUrl, ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ package org.shredzone.acme4j.provider.letsencrypt;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
import java.net.URI;
|
import java.net.URL;
|
||||||
import java.security.KeyManagementException;
|
import java.security.KeyManagementException;
|
||||||
import java.security.KeyStore;
|
import java.security.KeyStore;
|
||||||
import java.security.KeyStoreException;
|
import java.security.KeyStoreException;
|
||||||
|
|
@ -42,8 +42,8 @@ public class LetsEncryptHttpConnector extends HttpConnector {
|
||||||
private static SSLSocketFactory sslSocketFactory;
|
private static SSLSocketFactory sslSocketFactory;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HttpURLConnection openConnection(URI uri) throws IOException {
|
public HttpURLConnection openConnection(URL url) throws IOException {
|
||||||
HttpURLConnection conn = super.openConnection(uri);
|
HttpURLConnection conn = super.openConnection(url);
|
||||||
if (conn instanceof HttpsURLConnection) {
|
if (conn instanceof HttpsURLConnection) {
|
||||||
((HttpsURLConnection) conn).setSSLSocketFactory(createSocketFactory());
|
((HttpsURLConnection) conn).setSSLSocketFactory(createSocketFactory());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ import java.io.ByteArrayInputStream;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.ObjectInputStream;
|
import java.io.ObjectInputStream;
|
||||||
import java.io.ObjectOutputStream;
|
import java.io.ObjectOutputStream;
|
||||||
import java.net.URI;
|
import java.net.URL;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.shredzone.acme4j.toolbox.TestUtils;
|
import org.shredzone.acme4j.toolbox.TestUtils;
|
||||||
|
|
@ -36,7 +36,7 @@ public class AcmeResourceTest {
|
||||||
@Test
|
@Test
|
||||||
public void testConstructor() throws Exception {
|
public void testConstructor() throws Exception {
|
||||||
Session session = TestUtils.session();
|
Session session = TestUtils.session();
|
||||||
URI location = new URI("http://example.com/acme/resource");
|
URL location = new URL("http://example.com/acme/resource");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
new DummyResource(null);
|
new DummyResource(null);
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ import static org.shredzone.acme4j.toolbox.TestUtils.*;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
import java.net.URI;
|
import java.net.URL;
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
@ -44,7 +44,7 @@ public class AuthorizationTest {
|
||||||
|
|
||||||
private static final String SNAILMAIL_TYPE = "snail-01"; // a non-existent challenge
|
private static final String SNAILMAIL_TYPE = "snail-01"; // a non-existent challenge
|
||||||
|
|
||||||
private URI locationUri = URI.create("http://example.com/acme/registration");;
|
private URL locationUrl = url("http://example.com/acme/registration");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test that {@link Authorization#findChallenge(String)} does only find standalone
|
* Test that {@link Authorization#findChallenge(String)} does only find standalone
|
||||||
|
|
@ -121,8 +121,8 @@ public class AuthorizationTest {
|
||||||
public void testUpdate() throws Exception {
|
public void testUpdate() throws Exception {
|
||||||
TestableConnectionProvider provider = new TestableConnectionProvider() {
|
TestableConnectionProvider provider = new TestableConnectionProvider() {
|
||||||
@Override
|
@Override
|
||||||
public void sendRequest(URI uri, Session session) {
|
public void sendRequest(URL url, Session session) {
|
||||||
assertThat(uri, is(locationUri));
|
assertThat(url, is(locationUrl));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -150,13 +150,13 @@ public class AuthorizationTest {
|
||||||
provider.putTestChallenge("http-01", httpChallenge);
|
provider.putTestChallenge("http-01", httpChallenge);
|
||||||
provider.putTestChallenge("dns-01", dnsChallenge);
|
provider.putTestChallenge("dns-01", dnsChallenge);
|
||||||
|
|
||||||
Authorization auth = new Authorization(session, locationUri);
|
Authorization auth = new Authorization(session, locationUrl);
|
||||||
auth.update();
|
auth.update();
|
||||||
|
|
||||||
assertThat(auth.getDomain(), is("example.org"));
|
assertThat(auth.getDomain(), is("example.org"));
|
||||||
assertThat(auth.getStatus(), is(Status.VALID));
|
assertThat(auth.getStatus(), is(Status.VALID));
|
||||||
assertThat(auth.getExpires(), is(parseTimestamp("2016-01-02T17:12:40Z")));
|
assertThat(auth.getExpires(), is(parseTimestamp("2016-01-02T17:12:40Z")));
|
||||||
assertThat(auth.getLocation(), is(locationUri));
|
assertThat(auth.getLocation(), is(locationUrl));
|
||||||
|
|
||||||
assertThat(auth.getChallenges(), containsInAnyOrder(
|
assertThat(auth.getChallenges(), containsInAnyOrder(
|
||||||
(Challenge) httpChallenge, (Challenge) dnsChallenge));
|
(Challenge) httpChallenge, (Challenge) dnsChallenge));
|
||||||
|
|
@ -179,9 +179,9 @@ public class AuthorizationTest {
|
||||||
|
|
||||||
TestableConnectionProvider provider = new TestableConnectionProvider() {
|
TestableConnectionProvider provider = new TestableConnectionProvider() {
|
||||||
@Override
|
@Override
|
||||||
public void sendRequest(URI uri, Session session) {
|
public void sendRequest(URL url, Session session) {
|
||||||
requestWasSent.set(true);
|
requestWasSent.set(true);
|
||||||
assertThat(uri, is(locationUri));
|
assertThat(url, is(locationUrl));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -207,7 +207,7 @@ public class AuthorizationTest {
|
||||||
provider.putTestChallenge("http-01", new Http01Challenge(session));
|
provider.putTestChallenge("http-01", new Http01Challenge(session));
|
||||||
provider.putTestChallenge("dns-01", new Dns01Challenge(session));
|
provider.putTestChallenge("dns-01", new Dns01Challenge(session));
|
||||||
|
|
||||||
Authorization auth = new Authorization(session, locationUri);
|
Authorization auth = new Authorization(session, locationUrl);
|
||||||
|
|
||||||
// Lazy loading
|
// Lazy loading
|
||||||
assertThat(requestWasSent.get(), is(false));
|
assertThat(requestWasSent.get(), is(false));
|
||||||
|
|
@ -233,8 +233,8 @@ public class AuthorizationTest {
|
||||||
|
|
||||||
TestableConnectionProvider provider = new TestableConnectionProvider() {
|
TestableConnectionProvider provider = new TestableConnectionProvider() {
|
||||||
@Override
|
@Override
|
||||||
public void sendRequest(URI uri, Session session) {
|
public void sendRequest(URL url, Session session) {
|
||||||
assertThat(uri, is(locationUri));
|
assertThat(url, is(locationUrl));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -262,7 +262,7 @@ public class AuthorizationTest {
|
||||||
provider.putTestChallenge("http-01", httpChallenge);
|
provider.putTestChallenge("http-01", httpChallenge);
|
||||||
provider.putTestChallenge("dns-01", dnsChallenge);
|
provider.putTestChallenge("dns-01", dnsChallenge);
|
||||||
|
|
||||||
Authorization auth = new Authorization(session, locationUri);
|
Authorization auth = new Authorization(session, locationUrl);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
auth.update();
|
auth.update();
|
||||||
|
|
@ -274,7 +274,7 @@ public class AuthorizationTest {
|
||||||
assertThat(auth.getDomain(), is("example.org"));
|
assertThat(auth.getDomain(), is("example.org"));
|
||||||
assertThat(auth.getStatus(), is(Status.VALID));
|
assertThat(auth.getStatus(), is(Status.VALID));
|
||||||
assertThat(auth.getExpires(), is(parseTimestamp("2016-01-02T17:12:40Z")));
|
assertThat(auth.getExpires(), is(parseTimestamp("2016-01-02T17:12:40Z")));
|
||||||
assertThat(auth.getLocation(), is(locationUri));
|
assertThat(auth.getLocation(), is(locationUrl));
|
||||||
|
|
||||||
assertThat(auth.getChallenges(), containsInAnyOrder(
|
assertThat(auth.getChallenges(), containsInAnyOrder(
|
||||||
(Challenge) httpChallenge, (Challenge) dnsChallenge));
|
(Challenge) httpChallenge, (Challenge) dnsChallenge));
|
||||||
|
|
@ -295,11 +295,11 @@ public class AuthorizationTest {
|
||||||
public void testDeactivate() throws Exception {
|
public void testDeactivate() throws Exception {
|
||||||
TestableConnectionProvider provider = new TestableConnectionProvider() {
|
TestableConnectionProvider provider = new TestableConnectionProvider() {
|
||||||
@Override
|
@Override
|
||||||
public void sendSignedRequest(URI uri, JSONBuilder claims, Session session) {
|
public void sendSignedRequest(URL url, JSONBuilder claims, Session session) {
|
||||||
JSON json = claims.toJSON();
|
JSON json = claims.toJSON();
|
||||||
assertThat(json.get("resource").asString(), is("authz"));
|
assertThat(json.get("resource").asString(), is("authz"));
|
||||||
assertThat(json.get("status").asString(), is("deactivated"));
|
assertThat(json.get("status").asString(), is("deactivated"));
|
||||||
assertThat(uri, is(locationUri));
|
assertThat(url, is(locationUrl));
|
||||||
assertThat(session, is(notNullValue()));
|
assertThat(session, is(notNullValue()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -311,7 +311,7 @@ public class AuthorizationTest {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Authorization auth = new Authorization(provider.createSession(), locationUri);
|
Authorization auth = new Authorization(provider.createSession(), locationUrl);
|
||||||
auth.deactivate();
|
auth.deactivate();
|
||||||
|
|
||||||
provider.close();
|
provider.close();
|
||||||
|
|
@ -328,7 +328,7 @@ public class AuthorizationTest {
|
||||||
provider.putTestChallenge(Dns01Challenge.TYPE, new Dns01Challenge(session));
|
provider.putTestChallenge(Dns01Challenge.TYPE, new Dns01Challenge(session));
|
||||||
provider.putTestChallenge(TlsSni02Challenge.TYPE, new TlsSni02Challenge(session));
|
provider.putTestChallenge(TlsSni02Challenge.TYPE, new TlsSni02Challenge(session));
|
||||||
|
|
||||||
Authorization authorization = new Authorization(session, locationUri);
|
Authorization authorization = new Authorization(session, locationUrl);
|
||||||
authorization.unmarshalAuthorization(getJsonAsObject("authorizationChallenges"));
|
authorization.unmarshalAuthorization(getJsonAsObject("authorizationChallenges"));
|
||||||
return authorization;
|
return authorization;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ import static uk.co.datumedge.hamcrest.json.SameJSONAs.sameJSONAs;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
import java.net.URI;
|
import java.net.URL;
|
||||||
import java.security.KeyPair;
|
import java.security.KeyPair;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
|
|
@ -39,9 +39,9 @@ import org.shredzone.acme4j.toolbox.TestUtils;
|
||||||
*/
|
*/
|
||||||
public class CertificateTest {
|
public class CertificateTest {
|
||||||
|
|
||||||
private URI resourceUri = URI.create("http://example.com/acme/resource");
|
private URL resourceUrl = url("http://example.com/acme/resource");
|
||||||
private URI locationUri = URI.create("http://example.com/acme/certificate");
|
private URL locationUrl = url("http://example.com/acme/certificate");
|
||||||
private URI chainUri = URI.create("http://example.com/acme/chain");
|
private URL chainUrl = url("http://example.com/acme/chain");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test that a certificate can be downloaded.
|
* Test that a certificate can be downloaded.
|
||||||
|
|
@ -51,17 +51,17 @@ public class CertificateTest {
|
||||||
final X509Certificate originalCert = TestUtils.createCertificate();
|
final X509Certificate originalCert = TestUtils.createCertificate();
|
||||||
|
|
||||||
TestableConnectionProvider provider = new TestableConnectionProvider() {
|
TestableConnectionProvider provider = new TestableConnectionProvider() {
|
||||||
private boolean isLocationUri;
|
private boolean isLocationUrl;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendRequest(URI uri, Session session) {
|
public void sendRequest(URL url, Session session) {
|
||||||
assertThat(uri, isOneOf(locationUri, chainUri));
|
assertThat(url, isOneOf(locationUrl, chainUrl));
|
||||||
isLocationUri = uri.equals(locationUri);
|
isLocationUrl = url.equals(locationUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int accept(int... httpStatus) throws AcmeException {
|
public int accept(int... httpStatus) throws AcmeException {
|
||||||
if (isLocationUri) {
|
if (isLocationUrl) {
|
||||||
// The leaf certificate, might be asynchronous
|
// The leaf certificate, might be asynchronous
|
||||||
assertThat(httpStatus, isIntArrayContainingInAnyOrder(
|
assertThat(httpStatus, isIntArrayContainingInAnyOrder(
|
||||||
HttpURLConnection.HTTP_OK, HttpURLConnection.HTTP_ACCEPTED));
|
HttpURLConnection.HTTP_OK, HttpURLConnection.HTTP_ACCEPTED));
|
||||||
|
|
@ -84,18 +84,18 @@ public class CertificateTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public URI getLink(String relation) {
|
public URL getLink(String relation) {
|
||||||
switch(relation) {
|
switch(relation) {
|
||||||
case "up": return (isLocationUri ? chainUri : null);
|
case "up": return (isLocationUrl ? chainUrl : null);
|
||||||
default: return null;
|
default: return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Certificate cert = new Certificate(provider.createSession(), locationUri);
|
Certificate cert = new Certificate(provider.createSession(), locationUrl);
|
||||||
X509Certificate downloadedCert = cert.download();
|
X509Certificate downloadedCert = cert.download();
|
||||||
assertThat(downloadedCert, is(sameInstance(originalCert)));
|
assertThat(downloadedCert, is(sameInstance(originalCert)));
|
||||||
assertThat(cert.getChainLocation(), is(chainUri));
|
assertThat(cert.getChainLocation(), is(chainUrl));
|
||||||
|
|
||||||
X509Certificate[] downloadedChain = cert.downloadChain();
|
X509Certificate[] downloadedChain = cert.downloadChain();
|
||||||
assertThat(downloadedChain.length, is(1));
|
assertThat(downloadedChain.length, is(1));
|
||||||
|
|
@ -113,8 +113,8 @@ public class CertificateTest {
|
||||||
|
|
||||||
TestableConnectionProvider provider = new TestableConnectionProvider() {
|
TestableConnectionProvider provider = new TestableConnectionProvider() {
|
||||||
@Override
|
@Override
|
||||||
public void sendRequest(URI uri, Session session) {
|
public void sendRequest(URL url, Session session) {
|
||||||
assertThat(uri, is(locationUri));
|
assertThat(url, is(locationUrl));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -131,7 +131,7 @@ public class CertificateTest {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Certificate cert = new Certificate(provider.createSession(), locationUri);
|
Certificate cert = new Certificate(provider.createSession(), locationUrl);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
cert.download();
|
cert.download();
|
||||||
|
|
@ -152,8 +152,8 @@ public class CertificateTest {
|
||||||
|
|
||||||
TestableConnectionProvider provider = new TestableConnectionProvider() {
|
TestableConnectionProvider provider = new TestableConnectionProvider() {
|
||||||
@Override
|
@Override
|
||||||
public void sendSignedRequest(URI uri, JSONBuilder claims, Session session) {
|
public void sendSignedRequest(URL url, JSONBuilder claims, Session session) {
|
||||||
assertThat(uri, is(resourceUri));
|
assertThat(url, is(resourceUrl));
|
||||||
assertThat(claims.toString(), sameJSONAs(getJson("revokeCertificateRequest")));
|
assertThat(claims.toString(), sameJSONAs(getJson("revokeCertificateRequest")));
|
||||||
assertThat(session, is(notNullValue()));
|
assertThat(session, is(notNullValue()));
|
||||||
}
|
}
|
||||||
|
|
@ -165,9 +165,9 @@ public class CertificateTest {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
provider.putTestResource(Resource.REVOKE_CERT, resourceUri);
|
provider.putTestResource(Resource.REVOKE_CERT, resourceUrl);
|
||||||
|
|
||||||
Certificate cert = new Certificate(provider.createSession(), locationUri, null, originalCert);
|
Certificate cert = new Certificate(provider.createSession(), locationUrl, null, originalCert);
|
||||||
cert.revoke();
|
cert.revoke();
|
||||||
|
|
||||||
provider.close();
|
provider.close();
|
||||||
|
|
@ -182,8 +182,8 @@ public class CertificateTest {
|
||||||
|
|
||||||
TestableConnectionProvider provider = new TestableConnectionProvider() {
|
TestableConnectionProvider provider = new TestableConnectionProvider() {
|
||||||
@Override
|
@Override
|
||||||
public void sendSignedRequest(URI uri, JSONBuilder claims, Session session) {
|
public void sendSignedRequest(URL url, JSONBuilder claims, Session session) {
|
||||||
assertThat(uri, is(resourceUri));
|
assertThat(url, is(resourceUrl));
|
||||||
assertThat(claims.toString(), sameJSONAs(getJson("revokeCertificateWithReasonRequest")));
|
assertThat(claims.toString(), sameJSONAs(getJson("revokeCertificateWithReasonRequest")));
|
||||||
assertThat(session, is(notNullValue()));
|
assertThat(session, is(notNullValue()));
|
||||||
}
|
}
|
||||||
|
|
@ -195,9 +195,9 @@ public class CertificateTest {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
provider.putTestResource(Resource.REVOKE_CERT, resourceUri);
|
provider.putTestResource(Resource.REVOKE_CERT, resourceUrl);
|
||||||
|
|
||||||
Certificate cert = new Certificate(provider.createSession(), locationUri, null, originalCert);
|
Certificate cert = new Certificate(provider.createSession(), locationUrl, null, originalCert);
|
||||||
cert.revoke(RevocationReason.KEY_COMPROMISE);
|
cert.revoke(RevocationReason.KEY_COMPROMISE);
|
||||||
|
|
||||||
provider.close();
|
provider.close();
|
||||||
|
|
@ -213,8 +213,8 @@ public class CertificateTest {
|
||||||
|
|
||||||
TestableConnectionProvider provider = new TestableConnectionProvider() {
|
TestableConnectionProvider provider = new TestableConnectionProvider() {
|
||||||
@Override
|
@Override
|
||||||
public void sendSignedRequest(URI uri, JSONBuilder claims, Session session) {
|
public void sendSignedRequest(URL url, JSONBuilder claims, Session session) {
|
||||||
assertThat(uri, is(resourceUri));
|
assertThat(url, is(resourceUrl));
|
||||||
assertThat(claims.toString(), sameJSONAs(getJson("revokeCertificateWithReasonRequest")));
|
assertThat(claims.toString(), sameJSONAs(getJson("revokeCertificateWithReasonRequest")));
|
||||||
assertThat(session, is(notNullValue()));
|
assertThat(session, is(notNullValue()));
|
||||||
assertThat(session.getKeyPair(), is(certKeyPair));
|
assertThat(session.getKeyPair(), is(certKeyPair));
|
||||||
|
|
@ -227,7 +227,7 @@ public class CertificateTest {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
provider.putTestResource(Resource.REVOKE_CERT, resourceUri);
|
provider.putTestResource(Resource.REVOKE_CERT, resourceUrl);
|
||||||
|
|
||||||
Session session = provider.createSession();
|
Session session = provider.createSession();
|
||||||
session.setKeyPair(certKeyPair);
|
session.setKeyPair(certKeyPair);
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ import static uk.co.datumedge.hamcrest.json.SameJSONAs.sameJSONAs;
|
||||||
|
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.shredzone.acme4j.connector.Resource;
|
import org.shredzone.acme4j.connector.Resource;
|
||||||
|
|
@ -32,8 +33,8 @@ import org.shredzone.acme4j.toolbox.JSONBuilder;
|
||||||
*/
|
*/
|
||||||
public class RegistrationBuilderTest {
|
public class RegistrationBuilderTest {
|
||||||
|
|
||||||
private URI resourceUri = URI.create("http://example.com/acme/resource");;
|
private URL resourceUrl = url("http://example.com/acme/resource");
|
||||||
private URI locationUri = URI.create("http://example.com/acme/registration");;
|
private URL locationUrl = url("http://example.com/acme/registration");
|
||||||
private URI agreementUri = URI.create("http://example.com/agreement.pdf");;
|
private URI agreementUri = URI.create("http://example.com/agreement.pdf");;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -43,8 +44,8 @@ public class RegistrationBuilderTest {
|
||||||
public void testRegistration() throws Exception {
|
public void testRegistration() throws Exception {
|
||||||
TestableConnectionProvider provider = new TestableConnectionProvider() {
|
TestableConnectionProvider provider = new TestableConnectionProvider() {
|
||||||
@Override
|
@Override
|
||||||
public void sendSignedRequest(URI uri, JSONBuilder claims, Session session) {
|
public void sendSignedRequest(URL url, JSONBuilder claims, Session session) {
|
||||||
assertThat(uri, is(resourceUri));
|
assertThat(url, is(resourceUrl));
|
||||||
assertThat(claims.toString(), sameJSONAs(getJson("newRegistration")));
|
assertThat(claims.toString(), sameJSONAs(getJson("newRegistration")));
|
||||||
assertThat(session, is(notNullValue()));
|
assertThat(session, is(notNullValue()));
|
||||||
}
|
}
|
||||||
|
|
@ -56,12 +57,12 @@ public class RegistrationBuilderTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public URI getLocation() {
|
public URL getLocation() {
|
||||||
return locationUri;
|
return locationUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public URI getLink(String relation) {
|
public URI getLinkAsURI(String relation) {
|
||||||
switch(relation) {
|
switch(relation) {
|
||||||
case "terms-of-service": return agreementUri;
|
case "terms-of-service": return agreementUri;
|
||||||
default: return null;
|
default: return null;
|
||||||
|
|
@ -69,14 +70,14 @@ public class RegistrationBuilderTest {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
provider.putTestResource(Resource.NEW_REG, resourceUri);
|
provider.putTestResource(Resource.NEW_REG, resourceUrl);
|
||||||
|
|
||||||
RegistrationBuilder builder = new RegistrationBuilder();
|
RegistrationBuilder builder = new RegistrationBuilder();
|
||||||
builder.addContact("mailto:foo@example.com");
|
builder.addContact("mailto:foo@example.com");
|
||||||
|
|
||||||
Registration registration = builder.create(provider.createSession());
|
Registration registration = builder.create(provider.createSession());
|
||||||
|
|
||||||
assertThat(registration.getLocation(), is(locationUri));
|
assertThat(registration.getLocation(), is(locationUrl));
|
||||||
assertThat(registration.getAgreement(), is(agreementUri));
|
assertThat(registration.getAgreement(), is(agreementUri));
|
||||||
|
|
||||||
provider.close();
|
provider.close();
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ import static uk.co.datumedge.hamcrest.json.SameJSONAs.sameJSONAs;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
import java.net.URL;
|
||||||
import java.security.KeyPair;
|
import java.security.KeyPair;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
|
|
@ -51,10 +52,10 @@ import org.shredzone.acme4j.toolbox.TestUtils;
|
||||||
*/
|
*/
|
||||||
public class RegistrationTest {
|
public class RegistrationTest {
|
||||||
|
|
||||||
private URI resourceUri = URI.create("http://example.com/acme/resource");
|
private URL resourceUrl = url("http://example.com/acme/resource");
|
||||||
private URI locationUri = URI.create("http://example.com/acme/registration");
|
private URL locationUrl = url("http://example.com/acme/registration");
|
||||||
|
private URL chainUrl = url("http://example.com/acme/chain");
|
||||||
private URI agreementUri = URI.create("http://example.com/agreement.pdf");
|
private URI agreementUri = URI.create("http://example.com/agreement.pdf");
|
||||||
private URI chainUri = URI.create("http://example.com/acme/chain");
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test that a registration can be updated.
|
* Test that a registration can be updated.
|
||||||
|
|
@ -66,8 +67,8 @@ public class RegistrationTest {
|
||||||
private Integer response;
|
private Integer response;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendSignedRequest(URI uri, JSONBuilder claims, Session session) {
|
public void sendSignedRequest(URL url, JSONBuilder claims, Session session) {
|
||||||
assertThat(uri, is(locationUri));
|
assertThat(url, is(locationUrl));
|
||||||
assertThat(claims.toString(), sameJSONAs(getJson("updateRegistration")));
|
assertThat(claims.toString(), sameJSONAs(getJson("updateRegistration")));
|
||||||
assertThat(session, is(notNullValue()));
|
assertThat(session, is(notNullValue()));
|
||||||
jsonResponse = getJsonAsObject("updateRegistrationResponse");
|
jsonResponse = getJsonAsObject("updateRegistrationResponse");
|
||||||
|
|
@ -75,8 +76,8 @@ public class RegistrationTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendRequest(URI uri, Session session) {
|
public void sendRequest(URL url, Session session) {
|
||||||
if (URI.create("https://example.com/acme/reg/1/authz").equals(uri)) {
|
if (url("https://example.com/acme/reg/1/authz").equals(url)) {
|
||||||
jsonResponse = new JSONBuilder()
|
jsonResponse = new JSONBuilder()
|
||||||
.array("authorizations", "https://example.com/acme/auth/1")
|
.array("authorizations", "https://example.com/acme/auth/1")
|
||||||
.toJSON();
|
.toJSON();
|
||||||
|
|
@ -84,7 +85,7 @@ public class RegistrationTest {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (URI.create("https://example.com/acme/reg/1/cert").equals(uri)) {
|
if (url("https://example.com/acme/reg/1/cert").equals(url)) {
|
||||||
jsonResponse = new JSONBuilder()
|
jsonResponse = new JSONBuilder()
|
||||||
.array("certificates", "https://example.com/acme/cert/1")
|
.array("certificates", "https://example.com/acme/cert/1")
|
||||||
.toJSON();
|
.toJSON();
|
||||||
|
|
@ -107,24 +108,28 @@ public class RegistrationTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public URI getLocation() {
|
public URL getLocation() {
|
||||||
return locationUri;
|
return locationUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public URI getLink(String relation) {
|
public URL getLink(String relation) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public URI getLinkAsURI(String relation) {
|
||||||
switch(relation) {
|
switch(relation) {
|
||||||
case "terms-of-service": return agreementUri;
|
case "terms-of-service": return agreementUri;
|
||||||
case "next": return null;
|
|
||||||
default: return null;
|
default: return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Registration registration = new Registration(provider.createSession(), locationUri);
|
Registration registration = new Registration(provider.createSession(), locationUrl);
|
||||||
registration.update();
|
registration.update();
|
||||||
|
|
||||||
assertThat(registration.getLocation(), is(locationUri));
|
assertThat(registration.getLocation(), is(locationUrl));
|
||||||
assertThat(registration.getAgreement(), is(agreementUri));
|
assertThat(registration.getAgreement(), is(agreementUri));
|
||||||
assertThat(registration.getContacts(), hasSize(1));
|
assertThat(registration.getContacts(), hasSize(1));
|
||||||
assertThat(registration.getContacts().get(0), is(URI.create("mailto:foo2@example.com")));
|
assertThat(registration.getContacts().get(0), is(URI.create("mailto:foo2@example.com")));
|
||||||
|
|
@ -132,14 +137,12 @@ public class RegistrationTest {
|
||||||
|
|
||||||
Iterator<Authorization> authIt = registration.getAuthorizations();
|
Iterator<Authorization> authIt = registration.getAuthorizations();
|
||||||
assertThat(authIt, not(nullValue()));
|
assertThat(authIt, not(nullValue()));
|
||||||
assertThat(authIt.next().getLocation(),
|
assertThat(authIt.next().getLocation(), is(url("https://example.com/acme/auth/1")));
|
||||||
is(URI.create("https://example.com/acme/auth/1")));
|
|
||||||
assertThat(authIt.hasNext(), is(false));
|
assertThat(authIt.hasNext(), is(false));
|
||||||
|
|
||||||
Iterator<Certificate> certIt = registration.getCertificates();
|
Iterator<Certificate> certIt = registration.getCertificates();
|
||||||
assertThat(certIt, not(nullValue()));
|
assertThat(certIt, not(nullValue()));
|
||||||
assertThat(certIt.next().getLocation(),
|
assertThat(certIt.next().getLocation(), is(url("https://example.com/acme/cert/1")));
|
||||||
is(URI.create("https://example.com/acme/cert/1")));
|
|
||||||
assertThat(certIt.hasNext(), is(false));
|
assertThat(certIt.hasNext(), is(false));
|
||||||
|
|
||||||
provider.close();
|
provider.close();
|
||||||
|
|
@ -154,9 +157,9 @@ public class RegistrationTest {
|
||||||
|
|
||||||
TestableConnectionProvider provider = new TestableConnectionProvider() {
|
TestableConnectionProvider provider = new TestableConnectionProvider() {
|
||||||
@Override
|
@Override
|
||||||
public void sendSignedRequest(URI uri, JSONBuilder claims, Session session) {
|
public void sendSignedRequest(URL url, JSONBuilder claims, Session session) {
|
||||||
requestWasSent.set(true);
|
requestWasSent.set(true);
|
||||||
assertThat(uri, is(locationUri));
|
assertThat(url, is(locationUrl));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -172,12 +175,12 @@ public class RegistrationTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public URI getLocation() {
|
public URL getLocation() {
|
||||||
return locationUri;
|
return locationUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public URI getLink(String relation) {
|
public URI getLinkAsURI(String relation) {
|
||||||
switch(relation) {
|
switch(relation) {
|
||||||
case "terms-of-service": return agreementUri;
|
case "terms-of-service": return agreementUri;
|
||||||
default: return null;
|
default: return null;
|
||||||
|
|
@ -185,7 +188,7 @@ public class RegistrationTest {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Registration registration = new Registration(provider.createSession(), locationUri);
|
Registration registration = new Registration(provider.createSession(), locationUrl);
|
||||||
|
|
||||||
// Lazy loading
|
// Lazy loading
|
||||||
assertThat(requestWasSent.get(), is(false));
|
assertThat(requestWasSent.get(), is(false));
|
||||||
|
|
@ -208,8 +211,8 @@ public class RegistrationTest {
|
||||||
public void testAuthorizeDomain() throws Exception {
|
public void testAuthorizeDomain() throws Exception {
|
||||||
TestableConnectionProvider provider = new TestableConnectionProvider() {
|
TestableConnectionProvider provider = new TestableConnectionProvider() {
|
||||||
@Override
|
@Override
|
||||||
public void sendSignedRequest(URI uri, JSONBuilder claims, Session session) {
|
public void sendSignedRequest(URL url, JSONBuilder claims, Session session) {
|
||||||
assertThat(uri, is(resourceUri));
|
assertThat(url, is(resourceUrl));
|
||||||
assertThat(claims.toString(), sameJSONAs(getJson("newAuthorizationRequest")));
|
assertThat(claims.toString(), sameJSONAs(getJson("newAuthorizationRequest")));
|
||||||
assertThat(session, is(notNullValue()));
|
assertThat(session, is(notNullValue()));
|
||||||
}
|
}
|
||||||
|
|
@ -226,8 +229,8 @@ public class RegistrationTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public URI getLocation() {
|
public URL getLocation() {
|
||||||
return locationUri;
|
return locationUrl;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -236,19 +239,19 @@ public class RegistrationTest {
|
||||||
Http01Challenge httpChallenge = new Http01Challenge(session);
|
Http01Challenge httpChallenge = new Http01Challenge(session);
|
||||||
Dns01Challenge dnsChallenge = new Dns01Challenge(session);
|
Dns01Challenge dnsChallenge = new Dns01Challenge(session);
|
||||||
|
|
||||||
provider.putTestResource(Resource.NEW_AUTHZ, resourceUri);
|
provider.putTestResource(Resource.NEW_AUTHZ, resourceUrl);
|
||||||
provider.putTestChallenge(Http01Challenge.TYPE, httpChallenge);
|
provider.putTestChallenge(Http01Challenge.TYPE, httpChallenge);
|
||||||
provider.putTestChallenge(Dns01Challenge.TYPE, dnsChallenge);
|
provider.putTestChallenge(Dns01Challenge.TYPE, dnsChallenge);
|
||||||
|
|
||||||
String domainName = "example.org";
|
String domainName = "example.org";
|
||||||
|
|
||||||
Registration registration = new Registration(session, locationUri);
|
Registration registration = new Registration(session, locationUrl);
|
||||||
Authorization auth = registration.authorizeDomain(domainName);
|
Authorization auth = registration.authorizeDomain(domainName);
|
||||||
|
|
||||||
assertThat(auth.getDomain(), is(domainName));
|
assertThat(auth.getDomain(), is(domainName));
|
||||||
assertThat(auth.getStatus(), is(Status.PENDING));
|
assertThat(auth.getStatus(), is(Status.PENDING));
|
||||||
assertThat(auth.getExpires(), is(nullValue()));
|
assertThat(auth.getExpires(), is(nullValue()));
|
||||||
assertThat(auth.getLocation(), is(locationUri));
|
assertThat(auth.getLocation(), is(locationUrl));
|
||||||
|
|
||||||
assertThat(auth.getChallenges(), containsInAnyOrder(
|
assertThat(auth.getChallenges(), containsInAnyOrder(
|
||||||
(Challenge) httpChallenge, (Challenge) dnsChallenge));
|
(Challenge) httpChallenge, (Challenge) dnsChallenge));
|
||||||
|
|
@ -269,7 +272,7 @@ public class RegistrationTest {
|
||||||
public void testAuthorizeBadDomain() throws Exception {
|
public void testAuthorizeBadDomain() throws Exception {
|
||||||
TestableConnectionProvider provider = new TestableConnectionProvider();
|
TestableConnectionProvider provider = new TestableConnectionProvider();
|
||||||
Session session = provider.createSession();
|
Session session = provider.createSession();
|
||||||
Registration registration = Registration.bind(session, locationUri);
|
Registration registration = Registration.bind(session, locationUrl);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
registration.authorizeDomain(null);
|
registration.authorizeDomain(null);
|
||||||
|
|
@ -297,13 +300,13 @@ public class RegistrationTest {
|
||||||
|
|
||||||
TestableConnectionProvider provider = new TestableConnectionProvider() {
|
TestableConnectionProvider provider = new TestableConnectionProvider() {
|
||||||
@Override
|
@Override
|
||||||
public void sendRequest(URI uri, Session session) {
|
public void sendRequest(URL url, Session session) {
|
||||||
fail("Attempted to download the certificate. Should be downloaded already!");
|
fail("Attempted to download the certificate. Should be downloaded already!");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendSignedRequest(URI uri, JSONBuilder claims, Session session) {
|
public void sendSignedRequest(URL url, JSONBuilder claims, Session session) {
|
||||||
assertThat(uri, is(resourceUri));
|
assertThat(url, is(resourceUrl));
|
||||||
assertThat(claims.toString(), sameJSONAs(getJson("requestCertificateRequestWithDate")));
|
assertThat(claims.toString(), sameJSONAs(getJson("requestCertificateRequestWithDate")));
|
||||||
assertThat(session, is(notNullValue()));
|
assertThat(session, is(notNullValue()));
|
||||||
}
|
}
|
||||||
|
|
@ -321,32 +324,32 @@ public class RegistrationTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public URI getLocation() {
|
public URL getLocation() {
|
||||||
return locationUri;
|
return locationUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public URI getLink(String relation) {
|
public URL getLink(String relation) {
|
||||||
switch(relation) {
|
switch(relation) {
|
||||||
case "up": return chainUri;
|
case "up": return chainUrl;
|
||||||
default: return null;
|
default: return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
provider.putTestResource(Resource.NEW_CERT, resourceUri);
|
provider.putTestResource(Resource.NEW_CERT, resourceUrl);
|
||||||
|
|
||||||
byte[] csr = TestUtils.getResourceAsByteArray("/csr.der");
|
byte[] csr = TestUtils.getResourceAsByteArray("/csr.der");
|
||||||
ZoneId utc = ZoneId.of("UTC");
|
ZoneId utc = ZoneId.of("UTC");
|
||||||
Instant notBefore = LocalDate.of(2016, 1, 1).atStartOfDay(utc).toInstant();
|
Instant notBefore = LocalDate.of(2016, 1, 1).atStartOfDay(utc).toInstant();
|
||||||
Instant notAfter = LocalDate.of(2016, 1, 8).atStartOfDay(utc).toInstant();
|
Instant notAfter = LocalDate.of(2016, 1, 8).atStartOfDay(utc).toInstant();
|
||||||
|
|
||||||
Registration registration = new Registration(provider.createSession(), locationUri);
|
Registration registration = new Registration(provider.createSession(), locationUrl);
|
||||||
Certificate cert = registration.requestCertificate(csr, notBefore, notAfter);
|
Certificate cert = registration.requestCertificate(csr, notBefore, notAfter);
|
||||||
|
|
||||||
assertThat(cert.download(), is(originalCert));
|
assertThat(cert.download(), is(originalCert));
|
||||||
assertThat(cert.getLocation(), is(locationUri));
|
assertThat(cert.getLocation(), is(locationUrl));
|
||||||
assertThat(cert.getChainLocation(), is(chainUri));
|
assertThat(cert.getChainLocation(), is(chainUrl));
|
||||||
|
|
||||||
provider.close();
|
provider.close();
|
||||||
}
|
}
|
||||||
|
|
@ -358,8 +361,8 @@ public class RegistrationTest {
|
||||||
public void testRequestCertificateAsync() throws AcmeException, IOException {
|
public void testRequestCertificateAsync() throws AcmeException, IOException {
|
||||||
TestableConnectionProvider provider = new TestableConnectionProvider() {
|
TestableConnectionProvider provider = new TestableConnectionProvider() {
|
||||||
@Override
|
@Override
|
||||||
public void sendSignedRequest(URI uri, JSONBuilder claims, Session session) {
|
public void sendSignedRequest(URL url, JSONBuilder claims, Session session) {
|
||||||
assertThat(uri, is(resourceUri));
|
assertThat(url, is(resourceUrl));
|
||||||
assertThat(claims.toString(), sameJSONAs(getJson("requestCertificateRequest")));
|
assertThat(claims.toString(), sameJSONAs(getJson("requestCertificateRequest")));
|
||||||
assertThat(session, is(notNullValue()));
|
assertThat(session, is(notNullValue()));
|
||||||
}
|
}
|
||||||
|
|
@ -372,28 +375,28 @@ public class RegistrationTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public URI getLink(String relation) {
|
public URL getLink(String relation) {
|
||||||
switch(relation) {
|
switch(relation) {
|
||||||
case "up": return chainUri;
|
case "up": return chainUrl;
|
||||||
default: return null;
|
default: return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public URI getLocation() {
|
public URL getLocation() {
|
||||||
return locationUri;
|
return locationUrl;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
provider.putTestResource(Resource.NEW_CERT, resourceUri);
|
provider.putTestResource(Resource.NEW_CERT, resourceUrl);
|
||||||
|
|
||||||
byte[] csr = TestUtils.getResourceAsByteArray("/csr.der");
|
byte[] csr = TestUtils.getResourceAsByteArray("/csr.der");
|
||||||
|
|
||||||
Registration registration = new Registration(provider.createSession(), locationUri);
|
Registration registration = new Registration(provider.createSession(), locationUrl);
|
||||||
Certificate cert = registration.requestCertificate(csr);
|
Certificate cert = registration.requestCertificate(csr);
|
||||||
|
|
||||||
assertThat(cert.getLocation(), is(locationUri));
|
assertThat(cert.getLocation(), is(locationUrl));
|
||||||
assertThat(cert.getChainLocation(), is(chainUri));
|
assertThat(cert.getChainLocation(), is(chainUrl));
|
||||||
|
|
||||||
provider.close();
|
provider.close();
|
||||||
}
|
}
|
||||||
|
|
@ -406,8 +409,8 @@ public class RegistrationTest {
|
||||||
public void testRequestCertificateBrokenSync() throws AcmeException, IOException {
|
public void testRequestCertificateBrokenSync() throws AcmeException, IOException {
|
||||||
TestableConnectionProvider provider = new TestableConnectionProvider() {
|
TestableConnectionProvider provider = new TestableConnectionProvider() {
|
||||||
@Override
|
@Override
|
||||||
public void sendSignedRequest(URI uri, JSONBuilder claims, Session session) {
|
public void sendSignedRequest(URL url, JSONBuilder claims, Session session) {
|
||||||
assertThat(uri, is(resourceUri));
|
assertThat(url, is(resourceUrl));
|
||||||
assertThat(claims.toString(), sameJSONAs(getJson("requestCertificateRequestWithDate")));
|
assertThat(claims.toString(), sameJSONAs(getJson("requestCertificateRequestWithDate")));
|
||||||
assertThat(session, is(notNullValue()));
|
assertThat(session, is(notNullValue()));
|
||||||
}
|
}
|
||||||
|
|
@ -425,31 +428,31 @@ public class RegistrationTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public URI getLink(String relation) {
|
public URL getLink(String relation) {
|
||||||
switch(relation) {
|
switch(relation) {
|
||||||
case "up": return chainUri;
|
case "up": return chainUrl;
|
||||||
default: return null;
|
default: return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public URI getLocation() {
|
public URL getLocation() {
|
||||||
return locationUri;
|
return locationUrl;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
provider.putTestResource(Resource.NEW_CERT, resourceUri);
|
provider.putTestResource(Resource.NEW_CERT, resourceUrl);
|
||||||
|
|
||||||
byte[] csr = TestUtils.getResourceAsByteArray("/csr.der");
|
byte[] csr = TestUtils.getResourceAsByteArray("/csr.der");
|
||||||
ZoneId utc = ZoneId.of("UTC");
|
ZoneId utc = ZoneId.of("UTC");
|
||||||
Instant notBefore = LocalDate.of(2016, 1, 1).atStartOfDay(utc).toInstant();
|
Instant notBefore = LocalDate.of(2016, 1, 1).atStartOfDay(utc).toInstant();
|
||||||
Instant notAfter = LocalDate.of(2016, 1, 8).atStartOfDay(utc).toInstant();
|
Instant notAfter = LocalDate.of(2016, 1, 8).atStartOfDay(utc).toInstant();
|
||||||
|
|
||||||
Registration registration = new Registration(provider.createSession(), locationUri);
|
Registration registration = new Registration(provider.createSession(), locationUrl);
|
||||||
Certificate cert = registration.requestCertificate(csr, notBefore, notAfter);
|
Certificate cert = registration.requestCertificate(csr, notBefore, notAfter);
|
||||||
|
|
||||||
assertThat(cert.getLocation(), is(locationUri));
|
assertThat(cert.getLocation(), is(locationUrl));
|
||||||
assertThat(cert.getChainLocation(), is(chainUri));
|
assertThat(cert.getChainLocation(), is(chainUrl));
|
||||||
|
|
||||||
provider.close();
|
provider.close();
|
||||||
}
|
}
|
||||||
|
|
@ -464,9 +467,9 @@ public class RegistrationTest {
|
||||||
|
|
||||||
final TestableConnectionProvider provider = new TestableConnectionProvider() {
|
final TestableConnectionProvider provider = new TestableConnectionProvider() {
|
||||||
@Override
|
@Override
|
||||||
public void sendSignedRequest(URI uri, JSONBuilder payload, Session session) {
|
public void sendSignedRequest(URL url, JSONBuilder payload, Session session) {
|
||||||
try {
|
try {
|
||||||
assertThat(uri, is(locationUri));
|
assertThat(url, is(locationUrl));
|
||||||
assertThat(session, is(notNullValue()));
|
assertThat(session, is(notNullValue()));
|
||||||
assertThat(session.getKeyPair(), is(sameInstance(oldKeyPair)));
|
assertThat(session.getKeyPair(), is(sameInstance(oldKeyPair)));
|
||||||
|
|
||||||
|
|
@ -487,7 +490,7 @@ public class RegistrationTest {
|
||||||
|
|
||||||
StringBuilder expectedPayload = new StringBuilder();
|
StringBuilder expectedPayload = new StringBuilder();
|
||||||
expectedPayload.append('{');
|
expectedPayload.append('{');
|
||||||
expectedPayload.append("\"account\":\"").append(resourceUri).append("\",");
|
expectedPayload.append("\"account\":\"").append(resourceUrl).append("\",");
|
||||||
expectedPayload.append("\"newKey\":{");
|
expectedPayload.append("\"newKey\":{");
|
||||||
expectedPayload.append("\"kty\":\"").append(TestUtils.D_KTY).append("\",");
|
expectedPayload.append("\"kty\":\"").append(TestUtils.D_KTY).append("\",");
|
||||||
expectedPayload.append("\"e\":\"").append(TestUtils.D_E).append("\",");
|
expectedPayload.append("\"e\":\"").append(TestUtils.D_E).append("\",");
|
||||||
|
|
@ -506,12 +509,12 @@ public class RegistrationTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public URI getLocation() {
|
public URL getLocation() {
|
||||||
return resourceUri;
|
return resourceUrl;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
provider.putTestResource(Resource.KEY_CHANGE, locationUri);
|
provider.putTestResource(Resource.KEY_CHANGE, locationUrl);
|
||||||
|
|
||||||
Session session = new Session(new URI(TestUtils.ACME_SERVER_URI), oldKeyPair) {
|
Session session = new Session(new URI(TestUtils.ACME_SERVER_URI), oldKeyPair) {
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -522,7 +525,7 @@ public class RegistrationTest {
|
||||||
|
|
||||||
assertThat(session.getKeyPair(), is(sameInstance(oldKeyPair)));
|
assertThat(session.getKeyPair(), is(sameInstance(oldKeyPair)));
|
||||||
|
|
||||||
Registration registration = new Registration(session, resourceUri);
|
Registration registration = new Registration(session, resourceUrl);
|
||||||
registration.changeKey(newKeyPair);
|
registration.changeKey(newKeyPair);
|
||||||
|
|
||||||
assertThat(session.getKeyPair(), is(sameInstance(newKeyPair)));
|
assertThat(session.getKeyPair(), is(sameInstance(newKeyPair)));
|
||||||
|
|
@ -536,7 +539,7 @@ public class RegistrationTest {
|
||||||
TestableConnectionProvider provider = new TestableConnectionProvider();
|
TestableConnectionProvider provider = new TestableConnectionProvider();
|
||||||
Session session = provider.createSession();
|
Session session = provider.createSession();
|
||||||
|
|
||||||
Registration registration = new Registration(session, locationUri);
|
Registration registration = new Registration(session, locationUrl);
|
||||||
registration.changeKey(session.getKeyPair());
|
registration.changeKey(session.getKeyPair());
|
||||||
|
|
||||||
provider.close();
|
provider.close();
|
||||||
|
|
@ -549,11 +552,11 @@ public class RegistrationTest {
|
||||||
public void testDeactivate() throws Exception {
|
public void testDeactivate() throws Exception {
|
||||||
TestableConnectionProvider provider = new TestableConnectionProvider() {
|
TestableConnectionProvider provider = new TestableConnectionProvider() {
|
||||||
@Override
|
@Override
|
||||||
public void sendSignedRequest(URI uri, JSONBuilder claims, Session session) {
|
public void sendSignedRequest(URL url, JSONBuilder claims, Session session) {
|
||||||
JSON json = claims.toJSON();
|
JSON json = claims.toJSON();
|
||||||
assertThat(json.get("resource").asString(), is("reg"));
|
assertThat(json.get("resource").asString(), is("reg"));
|
||||||
assertThat(json.get("status").asString(), is("deactivated"));
|
assertThat(json.get("status").asString(), is("deactivated"));
|
||||||
assertThat(uri, is(locationUri));
|
assertThat(url, is(locationUrl));
|
||||||
assertThat(session, is(notNullValue()));
|
assertThat(session, is(notNullValue()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -565,7 +568,7 @@ public class RegistrationTest {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Registration registration = new Registration(provider.createSession(), locationUri);
|
Registration registration = new Registration(provider.createSession(), locationUrl);
|
||||||
registration.deactivate();
|
registration.deactivate();
|
||||||
|
|
||||||
provider.close();
|
provider.close();
|
||||||
|
|
@ -580,8 +583,8 @@ public class RegistrationTest {
|
||||||
|
|
||||||
TestableConnectionProvider provider = new TestableConnectionProvider() {
|
TestableConnectionProvider provider = new TestableConnectionProvider() {
|
||||||
@Override
|
@Override
|
||||||
public void sendSignedRequest(URI uri, JSONBuilder claims, Session session) {
|
public void sendSignedRequest(URL url, JSONBuilder claims, Session session) {
|
||||||
assertThat(uri, is(locationUri));
|
assertThat(url, is(locationUrl));
|
||||||
assertThat(claims.toString(), sameJSONAs(getJson("modifyRegistration")));
|
assertThat(claims.toString(), sameJSONAs(getJson("modifyRegistration")));
|
||||||
assertThat(session, is(notNullValue()));
|
assertThat(session, is(notNullValue()));
|
||||||
}
|
}
|
||||||
|
|
@ -598,12 +601,12 @@ public class RegistrationTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public URI getLocation() {
|
public URL getLocation() {
|
||||||
return locationUri;
|
return locationUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public URI getLink(String relation) {
|
public URI getLinkAsURI(String relation) {
|
||||||
switch(relation) {
|
switch(relation) {
|
||||||
case "terms-of-service": return agreementUri;
|
case "terms-of-service": return agreementUri;
|
||||||
default: return null;
|
default: return null;
|
||||||
|
|
@ -611,7 +614,7 @@ public class RegistrationTest {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Registration registration = new Registration(provider.createSession(), locationUri);
|
Registration registration = new Registration(provider.createSession(), locationUrl);
|
||||||
|
|
||||||
EditableRegistration editable = registration.modify();
|
EditableRegistration editable = registration.modify();
|
||||||
assertThat(editable, notNullValue());
|
assertThat(editable, notNullValue());
|
||||||
|
|
@ -621,7 +624,7 @@ public class RegistrationTest {
|
||||||
editable.getContacts().add(URI.create("mailto:foo3@example.com"));
|
editable.getContacts().add(URI.create("mailto:foo3@example.com"));
|
||||||
editable.commit();
|
editable.commit();
|
||||||
|
|
||||||
assertThat(registration.getLocation(), is(locationUri));
|
assertThat(registration.getLocation(), is(locationUrl));
|
||||||
assertThat(registration.getAgreement(), is(agreementUri));
|
assertThat(registration.getAgreement(), is(agreementUri));
|
||||||
assertThat(registration.getContacts().size(), is(2));
|
assertThat(registration.getContacts().size(), is(2));
|
||||||
assertThat(registration.getContacts().get(0), is(URI.create("mailto:foo2@example.com")));
|
assertThat(registration.getContacts().get(0), is(URI.create("mailto:foo2@example.com")));
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ package org.shredzone.acme4j;
|
||||||
import static org.hamcrest.Matchers.*;
|
import static org.hamcrest.Matchers.*;
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
import static org.mockito.Mockito.*;
|
import static org.mockito.Mockito.*;
|
||||||
import static org.shredzone.acme4j.toolbox.TestUtils.getJsonAsObject;
|
import static org.shredzone.acme4j.toolbox.TestUtils.*;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
|
@ -203,13 +203,13 @@ public class SessionTest {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
assertThat(session.resourceUri(Resource.NEW_REG),
|
assertThat(session.resourceUrl(Resource.NEW_REG),
|
||||||
is(URI.create("https://example.com/acme/new-reg")));
|
is(url("https://example.com/acme/new-reg")));
|
||||||
assertThat(session.resourceUri(Resource.NEW_AUTHZ),
|
assertThat(session.resourceUrl(Resource.NEW_AUTHZ),
|
||||||
is(URI.create("https://example.com/acme/new-authz")));
|
is(url("https://example.com/acme/new-authz")));
|
||||||
assertThat(session.resourceUri(Resource.NEW_CERT),
|
assertThat(session.resourceUrl(Resource.NEW_CERT),
|
||||||
is(URI.create("https://example.com/acme/new-cert")));
|
is(url("https://example.com/acme/new-cert")));
|
||||||
assertThat(session.resourceUri(Resource.REVOKE_CERT),
|
assertThat(session.resourceUrl(Resource.REVOKE_CERT),
|
||||||
is(nullValue()));
|
is(nullValue()));
|
||||||
|
|
||||||
Metadata meta = session.getMetadata();
|
Metadata meta = session.getMetadata();
|
||||||
|
|
@ -227,13 +227,13 @@ public class SessionTest {
|
||||||
* {@link Session} to assert
|
* {@link Session} to assert
|
||||||
*/
|
*/
|
||||||
private void assertSession(Session session) throws AcmeException {
|
private void assertSession(Session session) throws AcmeException {
|
||||||
assertThat(session.resourceUri(Resource.NEW_REG),
|
assertThat(session.resourceUrl(Resource.NEW_REG),
|
||||||
is(URI.create("https://example.com/acme/new-reg")));
|
is(url("https://example.com/acme/new-reg")));
|
||||||
assertThat(session.resourceUri(Resource.NEW_AUTHZ),
|
assertThat(session.resourceUrl(Resource.NEW_AUTHZ),
|
||||||
is(URI.create("https://example.com/acme/new-authz")));
|
is(url("https://example.com/acme/new-authz")));
|
||||||
assertThat(session.resourceUri(Resource.NEW_CERT),
|
assertThat(session.resourceUrl(Resource.NEW_CERT),
|
||||||
is(URI.create("https://example.com/acme/new-cert")));
|
is(url("https://example.com/acme/new-cert")));
|
||||||
assertThat(session.resourceUri(Resource.REVOKE_CERT),
|
assertThat(session.resourceUrl(Resource.REVOKE_CERT),
|
||||||
is(nullValue()));
|
is(nullValue()));
|
||||||
|
|
||||||
Metadata meta = session.getMetadata();
|
Metadata meta = session.getMetadata();
|
||||||
|
|
|
||||||
|
|
@ -46,8 +46,8 @@ import org.shredzone.acme4j.toolbox.TestUtils;
|
||||||
*/
|
*/
|
||||||
public class ChallengeTest {
|
public class ChallengeTest {
|
||||||
private Session session;
|
private Session session;
|
||||||
private URI resourceUri = URI.create("https://example.com/acme/some-resource");
|
private URL resourceUrl = url("https://example.com/acme/some-resource");
|
||||||
private URI locationUri = URI.create("https://example.com/acme/some-location");
|
private URL locationUrl = url("https://example.com/acme/some-location");
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setup() throws IOException {
|
public void setup() throws IOException {
|
||||||
|
|
@ -61,8 +61,8 @@ public class ChallengeTest {
|
||||||
public void testChallenge() throws Exception {
|
public void testChallenge() throws Exception {
|
||||||
TestableConnectionProvider provider = new TestableConnectionProvider() {
|
TestableConnectionProvider provider = new TestableConnectionProvider() {
|
||||||
@Override
|
@Override
|
||||||
public void sendRequest(URI uri, Session session) {
|
public void sendRequest(URL url, Session session) {
|
||||||
assertThat(uri, is(locationUri));
|
assertThat(url, is(locationUrl));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -82,11 +82,11 @@ public class ChallengeTest {
|
||||||
|
|
||||||
provider.putTestChallenge(Http01Challenge.TYPE, new Http01Challenge(session));
|
provider.putTestChallenge(Http01Challenge.TYPE, new Http01Challenge(session));
|
||||||
|
|
||||||
Http01Challenge challenge = Challenge.bind(session, locationUri);
|
Http01Challenge challenge = Challenge.bind(session, locationUrl);
|
||||||
|
|
||||||
assertThat(challenge.getType(), is(Http01Challenge.TYPE));
|
assertThat(challenge.getType(), is(Http01Challenge.TYPE));
|
||||||
assertThat(challenge.getStatus(), is(Status.VALID));
|
assertThat(challenge.getStatus(), is(Status.VALID));
|
||||||
assertThat(challenge.getLocation(), is(locationUri));
|
assertThat(challenge.getLocation(), is(locationUrl));
|
||||||
assertThat(challenge.getToken(), is("IlirfxKKXAsHtmzK29Pj8A"));
|
assertThat(challenge.getToken(), is("IlirfxKKXAsHtmzK29Pj8A"));
|
||||||
|
|
||||||
provider.close();
|
provider.close();
|
||||||
|
|
@ -111,7 +111,7 @@ public class ChallengeTest {
|
||||||
// Test unmarshalled values
|
// Test unmarshalled values
|
||||||
assertThat(challenge.getType(), is("generic-01"));
|
assertThat(challenge.getType(), is("generic-01"));
|
||||||
assertThat(challenge.getStatus(), is(Status.VALID));
|
assertThat(challenge.getStatus(), is(Status.VALID));
|
||||||
assertThat(challenge.getLocation(), is(new URI("http://example.com/challenge/123")));
|
assertThat(challenge.getLocation(), is(url("http://example.com/challenge/123")));
|
||||||
assertThat(challenge.getValidated(), is(parseTimestamp("2015-12-12T17:19:36.336785823Z")));
|
assertThat(challenge.getValidated(), is(parseTimestamp("2015-12-12T17:19:36.336785823Z")));
|
||||||
assertThat(challenge.getError(), is(notNullValue()));
|
assertThat(challenge.getError(), is(notNullValue()));
|
||||||
assertThat(challenge.getError().getType(), is(URI.create("urn:ietf:params:acme:error:connection")));
|
assertThat(challenge.getError().getType(), is(URI.create("urn:ietf:params:acme:error:connection")));
|
||||||
|
|
@ -154,8 +154,8 @@ public class ChallengeTest {
|
||||||
public void testTrigger() throws Exception {
|
public void testTrigger() throws Exception {
|
||||||
TestableConnectionProvider provider = new TestableConnectionProvider() {
|
TestableConnectionProvider provider = new TestableConnectionProvider() {
|
||||||
@Override
|
@Override
|
||||||
public void sendSignedRequest(URI uri, JSONBuilder claims, Session session) {
|
public void sendSignedRequest(URL url, JSONBuilder claims, Session session) {
|
||||||
assertThat(uri, is(resourceUri));
|
assertThat(url, is(resourceUrl));
|
||||||
assertThat(claims.toString(), sameJSONAs(getJson("triggerHttpChallengeRequest")));
|
assertThat(claims.toString(), sameJSONAs(getJson("triggerHttpChallengeRequest")));
|
||||||
assertThat(session, is(notNullValue()));
|
assertThat(session, is(notNullValue()));
|
||||||
}
|
}
|
||||||
|
|
@ -181,7 +181,7 @@ public class ChallengeTest {
|
||||||
challenge.trigger();
|
challenge.trigger();
|
||||||
|
|
||||||
assertThat(challenge.getStatus(), is(Status.PENDING));
|
assertThat(challenge.getStatus(), is(Status.PENDING));
|
||||||
assertThat(challenge.getLocation(), is(locationUri));
|
assertThat(challenge.getLocation(), is(locationUrl));
|
||||||
|
|
||||||
provider.close();
|
provider.close();
|
||||||
}
|
}
|
||||||
|
|
@ -193,8 +193,8 @@ public class ChallengeTest {
|
||||||
public void testUpdate() throws Exception {
|
public void testUpdate() throws Exception {
|
||||||
TestableConnectionProvider provider = new TestableConnectionProvider() {
|
TestableConnectionProvider provider = new TestableConnectionProvider() {
|
||||||
@Override
|
@Override
|
||||||
public void sendRequest(URI uri, Session session) {
|
public void sendRequest(URL url, Session session) {
|
||||||
assertThat(uri, is(locationUri));
|
assertThat(url, is(locationUrl));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -223,7 +223,7 @@ public class ChallengeTest {
|
||||||
challenge.update();
|
challenge.update();
|
||||||
|
|
||||||
assertThat(challenge.getStatus(), is(Status.VALID));
|
assertThat(challenge.getStatus(), is(Status.VALID));
|
||||||
assertThat(challenge.getLocation(), is(locationUri));
|
assertThat(challenge.getLocation(), is(locationUrl));
|
||||||
|
|
||||||
provider.close();
|
provider.close();
|
||||||
}
|
}
|
||||||
|
|
@ -237,8 +237,8 @@ public class ChallengeTest {
|
||||||
|
|
||||||
TestableConnectionProvider provider = new TestableConnectionProvider() {
|
TestableConnectionProvider provider = new TestableConnectionProvider() {
|
||||||
@Override
|
@Override
|
||||||
public void sendRequest(URI uri, Session session) {
|
public void sendRequest(URL url, Session session) {
|
||||||
assertThat(uri, is(locationUri));
|
assertThat(url, is(locationUrl));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -273,7 +273,7 @@ public class ChallengeTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
assertThat(challenge.getStatus(), is(Status.VALID));
|
assertThat(challenge.getStatus(), is(Status.VALID));
|
||||||
assertThat(challenge.getLocation(), is(locationUri));
|
assertThat(challenge.getLocation(), is(locationUrl));
|
||||||
|
|
||||||
provider.close();
|
provider.close();
|
||||||
}
|
}
|
||||||
|
|
@ -291,7 +291,7 @@ public class ChallengeTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Challenge.bind(null, locationUri);
|
Challenge.bind(null, locationUrl);
|
||||||
fail("session accepts null");
|
fail("session accepts null");
|
||||||
} catch (NullPointerException ex) {
|
} catch (NullPointerException ex) {
|
||||||
// expected
|
// expected
|
||||||
|
|
@ -305,8 +305,8 @@ public class ChallengeTest {
|
||||||
public void testBadBind() throws Exception {
|
public void testBadBind() throws Exception {
|
||||||
TestableConnectionProvider provider = new TestableConnectionProvider() {
|
TestableConnectionProvider provider = new TestableConnectionProvider() {
|
||||||
@Override
|
@Override
|
||||||
public void sendRequest(URI uri, Session session) {
|
public void sendRequest(URL url, Session session) {
|
||||||
assertThat(uri, is(locationUri));
|
assertThat(url, is(locationUrl));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -323,7 +323,7 @@ public class ChallengeTest {
|
||||||
};
|
};
|
||||||
|
|
||||||
Session session = provider.createSession();
|
Session session = provider.createSession();
|
||||||
Challenge.bind(session, locationUri);
|
Challenge.bind(session, locationUrl);
|
||||||
|
|
||||||
provider.close();
|
provider.close();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ package org.shredzone.acme4j.connector;
|
||||||
import static org.hamcrest.Matchers.*;
|
import static org.hamcrest.Matchers.*;
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
import static org.mockito.Mockito.*;
|
import static org.mockito.Mockito.*;
|
||||||
|
import static org.shredzone.acme4j.toolbox.TestUtils.url;
|
||||||
import static uk.co.datumedge.hamcrest.json.SameJSONAs.sameJSONAs;
|
import static uk.co.datumedge.hamcrest.json.SameJSONAs.sameJSONAs;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
|
|
@ -29,7 +30,6 @@ import java.time.Duration;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.time.temporal.ChronoUnit;
|
import java.time.temporal.ChronoUnit;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
@ -56,7 +56,7 @@ import org.shredzone.acme4j.toolbox.TestUtils;
|
||||||
*/
|
*/
|
||||||
public class DefaultConnectionTest {
|
public class DefaultConnectionTest {
|
||||||
|
|
||||||
private URI requestUri = URI.create("http://example.com/acme/");;
|
private URL requestUrl = url("http://example.com/acme/");
|
||||||
private HttpURLConnection mockUrlConnection;
|
private HttpURLConnection mockUrlConnection;
|
||||||
private HttpConnector mockHttpConnection;
|
private HttpConnector mockHttpConnection;
|
||||||
private Session session;
|
private Session session;
|
||||||
|
|
@ -66,7 +66,7 @@ public class DefaultConnectionTest {
|
||||||
mockUrlConnection = mock(HttpURLConnection.class);
|
mockUrlConnection = mock(HttpURLConnection.class);
|
||||||
|
|
||||||
mockHttpConnection = mock(HttpConnector.class);
|
mockHttpConnection = mock(HttpConnector.class);
|
||||||
when(mockHttpConnection.openConnection(requestUri)).thenReturn(mockUrlConnection);
|
when(mockHttpConnection.openConnection(requestUrl)).thenReturn(mockUrlConnection);
|
||||||
|
|
||||||
session = TestUtils.session();
|
session = TestUtils.session();
|
||||||
session.setLocale(Locale.JAPAN);
|
session.setLocale(Locale.JAPAN);
|
||||||
|
|
@ -144,8 +144,8 @@ public class DefaultConnectionTest {
|
||||||
|
|
||||||
try (DefaultConnection conn = new DefaultConnection(mockHttpConnection)) {
|
try (DefaultConnection conn = new DefaultConnection(mockHttpConnection)) {
|
||||||
conn.conn = mockUrlConnection;
|
conn.conn = mockUrlConnection;
|
||||||
URI location = conn.getLocation();
|
URL location = conn.getLocation();
|
||||||
assertThat(location, is(new URI("https://example.com/otherlocation")));
|
assertThat(location, is(url("https://example.com/otherlocation")));
|
||||||
}
|
}
|
||||||
|
|
||||||
verify(mockUrlConnection).getHeaderField("Location");
|
verify(mockUrlConnection).getHeaderField("Location");
|
||||||
|
|
@ -163,8 +163,8 @@ public class DefaultConnectionTest {
|
||||||
|
|
||||||
try (DefaultConnection conn = new DefaultConnection(mockHttpConnection)) {
|
try (DefaultConnection conn = new DefaultConnection(mockHttpConnection)) {
|
||||||
conn.conn = mockUrlConnection;
|
conn.conn = mockUrlConnection;
|
||||||
URI location = conn.getLocation();
|
URL location = conn.getLocation();
|
||||||
assertThat(location, is(new URI("https://example.org/otherlocation")));
|
assertThat(location, is(url("https://example.org/otherlocation")));
|
||||||
}
|
}
|
||||||
|
|
||||||
verify(mockUrlConnection).getHeaderField("Location");
|
verify(mockUrlConnection).getHeaderField("Location");
|
||||||
|
|
@ -191,48 +191,15 @@ public class DefaultConnectionTest {
|
||||||
|
|
||||||
try (DefaultConnection conn = new DefaultConnection(mockHttpConnection)) {
|
try (DefaultConnection conn = new DefaultConnection(mockHttpConnection)) {
|
||||||
conn.conn = mockUrlConnection;
|
conn.conn = mockUrlConnection;
|
||||||
assertThat(conn.getLink("next"), is(new URI("https://example.com/acme/new-authz")));
|
assertThat(conn.getLink("next"), is(url("https://example.com/acme/new-authz")));
|
||||||
assertThat(conn.getLink("recover"), is(new URI("https://example.org/recover-reg")));
|
assertThat(conn.getLink("recover"), is(url("https://example.org/recover-reg")));
|
||||||
assertThat(conn.getLink("terms-of-service"), is(new URI("https://example.com/acme/terms")));
|
assertThat(conn.getLink("terms-of-service"), is(url("https://example.com/acme/terms")));
|
||||||
assertThat(conn.getLink("secret-stuff"), is(nullValue()));
|
assertThat(conn.getLink("secret-stuff"), is(nullValue()));
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
assertThat(conn.getLinkAsURI("next"), is(new URI("https://example.com/acme/new-authz")));
|
||||||
* Test that multiple link headers are evaluated.
|
assertThat(conn.getLinkAsURI("recover"), is(new URI("https://example.org/recover-reg")));
|
||||||
*/
|
assertThat(conn.getLinkAsURI("terms-of-service"), is(new URI("https://example.com/acme/terms")));
|
||||||
@Test
|
assertThat(conn.getLinkAsURI("secret-stuff"), is(nullValue()));
|
||||||
public void testGetMultiLink() {
|
|
||||||
Map<String, List<String>> headers = new HashMap<>();
|
|
||||||
headers.put("Link", Arrays.asList(
|
|
||||||
"<https://example.com/acme/terms1>; rel=\"terms-of-service\"",
|
|
||||||
"<https://example.com/acme/terms2>; rel=\"terms-of-service\"",
|
|
||||||
"<https://example.com/acme/terms3>; rel=\"terms-of-service\""
|
|
||||||
));
|
|
||||||
|
|
||||||
when(mockUrlConnection.getHeaderFields()).thenReturn(headers);
|
|
||||||
|
|
||||||
try (DefaultConnection conn = new DefaultConnection(mockHttpConnection)) {
|
|
||||||
conn.conn = mockUrlConnection;
|
|
||||||
assertThat(conn.getLinks("terms-of-service"), containsInAnyOrder(
|
|
||||||
URI.create("https://example.com/acme/terms1"),
|
|
||||||
URI.create("https://example.com/acme/terms2"),
|
|
||||||
URI.create("https://example.com/acme/terms3")
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that no link headers are properly handled.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void testGetNoLink() {
|
|
||||||
Map<String, List<String>> headers = Collections.emptyMap();
|
|
||||||
when(mockUrlConnection.getHeaderFields()).thenReturn(headers);
|
|
||||||
|
|
||||||
try (DefaultConnection conn = new DefaultConnection(mockHttpConnection)) {
|
|
||||||
conn.conn = mockUrlConnection;
|
|
||||||
assertThat(conn.getLinks("something"), is(nullValue()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -243,7 +210,7 @@ public class DefaultConnectionTest {
|
||||||
public void testNoLocation() throws Exception {
|
public void testNoLocation() throws Exception {
|
||||||
try (DefaultConnection conn = new DefaultConnection(mockHttpConnection)) {
|
try (DefaultConnection conn = new DefaultConnection(mockHttpConnection)) {
|
||||||
conn.conn = mockUrlConnection;
|
conn.conn = mockUrlConnection;
|
||||||
URI location = conn.getLocation();
|
URL location = conn.getLocation();
|
||||||
assertThat(location, is(nullValue()));
|
assertThat(location, is(nullValue()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -488,7 +455,7 @@ public class DefaultConnectionTest {
|
||||||
@Test
|
@Test
|
||||||
public void testSendRequest() throws Exception {
|
public void testSendRequest() throws Exception {
|
||||||
try (DefaultConnection conn = new DefaultConnection(mockHttpConnection)) {
|
try (DefaultConnection conn = new DefaultConnection(mockHttpConnection)) {
|
||||||
conn.sendRequest(requestUri, session);
|
conn.sendRequest(requestUrl, session);
|
||||||
}
|
}
|
||||||
|
|
||||||
verify(mockUrlConnection).setRequestMethod("GET");
|
verify(mockUrlConnection).setRequestMethod("GET");
|
||||||
|
|
@ -526,7 +493,7 @@ public class DefaultConnectionTest {
|
||||||
}) {
|
}) {
|
||||||
JSONBuilder cb = new JSONBuilder();
|
JSONBuilder cb = new JSONBuilder();
|
||||||
cb.put("foo", 123).put("bar", "a-string");
|
cb.put("foo", 123).put("bar", "a-string");
|
||||||
conn.sendSignedRequest(requestUri, cb, DefaultConnectionTest.this.session);
|
conn.sendSignedRequest(requestUrl, cb, DefaultConnectionTest.this.session);
|
||||||
}
|
}
|
||||||
|
|
||||||
verify(mockUrlConnection).setRequestMethod("HEAD");
|
verify(mockUrlConnection).setRequestMethod("HEAD");
|
||||||
|
|
@ -551,7 +518,7 @@ public class DefaultConnectionTest {
|
||||||
StringBuilder expectedHeader = new StringBuilder();
|
StringBuilder expectedHeader = new StringBuilder();
|
||||||
expectedHeader.append('{');
|
expectedHeader.append('{');
|
||||||
expectedHeader.append("\"nonce\":\"").append(Base64Url.encode(nonce1)).append("\",");
|
expectedHeader.append("\"nonce\":\"").append(Base64Url.encode(nonce1)).append("\",");
|
||||||
expectedHeader.append("\"url\":\"").append(requestUri).append("\",");
|
expectedHeader.append("\"url\":\"").append(requestUrl).append("\",");
|
||||||
expectedHeader.append("\"alg\":\"RS256\",");
|
expectedHeader.append("\"alg\":\"RS256\",");
|
||||||
expectedHeader.append("\"jwk\":{");
|
expectedHeader.append("\"jwk\":{");
|
||||||
expectedHeader.append("\"kty\":\"").append(TestUtils.KTY).append("\",");
|
expectedHeader.append("\"kty\":\"").append(TestUtils.KTY).append("\",");
|
||||||
|
|
@ -576,7 +543,7 @@ public class DefaultConnectionTest {
|
||||||
public void testSendSignedRequestNoNonce() throws Exception {
|
public void testSendSignedRequestNoNonce() throws Exception {
|
||||||
try (DefaultConnection conn = new DefaultConnection(mockHttpConnection)) {
|
try (DefaultConnection conn = new DefaultConnection(mockHttpConnection)) {
|
||||||
JSONBuilder cb = new JSONBuilder();
|
JSONBuilder cb = new JSONBuilder();
|
||||||
conn.sendSignedRequest(requestUri, cb, DefaultConnectionTest.this.session);
|
conn.sendSignedRequest(requestUrl, cb, DefaultConnectionTest.this.session);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,8 +14,8 @@
|
||||||
package org.shredzone.acme4j.connector;
|
package org.shredzone.acme4j.connector;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
import java.net.URL;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
import java.util.Collection;
|
|
||||||
|
|
||||||
import org.shredzone.acme4j.Session;
|
import org.shredzone.acme4j.Session;
|
||||||
import org.shredzone.acme4j.exception.AcmeException;
|
import org.shredzone.acme4j.exception.AcmeException;
|
||||||
|
|
@ -29,12 +29,12 @@ import org.shredzone.acme4j.toolbox.JSONBuilder;
|
||||||
public class DummyConnection implements Connection {
|
public class DummyConnection implements Connection {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendRequest(URI uri, Session session) {
|
public void sendRequest(URL url, Session session) {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendSignedRequest(URI uri, JSONBuilder claims, Session session) {
|
public void sendSignedRequest(URL url, JSONBuilder claims, Session session) {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -64,17 +64,17 @@ public class DummyConnection implements Connection {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public URI getLocation() {
|
public URL getLocation() {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public URI getLink(String relation) {
|
public URL getLink(String relation) {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<URI> getLinks(String relation) {
|
public URI getLinkAsURI(String relation) {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,10 +17,10 @@ import static org.hamcrest.Matchers.*;
|
||||||
import static org.junit.Assert.assertThat;
|
import static org.junit.Assert.assertThat;
|
||||||
import static org.mockito.ArgumentMatchers.anyInt;
|
import static org.mockito.ArgumentMatchers.anyInt;
|
||||||
import static org.mockito.Mockito.*;
|
import static org.mockito.Mockito.*;
|
||||||
|
import static org.shredzone.acme4j.toolbox.TestUtils.url;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
import java.net.URI;
|
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
@ -59,7 +59,7 @@ public class HttpConnectorTest {
|
||||||
@Category(HttpURLConnection.class)
|
@Category(HttpURLConnection.class)
|
||||||
public void testOpenConnection() throws IOException, URISyntaxException {
|
public void testOpenConnection() throws IOException, URISyntaxException {
|
||||||
HttpConnector connector = new HttpConnector();
|
HttpConnector connector = new HttpConnector();
|
||||||
HttpURLConnection conn = connector.openConnection(new URI("http://example.com"));
|
HttpURLConnection conn = connector.openConnection(url("http://example.com"));
|
||||||
assertThat(conn, not(nullValue()));
|
assertThat(conn, not(nullValue()));
|
||||||
conn.connect();
|
conn.connect();
|
||||||
assertThat(conn.getResponseCode(), is(HttpURLConnection.HTTP_OK));
|
assertThat(conn.getResponseCode(), is(HttpURLConnection.HTTP_OK));
|
||||||
|
|
|
||||||
|
|
@ -15,11 +15,11 @@ package org.shredzone.acme4j.connector;
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.*;
|
import static org.hamcrest.Matchers.*;
|
||||||
import static org.junit.Assert.assertThat;
|
import static org.junit.Assert.assertThat;
|
||||||
import static org.shredzone.acme4j.toolbox.TestUtils.isIntArrayContainingInAnyOrder;
|
import static org.shredzone.acme4j.toolbox.TestUtils.*;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
import java.net.URI;
|
import java.net.URL;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
@ -43,19 +43,19 @@ public class ResourceIteratorTest {
|
||||||
private final int RESOURCES_PER_PAGE = 5;
|
private final int RESOURCES_PER_PAGE = 5;
|
||||||
private final String TYPE = "authorizations";
|
private final String TYPE = "authorizations";
|
||||||
|
|
||||||
private List<URI> resourceURIs = new ArrayList<>(PAGES * RESOURCES_PER_PAGE);
|
private List<URL> resourceURLs = new ArrayList<>(PAGES * RESOURCES_PER_PAGE);
|
||||||
private List<URI> pageURIs = new ArrayList<>(PAGES);
|
private List<URL> pageURLs = new ArrayList<>(PAGES);
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setup() {
|
public void setup() {
|
||||||
resourceURIs.clear();
|
resourceURLs.clear();
|
||||||
for (int ix = 0; ix < RESOURCES_PER_PAGE * PAGES; ix++) {
|
for (int ix = 0; ix < RESOURCES_PER_PAGE * PAGES; ix++) {
|
||||||
resourceURIs.add(URI.create("https://example.com/acme/auth/" + ix));
|
resourceURLs.add(url("https://example.com/acme/auth/" + ix));
|
||||||
}
|
}
|
||||||
|
|
||||||
pageURIs.clear();
|
pageURLs.clear();
|
||||||
for (int ix = 0; ix < PAGES; ix++) {
|
for (int ix = 0; ix < PAGES; ix++) {
|
||||||
pageURIs.add(URI.create("https://example.com/acme/batch/" + ix));
|
pageURLs.add(url("https://example.com/acme/batch/" + ix));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -76,14 +76,14 @@ public class ResourceIteratorTest {
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void iteratorTest() throws IOException {
|
public void iteratorTest() throws IOException {
|
||||||
List<URI> result = new ArrayList<>();
|
List<URL> result = new ArrayList<>();
|
||||||
|
|
||||||
Iterator<Authorization> it = createIterator(pageURIs.get(0));
|
Iterator<Authorization> it = createIterator(pageURLs.get(0));
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
result.add(it.next().getLocation());
|
result.add(it.next().getLocation());
|
||||||
}
|
}
|
||||||
|
|
||||||
assertThat(result, is(equalTo(resourceURIs)));
|
assertThat(result, is(equalTo(resourceURLs)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -91,9 +91,9 @@ public class ResourceIteratorTest {
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void nextHasNextTest() throws IOException {
|
public void nextHasNextTest() throws IOException {
|
||||||
List<URI> result = new ArrayList<>();
|
List<URL> result = new ArrayList<>();
|
||||||
|
|
||||||
Iterator<Authorization> it = createIterator(pageURIs.get(0));
|
Iterator<Authorization> it = createIterator(pageURLs.get(0));
|
||||||
assertThat(it.hasNext(), is(true));
|
assertThat(it.hasNext(), is(true));
|
||||||
assertThat(it.hasNext(), is(true));
|
assertThat(it.hasNext(), is(true));
|
||||||
|
|
||||||
|
|
@ -107,7 +107,7 @@ public class ResourceIteratorTest {
|
||||||
assertThat(it.hasNext(), is(false));
|
assertThat(it.hasNext(), is(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
assertThat(result, is(equalTo(resourceURIs)));
|
assertThat(result, is(equalTo(resourceURLs)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -115,7 +115,7 @@ public class ResourceIteratorTest {
|
||||||
*/
|
*/
|
||||||
@Test(expected = UnsupportedOperationException.class)
|
@Test(expected = UnsupportedOperationException.class)
|
||||||
public void removeTest() throws IOException {
|
public void removeTest() throws IOException {
|
||||||
Iterator<Authorization> it = createIterator(pageURIs.get(0));
|
Iterator<Authorization> it = createIterator(pageURLs.get(0));
|
||||||
it.next();
|
it.next();
|
||||||
it.remove(); // throws UnsupportedOperationException
|
it.remove(); // throws UnsupportedOperationException
|
||||||
}
|
}
|
||||||
|
|
@ -127,13 +127,13 @@ public class ResourceIteratorTest {
|
||||||
* URI of the first page
|
* URI of the first page
|
||||||
* @return Created {@link Iterator}
|
* @return Created {@link Iterator}
|
||||||
*/
|
*/
|
||||||
private Iterator<Authorization> createIterator(URI first) throws IOException {
|
private Iterator<Authorization> createIterator(URL first) throws IOException {
|
||||||
TestableConnectionProvider provider = new TestableConnectionProvider() {
|
TestableConnectionProvider provider = new TestableConnectionProvider() {
|
||||||
private int ix;
|
private int ix;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendRequest(URI uri, Session session) {
|
public void sendRequest(URL url, Session session) {
|
||||||
ix = pageURIs.indexOf(uri);
|
ix = pageURLs.indexOf(url);
|
||||||
assertThat(ix, is(greaterThanOrEqualTo(0)));
|
assertThat(ix, is(greaterThanOrEqualTo(0)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -149,15 +149,15 @@ public class ResourceIteratorTest {
|
||||||
int end = (ix + 1) * RESOURCES_PER_PAGE;
|
int end = (ix + 1) * RESOURCES_PER_PAGE;
|
||||||
|
|
||||||
JSONBuilder cb = new JSONBuilder();
|
JSONBuilder cb = new JSONBuilder();
|
||||||
cb.array(TYPE, resourceURIs.subList(start, end).toArray());
|
cb.array(TYPE, resourceURLs.subList(start, end).toArray());
|
||||||
|
|
||||||
return JSON.parse(cb.toString());
|
return JSON.parse(cb.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public URI getLink(String relation) {
|
public URL getLink(String relation) {
|
||||||
if ("next".equals(relation) && (ix + 1 < pageURIs.size())) {
|
if ("next".equals(relation) && (ix + 1 < pageURLs.size())) {
|
||||||
return pageURIs.get(ix + 1);
|
return pageURLs.get(ix + 1);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ import static org.junit.Assert.assertThat;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
import java.net.URL;
|
||||||
import java.security.KeyPair;
|
import java.security.KeyPair;
|
||||||
import java.util.ServiceLoader;
|
import java.util.ServiceLoader;
|
||||||
|
|
||||||
|
|
@ -92,7 +93,7 @@ public class SessionProviderTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public URI resolve(URI serverUri) {
|
public URL resolve(URI serverUri) {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -120,7 +121,7 @@ public class SessionProviderTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public URI resolve(URI serverUri) {
|
public URL resolve(URI serverUri) {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,8 +15,9 @@ package org.shredzone.acme4j.exception;
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.is;
|
import static org.hamcrest.Matchers.is;
|
||||||
import static org.junit.Assert.assertThat;
|
import static org.junit.Assert.assertThat;
|
||||||
|
import static org.shredzone.acme4j.toolbox.TestUtils.url;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URL;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
|
@ -28,13 +29,13 @@ public class AcmeConflictExceptionTest {
|
||||||
@Test
|
@Test
|
||||||
public void testAcmeConflictException() {
|
public void testAcmeConflictException() {
|
||||||
String msg = "Account already exists";
|
String msg = "Account already exists";
|
||||||
URI locationUri = URI.create("http://example.com/location/123");
|
URL locationUrl = url("http://example.com/location/123");
|
||||||
|
|
||||||
AcmeConflictException ex
|
AcmeConflictException ex
|
||||||
= new AcmeConflictException(msg, locationUri);
|
= new AcmeConflictException(msg, locationUrl);
|
||||||
|
|
||||||
assertThat(ex.getMessage(), is(msg));
|
assertThat(ex.getMessage(), is(msg));
|
||||||
assertThat(ex.getLocation(), is(locationUri));
|
assertThat(ex.getLocation(), is(locationUrl));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,11 +17,12 @@ import static org.hamcrest.Matchers.*;
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.Mockito.*;
|
import static org.mockito.Mockito.*;
|
||||||
import static org.shredzone.acme4j.toolbox.TestUtils.getJsonAsObject;
|
import static org.shredzone.acme4j.toolbox.TestUtils.*;
|
||||||
import static uk.co.datumedge.hamcrest.json.SameJSONAs.sameJSONAs;
|
import static uk.co.datumedge.hamcrest.json.SameJSONAs.sameJSONAs;
|
||||||
|
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
import java.net.URL;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
@ -56,7 +57,7 @@ public class AbstractAcmeProviderTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public URI resolve(URI serverUri) {
|
public URL resolve(URI serverUri) {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -79,7 +80,7 @@ public class AbstractAcmeProviderTest {
|
||||||
@Test
|
@Test
|
||||||
public void testResources() throws Exception {
|
public void testResources() throws Exception {
|
||||||
final URI testServerUri = new URI("http://example.com/acme");
|
final URI testServerUri = new URI("http://example.com/acme");
|
||||||
final URI testResolvedUri = new URI("http://example.com/acme/directory");
|
final URL testResolvedUrl = url("http://example.com/acme/directory");
|
||||||
final Connection connection = mock(Connection.class);
|
final Connection connection = mock(Connection.class);
|
||||||
final Session session = mock(Session.class);
|
final Session session = mock(Session.class);
|
||||||
|
|
||||||
|
|
@ -99,16 +100,16 @@ public class AbstractAcmeProviderTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public URI resolve(URI serverUri) {
|
public URL resolve(URI serverUri) {
|
||||||
assertThat(serverUri, is(testServerUri));
|
assertThat(serverUri, is(testServerUri));
|
||||||
return testResolvedUri;
|
return testResolvedUrl;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
JSON map = provider.directory(session, testServerUri);
|
JSON map = provider.directory(session, testServerUri);
|
||||||
assertThat(map.toString(), sameJSONAs(TestUtils.getJson("directory")));
|
assertThat(map.toString(), sameJSONAs(TestUtils.getJson("directory")));
|
||||||
|
|
||||||
verify(connection).sendRequest(testResolvedUri, session);
|
verify(connection).sendRequest(testResolvedUrl, session);
|
||||||
verify(connection).accept(any(Integer.class));
|
verify(connection).accept(any(Integer.class));
|
||||||
verify(connection).updateSession(any(Session.class));
|
verify(connection).updateSession(any(Session.class));
|
||||||
verify(connection).readJsonResponse();
|
verify(connection).readJsonResponse();
|
||||||
|
|
@ -131,7 +132,7 @@ public class AbstractAcmeProviderTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public URI resolve(URI serverUri) {
|
public URL resolve(URI serverUri) {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,10 @@ package org.shredzone.acme4j.provider;
|
||||||
import static org.hamcrest.Matchers.*;
|
import static org.hamcrest.Matchers.*;
|
||||||
import static org.junit.Assert.assertThat;
|
import static org.junit.Assert.assertThat;
|
||||||
|
|
||||||
|
import java.net.MalformedURLException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
|
@ -42,13 +44,13 @@ public class GenericAcmeProviderTest {
|
||||||
* Test if the provider resolves the URI correctly.
|
* Test if the provider resolves the URI correctly.
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testResolve() throws URISyntaxException {
|
public void testResolve() throws URISyntaxException, MalformedURLException {
|
||||||
URI serverUri = new URI("http://example.com/acme");
|
URI serverUri = new URI("http://example.com/acme");
|
||||||
|
|
||||||
GenericAcmeProvider provider = new GenericAcmeProvider();
|
GenericAcmeProvider provider = new GenericAcmeProvider();
|
||||||
|
|
||||||
URI resolvedUri = provider.resolve(serverUri);
|
URL resolvedUrl = provider.resolve(serverUri);
|
||||||
assertThat(resolvedUri, is(equalTo(serverUri)));
|
assertThat(resolvedUrl, is(equalTo(serverUri.toURL())));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ package org.shredzone.acme4j.provider;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
import java.net.URL;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
|
@ -42,9 +43,9 @@ public class TestableConnectionProvider extends DummyConnection implements AcmeP
|
||||||
* @param r
|
* @param r
|
||||||
* {@link Resource} to be mapped
|
* {@link Resource} to be mapped
|
||||||
* @param u
|
* @param u
|
||||||
* {@link URI} to be returned
|
* {@link URL} to be returned
|
||||||
*/
|
*/
|
||||||
public void putTestResource(Resource r, URI u) {
|
public void putTestResource(Resource r, URL u) {
|
||||||
directory.put(r.path(), u);
|
directory.put(r.path(), u);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -75,7 +76,7 @@ public class TestableConnectionProvider extends DummyConnection implements AcmeP
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public URI resolve(URI serverUri) {
|
public URL resolve(URI serverUri) {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ package org.shredzone.acme4j.provider.letsencrypt;
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.is;
|
import static org.hamcrest.Matchers.is;
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
import static org.shredzone.acme4j.toolbox.TestUtils.url;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
|
|
@ -52,10 +53,10 @@ public class LetsEncryptAcmeProviderTest {
|
||||||
public void testResolve() throws URISyntaxException {
|
public void testResolve() throws URISyntaxException {
|
||||||
LetsEncryptAcmeProvider provider = new LetsEncryptAcmeProvider();
|
LetsEncryptAcmeProvider provider = new LetsEncryptAcmeProvider();
|
||||||
|
|
||||||
assertThat(provider.resolve(new URI("acme://letsencrypt.org")), is(new URI(V01_DIRECTORY_URI)));
|
assertThat(provider.resolve(new URI("acme://letsencrypt.org")), is(url(V01_DIRECTORY_URI)));
|
||||||
assertThat(provider.resolve(new URI("acme://letsencrypt.org/")), is(new URI(V01_DIRECTORY_URI)));
|
assertThat(provider.resolve(new URI("acme://letsencrypt.org/")), is(url(V01_DIRECTORY_URI)));
|
||||||
assertThat(provider.resolve(new URI("acme://letsencrypt.org/v01")), is(new URI(V01_DIRECTORY_URI)));
|
assertThat(provider.resolve(new URI("acme://letsencrypt.org/v01")), is(url(V01_DIRECTORY_URI)));
|
||||||
assertThat(provider.resolve(new URI("acme://letsencrypt.org/staging")), is(new URI(STAGING_DIRECTORY_URI)));
|
assertThat(provider.resolve(new URI("acme://letsencrypt.org/staging")), is(url(STAGING_DIRECTORY_URI)));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
provider.resolve(new URI("acme://letsencrypt.org/v99"));
|
provider.resolve(new URI("acme://letsencrypt.org/v99"));
|
||||||
|
|
|
||||||
|
|
@ -15,10 +15,10 @@ package org.shredzone.acme4j.provider.letsencrypt;
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.*;
|
import static org.hamcrest.Matchers.*;
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
import static org.shredzone.acme4j.toolbox.TestUtils.url;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
import java.net.URI;
|
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
|
|
||||||
import javax.net.ssl.HttpsURLConnection;
|
import javax.net.ssl.HttpsURLConnection;
|
||||||
|
|
@ -46,7 +46,7 @@ public class LetsEncryptHttpConnectorTest {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
HttpURLConnection goodConn = connector.openConnection(
|
HttpURLConnection goodConn = connector.openConnection(
|
||||||
new URI("https://acme-staging.api.letsencrypt.org/directory"));
|
url("https://acme-staging.api.letsencrypt.org/directory"));
|
||||||
assertThat(goodConn, is(instanceOf(HttpsURLConnection.class)));
|
assertThat(goodConn, is(instanceOf(HttpsURLConnection.class)));
|
||||||
goodConn.connect();
|
goodConn.connect();
|
||||||
} catch (SSLHandshakeException ex) {
|
} catch (SSLHandshakeException ex) {
|
||||||
|
|
@ -55,7 +55,7 @@ public class LetsEncryptHttpConnectorTest {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
HttpURLConnection badConn = connector.openConnection(
|
HttpURLConnection badConn = connector.openConnection(
|
||||||
new URI("https://www.google.com"));
|
url("https://www.google.com"));
|
||||||
assertThat(badConn, is(instanceOf(HttpsURLConnection.class)));
|
assertThat(badConn, is(instanceOf(HttpsURLConnection.class)));
|
||||||
badConn.connect();
|
badConn.connect();
|
||||||
fail("Connection accepts foreign certificate");
|
fail("Connection accepts foreign certificate");
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,9 @@ import java.io.ByteArrayOutputStream;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
import java.net.URL;
|
||||||
import java.security.InvalidAlgorithmParameterException;
|
import java.security.InvalidAlgorithmParameterException;
|
||||||
import java.security.KeyFactory;
|
import java.security.KeyFactory;
|
||||||
import java.security.KeyPair;
|
import java.security.KeyPair;
|
||||||
|
|
@ -112,6 +114,22 @@ public final class TestUtils {
|
||||||
return JSON.parse(getJson(key));
|
return JSON.parse(getJson(key));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an {@link URL} from a String. Only throws a runtime exception if the URL is
|
||||||
|
* malformed.
|
||||||
|
*
|
||||||
|
* @param url
|
||||||
|
* URL to use
|
||||||
|
* @return {@link URL} object
|
||||||
|
*/
|
||||||
|
public static URL url(String url) {
|
||||||
|
try {
|
||||||
|
return new URL(url);
|
||||||
|
} catch (MalformedURLException ex) {
|
||||||
|
throw new IllegalArgumentException(url, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a {@link Session} instance. It uses {@link #ACME_SERVER_URI} as server URI.
|
* Creates a {@link Session} instance. It uses {@link #ACME_SERVER_URI} as server URI.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -110,7 +110,7 @@ public class ClientTest {
|
||||||
Certificate certificate = reg.requestCertificate(csrb.getEncoded());
|
Certificate certificate = reg.requestCertificate(csrb.getEncoded());
|
||||||
|
|
||||||
LOG.info("Success! The certificate for domains " + domains + " has been generated!");
|
LOG.info("Success! The certificate for domains " + domains + " has been generated!");
|
||||||
LOG.info("Certificate URI: " + certificate.getLocation());
|
LOG.info("Certificate URL: " + certificate.getLocation());
|
||||||
|
|
||||||
// Download the leaf certificate and certificate chain.
|
// Download the leaf certificate and certificate chain.
|
||||||
X509Certificate cert = certificate.download();
|
X509Certificate cert = certificate.download();
|
||||||
|
|
@ -151,9 +151,9 @@ public class ClientTest {
|
||||||
* created.
|
* created.
|
||||||
* <p>
|
* <p>
|
||||||
* This is a simple way of finding your {@link Registration}. A better way is to get
|
* This is a simple way of finding your {@link Registration}. A better way is to get
|
||||||
* the URI of your new registration with {@link Registration#getLocation()} and store
|
* the URL of your new registration with {@link Registration#getLocation()} and store
|
||||||
* it somewhere. If you need to get access to your account later, reconnect to it via
|
* it somewhere. If you need to get access to your account later, reconnect to it via
|
||||||
* {@link Registration#bind(Session, URI)} by using the stored location.
|
* {@link Registration#bind(Session, URL)} by using the stored location.
|
||||||
*
|
*
|
||||||
* @param session
|
* @param session
|
||||||
* {@link Session} to bind with
|
* {@link Session} to bind with
|
||||||
|
|
@ -165,7 +165,7 @@ public class ClientTest {
|
||||||
try {
|
try {
|
||||||
// Try to create a new Registration.
|
// Try to create a new Registration.
|
||||||
reg = new RegistrationBuilder().create(session);
|
reg = new RegistrationBuilder().create(session);
|
||||||
LOG.info("Registered a new user, URI: " + reg.getLocation());
|
LOG.info("Registered a new user, URL: " + reg.getLocation());
|
||||||
|
|
||||||
// This is a new account. Let the user accept the Terms of Service.
|
// This is a new account. Let the user accept the Terms of Service.
|
||||||
// We won't be able to authorize domains until the ToS is accepted.
|
// We won't be able to authorize domains until the ToS is accepted.
|
||||||
|
|
@ -177,7 +177,7 @@ public class ClientTest {
|
||||||
// The Key Pair is already registered. getLocation() contains the
|
// The Key Pair is already registered. getLocation() contains the
|
||||||
// URL of the existing registration's location. Bind it to the session.
|
// URL of the existing registration's location. Bind it to the session.
|
||||||
reg = Registration.bind(session, ex.getLocation());
|
reg = Registration.bind(session, ex.getLocation());
|
||||||
LOG.info("Account does already exist, URI: " + reg.getLocation(), ex);
|
LOG.info("Account does already exist, URL: " + reg.getLocation(), ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
return reg;
|
return reg;
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,10 @@
|
||||||
|
|
||||||
This document will help you migrate your code to the latest _acme4j_ version.
|
This document will help you migrate your code to the latest _acme4j_ version.
|
||||||
|
|
||||||
|
## Migration to Version 0.14
|
||||||
|
|
||||||
|
All resource locations are now `URL` objects (previously they were `URI`s). This should affect your source only in a minimum way, if any.
|
||||||
|
|
||||||
## Migration to Version 0.13
|
## Migration to Version 0.13
|
||||||
|
|
||||||
In the `acme4j-client` module, the `org.shredzone.acme4j.util` package has been renamed in order to fix a split package in Java 9. This package is meant to be internal, so this change should not break your code. The same named public package in the `acme4j-utils` module is unchanged.
|
In the `acme4j-client` module, the `org.shredzone.acme4j.util` package has been renamed in order to fix a split package in Java 9. This package is meant to be internal, so this change should not break your code. The same named public package in the `acme4j-utils` module is unchanged.
|
||||||
|
|
|
||||||
|
|
@ -21,11 +21,11 @@ However, it is also possible to adapt the behavior of wide parts of _acme4j_ to
|
||||||
A client provider implements the [`AcmeProvider`](./apidocs/org/shredzone/acme4j/provider/AcmeProvider.html) interface, but usually it is easier to extend [`AbstractAcmeProvider`](./apidocs/org/shredzone/acme4j/provider/AbstractAcmeProvider.html) and implement only these two methods:
|
A client provider implements the [`AcmeProvider`](./apidocs/org/shredzone/acme4j/provider/AcmeProvider.html) interface, but usually it is easier to extend [`AbstractAcmeProvider`](./apidocs/org/shredzone/acme4j/provider/AbstractAcmeProvider.html) and implement only these two methods:
|
||||||
|
|
||||||
* `accepts(URI)` checks if the client provider is accepting the provided URI. Usually it would be an URI like `acme://example.com`. Note that the `http` and `https` schemes are reserved for the generic provider and cannot be used by other providers.
|
* `accepts(URI)` checks if the client provider is accepting the provided URI. Usually it would be an URI like `acme://example.com`. Note that the `http` and `https` schemes are reserved for the generic provider and cannot be used by other providers.
|
||||||
* `resolve(URI)` parses that URI and returns the corresponding URI of the directory service.
|
* `resolve(URI)` parses that URI and returns the corresponding URL of the directory service.
|
||||||
|
|
||||||
The `AcmeProvider` implementation needs to be registered with Java's `ServiceLoader`. In the `META-INF/services` path of your project, create a file `org.shredzone.acme4j.provider.AcmeProvider` and write the fully qualified class name of your implementation into that file.
|
The `AcmeProvider` implementation needs to be registered with Java's `ServiceLoader`. In the `META-INF/services` path of your project, create a file `org.shredzone.acme4j.provider.AcmeProvider` and write the fully qualified class name of your implementation into that file.
|
||||||
|
|
||||||
When _acme4j_ tries to connect to an acme URI, it first invokes the `accepts(URI)` method of all registered `AcmeProvider`s. Only one of the providers must return `true` for a successful connection. _acme4j_ then invokes the `resolve(URI)` method of that provider, and connects to the directory URI that is returned.
|
When _acme4j_ tries to connect to an acme URI, it first invokes the `accepts(URI)` method of all registered `AcmeProvider`s. Only one of the providers must return `true` for a successful connection. _acme4j_ then invokes the `resolve(URI)` method of that provider, and connects to the directory URL that is returned.
|
||||||
|
|
||||||
The connection fails if none or more than one `AcmeProvider` implementations `accept` the acme URI.
|
The connection fails if none or more than one `AcmeProvider` implementations `accept` the acme URI.
|
||||||
|
|
||||||
|
|
@ -43,6 +43,6 @@ In your `AcmeProvider` implementation, override the `createChallenge(Session, St
|
||||||
|
|
||||||
## No directory service
|
## No directory service
|
||||||
|
|
||||||
An ACME server may not provide a directory service, for example when fixed URIs are to be used.
|
An ACME server may not provide a directory service, for example when fixed URLs are to be used.
|
||||||
|
|
||||||
In this case, override the `resources(Session, URI)` method, and return a `Map` of all available resources and their respective URI.
|
In this case, override the `resources(Session, URI)` method, and return a `Map` of all available resources and their respective URL.
|
||||||
|
|
|
||||||
|
|
@ -56,12 +56,12 @@ If your final certificate will contain further domains or subdomains, repeat the
|
||||||
|
|
||||||
## Update an Authorization
|
## Update an Authorization
|
||||||
|
|
||||||
The server also provides an authorization URI. It can be retrieved from `Authorization.getLocation()`. You can recreate the `Authorization` object at a later time just by binding it to your `Session`:
|
The server also provides an authorization URL. It can be retrieved from `Authorization.getLocation()`. You can recreate the `Authorization` object at a later time just by binding it to your `Session`:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
URI authUri = ... // Authorization URI
|
URL authUrl = ... // Authorization URL
|
||||||
|
|
||||||
Authorization auth = Authorization.bind(session, authUri);
|
Authorization auth = Authorization.bind(session, authUrl);
|
||||||
```
|
```
|
||||||
|
|
||||||
As soon as you invoke a getter, the `Authorization` object lazily loads the current server state of your authorization, including the domain name, the overall status, and an expiry date.
|
As soon as you invoke a getter, the `Authorization` object lazily loads the current server state of your authorization, including the domain name, the overall status, and an expiry date.
|
||||||
|
|
@ -84,14 +84,14 @@ To recreate a `Challenge` object at a later time, all you need is to store the o
|
||||||
|
|
||||||
```java
|
```java
|
||||||
Challenge originalChallenge = ... // some Challenge instance
|
Challenge originalChallenge = ... // some Challenge instance
|
||||||
URI challengeUri = originalChallenge.getLocation();
|
URL challengeUrl = originalChallenge.getLocation();
|
||||||
```
|
```
|
||||||
|
|
||||||
Later, you restore the `Challenge` object by invoking `Challenge.bind()`.
|
Later, you restore the `Challenge` object by invoking `Challenge.bind()`.
|
||||||
|
|
||||||
```java
|
```java
|
||||||
URI challengeUri = ... // challenge URI
|
URL challengeUrl = ... // challenge URL
|
||||||
Challenge restoredChallenge = Challenge.bind(session, challengeUri);
|
Challenge restoredChallenge = Challenge.bind(session, challengeUrl);
|
||||||
```
|
```
|
||||||
|
|
||||||
The `restoredChallenge` already reflects the current state of the challenge.
|
The `restoredChallenge` already reflects the current state of the challenge.
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ Now all you need to do is to pass in a binary representation of the CSR and requ
|
||||||
Certificate cert = registration.requestCertificate(csr);
|
Certificate cert = registration.requestCertificate(csr);
|
||||||
```
|
```
|
||||||
|
|
||||||
`cert.getLocation()` returns an URI where the signed certificate can be downloaded from. Optionally (if delivered by the ACME server) `cert.getChainLocation()` returns the URI of the first part of the CA chain.
|
`cert.getLocation()` returns an URL where the signed certificate can be downloaded from. Optionally (if delivered by the ACME server) `cert.getChainLocation()` returns the URL of the first part of the CA chain.
|
||||||
|
|
||||||
The `Certificate` object offers methods to download the certificate and the certificate chain.
|
The `Certificate` object offers methods to download the certificate and the certificate chain.
|
||||||
|
|
||||||
|
|
@ -50,8 +50,8 @@ Congratulations! You have just created your first certificate via _acme4j_.
|
||||||
To recreate a `Certificate` object from the location, just bind it:
|
To recreate a `Certificate` object from the location, just bind it:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
URI locationUri = ... // location URI from cert.getLocation()
|
URL locationUrl = ... // location URL from cert.getLocation()
|
||||||
Certificate cert = Certificate.bind(session, locationUri);
|
Certificate cert = Certificate.bind(session, locationUrl);
|
||||||
```
|
```
|
||||||
|
|
||||||
### Saving Certificates
|
### Saving Certificates
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
If it is the first time you connect to the ACME server, you need to register your account key.
|
If it is the first time you connect to the ACME server, you need to register your account key.
|
||||||
|
|
||||||
To do so, create a `RegistrationBuilder`, optionally add some contact information, then invoke `create()`. If the account was successfully created, you will get a `Registration` object in return. Invoking its `getLocation()` method will return the location URI of your account. You should store it somewhere, because you will need it later. Unlike your key pair, the location is a public information that does not need security precautions.
|
To do so, create a `RegistrationBuilder`, optionally add some contact information, then invoke `create()`. If the account was successfully created, you will get a `Registration` object in return. Invoking its `getLocation()` method will return the location URL of your account. You should store it somewhere, because you will need it later. Unlike your key pair, the location is a public information that does not need security precautions.
|
||||||
|
|
||||||
```java
|
```java
|
||||||
RegistrationBuilder builder = new RegistrationBuilder();
|
RegistrationBuilder builder = new RegistrationBuilder();
|
||||||
|
|
@ -10,10 +10,10 @@ builder.addContact("mailto:acme@example.com");
|
||||||
|
|
||||||
Registration registration = builder.create(session);
|
Registration registration = builder.create(session);
|
||||||
|
|
||||||
URI accountLocationUri = registration.getLocation();
|
URL accountLocationUrl = registration.getLocation();
|
||||||
```
|
```
|
||||||
|
|
||||||
`create()` will fail and throw an `AcmeConflictException` if your key was already registered with the CA. The `AcmeConflictException` contains the location of the registration. This may be helpful if you forgot your account URI and need to recover it.
|
`create()` will fail and throw an `AcmeConflictException` if your key was already registered with the CA. The `AcmeConflictException` contains the location of the registration. This may be helpful if you forgot your account URL and need to recover it.
|
||||||
|
|
||||||
The following example will create a new `Registration` and restore an existing `Registration`.
|
The following example will create a new `Registration` and restore an existing `Registration`.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,12 +31,12 @@ Instead of a generic provider, this call uses a special _Let's Encrypt_ provider
|
||||||
Now that you have a `Session` object, you can use it to bind ACME resource objects. For example, this is the way to get a `Registration` object to an existing registration:
|
Now that you have a `Session` object, you can use it to bind ACME resource objects. For example, this is the way to get a `Registration` object to an existing registration:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
URI accountLocationUri = ... // your account's URI, as returned by Registration.getLocation()
|
URL accountLocationUrl = ... // your account's URL, as returned by Registration.getLocation()
|
||||||
|
|
||||||
Registration registration = Registration.bind(session, accountLocationUri);
|
Registration registration = Registration.bind(session, accountLocationUrl);
|
||||||
```
|
```
|
||||||
|
|
||||||
You can create any of the resource objects `Registration`, `Authorization`, `Challenge` and `Certificate` like that, as long as you know the corresponding resource URI. To get the resource URI, use the `getLocation()` method.
|
You can create any of the resource objects `Registration`, `Authorization`, `Challenge` and `Certificate` like that, as long as you know the corresponding resource URL. To get the resource URL, use the `getLocation()` method.
|
||||||
|
|
||||||
## Serialization
|
## Serialization
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue