sasa1977 / site_encrypt

Integrated certification via Let's encrypt for Elixir-powered sites
MIT License
462 stars 33 forks source link

Feature Request: Other challenge types (e.g. DNS-01) #31

Open ryanwinchester opened 3 years ago

ryanwinchester commented 3 years ago

How much effort do you think would be required to make challenge type configurable, so we could use DNS-01 challenges?

https://letsencrypt.org/docs/challenge-types/#dns-01-challenge

This challenge asks you to prove that you control the DNS for your domain name by putting a specific value in a TXT record under that domain name. It is harder to configure than HTTP-01, but can work in scenarios that HTTP-01 can’t. It also allows you to issue wildcard certificates. After Let’s Encrypt gives your ACME client a token, your client will create a TXT record derived from that token and your account key, and put that record at _acme-challenge.<YOUR_DOMAIN>. Then Let’s Encrypt will query the DNS system for that record. If it finds a match, you can proceed to issue a certificate!

And in that case maybe we could provide our own modules that implements a behaviour, which would probably be needed.

Maybe something that looks similar to:

defmodule SiteEncrypt.DNSProviderAPI do

  alias SiteEncrypt.DNSRecord

  @type name :: String.t()

  @callback fetch_dns_record(name) :: {:ok, DNSRecord.t()} | {:error, :not_found | term()}

  @callback create_dns_record(name, map()) :: {:ok, DNSRecord.t()} | {:error, term()}

  @callback patch_dns_record(DNSRecord.t(), map()) :: {:ok, DNSRecord.t()} | {:error, term()}
end

And the community could easily contribute modules for different DNS provider APIs: https://community.letsencrypt.org/t/dns-providers-who-easily-integrate-with-lets-encrypt-dns-validation/86438

sasa1977 commented 3 years ago

How much effort do you think would be required to make challenge type configurable, so we could use DNS-01 challenges?

Thanks for asking! I would love to see this happen, but I don't have the capacity to work on this myself, other than reviewing design & implementation.

I feel that the most challenging part is indeed supporting different providers. I agree that behaviour is the way to go, and we should start by choosing a single provider. If we can make that work, the wider community can contribute other providers.

It would be great if we could keep local-development & testing friendliness, i.e. if it would be easy to run a dns certification locally without talking to a remote dns server. I currently don't know what this requires in practice though.

I'm pretty short on time these days, but if you're interested in giving this a try, I'll try to make some room for discussing possible approaches.

ryanwinchester commented 3 years ago

Thanks for asking! I would love to see this happen, but I don't have the capacity to work on this myself, other than reviewing design & implementation.

I'm pretty short on time these days, but if you're interested in giving this a try, I'll try to make some room for discussing possible approaches.

I'd be willing to give it a shot, but probably won't have time for about a month (depending on the effort involved).

I feel that the most challenging part is indeed supporting different providers. I agree that behaviour is the way to go, and we should start by choosing a single provider. If we can make that work, the wider community can contribute other providers.

I could also provide a CloudFlare provider behaviour implementation relatively easily. It looks like DNSimple also has an official Elixir client as well.

It would be great if we could keep local-development & testing friendliness, i.e. if it would be easy to run a dns certification locally without talking to a remote dns server. I currently don't know what this requires in practice though.

I have no idea what would be required for the local DNS testing either...

Also, I personally just recently (manually) scratched this itch in the meantime by finding out that there are docker containers for a bunch of different DNS providers, like this certbot/dns-cloudflare

docker run -it --rm --name certbot \
    -v "/etc/letsencrypt:/etc/letsencrypt" \
    -v "/var/lib/letsencrypt:/var/lib/letsencrypt" \
    certbot/dns-cloudflare certonly \
        --dns-cloudflare \
        --dns-cloudflare-credentials /path/to/cloudflare.ini \
        -d local.mysite.com

I needed this to test in local dev working with S3 presigned URLs with customer provided encryption keys (AWS requires https in this case but also didn't like my self-signed certs)

ryanwinchester commented 3 years ago

It would be great if we could keep local-development & testing friendliness, i.e. if it would be easy to run a dns certification locally without talking to a remote dns server. I currently don't know what this requires in practice though.

Well, of course there is an erlang DNS server https://github.com/dnsimple/erldns 😄

https://hex.pm/packages/erldns

erldns_zone_cache:put_zone({
  <<"example.com">>, [
    #dns_rr{
      name = <<"example.com">>,
      type = ?DNS_TYPE_A,
      ttl = 3600,
      data = #dns_rrdata_a{ip = {1,2,3,4}}
    },
    #dns_rr{
      name = <<"www.example.com">>,
      type = ?DNS_TYPE_CNAME,
      ttl = 3600,
      data = #dns_rrdata_cname{dname = <<"example.com">>}
    }
  ]}).

plus something like http://erlang.org/doc/man/inet_res.html

And if we really needed more than that, maybe a tool like dnsmasq?

sasa1977 commented 3 years ago

I'd be willing to give it a shot, but probably won't have time for about a month (depending on the effort involved).

That's cool. Ping me when you're ready, and we'll discuss it then.

Well, of course there is an erlang DNS server

this is the way

ryanwinchester commented 3 years ago

@sasa1977 We could really use something like this at work, so I might be able to dedicate some time to this now.