Create tls-alpn-01 cert in challenge class

This commit is contained in:
Richard Körber
2023-05-19 10:20:07 +02:00
parent 16b02efe23
commit e22b47f140
3 changed files with 57 additions and 14 deletions

View File

@@ -15,8 +15,14 @@ package org.shredzone.acme4j.challenge;
import static org.shredzone.acme4j.toolbox.AcmeUtils.sha256hash;
import java.io.IOException;
import java.security.KeyPair;
import java.security.cert.X509Certificate;
import org.shredzone.acme4j.Identifier;
import org.shredzone.acme4j.Login;
import org.shredzone.acme4j.toolbox.JSON;
import org.shredzone.acme4j.util.CertificateUtils;
/**
* Implements the {@value TYPE} challenge. It requires a specific certificate that can be
@@ -63,6 +69,25 @@ public class TlsAlpn01Challenge extends TokenChallenge {
return sha256hash(getAuthorization());
}
/**
* Creates a self-signed {@link X509Certificate} for this challenge. The certificate
* is valid for 7 days.
*
* @param keypair
* A domain {@link KeyPair} to be used for the challenge
* @param id
* The {@link Identifier} that is to be validated
* @return Created certificate
* @since 3.0.0
*/
public X509Certificate createCertificate(KeyPair keypair, Identifier id) {
try {
return CertificateUtils.createTlsAlpn01Certificate(keypair, id, getAcmeValidation());
} catch (IOException ex) {
throw new IllegalArgumentException("Bad certificate parameters", ex);
}
}
@Override
protected boolean acceptable(String type) {
return TYPE.equals(type);

View File

@@ -15,14 +15,19 @@ package org.shredzone.acme4j.challenge;
import static net.javacrumbs.jsonunit.assertj.JsonAssertions.assertThatJson;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatNoException;
import static org.shredzone.acme4j.toolbox.TestUtils.getJSON;
import java.security.cert.CertificateParsingException;
import org.junit.jupiter.api.Test;
import org.shredzone.acme4j.Identifier;
import org.shredzone.acme4j.Login;
import org.shredzone.acme4j.Status;
import org.shredzone.acme4j.toolbox.AcmeUtils;
import org.shredzone.acme4j.toolbox.JSONBuilder;
import org.shredzone.acme4j.toolbox.TestUtils;
import org.shredzone.acme4j.util.KeyPairUtils;
/**
* Unit tests for {@link TlsAlpn01ChallengeTest}.
@@ -54,4 +59,25 @@ public class TlsAlpn01ChallengeTest {
assertThatJson(response.toString()).isEqualTo("{}");
}
/**
* Test that {@link TlsAlpn01Challenge} generates a correct test certificate
*/
@Test
public void testTlsAlpn01Certificate() throws CertificateParsingException {
var challenge = new TlsAlpn01Challenge(login, getJSON("tlsAlpnChallenge"));
var keypair = KeyPairUtils.createKeyPair(2048);
var subject = Identifier.dns("example.com");
var certificate = challenge.createCertificate(keypair, subject);
// Only check the main requirements. Cert generation is fully tested in CertificateUtilsTest.
assertThat(certificate).isNotNull();
assertThat(certificate.getSubjectX500Principal().getName()).isEqualTo("CN=acme.invalid");
assertThat(certificate.getSubjectAlternativeNames().stream()
.map(l -> l.get(1))
.map(Object::toString)).contains(subject.getDomain());
assertThat(certificate.getCriticalExtensionOIDs()).contains(TlsAlpn01Challenge.ACME_VALIDATION_OID);
assertThatNoException().isThrownBy(() -> certificate.verify(keypair.getPublic()));
}
}