diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/Metadata.java b/acme4j-client/src/main/java/org/shredzone/acme4j/Metadata.java index ffeedfcc..dcb12943 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/Metadata.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/Metadata.java @@ -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 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 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 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); } /** diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/Order.java b/acme4j-client/src/main/java/org/shredzone/acme4j/Order.java index 395c41e4..c9503668 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/Order.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/Order.java @@ -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,11 +241,15 @@ public class Order extends AcmeJsonResource { * @since 2.7 */ @CheckForNull - public Duration getRecurrentCertificatePredate() { - return getJSON().get("recurrent-certificate-predate") - .optional() - .map(Value::asDuration) - .orElse(null); + 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"); } diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/OrderBuilder.java b/acme4j-client/src/main/java/org/shredzone/acme4j/OrderBuilder.java index 43590f97..0b5b84ef 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/OrderBuilder.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/OrderBuilder.java @@ -45,12 +45,12 @@ public class OrderBuilder { private final Set 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. *

- * 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. *

- * 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. *

- * 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. *

- * 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. *

- * 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. *

* This option is only needed if you plan to fetch the STAR certificate via other * means than by using acme4j. *

- * 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); } } diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/Status.java b/acme4j-client/src/main/java/org/shredzone/acme4j/Status.java index 999c2aea..8e0ee2f6 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/Status.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/Status.java @@ -68,7 +68,7 @@ public enum Status { EXPIRED, /** - * A recurrent {@link Order} is canceled. + * An auto-renewing {@link Order} is canceled. * * @since 2.3 */ diff --git a/acme4j-client/src/test/java/org/shredzone/acme4j/OrderBuilderTest.java b/acme4j-client/src/test/java/org/shredzone/acme4j/OrderBuilderTest.java index 1e05ff40..eaf2c1b7 100644 --- a/acme4j-client/src/test/java/org/shredzone/acme4j/OrderBuilderTest.java +++ b/acme4j-client/src/test/java/org/shredzone/acme4j/OrderBuilderTest.java @@ -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 } diff --git a/acme4j-client/src/test/java/org/shredzone/acme4j/OrderTest.java b/acme4j-client/src/test/java/org/shredzone/acme4j/OrderTest.java index 851ff78f..34e912d0 100644 --- a/acme4j-client/src/test/java/org/shredzone/acme4j/OrderTest.java +++ b/acme4j-client/src/test/java/org/shredzone/acme4j/OrderTest.java @@ -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 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)); diff --git a/acme4j-client/src/test/java/org/shredzone/acme4j/SessionTest.java b/acme4j-client/src/test/java/org/shredzone/acme4j/SessionTest.java index 8e2f2d1d..aa3945d2 100644 --- a/acme4j-client/src/test/java/org/shredzone/acme4j/SessionTest.java +++ b/acme4j-client/src/test/java/org/shredzone/acme4j/SessionTest.java @@ -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())); } diff --git a/acme4j-client/src/test/resources/json/directory.json b/acme4j-client/src/test/resources/json/directory.json index 4a887e00..f2f4cc1a 100644 --- a/acme4j-client/src/test/resources/json/directory.json +++ b/acme4j-client/src/test/resources/json/directory.json @@ -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": [ diff --git a/acme4j-client/src/test/resources/json/finalizeRecurrentResponse.json b/acme4j-client/src/test/resources/json/finalizeAutoRenewResponse.json similarity index 65% rename from acme4j-client/src/test/resources/json/finalizeRecurrentResponse.json rename to acme4j-client/src/test/resources/json/finalizeAutoRenewResponse.json index 05caef56..15ad6b9f 100644 --- a/acme4j-client/src/test/resources/json/finalizeRecurrentResponse.json +++ b/acme4j-client/src/test/resources/json/finalizeAutoRenewResponse.json @@ -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" diff --git a/acme4j-client/src/test/resources/json/requestAutoRenewOrderRequest.json b/acme4j-client/src/test/resources/json/requestAutoRenewOrderRequest.json new file mode 100644 index 00000000..18a9b0fa --- /dev/null +++ b/acme4j-client/src/test/resources/json/requestAutoRenewOrderRequest.json @@ -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 + } +} diff --git a/acme4j-client/src/test/resources/json/requestRecurrentOrderResponse.json b/acme4j-client/src/test/resources/json/requestAutoRenewOrderResponse.json similarity index 57% rename from acme4j-client/src/test/resources/json/requestRecurrentOrderResponse.json rename to acme4j-client/src/test/resources/json/requestAutoRenewOrderResponse.json index 24193fb4..b5100c0b 100644 --- a/acme4j-client/src/test/resources/json/requestRecurrentOrderResponse.json +++ b/acme4j-client/src/test/resources/json/requestAutoRenewOrderResponse.json @@ -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" diff --git a/acme4j-client/src/test/resources/json/requestRecurrentOrderRequest.json b/acme4j-client/src/test/resources/json/requestRecurrentOrderRequest.json deleted file mode 100644 index cadd4856..00000000 --- a/acme4j-client/src/test/resources/json/requestRecurrentOrderRequest.json +++ /dev/null @@ -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 -} diff --git a/acme4j-client/src/test/resources/json/updateAutoRenewOrderResponse.json b/acme4j-client/src/test/resources/json/updateAutoRenewOrderResponse.json new file mode 100644 index 00000000..d2adb438 --- /dev/null +++ b/acme4j-client/src/test/resources/json/updateAutoRenewOrderResponse.json @@ -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 + } +} diff --git a/acme4j-client/src/test/resources/json/updateRecurrentOrderResponse.json b/acme4j-client/src/test/resources/json/updateRecurrentOrderResponse.json deleted file mode 100644 index 3a0784bc..00000000 --- a/acme4j-client/src/test/resources/json/updateRecurrentOrderResponse.json +++ /dev/null @@ -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 -} diff --git a/src/doc/docs/migration.md b/src/doc/docs/migration.md index 95bed6b6..6a4db34a 100644 --- a/src/doc/docs/migration.md +++ b/src/doc/docs/migration.md @@ -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: diff --git a/src/doc/docs/usage/order.md b/src/doc/docs/usage/order.md index 10c0c225..968a1c0f 100644 --- a/src/doc/docs/usage/order.md +++ b/src/doc/docs/usage/order.md @@ -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.