Index | Thread | Search

From:
Stuart Henderson <stu@spacehopper.org>
Subject:
Re: acme-client: add challenge hook to support dns-01
To:
ports@openbsd.org, Florian Obser <florian@openbsd.org>, Evan Silberman <evan@jklol.net>
Date:
Sun, 25 Feb 2024 11:27:33 +0000

Download raw body.

Thread
  • Chaz Kettleson:

    acme-client: add challenge hook to support dns-01

  • On 2024/02/21 17:38, Florian Obser wrote:
    > | I implemented the uacme api since I find that less ugly. It should be
    > | trivial to transmogrify it with a shell one-liner to support
    > | dehydrated.
    
    and is particular nice to use because it doesn't have the awful sha256
    generation done in sh...
    
    > However, one stated requirement at the time was that the dns-01
    > challenge must work with base tools out of the box, i.e. nsd(8). I have
    > no idea how one would do that. So I dropped the diff and figured out how
    > to avoid wildcard certs.
    
    The least insane way to do this is probably to make
    _acme_challenge.example.com a separate zone and write out the zonefile
    with a programatically created serial (date +%s) and nsd reload, but
    it's rather ugly.
    
    NSD does support $INCLUDE which is another option but since you can't
    bump the serial that way, you can't use normal DNS mechanisms and would
    need to distribute the zone via something like rsync and reload on
    secondary NS.
    
    Personally I'm doing this (using uacme) with nsupdate and BIND servers.
    I don't love BIND but it works ok for me. I add domains/hosts often
    enough that having a bunch of zonefiles and NS recpords in the parent
    domain for various _acme_challenge.foo.bar would be a pain.
    
    Another option would be to use ldns-read-zone to parse zonefiles and
    bump the serials. Not in base though. Or write something else to do that
    (perl is in base :)
    
    
    On 2024/02/24 21:44, Christopher Zimmermann wrote:
    > You added actual support for dns-01 challenges into acme-client. Digest
    > calculation is performed in acme-client. The hooks can only accept dns-01
    > challenges.
    > I add a generic hook interface that will pass any challenge to the hook,
    > which can then decide, which challenges to accept and must perform digest
    > computation by itself.
    
    Keep it simple, there's no need to handle every way to do things here.
    
    TLS-ALPN-01 needs webserver integration or a TLS proxy, and letsencrypt
    don't allow it for wildcards. It doesn't seem very useful for
    acme-client to support.
    
    HTTP-01 I don't think really needs to be supported by a hook, ok it
    would add some more options, but are they really useful? You can already
    redirect .well-known/acme_challenge to the machine where you run
    acme-client if you're trying to deal with multiple servers, and that
    handles most of the important cases.
    
    > The minimum the hook needs to do is:
    > 
    > for dns-01: add a dns txt record and tear down a dns txt record
    > 
    > for http-01: temporarily serve a http resource. Maybe by uploading a file
    > somewhere and deleting it afterwards.
    > 
    > The minimum information the hook needs from acme-client for dns-01
    > challenges is:
    > - the domain name of the dns record (_acme-challenge.example.com)
    > - what to put there (the sha256/base64 digest of token.thumb)
    > - authentication like username / password of dynamic dns service.
    >   username / password need not be passed in from acme-client, but still
    > need to be stored somewhere accissible by the hook script.
    > 
    > The minimum information for http-01 challenges is:
    > - the key authorization (token.thumb)
    > - where to serve the files (challengedir or domain)
    > - authentication.
    > 
    > I kept the digest calculation in the hook, since it is only needed for
    > dns-01 and I prefer to keep the hook mechanism in acme-client indifferent
    > to the hook type. This means this complexity stays in the example hook
    > script:
    > 
    > txt=`echo -n "$ACME_TOKEN.$ACME_THUMB" |sha256 -b |tr '+/' '-_' |tr -d '='`
    > 
    > ACME_TOKEN and ACME_THUMB are checked to only contain characters from the
    > base64_url alphabet. So this seems quite safe to me.
    
    Only support DNS-01 and pass the digest and things become much simpler
    to implement in the hook. Authentication for dynamic dns services is
    nothing to do with acme-client, that can totally be handled in the
    hook (if you run your own DNS infra you'll have that configured on
    the DNS side anyway).
    
    > +	#delay 310
    
    Seems unnecessary, just sleep in the hook, or do your own propagation
    tests and don't exit until they're ok.
    
    
    
  • Chaz Kettleson:

    acme-client: add challenge hook to support dns-01