mirror of https://github.com/shred/acme4j
Add generator for DNS challenge resource name
parent
8d9ab54782
commit
379f184a41
|
@ -16,6 +16,7 @@ package org.shredzone.acme4j.challenge;
|
||||||
import static org.shredzone.acme4j.toolbox.AcmeUtils.base64UrlEncode;
|
import static org.shredzone.acme4j.toolbox.AcmeUtils.base64UrlEncode;
|
||||||
import static org.shredzone.acme4j.toolbox.AcmeUtils.sha256hash;
|
import static org.shredzone.acme4j.toolbox.AcmeUtils.sha256hash;
|
||||||
|
|
||||||
|
import org.shredzone.acme4j.Identifier;
|
||||||
import org.shredzone.acme4j.Login;
|
import org.shredzone.acme4j.Login;
|
||||||
import org.shredzone.acme4j.toolbox.JSON;
|
import org.shredzone.acme4j.toolbox.JSON;
|
||||||
|
|
||||||
|
@ -30,6 +31,39 @@ public class Dns01Challenge extends TokenChallenge {
|
||||||
*/
|
*/
|
||||||
public static final String TYPE = "dns-01";
|
public static final String TYPE = "dns-01";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The prefix of the domain name to be used for the DNS TXT record.
|
||||||
|
*/
|
||||||
|
public static final String RECORD_NAME_PREFIX = "_acme-challenge";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a domain identifier to the Resource Record name to be used for the DNS TXT
|
||||||
|
* record.
|
||||||
|
*
|
||||||
|
* @param identifier
|
||||||
|
* Domain {@link Identifier} of the domain to be validated
|
||||||
|
* @return Resource Record name (e.g. {@code _acme-challenge.www.example.org.}, note
|
||||||
|
* the trailing full stop character).
|
||||||
|
* @since 2.14
|
||||||
|
*/
|
||||||
|
public static String toRRName(Identifier identifier) {
|
||||||
|
return toRRName(identifier.getDomain());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a domain identifier to the Resource Record name to be used for the DNS TXT
|
||||||
|
* record.
|
||||||
|
*
|
||||||
|
* @param domain
|
||||||
|
* Domain name to be validated
|
||||||
|
* @return Resource Record name (e.g. {@code _acme-challenge.www.example.org.}, note
|
||||||
|
* the trailing full stop character).
|
||||||
|
* @since 2.14
|
||||||
|
*/
|
||||||
|
public static String toRRName(String domain) {
|
||||||
|
return RECORD_NAME_PREFIX + '.' + domain + '.';
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new generic {@link Dns01Challenge} object.
|
* Creates a new generic {@link Dns01Challenge} object.
|
||||||
*
|
*
|
||||||
|
|
|
@ -15,11 +15,14 @@ package org.shredzone.acme4j.challenge;
|
||||||
|
|
||||||
import static net.javacrumbs.jsonunit.assertj.JsonAssertions.assertThatJson;
|
import static net.javacrumbs.jsonunit.assertj.JsonAssertions.assertThatJson;
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||||
import static org.shredzone.acme4j.toolbox.TestUtils.getJSON;
|
import static org.shredzone.acme4j.toolbox.TestUtils.getJSON;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.shredzone.acme4j.Identifier;
|
||||||
import org.shredzone.acme4j.Login;
|
import org.shredzone.acme4j.Login;
|
||||||
import org.shredzone.acme4j.Status;
|
import org.shredzone.acme4j.Status;
|
||||||
|
import org.shredzone.acme4j.exception.AcmeProtocolException;
|
||||||
import org.shredzone.acme4j.toolbox.JSONBuilder;
|
import org.shredzone.acme4j.toolbox.JSONBuilder;
|
||||||
import org.shredzone.acme4j.toolbox.TestUtils;
|
import org.shredzone.acme4j.toolbox.TestUtils;
|
||||||
|
|
||||||
|
@ -48,4 +51,16 @@ public class DnsChallengeTest {
|
||||||
assertThatJson(response.toString()).isEqualTo("{}");
|
assertThatJson(response.toString()).isEqualTo("{}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testToRRName() {
|
||||||
|
assertThat(Dns01Challenge.toRRName("www.example.org"))
|
||||||
|
.isEqualTo("_acme-challenge.www.example.org.");
|
||||||
|
assertThat(Dns01Challenge.toRRName(Identifier.dns("www.example.org")))
|
||||||
|
.isEqualTo("_acme-challenge.www.example.org.");
|
||||||
|
assertThatExceptionOfType(AcmeProtocolException.class)
|
||||||
|
.isThrownBy(() -> Dns01Challenge.toRRName(Identifier.ip("127.0.0.10")));
|
||||||
|
assertThat(Dns01Challenge.RECORD_NAME_PREFIX)
|
||||||
|
.isEqualTo("_acme-challenge");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -362,15 +362,14 @@ public class ClientTest {
|
||||||
|
|
||||||
// Output the challenge, wait for acknowledge...
|
// Output the challenge, wait for acknowledge...
|
||||||
LOG.info("Please create a TXT record:");
|
LOG.info("Please create a TXT record:");
|
||||||
LOG.info("_acme-challenge.{}. IN TXT {}",
|
LOG.info("{} IN TXT {}",
|
||||||
auth.getIdentifier().getDomain(), challenge.getDigest());
|
Dns01Challenge.toRRName(auth.getIdentifier()), challenge.getDigest());
|
||||||
LOG.info("If you're ready, dismiss the dialog...");
|
LOG.info("If you're ready, dismiss the dialog...");
|
||||||
|
|
||||||
StringBuilder message = new StringBuilder();
|
StringBuilder message = new StringBuilder();
|
||||||
message.append("Please create a TXT record:\n\n");
|
message.append("Please create a TXT record:\n\n");
|
||||||
message.append("_acme-challenge.")
|
message.append(Dns01Challenge.toRRName(auth.getIdentifier()))
|
||||||
.append(auth.getIdentifier().getDomain())
|
.append(" IN TXT ")
|
||||||
.append(". IN TXT ")
|
|
||||||
.append(challenge.getDigest());
|
.append(challenge.getDigest());
|
||||||
acceptChallenge(message.toString());
|
acceptChallenge(message.toString());
|
||||||
|
|
||||||
|
|
|
@ -107,13 +107,13 @@ public class BammBammClient {
|
||||||
* another TXT Record is set, it will replace the existing one.
|
* another TXT Record is set, it will replace the existing one.
|
||||||
*
|
*
|
||||||
* @param domain
|
* @param domain
|
||||||
* Domain to add the TXT Record to
|
* Domain name to add the TXT Record to
|
||||||
* @param txt
|
* @param txt
|
||||||
* TXT record to add
|
* TXT record to add
|
||||||
*/
|
*/
|
||||||
public void dnsAddTxtRecord(String domain, String txt) throws IOException {
|
public void dnsAddTxtRecord(String domain, String txt) throws IOException {
|
||||||
JSONBuilder jb = new JSONBuilder();
|
JSONBuilder jb = new JSONBuilder();
|
||||||
jb.put("host", domain + '.');
|
jb.put("host", domain);
|
||||||
jb.put("value", txt);
|
jb.put("value", txt);
|
||||||
sendRequest("set-txt", jb.toString());
|
sendRequest("set-txt", jb.toString());
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,7 +81,7 @@ public class OrderIT extends PebbleITBase {
|
||||||
Dns01Challenge challenge = auth.findChallenge(Dns01Challenge.TYPE);
|
Dns01Challenge challenge = auth.findChallenge(Dns01Challenge.TYPE);
|
||||||
assertThat(challenge).isNotNull();
|
assertThat(challenge).isNotNull();
|
||||||
|
|
||||||
String challengeDomainName = "_acme-challenge." + auth.getIdentifier().getDomain();
|
String challengeDomainName = Dns01Challenge.toRRName(auth.getIdentifier());
|
||||||
|
|
||||||
client.dnsAddTxtRecord(challengeDomainName, challenge.getDigest());
|
client.dnsAddTxtRecord(challengeDomainName, challenge.getDigest());
|
||||||
|
|
||||||
|
|
|
@ -87,7 +87,7 @@ public class OrderWildcardIT extends PebbleITBase {
|
||||||
Dns01Challenge challenge = auth.findChallenge(Dns01Challenge.TYPE);
|
Dns01Challenge challenge = auth.findChallenge(Dns01Challenge.TYPE);
|
||||||
assertThat(challenge).isNotNull();
|
assertThat(challenge).isNotNull();
|
||||||
|
|
||||||
String challengeDomainName = "_acme-challenge." + TEST_DOMAIN;
|
String challengeDomainName = Dns01Challenge.toRRName(TEST_DOMAIN);
|
||||||
|
|
||||||
client.dnsAddTxtRecord(challengeDomainName, challenge.getDigest());
|
client.dnsAddTxtRecord(challengeDomainName, challenge.getDigest());
|
||||||
cleanup(() -> client.dnsRemoveTxtRecord(challengeDomainName));
|
cleanup(() -> client.dnsRemoveTxtRecord(challengeDomainName));
|
||||||
|
|
|
@ -8,9 +8,10 @@ With the `dns-01` challenge, you prove to the CA that you are able to control th
|
||||||
Dns01Challenge challenge = auth.findChallenge(Dns01Challenge.class);
|
Dns01Challenge challenge = auth.findChallenge(Dns01Challenge.class);
|
||||||
String domain = auth.getIdentifier().getDomain();
|
String domain = auth.getIdentifier().getDomain();
|
||||||
|
|
||||||
|
String resourceName = Dns01Challenge.toRRName(auth.getIdentifier());
|
||||||
String digest = challenge.getDigest();
|
String digest = challenge.getDigest();
|
||||||
```
|
```
|
||||||
|
|
||||||
The CA expects a TXT record at `_acme-challenge.${domain}` with the `digest` string as value.
|
The CA expects a TXT record at `_acme-challenge.${domain}.` with the `digest` string as value. The `Dns01Challenge.toRRName()` method converts the domain name to a resource record name (including the trailing full stop, e.g. `_acme-challenge.www.example.org.`). The `_acme-challenge` prefix is also available as constant (`Dns01Challenge.RECORD_NAME_PREFIX`).
|
||||||
|
|
||||||
The validation was successful if the CA was able to fetch the TXT record and got the correct `digest` returned.
|
The validation was successful if the CA was able to fetch the TXT record and got the correct `digest` returned.
|
||||||
|
|
|
@ -348,15 +348,14 @@ public Challenge dnsChallenge(Authorization auth) throws AcmeException {
|
||||||
|
|
||||||
// Output the challenge, wait for acknowledge...
|
// Output the challenge, wait for acknowledge...
|
||||||
LOG.info("Please create a TXT record:");
|
LOG.info("Please create a TXT record:");
|
||||||
LOG.info("_acme-challenge.{}. IN TXT {}",
|
LOG.info("{} IN TXT {}",
|
||||||
auth.getIdentifier().getDomain(), challenge.getDigest());
|
Dns01Challenge.toRRName(auth.getIdentifier()), challenge.getDigest());
|
||||||
LOG.info("If you're ready, dismiss the dialog...");
|
LOG.info("If you're ready, dismiss the dialog...");
|
||||||
|
|
||||||
StringBuilder message = new StringBuilder();
|
StringBuilder message = new StringBuilder();
|
||||||
message.append("Please create a TXT record:\n\n");
|
message.append("Please create a TXT record:\n\n");
|
||||||
message.append("_acme-challenge.")
|
message.append(Dns01Challenge.toRRName(auth.getIdentifier()))
|
||||||
.append(auth.getIdentifier().getDomain())
|
.append(" IN TXT ")
|
||||||
.append(". IN TXT ")
|
|
||||||
.append(challenge.getDigest());
|
.append(challenge.getDigest());
|
||||||
acceptChallenge(message.toString());
|
acceptChallenge(message.toString());
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue