Skip to content

Let's encrypt

dadolhay edited this page Jan 14, 2023 · 1 revision

What is Let's encrypt?

It's a certificate authority (CA), that is:

  • recognized by most modern systems (they are added as a root ca to the key store)
  • Is free to use
  • Is completely automated

How are we using it?

Let's encrypt implements a common protocol called ACME. We can make use of a node library called acme-client to request new certificates

What do we need?

  • An accountKey, which is a PEM ancoded private key. This identifies the let's encrypt account that we connect the certificates we generate.
  • A way to list, add, and remove TXT records in the DNS server
  • An email address to use in the certificate
  • Possibly, some other details, country, state, locality, organization, organizationUnit and emailAddress
  • A way to securely store the cert, and it's expiration date

How does it work?

example adapted from official example

const generate = async ({ accountKey, domain }) => {
  /* Init client */
  const client = new acme.Client({
    directoryUrl: acme.directory.letsencrypt.production,
    accountKey,
  });

  /* Create CSR */
  const [key, csr] = await acme.crypto.createCsr({
    commonName: `*.${domain}`, // Yes, the wildcard has to be the commonName
    altNames: [domain], // But we also add the `root` or `naked` domain to the cert
    // We can also provide `country`, `state`, `locality`, `organization`, `organizationUnit` and `emailAddress` here
  });

  /* Certificate */
  const cert = await client.auto({
    csr,
    email,
    challengePriority: ["dns-01"],
    termsOfServiceAgreed: true,
    challengeCreateFn,
    challengeRemoveFn,
  });

  /* Done */
  log(`CSR:\n${csr.toString()}`);
  log(`Private key:\n${key.toString()}`);
  log(`Certificate:\n${cert.toString()}`);
};

generate({
  accountKey: await acme.crypto.createPrivateKey(),
  domain: "example.com",
  email: "test@example.com",
});

So ... How does it work again?

  • We are using a pre-existing account, by using it's PEM encoded account key. Professor will probably create this and store it in the hosting provider's secrets store
  • We are creating a CSR or certificate signing request, where we state the domain as a wildcard and as a "naked" or "root" domain as well. This means that the system will generate two challenges for us
  • It calls challengeCreateFn twice, ...actually with the exact same parameters in our case, but we have to add two TXT records with the same name
  • acme-client verifies this for us before sending the request to Let's encrypt.
  • Let's encrypt also verifies the exact same things ("dns-01" type challenge), and issues the certificate
  • The TXT records are then removed using the challengeRemoveFn, because if they were to pile up too bad (over multiple renewals), let's encrypt would start rejecting the requests.

Additional resources