mirror of https://github.com/shred/acme4j
Add pre-authorization support
parent
4e1ad652b0
commit
7d83ef0e80
|
@ -37,6 +37,7 @@ import org.shredzone.acme4j.exception.AcmeException;
|
|||
import org.shredzone.acme4j.exception.AcmeLazyLoadingException;
|
||||
import org.shredzone.acme4j.exception.AcmeProtocolException;
|
||||
import org.shredzone.acme4j.exception.AcmeRetryAfterException;
|
||||
import org.shredzone.acme4j.exception.AcmeServerException;
|
||||
import org.shredzone.acme4j.provider.pebble.Pebble;
|
||||
import org.shredzone.acme4j.util.JSON;
|
||||
import org.shredzone.acme4j.util.JSONBuilder;
|
||||
|
@ -176,28 +177,40 @@ public class Registration extends AcmeResource {
|
|||
}
|
||||
|
||||
/**
|
||||
* Authorizes a domain. The domain is associated with this registration.
|
||||
* Pre-authorizes a domain. The CA will check if it accepts the domain for
|
||||
* certification, and returns the necessary challenges.
|
||||
* <p>
|
||||
* IDN domain names will be ACE encoded automatically.
|
||||
* Some servers may not allow pre-authorization.
|
||||
*
|
||||
* @param domain
|
||||
* Domain name to be authorized
|
||||
* Domain name to be pre-authorized. IDN names are accepted and will be ACE
|
||||
* encoded automatically.
|
||||
* @return {@link Authorization} object for this domain
|
||||
* @throws AcmeException
|
||||
* if the server does not allow pre-authorization
|
||||
* @throws AcmeServerException
|
||||
* if the server allows pre-authorization, but will refuse to issue a
|
||||
* certificate for this domain
|
||||
*/
|
||||
public Authorization authorizeDomain(String domain) throws AcmeException {
|
||||
public Authorization preAuthorizeDomain(String domain) throws AcmeException {
|
||||
Objects.requireNonNull(domain, "domain");
|
||||
if (domain.isEmpty()) {
|
||||
throw new IllegalArgumentException("domain must not be empty");
|
||||
}
|
||||
|
||||
LOG.debug("authorizeDomain {}", domain);
|
||||
URL newAuthzUrl = getSession().resourceUrl(Resource.NEW_AUTHZ);
|
||||
if (newAuthzUrl == null) {
|
||||
throw new AcmeException("Server does not allow pre-authorization");
|
||||
}
|
||||
|
||||
LOG.debug("preAuthorizeDomain {}", domain);
|
||||
try (Connection conn = getSession().provider().connect()) {
|
||||
JSONBuilder claims = new JSONBuilder();
|
||||
claims.object("identifier")
|
||||
.put("type", "dns")
|
||||
.put("value", toAce(domain));
|
||||
|
||||
conn.sendSignedRequest(getSession().resourceUrl(Resource.NEW_AUTHZ), claims, getSession());
|
||||
conn.sendSignedRequest(newAuthzUrl, claims, getSession());
|
||||
conn.accept(HttpURLConnection.HTTP_CREATED);
|
||||
|
||||
JSON json = conn.readJsonResponse();
|
||||
|
|
|
@ -41,6 +41,7 @@ import org.shredzone.acme4j.challenge.Dns01Challenge;
|
|||
import org.shredzone.acme4j.challenge.Http01Challenge;
|
||||
import org.shredzone.acme4j.connector.Resource;
|
||||
import org.shredzone.acme4j.exception.AcmeException;
|
||||
import org.shredzone.acme4j.exception.AcmeServerException;
|
||||
import org.shredzone.acme4j.provider.AcmeProvider;
|
||||
import org.shredzone.acme4j.provider.TestableConnectionProvider;
|
||||
import org.shredzone.acme4j.util.JSON;
|
||||
|
@ -251,10 +252,10 @@ public class RegistrationTest {
|
|||
}
|
||||
|
||||
/**
|
||||
* Test that a new {@link Authorization} can be created.
|
||||
* Test that a domain can be pre-authorized.
|
||||
*/
|
||||
@Test
|
||||
public void testAuthorizeDomain() throws Exception {
|
||||
public void testPreAuthorizeDomain() throws Exception {
|
||||
TestableConnectionProvider provider = new TestableConnectionProvider() {
|
||||
@Override
|
||||
public void sendSignedRequest(URL url, JSONBuilder claims, Session session) {
|
||||
|
@ -292,7 +293,7 @@ public class RegistrationTest {
|
|||
String domainName = "example.org";
|
||||
|
||||
Registration registration = new Registration(session, locationUrl);
|
||||
Authorization auth = registration.authorizeDomain(domainName);
|
||||
Authorization auth = registration.preAuthorizeDomain(domainName);
|
||||
|
||||
assertThat(auth.getDomain(), is(domainName));
|
||||
assertThat(auth.getStatus(), is(Status.PENDING));
|
||||
|
@ -305,29 +306,80 @@ public class RegistrationTest {
|
|||
provider.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that a domain pre-authorization can fail.
|
||||
*/
|
||||
@Test
|
||||
public void testNoPreAuthorizeDomain() throws Exception {
|
||||
URI problemType = URI.create("urn:ietf:params:acme:error:rejectedIdentifier");
|
||||
String problemDetail = "example.org is blacklisted";
|
||||
|
||||
TestableConnectionProvider provider = new TestableConnectionProvider() {
|
||||
@Override
|
||||
public void sendSignedRequest(URL url, JSONBuilder claims, Session session) {
|
||||
assertThat(url, is(resourceUrl));
|
||||
assertThat(claims.toString(), sameJSONAs(getJSON("newAuthorizationRequest").toString()));
|
||||
assertThat(session, is(notNullValue()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int accept(int... httpStatus) throws AcmeException {
|
||||
Problem problem = TestUtils.createProblem(problemType, problemDetail, resourceUrl);
|
||||
throw new AcmeServerException(problem);
|
||||
}
|
||||
};
|
||||
|
||||
Session session = provider.createSession();
|
||||
|
||||
provider.putTestResource(Resource.NEW_AUTHZ, resourceUrl);
|
||||
|
||||
Registration registration = new Registration(session, locationUrl);
|
||||
|
||||
try {
|
||||
registration.preAuthorizeDomain("example.org");
|
||||
fail("preauthorization was accepted");
|
||||
} catch (AcmeServerException ex) {
|
||||
assertThat(ex.getType(), is(problemType));
|
||||
assertThat(ex.getMessage(), is(problemDetail));
|
||||
}
|
||||
|
||||
provider.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that a bad domain parameter is not accepted.
|
||||
*/
|
||||
@Test
|
||||
public void testAuthorizeBadDomain() throws Exception {
|
||||
TestableConnectionProvider provider = new TestableConnectionProvider();
|
||||
// just provide a resource record so the provider returns a directory
|
||||
provider.putTestResource(Resource.NEW_NONCE, resourceUrl);
|
||||
|
||||
Session session = provider.createSession();
|
||||
Registration registration = Registration.bind(session, locationUrl);
|
||||
|
||||
try {
|
||||
registration.authorizeDomain(null);
|
||||
registration.preAuthorizeDomain(null);
|
||||
fail("null domain was accepted");
|
||||
} catch (NullPointerException ex) {
|
||||
// expected
|
||||
}
|
||||
|
||||
try {
|
||||
registration.authorizeDomain("");
|
||||
registration.preAuthorizeDomain("");
|
||||
fail("empty domain string was accepted");
|
||||
} catch (IllegalArgumentException ex) {
|
||||
// expected
|
||||
}
|
||||
|
||||
try {
|
||||
registration.preAuthorizeDomain("example.com");
|
||||
fail("preauthorization was accepted");
|
||||
} catch (AcmeException ex) {
|
||||
// expected
|
||||
assertThat(ex.getMessage(), is("Server does not allow pre-authorization"));
|
||||
}
|
||||
|
||||
provider.close();
|
||||
}
|
||||
|
||||
|
|
|
@ -209,7 +209,7 @@ public class ClientTest {
|
|||
*/
|
||||
private void authorize(Registration reg, String domain) throws AcmeException {
|
||||
// Authorize the domain.
|
||||
Authorization auth = reg.authorizeDomain(domain);
|
||||
Authorization auth = reg.preAuthorizeDomain(domain);
|
||||
LOG.info("Authorization for domain " + domain);
|
||||
|
||||
// Find the desired challenge and prepare it.
|
||||
|
|
Loading…
Reference in New Issue