Add missing acme-ari-01 call

pull/144/head
Richard Körber 2023-09-27 18:45:20 +02:00
parent 3ad325782b
commit 2485666b87
No known key found for this signature in database
GPG Key ID: AAB9FD19C78AA3E0
3 changed files with 125 additions and 0 deletions

View File

@ -268,6 +268,28 @@ public class Certificate extends AcmeResource {
return renewalInfo;
}
/**
* Signals to the CA that this certificate has been successfully replaced by a newer
* one. A revocation of this certificate would not disrupt any ongoing services.
* <p>
* This method is only supported by CAs that are providing renewal information
* (see {@link #hasRenewalInfo()}. An {@link AcmeNotSupportedException} is thrown
* otherwise.
*
* @since 3.1.0
*/
public void markAsReplaced() throws AcmeException {
LOG.debug("mark as replaced");
var session = getSession();
var renewalInfoUrl = session.resourceUrl(Resource.RENEWAL_INFO);
try (var conn = session.connect()) {
var claims = new JSONBuilder();
claims.put("certID", getCertID());
claims.put("replaced", true);
conn.sendSignedRequest(renewalInfoUrl, claims, getLogin());
}
}
/**
* Revokes this certificate.
*/

View File

@ -15,6 +15,7 @@ package org.shredzone.acme4j;
import static net.javacrumbs.jsonunit.assertj.JsonAssertions.assertThatJson;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.shredzone.acme4j.toolbox.TestUtils.*;
import java.io.ByteArrayOutputStream;
@ -36,6 +37,7 @@ import java.util.Optional;
import org.junit.jupiter.api.Test;
import org.shredzone.acme4j.connector.Resource;
import org.shredzone.acme4j.exception.AcmeException;
import org.shredzone.acme4j.exception.AcmeNotSupportedException;
import org.shredzone.acme4j.provider.TestableConnectionProvider;
import org.shredzone.acme4j.toolbox.JSON;
import org.shredzone.acme4j.toolbox.JSONBuilder;
@ -358,4 +360,101 @@ public class CertificateTest {
provider.close();
}
/**
* Test that a certificate is marked as replaced.
*/
@Test
public void testMarkedAsReplaced() throws AcmeException, IOException {
// certid-cert.pem and certId provided by draft-ietf-acme-ari-01 and known good
var certId = "MFswCwYJYIZIAWUDBAIBBCCeWLRusNLb--vmWOkxm34qDjTMWkc3utIhOMoMwKDqbgQg2iiKWySZrD-6c88HMZ6vhIHZPamChLlzGHeZ7pTS8jYCCD6jRWhlRB8c";
var certIdCert = TestUtils.createCertificate("/certid-cert.pem");
var certResourceUrl = new URL(resourceUrl.toExternalForm() + "/" + certId);
var provider = new TestableConnectionProvider() {
private boolean certRequested = false;
@Override
public int sendCertificateRequest(URL url, Login login) {
assertThat(url).isEqualTo(locationUrl);
assertThat(login).isNotNull();
certRequested = true;
return HttpURLConnection.HTTP_OK;
}
@Override
public int sendSignedRequest(URL url, JSONBuilder claims, Login login) {
assertThat(certRequested).isTrue();
assertThat(url).isEqualTo(resourceUrl);
assertThatJson(claims.toString()).isEqualTo(getJSON("replacedCertificateRequest").toString());
assertThat(login).isNotNull();
return HttpURLConnection.HTTP_OK;
}
@Override
public List<X509Certificate> readCertificates() {
assertThat(certRequested).isTrue();
return certIdCert;
}
@Override
public Collection<URL> getLinks(String relation) {
return Collections.emptyList();
}
};
provider.putTestResource(Resource.RENEWAL_INFO, resourceUrl);
var cert = new Certificate(provider.createLogin(), locationUrl);
assertThat(cert.getCertID()).isEqualTo(certId);
assertThat(cert.hasRenewalInfo()).isTrue();
assertThat(cert.getRenewalInfoLocation())
.isNotEmpty()
.contains(certResourceUrl);
cert.markAsReplaced();
provider.close();
}
/**
* Test that markAsReplaced() throws an exception if not supported.
*/
@Test
public void testMarkedAsReplacedThrowsIfNotSupported() throws AcmeException, IOException {
var certIdCert = TestUtils.createCertificate("/certid-cert.pem");
var provider = new TestableConnectionProvider() {
private boolean certRequested = false;
@Override
public int sendCertificateRequest(URL url, Login login) {
assertThat(url).isEqualTo(locationUrl);
assertThat(login).isNotNull();
certRequested = true;
return HttpURLConnection.HTTP_OK;
}
@Override
public List<X509Certificate> readCertificates() {
assertThat(certRequested).isTrue();
return certIdCert;
}
@Override
public Collection<URL> getLinks(String relation) {
return Collections.emptyList();
}
};
// We just need a dummy resource to create a directory
provider.putTestResource(Resource.NEW_ORDER, resourceUrl);
assertThatExceptionOfType(AcmeNotSupportedException.class).isThrownBy(() -> {
var cert = new Certificate(provider.createLogin(), locationUrl);
cert.markAsReplaced();
});
provider.close();
}
}

View File

@ -0,0 +1,4 @@
{
"certID": "MFswCwYJYIZIAWUDBAIBBCCeWLRusNLb--vmWOkxm34qDjTMWkc3utIhOMoMwKDqbgQg2iiKWySZrD-6c88HMZ6vhIHZPamChLlzGHeZ7pTS8jYCCD6jRWhlRB8c",
"replaced": true
}