mirror of https://github.com/shred/acme4j
Use an OrderBuilder for collecting order parameters
parent
e0673c93bd
commit
827e1277ef
|
@ -19,10 +19,8 @@ import java.net.HttpURLConnection;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.security.KeyPair;
|
import java.security.KeyPair;
|
||||||
import java.time.Instant;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -140,54 +138,12 @@ public class Account extends AcmeResource {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Orders a certificate. The certificate will be associated with this account.
|
* Creates a builder for a new {@link Order}.
|
||||||
*
|
*
|
||||||
* @param domains
|
* @return {@link OrderBuilder} object
|
||||||
* Domains of the certificate to be ordered. May contain wildcard domains.
|
|
||||||
* IDN names are accepted and will be ACE encoded automatically.
|
|
||||||
* @param notBefore
|
|
||||||
* Requested "notBefore" date in the certificate, or {@code null}
|
|
||||||
* @param notAfter
|
|
||||||
* Requested "notAfter" date in the certificate, or {@code null}
|
|
||||||
* @return {@link Order} object for this domain
|
|
||||||
*/
|
*/
|
||||||
public Order orderCertificate(Collection<String> domains, Instant notBefore, Instant notAfter)
|
public OrderBuilder newOrder() throws AcmeException {
|
||||||
throws AcmeException {
|
return new OrderBuilder(getSession());
|
||||||
Objects.requireNonNull(domains, "domains");
|
|
||||||
if (domains.isEmpty()) {
|
|
||||||
throw new IllegalArgumentException("Cannot order an empty collection of domains");
|
|
||||||
}
|
|
||||||
|
|
||||||
Object[] identifiers = new Object[domains.size()];
|
|
||||||
Iterator<String> di = domains.iterator();
|
|
||||||
for (int ix = 0; ix < identifiers.length; ix++) {
|
|
||||||
identifiers[ix] = new JSONBuilder()
|
|
||||||
.put("type", "dns")
|
|
||||||
.put("value", toAce(di.next()))
|
|
||||||
.toMap();
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG.debug("orderCertificate");
|
|
||||||
try (Connection conn = getSession().provider().connect()) {
|
|
||||||
JSONBuilder claims = new JSONBuilder();
|
|
||||||
claims.array("identifiers", identifiers);
|
|
||||||
|
|
||||||
if (notBefore != null) {
|
|
||||||
claims.put("notBefore", notBefore);
|
|
||||||
}
|
|
||||||
if (notAfter != null) {
|
|
||||||
claims.put("notAfter", notAfter);
|
|
||||||
}
|
|
||||||
|
|
||||||
conn.sendSignedRequest(getSession().resourceUrl(Resource.NEW_ORDER), claims, getSession());
|
|
||||||
conn.accept(HttpURLConnection.HTTP_CREATED);
|
|
||||||
|
|
||||||
JSON json = conn.readJsonResponse();
|
|
||||||
|
|
||||||
Order order = new Order(getSession(), conn.getLocation());
|
|
||||||
order.unmarshal(json);
|
|
||||||
return order;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -0,0 +1,162 @@
|
||||||
|
/*
|
||||||
|
* acme4j - Java ACME client
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017 Richard "Shred" Körber
|
||||||
|
* http://acme4j.shredzone.org
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
*/
|
||||||
|
package org.shredzone.acme4j;
|
||||||
|
|
||||||
|
import static java.util.Objects.requireNonNull;
|
||||||
|
import static org.shredzone.acme4j.toolbox.AcmeUtils.toAce;
|
||||||
|
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.shredzone.acme4j.connector.Connection;
|
||||||
|
import org.shredzone.acme4j.connector.Resource;
|
||||||
|
import org.shredzone.acme4j.exception.AcmeException;
|
||||||
|
import org.shredzone.acme4j.toolbox.JSON;
|
||||||
|
import org.shredzone.acme4j.toolbox.JSONBuilder;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A builder for a new {@link Order} object.
|
||||||
|
*/
|
||||||
|
public class OrderBuilder {
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(OrderBuilder.class);
|
||||||
|
|
||||||
|
private final Session session;
|
||||||
|
|
||||||
|
private final Set<String> domainSet = new LinkedHashSet<>();
|
||||||
|
private Instant notBefore;
|
||||||
|
private Instant notAfter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new {@link OrderBuilder}.
|
||||||
|
*
|
||||||
|
* @param session {@link Session} to bind with
|
||||||
|
*/
|
||||||
|
protected OrderBuilder(Session session) {
|
||||||
|
this.session = session;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a domain name to the order.
|
||||||
|
*
|
||||||
|
* @param domain
|
||||||
|
* Name of a domain to be ordered. May be a wildcard domain if supported by
|
||||||
|
* the CA. IDN names are accepted and will be ACE encoded automatically.
|
||||||
|
* @return itself
|
||||||
|
*/
|
||||||
|
public OrderBuilder domain(String domain) {
|
||||||
|
domainSet.add(toAce(requireNonNull(domain, "domain")));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds domain names to the order.
|
||||||
|
*
|
||||||
|
* @param domains
|
||||||
|
* Collection of domain names to be ordered. May be wildcard domains if
|
||||||
|
* supported by the CA. IDN names are accepted and will be ACE encoded
|
||||||
|
* automatically.
|
||||||
|
* @return itself
|
||||||
|
*/
|
||||||
|
public OrderBuilder domains(String... domains) {
|
||||||
|
for (String domain : requireNonNull(domains, "domains")) {
|
||||||
|
domain(domain);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a collection of domain names to the order.
|
||||||
|
*
|
||||||
|
* @param domains
|
||||||
|
* Collection of domain names to be ordered. May be wildcard domains if
|
||||||
|
* supported by the CA. IDN names are accepted and will be ACE encoded
|
||||||
|
* automatically.
|
||||||
|
* @return itself
|
||||||
|
*/
|
||||||
|
public OrderBuilder domains(Collection<String> domains) {
|
||||||
|
requireNonNull(domains, "domains").forEach(this::domain);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a "not before" date in the certificate. May be ignored by the CA.
|
||||||
|
*
|
||||||
|
* @param notBefore "not before" date
|
||||||
|
* @return itself
|
||||||
|
*/
|
||||||
|
public OrderBuilder notBefore(Instant notBefore) {
|
||||||
|
this.notBefore = requireNonNull(notBefore, "notBefore");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a "not after" date in the certificate. May be ignored by the CA.
|
||||||
|
*
|
||||||
|
* @param notAfter "not after" date
|
||||||
|
* @return itself
|
||||||
|
*/
|
||||||
|
public OrderBuilder notAfter(Instant notAfter) {
|
||||||
|
this.notAfter = requireNonNull(notAfter, "notAfter");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends a new order to the server, and returns an {@link Order} object.
|
||||||
|
*
|
||||||
|
* @return {@link Order} that was created
|
||||||
|
*/
|
||||||
|
public Order create() throws AcmeException {
|
||||||
|
if (domainSet.isEmpty()) {
|
||||||
|
throw new IllegalArgumentException("At least one domain is required");
|
||||||
|
}
|
||||||
|
|
||||||
|
Object[] identifiers = new Object[domainSet.size()];
|
||||||
|
Iterator<String> di = domainSet.iterator();
|
||||||
|
for (int ix = 0; ix < identifiers.length; ix++) {
|
||||||
|
identifiers[ix] = new JSONBuilder()
|
||||||
|
.put("type", "dns")
|
||||||
|
.put("value", di.next())
|
||||||
|
.toMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG.debug("create");
|
||||||
|
try (Connection conn = session.provider().connect()) {
|
||||||
|
JSONBuilder claims = new JSONBuilder();
|
||||||
|
claims.array("identifiers", identifiers);
|
||||||
|
|
||||||
|
if (notBefore != null) {
|
||||||
|
claims.put("notBefore", notBefore);
|
||||||
|
}
|
||||||
|
if (notAfter != null) {
|
||||||
|
claims.put("notAfter", notAfter);
|
||||||
|
}
|
||||||
|
|
||||||
|
conn.sendSignedRequest(session.resourceUrl(Resource.NEW_ORDER), claims, session);
|
||||||
|
conn.accept(HttpURLConnection.HTTP_CREATED);
|
||||||
|
|
||||||
|
JSON json = conn.readJsonResponse();
|
||||||
|
|
||||||
|
Order order = new Order(session, conn.getLocation());
|
||||||
|
order.unmarshal(json);
|
||||||
|
return order;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -15,7 +15,6 @@ 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.shredzone.acme4j.toolbox.AcmeUtils.parseTimestamp;
|
|
||||||
import static org.shredzone.acme4j.toolbox.TestUtils.*;
|
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;
|
||||||
|
|
||||||
|
@ -25,7 +24,6 @@ import java.net.URI;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.security.KeyPair;
|
import java.security.KeyPair;
|
||||||
import java.time.Instant;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
@ -185,60 +183,6 @@ public class AccountTest {
|
||||||
provider.close();
|
provider.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that a new {@link Authorization} can be created.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void testOrderCertificate() throws Exception {
|
|
||||||
Instant notBefore = parseTimestamp("2016-01-01T00:00:00Z");
|
|
||||||
Instant notAfter = parseTimestamp("2016-01-08T00:00:00Z");
|
|
||||||
|
|
||||||
TestableConnectionProvider provider = new TestableConnectionProvider() {
|
|
||||||
@Override
|
|
||||||
public void sendSignedRequest(URL url, JSONBuilder claims, Session session) {
|
|
||||||
assertThat(url, is(resourceUrl));
|
|
||||||
assertThat(claims.toString(), sameJSONAs(getJSON("requestOrderRequest").toString()));
|
|
||||||
assertThat(session, is(notNullValue()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int accept(int... httpStatus) throws AcmeException {
|
|
||||||
assertThat(httpStatus, isIntArrayContainingInAnyOrder(HttpURLConnection.HTTP_CREATED));
|
|
||||||
return HttpURLConnection.HTTP_CREATED;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public JSON readJsonResponse() {
|
|
||||||
return getJSON("requestOrderResponse");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public URL getLocation() {
|
|
||||||
return locationUrl;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Session session = provider.createSession();
|
|
||||||
|
|
||||||
provider.putTestResource(Resource.NEW_ORDER, resourceUrl);
|
|
||||||
|
|
||||||
Account account = new Account(session, locationUrl);
|
|
||||||
Order order = account.orderCertificate(
|
|
||||||
Arrays.asList("example.com", "www.example.com"),
|
|
||||||
notBefore, notAfter);
|
|
||||||
|
|
||||||
assertThat(order.getDomains(), containsInAnyOrder("example.com", "www.example.com"));
|
|
||||||
assertThat(order.getNotBefore(), is(parseTimestamp("2016-01-01T00:10:00Z")));
|
|
||||||
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.getLocation(), is(locationUrl));
|
|
||||||
assertThat(order.getAuthorizations(), is(notNullValue()));
|
|
||||||
assertThat(order.getAuthorizations().size(), is(2));
|
|
||||||
|
|
||||||
provider.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test that a domain can be pre-authorized.
|
* Test that a domain can be pre-authorized.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -0,0 +1,103 @@
|
||||||
|
/*
|
||||||
|
* acme4j - Java ACME client
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017 Richard "Shred" Körber
|
||||||
|
* http://acme4j.shredzone.org
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
*/
|
||||||
|
package org.shredzone.acme4j;
|
||||||
|
|
||||||
|
import static org.hamcrest.Matchers.*;
|
||||||
|
import static org.junit.Assert.assertThat;
|
||||||
|
import static org.shredzone.acme4j.toolbox.AcmeUtils.parseTimestamp;
|
||||||
|
import static org.shredzone.acme4j.toolbox.TestUtils.*;
|
||||||
|
import static uk.co.datumedge.hamcrest.json.SameJSONAs.sameJSONAs;
|
||||||
|
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.shredzone.acme4j.connector.Resource;
|
||||||
|
import org.shredzone.acme4j.exception.AcmeException;
|
||||||
|
import org.shredzone.acme4j.provider.TestableConnectionProvider;
|
||||||
|
import org.shredzone.acme4j.toolbox.JSON;
|
||||||
|
import org.shredzone.acme4j.toolbox.JSONBuilder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unit tests for {@link OrderBuilder}.
|
||||||
|
*/
|
||||||
|
public class OrderBuilderTest {
|
||||||
|
|
||||||
|
private URL resourceUrl = url("http://example.com/acme/resource");
|
||||||
|
private URL locationUrl = url("http://example.com/acme/account");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test that a new {@link Order} can be created.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testOrderCertificate() throws Exception {
|
||||||
|
Instant notBefore = parseTimestamp("2016-01-01T00:00:00Z");
|
||||||
|
Instant notAfter = parseTimestamp("2016-01-08T00:00:00Z");
|
||||||
|
|
||||||
|
TestableConnectionProvider provider = new TestableConnectionProvider() {
|
||||||
|
@Override
|
||||||
|
public void sendSignedRequest(URL url, JSONBuilder claims, Session session) {
|
||||||
|
assertThat(url, is(resourceUrl));
|
||||||
|
assertThat(claims.toString(), sameJSONAs(getJSON("requestOrderRequest").toString()));
|
||||||
|
assertThat(session, is(notNullValue()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int accept(int... httpStatus) throws AcmeException {
|
||||||
|
assertThat(httpStatus, isIntArrayContainingInAnyOrder(HttpURLConnection.HTTP_CREATED));
|
||||||
|
return HttpURLConnection.HTTP_CREATED;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JSON readJsonResponse() {
|
||||||
|
return getJSON("requestOrderResponse");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public URL getLocation() {
|
||||||
|
return locationUrl;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Session session = provider.createSession();
|
||||||
|
|
||||||
|
provider.putTestResource(Resource.NEW_ORDER, resourceUrl);
|
||||||
|
|
||||||
|
Account account = new Account(session, locationUrl);
|
||||||
|
Order order = account.newOrder()
|
||||||
|
.domains("example.com", "www.example.com")
|
||||||
|
.domain("example.org")
|
||||||
|
.domains(Arrays.asList("m.example.com", "m.example.org"))
|
||||||
|
.notBefore(notBefore)
|
||||||
|
.notAfter(notAfter)
|
||||||
|
.create();
|
||||||
|
|
||||||
|
assertThat(order.getDomains(), containsInAnyOrder(
|
||||||
|
"example.com", "www.example.com",
|
||||||
|
"example.org",
|
||||||
|
"m.example.com", "m.example.org"));
|
||||||
|
assertThat(order.getNotBefore(), is(parseTimestamp("2016-01-01T00:10:00Z")));
|
||||||
|
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.getLocation(), is(locationUrl));
|
||||||
|
assertThat(order.getAuthorizations(), is(notNullValue()));
|
||||||
|
assertThat(order.getAuthorizations().size(), is(2));
|
||||||
|
|
||||||
|
provider.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -7,6 +7,18 @@
|
||||||
{
|
{
|
||||||
"type": "dns",
|
"type": "dns",
|
||||||
"value": "www.example.com"
|
"value": "www.example.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "dns",
|
||||||
|
"value": "example.org"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "dns",
|
||||||
|
"value": "m.example.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "dns",
|
||||||
|
"value": "m.example.org"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"notBefore": "2016-01-01T00:00:00Z",
|
"notBefore": "2016-01-01T00:00:00Z",
|
||||||
|
|
|
@ -9,6 +9,18 @@
|
||||||
{
|
{
|
||||||
"type": "dns",
|
"type": "dns",
|
||||||
"value": "www.example.com"
|
"value": "www.example.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "dns",
|
||||||
|
"value": "example.org"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "dns",
|
||||||
|
"value": "m.example.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "dns",
|
||||||
|
"value": "m.example.org"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"notBefore": "2016-01-01T00:10:00Z",
|
"notBefore": "2016-01-01T00:10:00Z",
|
||||||
|
|
|
@ -91,7 +91,7 @@ public class ClientTest {
|
||||||
KeyPair domainKeyPair = loadOrCreateDomainKeyPair();
|
KeyPair domainKeyPair = loadOrCreateDomainKeyPair();
|
||||||
|
|
||||||
// Order the certificate
|
// Order the certificate
|
||||||
Order order = acct.orderCertificate(domains, null, null);
|
Order order = acct.newOrder().domains(domains).create();
|
||||||
|
|
||||||
// Perform all required authorizations
|
// Perform all required authorizations
|
||||||
for (Authorization auth : order.getAuthorizations()) {
|
for (Authorization auth : order.getAuthorizations()) {
|
||||||
|
|
|
@ -23,7 +23,6 @@ import java.security.cert.X509Certificate;
|
||||||
import java.time.Duration;
|
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 org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.shredzone.acme4j.Account;
|
import org.shredzone.acme4j.Account;
|
||||||
|
@ -138,7 +137,11 @@ public class OrderIT extends PebbleITBase {
|
||||||
Instant notBefore = Instant.now().truncatedTo(ChronoUnit.MILLIS);
|
Instant notBefore = Instant.now().truncatedTo(ChronoUnit.MILLIS);
|
||||||
Instant notAfter = notBefore.plus(Duration.ofDays(20L));
|
Instant notAfter = notBefore.plus(Duration.ofDays(20L));
|
||||||
|
|
||||||
Order order = account.orderCertificate(Arrays.asList(domain), notBefore, notAfter);
|
Order order = account.newOrder()
|
||||||
|
.domain(domain)
|
||||||
|
.notBefore(notBefore)
|
||||||
|
.notAfter(notAfter)
|
||||||
|
.create();
|
||||||
assertThat(order.getNotBefore(), is(notBefore));
|
assertThat(order.getNotBefore(), is(notBefore));
|
||||||
assertThat(order.getNotAfter(), is(notAfter));
|
assertThat(order.getNotAfter(), is(notAfter));
|
||||||
assertThat(order.getStatus(), is(Status.PENDING));
|
assertThat(order.getStatus(), is(Status.PENDING));
|
||||||
|
|
|
@ -2,14 +2,15 @@
|
||||||
|
|
||||||
Once you have your account set up, you are ready to order certificates.
|
Once you have your account set up, you are ready to order certificates.
|
||||||
|
|
||||||
Use your `Account` object to order the certificate, by using the `orderCertificate()` method. It requires a collection of domain names to be ordered. You can optionally give your desired `notBefore` and `notAfter` dates for the generated certificate, but it is at the discretion of the CA to use (or ignore) these values.
|
Use your `Account` object to order the certificate, by using the `newOrder()` method. It returns an OrderBuilder object that helps you to collect the parameters of the order. You can give one or more domain names. Optionally you can also give your desired `notBefore` and `notAfter` dates for the generated certificate, but it is at the discretion of the CA to use (or ignore) these values.
|
||||||
|
|
||||||
```java
|
```java
|
||||||
Account account = ... // your Account object
|
Account account = ... // your Account object
|
||||||
|
|
||||||
Order order = account.orderCertificate(
|
Order order = account.newOrder()
|
||||||
Arrays.of("example.org", "www.example.org", "m.example.org"),
|
.domains("example.org", "www.example.org", "m.example.org")
|
||||||
null, null);
|
.notAfter(Instant.now().plus(Duration.ofDays(20L)))
|
||||||
|
.create();
|
||||||
```
|
```
|
||||||
|
|
||||||
The `Order` resource contains a collection of `Authorization`s that can be read from the `getAuthorizations()` method. You must process _all of them_ in order to get the certificate.
|
The `Order` resource contains a collection of `Authorization`s that can be read from the `getAuthorizations()` method. You must process _all of them_ in order to get the certificate.
|
||||||
|
@ -89,13 +90,17 @@ order.execute(csr);
|
||||||
|
|
||||||
## Wildcard Certificates
|
## Wildcard Certificates
|
||||||
|
|
||||||
You can also generate a wildcard certificate that is valid for all subdomains of a domain, by prefixing the domain name with `*.` (e.g. `*.example.org`). The domain itself is not covered by the wildcard certificate, and also needs to be added to the CSR if necessary.
|
You can also generate a wildcard certificate that is valid for all subdomains of a domain, by prefixing the domain name with `*.` (e.g. `*.example.org`). The domain itself is not covered by the wildcard certificate, and also needs to be added to the order if necessary.
|
||||||
|
|
||||||
You must be able to prove ownership of the domain that you want to order a wildcard certificate for. The corresponding `Authorization` resource only refers to that domain, and does not contain the wildcard notation.
|
You must be able to prove ownership of the domain that you want to order a wildcard certificate for. The corresponding `Authorization` resource only refers to that domain, and does not contain the wildcard notation.
|
||||||
|
|
||||||
The following example creates a CSR for `example.org` and `*.example.org`:
|
The following example creates an `Order` and a CSR for `example.org` and `*.example.org`:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
|
Order order = account.newOrder()
|
||||||
|
.domains("example.org", "*.example.org")
|
||||||
|
.create();
|
||||||
|
|
||||||
KeyPair domainKeyPair = ... // KeyPair to be used for HTTPS encryption
|
KeyPair domainKeyPair = ... // KeyPair to be used for HTTPS encryption
|
||||||
|
|
||||||
CSRBuilder csrb = new CSRBuilder();
|
CSRBuilder csrb = new CSRBuilder();
|
||||||
|
|
Loading…
Reference in New Issue