Golang example using DNS verification

Which package? The /x/crypto/acme one only supports ACME v1, which doesn't have wildcard support. Try github.com/eggsampler/acme or github.com/xenolf/lego for ACME v2 libraries.

But even with the v1 package, it's a very minor change to use the DNS challenge.

package main

import (
	"context"
	"crypto/ecdsa"
	"crypto/elliptic"
	"crypto/rand"
	"log"

	"golang.org/x/crypto/acme"
)

func main() {

	// All the usual account registration prelude
	accountKey, _ := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)

	client := &acme.Client{
		Key:          accountKey,
		DirectoryURL: "https://acme-v01.api.letsencrypt.org/directory",
	}

	if _, err := client.Register(context.Background(), &acme.Account{},
		func(tos string) bool {
			log.Printf("Agreeing to ToS: %s", tos)
			return true
		}); err != nil {
		log.Fatal("Can't register an ACME account: ", err)
	}

	// Authorize a DNS name
	authz, err := client.Authorize(context.Background(), "example.org")
	if err != nil {
		log.Fatal("Can't authorize: ", err)
	}

	// Find the DNS challenge for this authorization
	var chal *acme.Challenge
	for _, c := range authz.Challenges {
		if c.Type == "dns-01" {
			chal = c
			break
		}
	}
	if chal == nil {
		log.Fatal("No DNS challenge was present")
	}

	// Determine the TXT record values for the DNS challenge
	txtLabel := "_acme-challenge." + authz.Identifier.Value
	txtValue, _ := client.DNS01ChallengeRecord(chal.Token)
	log.Printf("Creating record %s with value %s", txtLabel, txtValue)

	// Then the usual: accept the challenge, wait for the authorization ...
	if _, err := client.Accept(context.Background(), chal); err != nil {
		log.Fatal("Can't accept challenge: ", err)
	}

	if _, err := client.WaitAuthorization(context.Background(), authz.URI); err != nil {
		log.Fatal("Failed authorization: ", err)
	}

	// Submit certificate request if it suceeded ...
}
2 Likes