Search in sources :

Example 1 with Dns01Challenge

use of org.shredzone.acme4j.challenge.Dns01Challenge in project stdlib by petergeneric.

the class LetsEncryptService method proveOwnership.

@Retry
public void proveOwnership(final String domain) {
    Registration registration = getRegistration();
    final Authorization authorization;
    try {
        authorization = registration.authorizeDomain(domain);
    } catch (AcmeException e) {
        throw new RuntimeException("Error creating authorisation for " + domain, e);
    }
    Dns01Challenge challenge = authorization.findChallenge(Dns01Challenge.TYPE);
    if (challenge == null)
        throw new RuntimeException("DNS Challenge is not available! Cannot prove we own " + domain);
    final String domainName = "_acme-challenge." + domain;
    log.debug("Create TXT record " + domainName + " with value: " + challenge.getDigest());
    // Create the TXT record
    dns.createDNSRecord(domainName, RecordType.TXT, challenge.getDigest());
    // Wait for a short time for the change to DNS records to propagate through Microsoft's system
    // N.B. there's no docs suggesting this is needed or that this is the right value, but Let's Encrypt challenges
    // seem to fail more regularly against the live API without this wait
    new Timeout(5, TimeUnit.SECONDS).sleep();
    // Allow the CA to start checking the TXT record
    try {
        log.trace("Challenge status " + challenge.getStatus());
        challenge.trigger();
        log.trace("Challenge status " + challenge.getStatus());
    } catch (AcmeException e) {
        throw new RuntimeException("Error triggering authorisation for " + domain, e);
    }
    // Poll waiting for the challenge to complete
    int attempts = 10;
    for (int attempt = 0; attempt < 10; attempt++) {
        log.trace("Challenge status " + challenge.getStatus());
        if (challenge.getStatus() == Status.INVALID)
            break;
        else if (challenge.getStatus() == Status.VALID)
            break;
        Timeout.TEN_SECONDS.sleep();
        try {
            challenge.update();
        } catch (AcmeException e) {
            log.warn("Error updating challenge", e);
        }
    }
    log.trace("Challenge status " + challenge.getStatus());
    dns.deleteDNSRecord(domainName, RecordType.TXT);
    if (challenge.getStatus() != Status.VALID) {
        throw new RuntimeException("Challenge " + challenge + " failed for " + domainName + "! Failed with state " + challenge.getStatus());
    } else {
        log.debug("Challenge " + challenge + " passed!");
    }
}
Also used : Authorization(org.shredzone.acme4j.Authorization) Registration(org.shredzone.acme4j.Registration) AcmeException(org.shredzone.acme4j.exception.AcmeException) Timeout(com.peterphi.std.threading.Timeout) Dns01Challenge(org.shredzone.acme4j.challenge.Dns01Challenge) Retry(com.peterphi.std.guice.common.retry.annotation.Retry)

Aggregations

Retry (com.peterphi.std.guice.common.retry.annotation.Retry)1 Timeout (com.peterphi.std.threading.Timeout)1 Authorization (org.shredzone.acme4j.Authorization)1 Registration (org.shredzone.acme4j.Registration)1 Dns01Challenge (org.shredzone.acme4j.challenge.Dns01Challenge)1 AcmeException (org.shredzone.acme4j.exception.AcmeException)1