mirror of https://github.com/shred/acme4j
Support acme-star-09 draft, change API and documentation
parent
f1e3048dd2
commit
9d62cb6a55
|
@ -19,6 +19,7 @@ import java.net.URI;
|
|||
import java.net.URL;
|
||||
import java.time.Duration;
|
||||
import java.util.Collection;
|
||||
import java.util.Optional;
|
||||
|
||||
import javax.annotation.CheckForNull;
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
|
@ -88,8 +89,8 @@ public class Metadata {
|
|||
*
|
||||
* @since 2.3
|
||||
*/
|
||||
public boolean isStarEnabled() {
|
||||
return meta.get("star-enabled").map(Value::asBoolean).orElse(false);
|
||||
public boolean isAutoRenewalEnabled() {
|
||||
return meta.get("auto-renewal").isPresent();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -99,18 +100,26 @@ public class Metadata {
|
|||
*
|
||||
* @since 2.3
|
||||
*/
|
||||
public Duration getStarMinCertValidity() {
|
||||
return meta.get("star-min-cert-validity").map(Value::asDuration).orElse(null);
|
||||
public Duration getAutoRenewalMinLifetime() {
|
||||
Optional<JSON> ar = meta.get("auto-renewal").optional().map(Value::asObject);
|
||||
if (!ar.isPresent()) {
|
||||
return null;
|
||||
}
|
||||
return ar.get().get("min-lifetime").map(Value::asDuration).orElse(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the maximum delta between recurrent end date and recurrent start date.
|
||||
* {@code null} if the CA does not support short-term auto renewal.
|
||||
* Returns the maximum delta between auto-renewal end date and auto-renewal start
|
||||
* date. {@code null} if the CA does not support short-term auto renewal.
|
||||
*
|
||||
* @since 2.3
|
||||
*/
|
||||
public Duration getStarMaxRenewal() {
|
||||
return meta.get("star-max-renewal").map(Value::asDuration).orElse(null);
|
||||
public Duration getAutoRenewalMaxDuration() {
|
||||
Optional<JSON> ar = meta.get("auto-renewal").optional().map(Value::asObject);
|
||||
if (!ar.isPresent()) {
|
||||
return null;
|
||||
}
|
||||
return ar.get().get("max-duration").map(Value::asDuration).orElse(null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -118,8 +127,12 @@ public class Metadata {
|
|||
*
|
||||
* @since 2.6
|
||||
*/
|
||||
public boolean isStarCertificateGetAllowed() {
|
||||
return meta.get("star-allow-certificate-get").map(Value::asBoolean).orElse(false);
|
||||
public boolean isAutoRenewalGetAllowed() {
|
||||
Optional<JSON> ar = meta.get("auto-renewal").optional().map(Value::asObject);
|
||||
if (!ar.isPresent()) {
|
||||
return false;
|
||||
}
|
||||
return ar.get().get("allow-certificate-get").map(Value::asBoolean).orElse(false);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -26,6 +26,7 @@ import javax.annotation.ParametersAreNonnullByDefault;
|
|||
|
||||
import org.shredzone.acme4j.connector.Connection;
|
||||
import org.shredzone.acme4j.exception.AcmeException;
|
||||
import org.shredzone.acme4j.toolbox.JSON;
|
||||
import org.shredzone.acme4j.toolbox.JSON.Value;
|
||||
import org.shredzone.acme4j.toolbox.JSONBuilder;
|
||||
import org.slf4j.Logger;
|
||||
|
@ -138,7 +139,7 @@ public class Order extends AcmeJsonResource {
|
|||
* @since 2.6
|
||||
*/
|
||||
@CheckForNull
|
||||
public Certificate getStarCertificate() {
|
||||
public Certificate getAutoRenewalCertificate() {
|
||||
return getJSON().get("star-certificate")
|
||||
.map(Value::asURL)
|
||||
.map(getLogin()::bindCertificate)
|
||||
|
@ -171,15 +172,14 @@ public class Order extends AcmeJsonResource {
|
|||
}
|
||||
|
||||
/**
|
||||
* Checks if this order is recurrent, according to the ACME STAR specifications.
|
||||
* Checks if this order is auto-renewing, according to the ACME STAR specifications.
|
||||
*
|
||||
* @since 2.3
|
||||
*/
|
||||
public boolean isRecurrent() {
|
||||
return getJSON().get("recurrent")
|
||||
public boolean isAutoRenewing() {
|
||||
return getJSON().get("auto-renewal")
|
||||
.optional()
|
||||
.map(Value::asBoolean)
|
||||
.orElse(false);
|
||||
.isPresent();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -189,8 +189,12 @@ public class Order extends AcmeJsonResource {
|
|||
* @since 2.3
|
||||
*/
|
||||
@CheckForNull
|
||||
public Instant getRecurrentStart() {
|
||||
return getJSON().get("recurrent-start-date")
|
||||
public Instant getAutoRenewalStartDate() {
|
||||
return getJSON().get("auto-renewal")
|
||||
.optional()
|
||||
.map(Value::asObject)
|
||||
.orElseGet(JSON::empty)
|
||||
.get("start-date")
|
||||
.optional()
|
||||
.map(Value::asInstant)
|
||||
.orElse(null);
|
||||
|
@ -203,21 +207,29 @@ public class Order extends AcmeJsonResource {
|
|||
* @since 2.3
|
||||
*/
|
||||
@CheckForNull
|
||||
public Instant getRecurrentEnd() {
|
||||
return getJSON().get("recurrent-end-date")
|
||||
public Instant getAutoRenewalEndDate() {
|
||||
return getJSON().get("auto-renewal")
|
||||
.optional()
|
||||
.map(Value::asObject)
|
||||
.orElseGet(JSON::empty)
|
||||
.get("end-date")
|
||||
.optional()
|
||||
.map(Value::asInstant)
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the maximum validity period of each certificate, or {@code null}.
|
||||
* Returns the maximum lifetime of each certificate, or {@code null}.
|
||||
*
|
||||
* @since 2.3
|
||||
*/
|
||||
@CheckForNull
|
||||
public Duration getRecurrentCertificateValidity() {
|
||||
return getJSON().get("recurrent-certificate-validity")
|
||||
public Duration getAutoRenewalLifetime() {
|
||||
return getJSON().get("auto-renewal")
|
||||
.optional()
|
||||
.map(Value::asObject)
|
||||
.orElseGet(JSON::empty)
|
||||
.get("lifetime")
|
||||
.optional()
|
||||
.map(Value::asDuration)
|
||||
.orElse(null);
|
||||
|
@ -229,8 +241,12 @@ public class Order extends AcmeJsonResource {
|
|||
* @since 2.7
|
||||
*/
|
||||
@CheckForNull
|
||||
public Duration getRecurrentCertificatePredate() {
|
||||
return getJSON().get("recurrent-certificate-predate")
|
||||
public Duration getAutoRenewalLifetimeAdjust() {
|
||||
return getJSON().get("auto-renewal")
|
||||
.optional()
|
||||
.map(Value::asObject)
|
||||
.orElseGet(JSON::empty)
|
||||
.get("lifetime-adjust")
|
||||
.optional()
|
||||
.map(Value::asDuration)
|
||||
.orElse(null);
|
||||
|
@ -242,20 +258,24 @@ public class Order extends AcmeJsonResource {
|
|||
*
|
||||
* @since 2.6
|
||||
*/
|
||||
public boolean isRecurrentGetEnabled() {
|
||||
return getJSON().get("recurrent-certificate-get")
|
||||
public boolean isAutoRenewalGetEnabled() {
|
||||
return getJSON().get("auto-renewal")
|
||||
.optional()
|
||||
.map(Value::asObject)
|
||||
.orElseGet(JSON::empty)
|
||||
.get("allow-certificate-get")
|
||||
.optional()
|
||||
.map(Value::asBoolean)
|
||||
.orElse(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancels a recurrent order.
|
||||
* Cancels an auto-renewing order.
|
||||
*
|
||||
* @since 2.3
|
||||
*/
|
||||
public void cancelRecurrent() throws AcmeException {
|
||||
if (!getSession().getMetadata().isStarEnabled()) {
|
||||
public void cancelAutoRenewal() throws AcmeException {
|
||||
if (!getSession().getMetadata().isAutoRenewalEnabled()) {
|
||||
throw new AcmeException("CA does not support short-term automatic renewals");
|
||||
}
|
||||
|
||||
|
|
|
@ -45,12 +45,12 @@ public class OrderBuilder {
|
|||
private final Set<Identifier> identifierSet = new LinkedHashSet<>();
|
||||
private Instant notBefore;
|
||||
private Instant notAfter;
|
||||
private boolean recurrent;
|
||||
private Instant recurrentStart;
|
||||
private Instant recurrentEnd;
|
||||
private Duration recurrentValidity;
|
||||
private Duration recurrentPredate;
|
||||
private boolean recurrentGet;
|
||||
private boolean autoRenewal;
|
||||
private Instant autoRenewalStart;
|
||||
private Instant autoRenewalEnd;
|
||||
private Duration autoRenewalLifetime;
|
||||
private Duration autoRenewalLifetimeAdjust;
|
||||
private boolean autoRenewalGet;
|
||||
|
||||
/**
|
||||
* Create a new {@link OrderBuilder}.
|
||||
|
@ -137,8 +137,8 @@ public class OrderBuilder {
|
|||
* @return itself
|
||||
*/
|
||||
public OrderBuilder notBefore(Instant notBefore) {
|
||||
if (recurrent) {
|
||||
throw new IllegalArgumentException("cannot combine notBefore with recurrent");
|
||||
if (autoRenewal) {
|
||||
throw new IllegalArgumentException("cannot combine notBefore with autoRenew");
|
||||
}
|
||||
this.notBefore = requireNonNull(notBefore, "notBefore");
|
||||
return this;
|
||||
|
@ -151,8 +151,8 @@ public class OrderBuilder {
|
|||
* @return itself
|
||||
*/
|
||||
public OrderBuilder notAfter(Instant notAfter) {
|
||||
if (recurrent) {
|
||||
throw new IllegalArgumentException("cannot combine notAfter with recurrent");
|
||||
if (autoRenewal) {
|
||||
throw new IllegalArgumentException("cannot combine notAfter with autoRenew");
|
||||
}
|
||||
this.notAfter = requireNonNull(notAfter, "notAfter");
|
||||
return this;
|
||||
|
@ -162,17 +162,17 @@ public class OrderBuilder {
|
|||
* Enables short-term automatic renewal of the certificate. Must be supported by the
|
||||
* CA.
|
||||
* <p>
|
||||
* Recurrent renewals cannot be combined with {@link #notBefore(Instant)} or
|
||||
* {@link #notAfter(Instant)}.
|
||||
* Automatic renewals cannot be combined with {@link #notBefore(Instant)} or {@link
|
||||
* #notAfter(Instant)}.
|
||||
*
|
||||
* @return itself
|
||||
* @since 2.3
|
||||
*/
|
||||
public OrderBuilder recurrent() {
|
||||
public OrderBuilder autoRenewal() {
|
||||
if (notBefore != null || notAfter != null) {
|
||||
throw new IllegalArgumentException("cannot combine notBefore/notAfter with recurrent");
|
||||
throw new IllegalArgumentException("cannot combine notBefore/notAfter with autoRenewalOr");
|
||||
}
|
||||
this.recurrent = true;
|
||||
this.autoRenewal = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -180,16 +180,16 @@ public class OrderBuilder {
|
|||
* Sets the earliest date of validity of the first issued certificate. If not set,
|
||||
* the start date is the earliest possible date.
|
||||
* <p>
|
||||
* Implies {@link #recurrent()}.
|
||||
* Implies {@link #autoRenewal()}.
|
||||
*
|
||||
* @param start
|
||||
* Start date of validity
|
||||
* @return itself
|
||||
* @since 2.3
|
||||
*/
|
||||
public OrderBuilder recurrentStart(Instant start) {
|
||||
recurrent();
|
||||
this.recurrentStart = requireNonNull(start, "start");
|
||||
public OrderBuilder autoRenewalStart(Instant start) {
|
||||
autoRenewal();
|
||||
this.autoRenewalStart = requireNonNull(start, "start");
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -197,17 +197,17 @@ public class OrderBuilder {
|
|||
* Sets the latest date of validity of the last issued certificate. If not set, the
|
||||
* CA's default is used.
|
||||
* <p>
|
||||
* Implies {@link #recurrent()}.
|
||||
* Implies {@link #autoRenewal()}.
|
||||
*
|
||||
* @param end
|
||||
* End date of validity
|
||||
* @return itself
|
||||
* @see Metadata#getStarMaxRenewal()
|
||||
* @see Metadata#getAutoRenewalMaxDuration()
|
||||
* @since 2.3
|
||||
*/
|
||||
public OrderBuilder recurrentEnd(Instant end) {
|
||||
recurrent();
|
||||
this.recurrentEnd = requireNonNull(end, "end");
|
||||
public OrderBuilder autoRenewalEnd(Instant end) {
|
||||
autoRenewal();
|
||||
this.autoRenewalEnd = requireNonNull(end, "end");
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -215,17 +215,17 @@ public class OrderBuilder {
|
|||
* Sets the maximum validity period of each certificate. If not set, the CA's
|
||||
* default is used.
|
||||
* <p>
|
||||
* Implies {@link #recurrent()}.
|
||||
* Implies {@link #autoRenewal()}.
|
||||
*
|
||||
* @param duration
|
||||
* Duration of validity of each certificate
|
||||
* @return itself
|
||||
* @see Metadata#getStarMinCertValidity()
|
||||
* @see Metadata#getAutoRenewalMinLifetime()
|
||||
* @since 2.3
|
||||
*/
|
||||
public OrderBuilder recurrentCertificateValidity(Duration duration) {
|
||||
recurrent();
|
||||
this.recurrentValidity = requireNonNull(duration, "duration");
|
||||
public OrderBuilder autoRenewalLifetime(Duration duration) {
|
||||
autoRenewal();
|
||||
this.autoRenewalLifetime = requireNonNull(duration, "duration");
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -233,36 +233,36 @@ public class OrderBuilder {
|
|||
* Sets the amount of pre-dating each certificate. If not set, the CA's
|
||||
* default (0) is used.
|
||||
* <p>
|
||||
* Implies {@link #recurrent()}.
|
||||
* Implies {@link #autoRenewal()}.
|
||||
*
|
||||
* @param duration
|
||||
* Duration of certificate pre-dating
|
||||
* @return itself
|
||||
* @since 2.7
|
||||
*/
|
||||
public OrderBuilder recurrentCertificatePredate(Duration duration) {
|
||||
recurrent();
|
||||
this.recurrentPredate = requireNonNull(duration, "duration");
|
||||
public OrderBuilder autoRenewalLifetimeAdjust(Duration duration) {
|
||||
autoRenewal();
|
||||
this.autoRenewalLifetimeAdjust = requireNonNull(duration, "duration");
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Announces that the client wishes to fetch the recurring certificate via GET
|
||||
* Announces that the client wishes to fetch the auto-renewed certificate via GET
|
||||
* request. If not used, the STAR certificate can only be fetched via POST-as-GET
|
||||
* request. {@link Metadata#isStarCertificateGetAllowed()} must return {@code true} in
|
||||
* request. {@link Metadata#isAutoRenewalGetAllowed()} must return {@code true} in
|
||||
* order for this option to work.
|
||||
* <p>
|
||||
* This option is only needed if you plan to fetch the STAR certificate via other
|
||||
* means than by using acme4j.
|
||||
* <p>
|
||||
* Implies {@link #recurrent()}.
|
||||
* Implies {@link #autoRenewal()}.
|
||||
*
|
||||
* @return itself
|
||||
* @since 2.6
|
||||
*/
|
||||
public OrderBuilder recurrentEnableGet() {
|
||||
recurrent();
|
||||
this.recurrentGet = true;
|
||||
public OrderBuilder autoRenewalEnableGet() {
|
||||
autoRenewal();
|
||||
this.autoRenewalGet = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -278,7 +278,7 @@ public class OrderBuilder {
|
|||
|
||||
Session session = login.getSession();
|
||||
|
||||
if (recurrent && !session.getMetadata().isStarEnabled()) {
|
||||
if (autoRenewal && !session.getMetadata().isAutoRenewalEnabled()) {
|
||||
throw new AcmeException("CA does not support short-term automatic renewals");
|
||||
}
|
||||
|
||||
|
@ -294,22 +294,22 @@ public class OrderBuilder {
|
|||
claims.put("notAfter", notAfter);
|
||||
}
|
||||
|
||||
if (recurrent) {
|
||||
claims.put("recurrent", true);
|
||||
if (recurrentStart != null) {
|
||||
claims.put("recurrent-start-date", recurrentStart);
|
||||
if (autoRenewal) {
|
||||
JSONBuilder arClaims = claims.object("auto-renewal");
|
||||
if (autoRenewalStart != null) {
|
||||
arClaims.put("start-date", autoRenewalStart);
|
||||
}
|
||||
if (recurrentStart != null) {
|
||||
claims.put("recurrent-end-date", recurrentEnd);
|
||||
if (autoRenewalStart != null) {
|
||||
arClaims.put("end-date", autoRenewalEnd);
|
||||
}
|
||||
if (recurrentValidity != null) {
|
||||
claims.put("recurrent-certificate-validity", recurrentValidity);
|
||||
if (autoRenewalLifetime != null) {
|
||||
arClaims.put("lifetime", autoRenewalLifetime);
|
||||
}
|
||||
if (recurrentPredate != null) {
|
||||
claims.put("recurrent-certificate-predate", recurrentPredate);
|
||||
if (autoRenewalLifetimeAdjust != null) {
|
||||
arClaims.put("lifetime-adjust", autoRenewalLifetimeAdjust);
|
||||
}
|
||||
if (recurrentGet) {
|
||||
claims.put("recurrent-certificate-get", recurrentGet);
|
||||
if (autoRenewalGet) {
|
||||
arClaims.put("allow-certificate-get", autoRenewalGet);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -68,7 +68,7 @@ public enum Status {
|
|||
EXPIRED,
|
||||
|
||||
/**
|
||||
* A recurrent {@link Order} is canceled.
|
||||
* An auto-renewing {@link Order} is canceled.
|
||||
*
|
||||
* @since 2.3
|
||||
*/
|
||||
|
|
|
@ -102,6 +102,12 @@ public class OrderBuilderTest {
|
|||
assertThat(order.getNotAfter(), is(parseTimestamp("2016-01-08T00:10:00Z")));
|
||||
assertThat(order.getExpires(), is(parseTimestamp("2016-01-10T00:00:00Z")));
|
||||
assertThat(order.getStatus(), is(Status.PENDING));
|
||||
assertThat(order.isAutoRenewing(), is(false));
|
||||
assertThat(order.getAutoRenewalStartDate(), is(nullValue()));
|
||||
assertThat(order.getAutoRenewalEndDate(), is(nullValue()));
|
||||
assertThat(order.getAutoRenewalLifetime(), is(nullValue()));
|
||||
assertThat(order.getAutoRenewalLifetimeAdjust(), is(nullValue()));
|
||||
assertThat(order.isAutoRenewalGetEnabled(), is(false));
|
||||
assertThat(order.getLocation(), is(locationUrl));
|
||||
assertThat(order.getAuthorizations(), is(notNullValue()));
|
||||
assertThat(order.getAuthorizations().size(), is(2));
|
||||
|
@ -110,12 +116,12 @@ public class OrderBuilderTest {
|
|||
}
|
||||
|
||||
/**
|
||||
* Test that a new recurrent {@link Order} can be created.
|
||||
* Test that a new auto-renewal {@link Order} can be created.
|
||||
*/
|
||||
@Test
|
||||
public void testRecurrentOrderCertificate() throws Exception {
|
||||
Instant recurrentStart = parseTimestamp("2018-01-01T00:00:00Z");
|
||||
Instant recurrentEnd = parseTimestamp("2019-01-01T00:00:00Z");
|
||||
public void testAutoRenewOrderCertificate() throws Exception {
|
||||
Instant autoRenewStart = parseTimestamp("2018-01-01T00:00:00Z");
|
||||
Instant autoRenewEnd = parseTimestamp("2019-01-01T00:00:00Z");
|
||||
Duration validity = Duration.ofDays(7);
|
||||
Duration predate = Duration.ofDays(6);
|
||||
|
||||
|
@ -123,14 +129,14 @@ public class OrderBuilderTest {
|
|||
@Override
|
||||
public int sendSignedRequest(URL url, JSONBuilder claims, Login login) {
|
||||
assertThat(url, is(resourceUrl));
|
||||
assertThat(claims.toString(), sameJSONAs(getJSON("requestRecurrentOrderRequest").toString()));
|
||||
assertThat(claims.toString(), sameJSONAs(getJSON("requestAutoRenewOrderRequest").toString()));
|
||||
assertThat(login, is(notNullValue()));
|
||||
return HttpURLConnection.HTTP_CREATED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSON readJsonResponse() {
|
||||
return getJSON("requestRecurrentOrderResponse");
|
||||
return getJSON("requestAutoRenewOrderResponse");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -141,39 +147,39 @@ public class OrderBuilderTest {
|
|||
|
||||
Login login = provider.createLogin();
|
||||
|
||||
provider.putMetadata("star-enabled", true);
|
||||
provider.putMetadata("auto-renewal", JSON.empty());
|
||||
provider.putTestResource(Resource.NEW_ORDER, resourceUrl);
|
||||
|
||||
Account account = new Account(login);
|
||||
Order order = account.newOrder()
|
||||
.domain("example.org")
|
||||
.recurrent()
|
||||
.recurrentStart(recurrentStart)
|
||||
.recurrentEnd(recurrentEnd)
|
||||
.recurrentCertificateValidity(validity)
|
||||
.recurrentCertificatePredate(predate)
|
||||
.recurrentEnableGet()
|
||||
.autoRenewal()
|
||||
.autoRenewalStart(autoRenewStart)
|
||||
.autoRenewalEnd(autoRenewEnd)
|
||||
.autoRenewalLifetime(validity)
|
||||
.autoRenewalLifetimeAdjust(predate)
|
||||
.autoRenewalEnableGet()
|
||||
.create();
|
||||
|
||||
assertThat(order.getIdentifiers(), containsInAnyOrder(Identifier.dns("example.org")));
|
||||
assertThat(order.getNotBefore(), is(nullValue()));
|
||||
assertThat(order.getNotAfter(), is(nullValue()));
|
||||
assertThat(order.isRecurrent(), is(true));
|
||||
assertThat(order.getRecurrentStart(), is(recurrentStart));
|
||||
assertThat(order.getRecurrentEnd(), is(recurrentEnd));
|
||||
assertThat(order.getRecurrentCertificateValidity(), is(validity));
|
||||
assertThat(order.getRecurrentCertificatePredate(), is(predate));
|
||||
assertThat(order.isRecurrentGetEnabled(), is(true));
|
||||
assertThat(order.isAutoRenewing(), is(true));
|
||||
assertThat(order.getAutoRenewalStartDate(), is(autoRenewStart));
|
||||
assertThat(order.getAutoRenewalEndDate(), is(autoRenewEnd));
|
||||
assertThat(order.getAutoRenewalLifetime(), is(validity));
|
||||
assertThat(order.getAutoRenewalLifetimeAdjust(), is(predate));
|
||||
assertThat(order.isAutoRenewalGetEnabled(), is(true));
|
||||
assertThat(order.getLocation(), is(locationUrl));
|
||||
|
||||
provider.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that a recurrent {@link Order} cannot be created if unsupported by the CA.
|
||||
* Test that an auto-renewal {@link Order} cannot be created if unsupported by the CA.
|
||||
*/
|
||||
@Test(expected = AcmeException.class)
|
||||
public void testRecurrentOrderCertificateFails() throws Exception {
|
||||
public void testAutoRenewOrderCertificateFails() throws Exception {
|
||||
TestableConnectionProvider provider = new TestableConnectionProvider();
|
||||
provider.putTestResource(Resource.NEW_ORDER, resourceUrl);
|
||||
|
||||
|
@ -182,17 +188,17 @@ public class OrderBuilderTest {
|
|||
Account account = new Account(login);
|
||||
account.newOrder()
|
||||
.domain("example.org")
|
||||
.recurrent()
|
||||
.autoRenewal()
|
||||
.create();
|
||||
|
||||
provider.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that recurrent and notBefore/notAfter cannot be mixed.
|
||||
* Test that auto-renew and notBefore/notAfter cannot be mixed.
|
||||
*/
|
||||
@Test
|
||||
public void testRecurrentNotMixed() throws Exception {
|
||||
public void testAutoRenewNotMixed() throws Exception {
|
||||
Instant someInstant = parseTimestamp("2018-01-01T00:00:00Z");
|
||||
|
||||
TestableConnectionProvider provider = new TestableConnectionProvider();
|
||||
|
@ -201,7 +207,7 @@ public class OrderBuilderTest {
|
|||
Account account = new Account(login);
|
||||
|
||||
try {
|
||||
OrderBuilder ob = account.newOrder().recurrent();
|
||||
OrderBuilder ob = account.newOrder().autoRenewal();
|
||||
ob.notBefore(someInstant);
|
||||
fail("accepted notBefore");
|
||||
} catch (IllegalArgumentException ex) {
|
||||
|
@ -209,7 +215,7 @@ public class OrderBuilderTest {
|
|||
}
|
||||
|
||||
try {
|
||||
OrderBuilder ob = account.newOrder().recurrent();
|
||||
OrderBuilder ob = account.newOrder().autoRenewal();
|
||||
ob.notAfter(someInstant);
|
||||
fail("accepted notAfter");
|
||||
} catch (IllegalArgumentException ex) {
|
||||
|
@ -218,32 +224,32 @@ public class OrderBuilderTest {
|
|||
|
||||
try {
|
||||
OrderBuilder ob = account.newOrder().notBefore(someInstant);
|
||||
ob.recurrent();
|
||||
fail("accepted recurrent");
|
||||
ob.autoRenewal();
|
||||
fail("accepted autoRenewal");
|
||||
} catch (IllegalArgumentException ex) {
|
||||
// expected
|
||||
}
|
||||
|
||||
try {
|
||||
OrderBuilder ob = account.newOrder().notBefore(someInstant);
|
||||
ob.recurrentStart(someInstant);
|
||||
fail("accepted recurrentStart");
|
||||
ob.autoRenewalStart(someInstant);
|
||||
fail("accepted autoRenewalStart");
|
||||
} catch (IllegalArgumentException ex) {
|
||||
// expected
|
||||
}
|
||||
|
||||
try {
|
||||
OrderBuilder ob = account.newOrder().notBefore(someInstant);
|
||||
ob.recurrentEnd(someInstant);
|
||||
fail("accepted recurrentEnd");
|
||||
ob.autoRenewalEnd(someInstant);
|
||||
fail("accepted autoRenewalEnd");
|
||||
} catch (IllegalArgumentException ex) {
|
||||
// expected
|
||||
}
|
||||
|
||||
try {
|
||||
OrderBuilder ob = account.newOrder().notBefore(someInstant);
|
||||
ob.recurrentCertificateValidity(Duration.ofDays(7));
|
||||
fail("accepted recurrentCertificateValidity");
|
||||
ob.autoRenewalLifetime(Duration.ofDays(7));
|
||||
fail("accepted autoRenewalLifetime");
|
||||
} catch (IllegalArgumentException ex) {
|
||||
// expected
|
||||
}
|
||||
|
|
|
@ -81,12 +81,12 @@ public class OrderTest {
|
|||
assertThat(order.getCertificate().getLocation(), is(url("https://example.com/acme/cert/1234")));
|
||||
assertThat(order.getFinalizeLocation(), is(finalizeUrl));
|
||||
|
||||
assertThat(order.isRecurrent(), is(false));
|
||||
assertThat(order.getRecurrentStart(), is(nullValue()));
|
||||
assertThat(order.getRecurrentEnd(), is(nullValue()));
|
||||
assertThat(order.getRecurrentCertificateValidity(), is(nullValue()));
|
||||
assertThat(order.getRecurrentCertificatePredate(), is(nullValue()));
|
||||
assertThat(order.isRecurrentGetEnabled(), is(false));
|
||||
assertThat(order.isAutoRenewing(), is(false));
|
||||
assertThat(order.getAutoRenewalStartDate(), is(nullValue()));
|
||||
assertThat(order.getAutoRenewalEndDate(), is(nullValue()));
|
||||
assertThat(order.getAutoRenewalLifetime(), is(nullValue()));
|
||||
assertThat(order.getAutoRenewalLifetimeAdjust(), is(nullValue()));
|
||||
assertThat(order.isAutoRenewalGetEnabled(), is(false));
|
||||
|
||||
assertThat(order.getError(), is(notNullValue()));
|
||||
assertThat(order.getError().getType(), is(URI.create("urn:ietf:params:acme:error:connection")));
|
||||
|
@ -198,7 +198,7 @@ public class OrderTest {
|
|||
assertThat(order.getNotBefore(), is(parseTimestamp("2016-01-01T00:00:00Z")));
|
||||
assertThat(order.getNotAfter(), is(parseTimestamp("2016-01-08T00:00:00Z")));
|
||||
assertThat(order.getCertificate().getLocation(), is(url("https://example.com/acme/cert/1234")));
|
||||
assertThat(order.getStarCertificate(), is(nullValue()));
|
||||
assertThat(order.getAutoRenewalCertificate(), is(nullValue()));
|
||||
assertThat(order.getFinalizeLocation(), is(finalizeUrl));
|
||||
|
||||
List<Authorization> auths = order.getAuthorizations();
|
||||
|
@ -215,7 +215,7 @@ public class OrderTest {
|
|||
* Test that order is properly updated.
|
||||
*/
|
||||
@Test
|
||||
public void testRecurrentUpdate() throws Exception {
|
||||
public void testAutoRenewUpdate() throws Exception {
|
||||
TestableConnectionProvider provider = new TestableConnectionProvider() {
|
||||
@Override
|
||||
public int sendSignedPostAsGetRequest(URL url, Login login) {
|
||||
|
@ -225,7 +225,7 @@ public class OrderTest {
|
|||
|
||||
@Override
|
||||
public JSON readJsonResponse() {
|
||||
return getJSON("updateRecurrentOrderResponse");
|
||||
return getJSON("updateAutoRenewOrderResponse");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -234,30 +234,30 @@ public class OrderTest {
|
|||
}
|
||||
};
|
||||
|
||||
provider.putMetadata("star-enabled", true);
|
||||
provider.putMetadata("auto-renewal", JSON.empty());
|
||||
|
||||
Login login = provider.createLogin();
|
||||
|
||||
Order order = new Order(login, locationUrl);
|
||||
order.update();
|
||||
|
||||
assertThat(order.isRecurrent(), is(true));
|
||||
assertThat(order.getRecurrentStart(), is(parseTimestamp("2016-01-01T00:00:00Z")));
|
||||
assertThat(order.getRecurrentEnd(), is(parseTimestamp("2017-01-01T00:00:00Z")));
|
||||
assertThat(order.getRecurrentCertificateValidity(), is(Duration.ofHours(168)));
|
||||
assertThat(order.getRecurrentCertificatePredate(), is(Duration.ofDays(6)));
|
||||
assertThat(order.isAutoRenewing(), is(true));
|
||||
assertThat(order.getAutoRenewalStartDate(), is(parseTimestamp("2016-01-01T00:00:00Z")));
|
||||
assertThat(order.getAutoRenewalEndDate(), is(parseTimestamp("2017-01-01T00:00:00Z")));
|
||||
assertThat(order.getAutoRenewalLifetime(), is(Duration.ofHours(168)));
|
||||
assertThat(order.getAutoRenewalLifetimeAdjust(), is(Duration.ofDays(6)));
|
||||
assertThat(order.getNotBefore(), is(nullValue()));
|
||||
assertThat(order.getNotAfter(), is(nullValue()));
|
||||
assertThat(order.isRecurrentGetEnabled(), is(true));
|
||||
assertThat(order.isAutoRenewalGetEnabled(), is(true));
|
||||
|
||||
provider.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that recurrent order is properly finalized.
|
||||
* Test that auto-renew order is properly finalized.
|
||||
*/
|
||||
@Test
|
||||
public void testRecurrentFinalize() throws Exception {
|
||||
public void testAutoRenewFinalize() throws Exception {
|
||||
TestableConnectionProvider provider = new TestableConnectionProvider() {
|
||||
@Override
|
||||
public int sendSignedPostAsGetRequest(URL url, Login login) {
|
||||
|
@ -267,7 +267,7 @@ public class OrderTest {
|
|||
|
||||
@Override
|
||||
public JSON readJsonResponse() {
|
||||
return getJSON("finalizeRecurrentResponse");
|
||||
return getJSON("finalizeAutoRenewResponse");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -280,21 +280,21 @@ public class OrderTest {
|
|||
Order order = login.bindOrder(locationUrl);
|
||||
|
||||
assertThat(order.getCertificate(), is(nullValue()));
|
||||
assertThat(order.getStarCertificate().getLocation(), is(url("https://example.com/acme/cert/1234")));
|
||||
assertThat(order.isRecurrent(), is(true));
|
||||
assertThat(order.getRecurrentStart(), is(parseTimestamp("2018-01-01T00:00:00Z")));
|
||||
assertThat(order.getRecurrentEnd(), is(parseTimestamp("2019-01-01T00:00:00Z")));
|
||||
assertThat(order.getRecurrentCertificateValidity(), is(Duration.ofHours(168)));
|
||||
assertThat(order.getRecurrentCertificatePredate(), is(Duration.ofDays(6)));
|
||||
assertThat(order.getAutoRenewalCertificate().getLocation(), is(url("https://example.com/acme/cert/1234")));
|
||||
assertThat(order.isAutoRenewing(), is(true));
|
||||
assertThat(order.getAutoRenewalStartDate(), is(parseTimestamp("2018-01-01T00:00:00Z")));
|
||||
assertThat(order.getAutoRenewalEndDate(), is(parseTimestamp("2019-01-01T00:00:00Z")));
|
||||
assertThat(order.getAutoRenewalLifetime(), is(Duration.ofHours(168)));
|
||||
assertThat(order.getAutoRenewalLifetimeAdjust(), is(Duration.ofDays(6)));
|
||||
assertThat(order.getNotBefore(), is(nullValue()));
|
||||
assertThat(order.getNotAfter(), is(nullValue()));
|
||||
assertThat(order.isRecurrentGetEnabled(), is(true));
|
||||
assertThat(order.isAutoRenewalGetEnabled(), is(true));
|
||||
|
||||
provider.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that recurrent order is properly canceled.
|
||||
* Test that auto-renew order is properly canceled.
|
||||
*/
|
||||
@Test
|
||||
public void testCancel() throws Exception {
|
||||
|
@ -314,12 +314,12 @@ public class OrderTest {
|
|||
}
|
||||
};
|
||||
|
||||
provider.putMetadata("star-enabled", true);
|
||||
provider.putMetadata("auto-renewal", JSON.empty());
|
||||
|
||||
Login login = provider.createLogin();
|
||||
|
||||
Order order = new Order(login, locationUrl);
|
||||
order.cancelRecurrent();
|
||||
order.cancelAutoRenewal();
|
||||
|
||||
assertThat(order.getStatus(), is(Status.CANCELED));
|
||||
|
||||
|
|
|
@ -184,10 +184,10 @@ public class SessionTest {
|
|||
assertThat(meta.getTermsOfService(), is(nullValue()));
|
||||
assertThat(meta.getWebsite(), is(nullValue()));
|
||||
assertThat(meta.getCaaIdentities(), is(empty()));
|
||||
assertThat(meta.isStarEnabled(), is(false));
|
||||
assertThat(meta.getStarMaxRenewal(), is(nullValue()));
|
||||
assertThat(meta.getStarMinCertValidity(), is(nullValue()));
|
||||
assertThat(meta.isStarCertificateGetAllowed(), is(false));
|
||||
assertThat(meta.isAutoRenewalEnabled(), is(false));
|
||||
assertThat(meta.getAutoRenewalMaxDuration(), is(nullValue()));
|
||||
assertThat(meta.getAutoRenewalMinLifetime(), is(nullValue()));
|
||||
assertThat(meta.isAutoRenewalGetAllowed(), is(false));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -217,10 +217,10 @@ public class SessionTest {
|
|||
assertThat(meta.getTermsOfService(), is(URI.create("https://example.com/acme/terms")));
|
||||
assertThat(meta.getWebsite(), is(url("https://www.example.com/")));
|
||||
assertThat(meta.getCaaIdentities(), containsInAnyOrder("example.com"));
|
||||
assertThat(meta.isStarEnabled(), is(true));
|
||||
assertThat(meta.getStarMaxRenewal(), is(Duration.ofDays(365)));
|
||||
assertThat(meta.getStarMinCertValidity(), is(Duration.ofHours(24)));
|
||||
assertThat(meta.isStarCertificateGetAllowed(), is(true));
|
||||
assertThat(meta.isAutoRenewalEnabled(), is(true));
|
||||
assertThat(meta.getAutoRenewalMaxDuration(), is(Duration.ofDays(365)));
|
||||
assertThat(meta.getAutoRenewalMinLifetime(), is(Duration.ofHours(24)));
|
||||
assertThat(meta.isAutoRenewalGetAllowed(), is(true));
|
||||
assertThat(meta.isExternalAccountRequired(), is(true));
|
||||
assertThat(meta.getJSON(), is(notNullValue()));
|
||||
}
|
||||
|
|
|
@ -9,11 +9,12 @@
|
|||
"caaIdentities": [
|
||||
"example.com"
|
||||
],
|
||||
"auto-renewal": {
|
||||
"min-lifetime": 86400,
|
||||
"max-duration": 31536000,
|
||||
"allow-certificate-get": true
|
||||
},
|
||||
"externalAccountRequired": true,
|
||||
"star-enabled": true,
|
||||
"star-min-cert-validity": 86400,
|
||||
"star-max-renewal": 31536000,
|
||||
"star-allow-certificate-get": true,
|
||||
"xTestString": "foobar",
|
||||
"xTestUri": "https://www.example.org",
|
||||
"xTestArray": [
|
||||
|
|
|
@ -11,12 +11,13 @@
|
|||
"value": "www.example.com"
|
||||
}
|
||||
],
|
||||
"recurrent": true,
|
||||
"recurrent-start-date": "2018-01-01T00:00:00Z",
|
||||
"recurrent-end-date": "2019-01-01T00:00:00Z",
|
||||
"recurrent-certificate-validity": 604800,
|
||||
"recurrent-certificate-predate": 518400,
|
||||
"recurrent-certificate-get": true,
|
||||
"auto-renewal": {
|
||||
"start-date": "2018-01-01T00:00:00Z",
|
||||
"end-date": "2019-01-01T00:00:00Z",
|
||||
"lifetime": 604800,
|
||||
"lifetime-adjust": 518400,
|
||||
"allow-certificate-get": true
|
||||
},
|
||||
"authorizations": [
|
||||
"https://example.com/acme/authz/1234",
|
||||
"https://example.com/acme/authz/2345"
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"identifiers": [
|
||||
{
|
||||
"type": "dns",
|
||||
"value": "example.org"
|
||||
}
|
||||
],
|
||||
"auto-renewal": {
|
||||
"start-date": "2018-01-01T00:00:00Z",
|
||||
"end-date": "2019-01-01T00:00:00Z",
|
||||
"lifetime": 604800,
|
||||
"lifetime-adjust": 518400,
|
||||
"allow-certificate-get": true
|
||||
}
|
||||
}
|
|
@ -7,12 +7,13 @@
|
|||
"value": "example.org"
|
||||
}
|
||||
],
|
||||
"recurrent": true,
|
||||
"recurrent-start-date": "2018-01-01T00:00:00Z",
|
||||
"recurrent-end-date": "2019-01-01T00:00:00Z",
|
||||
"recurrent-certificate-validity": 604800,
|
||||
"recurrent-certificate-predate": 518400,
|
||||
"recurrent-certificate-get": true,
|
||||
"auto-renewal": {
|
||||
"start-date": "2018-01-01T00:00:00Z",
|
||||
"end-date": "2019-01-01T00:00:00Z",
|
||||
"lifetime": 604800,
|
||||
"lifetime-adjust": 518400,
|
||||
"allow-certificate-get": true
|
||||
},
|
||||
"authorizations": [
|
||||
"https://example.com/acme/authz/1234",
|
||||
"https://example.com/acme/authz/2345"
|
|
@ -1,14 +0,0 @@
|
|||
{
|
||||
"identifiers": [
|
||||
{
|
||||
"type": "dns",
|
||||
"value": "example.org"
|
||||
}
|
||||
],
|
||||
"recurrent": true,
|
||||
"recurrent-start-date": "2018-01-01T00:00:00Z",
|
||||
"recurrent-end-date": "2019-01-01T00:00:00Z",
|
||||
"recurrent-certificate-validity": 604800,
|
||||
"recurrent-certificate-predate": 518400,
|
||||
"recurrent-certificate-get": true
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"status": "valid",
|
||||
"auto-renewal": {
|
||||
"start-date": "2016-01-01T00:00:00Z",
|
||||
"end-date": "2017-01-01T00:00:00Z",
|
||||
"lifetime": 604800,
|
||||
"lifetime-adjust": 518400,
|
||||
"allow-certificate-get": true
|
||||
}
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
{
|
||||
"status": "valid",
|
||||
"recurrent": true,
|
||||
"recurrent-start-date": "2016-01-01T00:00:00Z",
|
||||
"recurrent-end-date": "2017-01-01T00:00:00Z",
|
||||
"recurrent-certificate-validity": 604800,
|
||||
"recurrent-certificate-predate": 518400,
|
||||
"recurrent-certificate-get": true
|
||||
}
|
|
@ -2,6 +2,10 @@
|
|||
|
||||
This document will help you migrate your code to the latest _acme4j_ version.
|
||||
|
||||
## Migration to Version 2.9
|
||||
|
||||
- In the ACME STAR draft 09, the term "recurring" has been changed to "auto-renewal". To reflect this change, all STAR related methods in the acme4j API have been renamed as well. If you are using the STAR extension, you are going to get a number of compile errors, but you will always find a corresponding new method. No functionality has been removed. I decided to do a hard API change because acme4j's STAR support is still experimental.
|
||||
|
||||
## Migration to Version 2.8
|
||||
|
||||
- Challenges can now be found by their class type instead of a type string, which makes finding a challenge type safe. I recommend to migrate your code to this new way. The classic way is not deprecated and will not be removed though. Example:
|
||||
|
|
|
@ -198,25 +198,25 @@ _acme4j_ supports the [ACME STAR](https://tools.ietf.org/html/draft-ietf-acme-st
|
|||
To find out if the CA supports the STAR extension, check the metadata:
|
||||
|
||||
```java
|
||||
if (session.getMetadata().isStarEnabled()) {
|
||||
if (session.getMetadata().isAutoRenewalEnabled()) {
|
||||
// CA supports STAR!
|
||||
}
|
||||
```
|
||||
|
||||
If STAR is supported, you can enable recurrent renewals by adding `recurrent()` to the order parameters:
|
||||
If STAR is supported, you can enable automatic renewals by adding `autoRenewal()` to the order parameters:
|
||||
|
||||
```java
|
||||
Order order = account.newOrder()
|
||||
.domain("example.org")
|
||||
.recurrent()
|
||||
.autoRenewal()
|
||||
.create();
|
||||
```
|
||||
|
||||
You can use `recurrentStart()`, `recurrentEnd()`, `recurrentCertificateValidity()` and `recurrentCertificatePredate()` to change the time span and frequency of automatic renewals. You cannot use `notBefore()` and `notAfter()` in combination with `recurrent()` though.
|
||||
You can use `autoRenewalStart()`, `autoRenewalEnd()`, `autoRenewalLifetime()` and `autoRenewalLifetimeAdjust()` to change the time span and frequency of automatic renewals. You cannot use `notBefore()` and `notAfter()` in combination with `autoRenewal()` though.
|
||||
|
||||
The `Metadata` object also holds the accepted renewal limits (see `Metadata.getStarMinCertValidity()` and `Metadata.getStarMaxRenewal()`).
|
||||
The `Metadata` object also holds the accepted renewal limits (see `Metadata.getAutoRenewalMinLifetime()` and `Metadata.getAutoRenewalMaxDuration()`).
|
||||
|
||||
After the validation process is completed and the order is finalized, the STAR certificate is available via `Order.getStarCertificate()` (_not_ `Order.getCertificate()`)!
|
||||
After the validation process is completed and the order is finalized, the STAR certificate is available via `Order.getAutoRenewalCertificate()` (_not_ `Order.getCertificate()`)!
|
||||
|
||||
Use `Certificate.getLocation()` to retrieve the URL of your certificate. It is renewed automatically, so you will always be able to download the latest issue of the certificate from this URL.
|
||||
|
||||
|
@ -233,6 +233,6 @@ X509Certificate latestCertificate = cert.getCertificate();
|
|||
|
||||
```
|
||||
|
||||
If supported by the CA, it is possible to negotiate that the certificate can also be downloaded via `GET` request. First use `Metadata.isStarCertificateGetAllowed()` to check if this option is supported by the CA. If it is, add `recurrentEnableGet()` to the order parameters to enable it. After the order was finalized, you can use any HTTP client to download the latest certificate from the certificate URL by a `GET` request.
|
||||
If supported by the CA, it is possible to negotiate that the certificate can also be downloaded via `GET` request. First use `Metadata.isAutoRenewalGetAllowed()` to check if this option is supported by the CA. If it is, add `autoRenewalEnableGet()` to the order parameters to enable it. After the order was finalized, you can use any HTTP client to download the latest certificate from the certificate URL by a `GET` request.
|
||||
|
||||
Use `Order.cancelRecurrent()` to terminate automatical certificate renewals.
|
||||
Use `Order.cancelAutoRenewal()` to terminate automatical certificate renewals.
|
||||
|
|
Loading…
Reference in New Issue