use of org.shredzone.acme4j.exception.AcmeException in project stdlib by petergeneric.
the class LetsEncryptService method generateOrRenewCertificate.
public LetsEncryptCertificateEntity generateOrRenewCertificate(final String domains) {
LetsEncryptCertificateEntity entity = getCertificate(domains);
// If we already have a keypair for these domains we shouldn't regenerate it, only regenerate the cert
final KeyPair domainKeyPair;
final boolean isNew;
try {
if (entity != null) {
final ByteArrayInputStream bis = new ByteArrayInputStream(entity.getKeypair());
final InputStreamReader isr = new InputStreamReader(bis, StandardCharsets.UTF_8);
domainKeyPair = KeyPairUtils.readKeyPair(isr);
isNew = false;
} else {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
OutputStreamWriter osr = new OutputStreamWriter(bos, StandardCharsets.UTF_8);
domainKeyPair = KeyPairUtils.createKeyPair(DOMAIN_KEY_SIZE);
KeyPairUtils.writeKeyPair(domainKeyPair, osr);
entity = new LetsEncryptCertificateEntity();
entity.setId(domains);
entity.setKeypair(bos.toByteArray());
isNew = true;
}
} catch (IOException e) {
throw new RuntimeException("Error serialising/deserialising keypair for domains " + domains, e);
}
final Registration registration = getRegistration();
// Generate a CSR for the domains
CSRBuilder csrb = new CSRBuilder();
for (String domain : domains.split(",")) csrb.addDomain(domain);
try {
csrb.sign(domainKeyPair);
} catch (IOException e) {
throw new RuntimeException("Error signing CSR for " + domains + " with domains keypair!", e);
}
// Request a signed certificate
final Certificate certificate;
try {
certificate = registration.requestCertificate(csrb.getEncoded());
log.info("Success! The certificate for domains " + domains + " has been generated!");
log.info("Certificate URI: " + certificate.getLocation());
} catch (IOException e) {
throw new RuntimeException("Failed to encode CSR request for " + domains, e);
} catch (AcmeException e) {
throw new RuntimeException("Failed to request certificate from Let's Encrypt for " + domains, e);
}
// Download the certificate
final X509Certificate cert;
final X509Certificate[] chain;
try {
cert = certificate.download();
chain = certificate.downloadChain();
} catch (AcmeException e) {
throw new RuntimeException("Error downloading certificate information for " + domains + " " + certificate.getLocation(), e);
}
// Write certificate only
final byte[] certBytes;
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
OutputStreamWriter osr = new OutputStreamWriter(bos, StandardCharsets.UTF_8);
CertificateUtils.writeX509Certificate(cert, osr);
certBytes = bos.toByteArray();
} catch (IOException e) {
throw new RuntimeException("Error serialising Cert for " + domains, e);
}
// Write chain only
byte[] chainBytes;
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
OutputStreamWriter osr = new OutputStreamWriter(bos, StandardCharsets.UTF_8);
CertificateUtils.writeX509CertificateChain(chain, osr);
chainBytes = bos.toByteArray();
} catch (IOException e) {
throw new RuntimeException("Error serialising Cert for " + domains, e);
}
entity.setCert(certBytes);
entity.setChain(chainBytes);
entity.setExpires(new DateTime(cert.getNotAfter()));
// Make sure a management token is assigned
if (entity.getManagementToken() == null)
entity.setManagementToken(SimpleId.alphanumeric(32));
if (isNew) {
certificateDao.save(entity);
} else {
certificateDao.update(entity);
}
return entity;
}
use of org.shredzone.acme4j.exception.AcmeException 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!");
}
}
Aggregations