mirror of https://github.com/shred/acme4j
revoke-cert sends JWK header
parent
0a63c65885
commit
7b6582ad78
|
@ -166,7 +166,7 @@ public class Certificate extends AcmeResource {
|
||||||
LOG.debug("revoke");
|
LOG.debug("revoke");
|
||||||
URL resUrl = getSession().resourceUrl(Resource.REVOKE_CERT);
|
URL resUrl = getSession().resourceUrl(Resource.REVOKE_CERT);
|
||||||
if (resUrl == null) {
|
if (resUrl == null) {
|
||||||
throw new AcmeProtocolException("CA does not support certificate revocation");
|
throw new AcmeException("Server does not allow certificate revocation");
|
||||||
}
|
}
|
||||||
|
|
||||||
try (Connection conn = getSession().provider().connect()) {
|
try (Connection conn = getSession().provider().connect()) {
|
||||||
|
@ -176,7 +176,7 @@ public class Certificate extends AcmeResource {
|
||||||
claims.put("reason", reason.getReasonCode());
|
claims.put("reason", reason.getReasonCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
conn.sendSignedRequest(resUrl, claims, getSession());
|
conn.sendSignedRequest(resUrl, claims, getSession(), true);
|
||||||
conn.accept(HttpURLConnection.HTTP_OK);
|
conn.accept(HttpURLConnection.HTTP_OK);
|
||||||
} catch (CertificateEncodingException ex) {
|
} catch (CertificateEncodingException ex) {
|
||||||
throw new AcmeProtocolException("Invalid certificate", ex);
|
throw new AcmeProtocolException("Invalid certificate", ex);
|
||||||
|
|
|
@ -126,7 +126,7 @@ public class RegistrationBuilder {
|
||||||
createExternalAccountBinding(keyIdentifier, session.getKeyPair(), resourceUrl));
|
createExternalAccountBinding(keyIdentifier, session.getKeyPair(), resourceUrl));
|
||||||
}
|
}
|
||||||
|
|
||||||
conn.sendJwkSignedRequest(resourceUrl, claims, session);
|
conn.sendSignedRequest(resourceUrl, claims, session, true);
|
||||||
conn.accept(HttpURLConnection.HTTP_OK, HttpURLConnection.HTTP_CREATED);
|
conn.accept(HttpURLConnection.HTTP_OK, HttpURLConnection.HTTP_CREATED);
|
||||||
|
|
||||||
URL location = conn.getLocation();
|
URL location = conn.getLocation();
|
||||||
|
|
|
@ -49,8 +49,8 @@ public interface Connection extends AutoCloseable {
|
||||||
void sendRequest(URL url, Session session) throws AcmeException;
|
void sendRequest(URL url, Session session) throws AcmeException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends a signed POST request. Ensures that the session has a KeyIdentifier set that
|
* Sends a signed POST request. Ensures that the session has a KeyIdentifier set, and
|
||||||
* is used in the "kid" protected header.
|
* that the "kid" protected header field is used.
|
||||||
*
|
*
|
||||||
* @param url
|
* @param url
|
||||||
* {@link URL} to send the request to.
|
* {@link URL} to send the request to.
|
||||||
|
@ -63,7 +63,7 @@ public interface Connection extends AutoCloseable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends a signed POST request. If the session's KeyIdentifier is set, a "kid"
|
* Sends a signed POST request. If the session's KeyIdentifier is set, a "kid"
|
||||||
* protected header is sent. If not, a "jwk" protected header is sent.
|
* protected header field is sent. If not, a "jwk" protected header field is sent.
|
||||||
*
|
*
|
||||||
* @param url
|
* @param url
|
||||||
* {@link URL} to send the request to.
|
* {@link URL} to send the request to.
|
||||||
|
@ -71,8 +71,13 @@ public interface Connection extends AutoCloseable {
|
||||||
* {@link JSONBuilder} containing claims. Must not be {@code null}.
|
* {@link JSONBuilder} containing claims. Must not be {@code null}.
|
||||||
* @param session
|
* @param session
|
||||||
* {@link Session} instance to be used for signing and tracking
|
* {@link Session} instance to be used for signing and tracking
|
||||||
|
* @param enforceJwk
|
||||||
|
* {@code true} to enforce a "jwk" header field even if a KeyIdentifier is
|
||||||
|
* set, {@code false} to choose between "kid" and "jwk" header field
|
||||||
|
* automatically
|
||||||
*/
|
*/
|
||||||
void sendJwkSignedRequest(URL url, JSONBuilder claims, Session session) throws AcmeException;
|
void sendSignedRequest(URL url, JSONBuilder claims, Session session, boolean enforceJwk)
|
||||||
|
throws AcmeException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the HTTP response status is in the given list of acceptable HTTP states,
|
* Checks if the HTTP response status is in the given list of acceptable HTTP states,
|
||||||
|
|
|
@ -152,11 +152,12 @@ public class DefaultConnection implements Connection {
|
||||||
throw new IllegalStateException("session has no KeyIdentifier set");
|
throw new IllegalStateException("session has no KeyIdentifier set");
|
||||||
}
|
}
|
||||||
|
|
||||||
sendJwkSignedRequest(url, claims, session);
|
sendSignedRequest(url, claims, session, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendJwkSignedRequest(URL url, JSONBuilder claims, Session session) throws AcmeException {
|
public void sendSignedRequest(URL url, JSONBuilder claims, Session session, boolean enforceJwk)
|
||||||
|
throws AcmeException {
|
||||||
Objects.requireNonNull(url, "url");
|
Objects.requireNonNull(url, "url");
|
||||||
Objects.requireNonNull(claims, "claims");
|
Objects.requireNonNull(claims, "claims");
|
||||||
Objects.requireNonNull(session, "session");
|
Objects.requireNonNull(session, "session");
|
||||||
|
@ -182,7 +183,9 @@ public class DefaultConnection implements Connection {
|
||||||
jws.setPayload(claims.toString());
|
jws.setPayload(claims.toString());
|
||||||
jws.getHeaders().setObjectHeaderValue("nonce", Base64Url.encode(session.getNonce()));
|
jws.getHeaders().setObjectHeaderValue("nonce", Base64Url.encode(session.getNonce()));
|
||||||
jws.getHeaders().setObjectHeaderValue("url", url);
|
jws.getHeaders().setObjectHeaderValue("url", url);
|
||||||
if (session.getKeyIdentifier() != null) {
|
if (enforceJwk || session.getKeyIdentifier() == null) {
|
||||||
|
jws.getHeaders().setJwkHeaderValue("jwk", jwk);
|
||||||
|
} else {
|
||||||
// TODO PEBBLE: cannot process "kid" yet, send "jwk" instead
|
// TODO PEBBLE: cannot process "kid" yet, send "jwk" instead
|
||||||
// https://github.com/letsencrypt/pebble/issues/23
|
// https://github.com/letsencrypt/pebble/issues/23
|
||||||
if (Pebble.workaround()) {
|
if (Pebble.workaround()) {
|
||||||
|
@ -190,8 +193,6 @@ public class DefaultConnection implements Connection {
|
||||||
} else {
|
} else {
|
||||||
jws.getHeaders().setObjectHeaderValue("kid", session.getKeyIdentifier());
|
jws.getHeaders().setObjectHeaderValue("kid", session.getKeyIdentifier());
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
jws.getHeaders().setJwkHeaderValue("jwk", jwk);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
jws.setAlgorithmHeaderValue(keyAlgorithm(jwk));
|
jws.setAlgorithmHeaderValue(keyAlgorithm(jwk));
|
||||||
|
|
|
@ -136,10 +136,12 @@ public class CertificateTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendSignedRequest(URL url, JSONBuilder claims, Session session) {
|
public void sendSignedRequest(URL url, JSONBuilder claims, Session session, boolean enforceJwk) {
|
||||||
assertThat(url, is(resourceUrl));
|
assertThat(url, is(resourceUrl));
|
||||||
assertThat(claims.toString(), sameJSONAs(getJSON("revokeCertificateRequest").toString()));
|
assertThat(claims.toString(), sameJSONAs(getJSON("revokeCertificateRequest").toString()));
|
||||||
assertThat(session, is(notNullValue()));
|
assertThat(session, is(notNullValue()));
|
||||||
|
assertThat(session.getKeyIdentifier(), is(nullValue()));
|
||||||
|
assertThat(enforceJwk, is(true));
|
||||||
certRequested = false;
|
certRequested = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,10 +190,11 @@ public class CertificateTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendSignedRequest(URL url, JSONBuilder claims, Session session) {
|
public void sendSignedRequest(URL url, JSONBuilder claims, Session session, boolean enforceJwk) {
|
||||||
assertThat(url, is(resourceUrl));
|
assertThat(url, is(resourceUrl));
|
||||||
assertThat(claims.toString(), sameJSONAs(getJSON("revokeCertificateWithReasonRequest").toString()));
|
assertThat(claims.toString(), sameJSONAs(getJSON("revokeCertificateWithReasonRequest").toString()));
|
||||||
assertThat(session, is(notNullValue()));
|
assertThat(session, is(notNullValue()));
|
||||||
|
assertThat(enforceJwk, is(true));
|
||||||
certRequested = false;
|
certRequested = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -57,10 +57,11 @@ public class RegistrationBuilderTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendJwkSignedRequest(URL url, JSONBuilder claims, Session session) {
|
public void sendSignedRequest(URL url, JSONBuilder claims, Session session, boolean enforceJwk) {
|
||||||
assertThat(session, is(notNullValue()));
|
assertThat(session, is(notNullValue()));
|
||||||
assertThat(url, is(resourceUrl));
|
assertThat(url, is(resourceUrl));
|
||||||
assertThat(claims.toString(), sameJSONAs(getJSON("newRegistration").toString()));
|
assertThat(claims.toString(), sameJSONAs(getJSON("newRegistration").toString()));
|
||||||
|
assertThat(enforceJwk, is(true));
|
||||||
isUpdate = false;
|
isUpdate = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,10 +121,11 @@ public class RegistrationBuilderTest {
|
||||||
|
|
||||||
TestableConnectionProvider provider = new TestableConnectionProvider() {
|
TestableConnectionProvider provider = new TestableConnectionProvider() {
|
||||||
@Override
|
@Override
|
||||||
public void sendJwkSignedRequest(URL url, JSONBuilder claims, Session session) {
|
public void sendSignedRequest(URL url, JSONBuilder claims, Session session, boolean enforceJwk) {
|
||||||
try {
|
try {
|
||||||
assertThat(session, is(notNullValue()));
|
assertThat(session, is(notNullValue()));
|
||||||
assertThat(url, is(resourceUrl));
|
assertThat(url, is(resourceUrl));
|
||||||
|
assertThat(enforceJwk, is(true));
|
||||||
|
|
||||||
JSON binding = claims.toJSON()
|
JSON binding = claims.toJSON()
|
||||||
.get("external-account-binding")
|
.get("external-account-binding")
|
||||||
|
|
|
@ -747,7 +747,7 @@ public class DefaultConnectionTest {
|
||||||
}) {
|
}) {
|
||||||
JSONBuilder cb = new JSONBuilder();
|
JSONBuilder cb = new JSONBuilder();
|
||||||
cb.put("foo", 123).put("bar", "a-string");
|
cb.put("foo", 123).put("bar", "a-string");
|
||||||
conn.sendJwkSignedRequest(requestUrl, cb, session);
|
conn.sendSignedRequest(requestUrl, cb, session, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
verify(mockUrlConnection).setRequestMethod("POST");
|
verify(mockUrlConnection).setRequestMethod("POST");
|
||||||
|
@ -812,7 +812,7 @@ public class DefaultConnectionTest {
|
||||||
|
|
||||||
try (DefaultConnection conn = new DefaultConnection(mockHttpConnection)) {
|
try (DefaultConnection conn = new DefaultConnection(mockHttpConnection)) {
|
||||||
JSONBuilder cb = new JSONBuilder();
|
JSONBuilder cb = new JSONBuilder();
|
||||||
conn.sendJwkSignedRequest(requestUrl, cb, DefaultConnectionTest.this.session);
|
conn.sendSignedRequest(requestUrl, cb, DefaultConnectionTest.this.session, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,7 +46,8 @@ public class DummyConnection implements Connection {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendJwkSignedRequest(URL url, JSONBuilder claims, Session session) {
|
public void sendSignedRequest(URL url, JSONBuilder claims, Session session, boolean enforceJwk)
|
||||||
|
throws AcmeException {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue