Add support for ACME DNS hooks
Closes: https://todo.sr.ht/~emersion/tlstunnel/2
This commit is contained in:
parent
3fd3471799
commit
662136ea74
|
@ -175,6 +175,19 @@ func parseTLS(srv *Server, d *scfg.Directive) error {
|
|||
if err := parseTLSOnDemand(srv, child); err != nil {
|
||||
return err
|
||||
}
|
||||
case "acme_dns_command":
|
||||
var cmdName string
|
||||
if err := child.ParseParams(&cmdName); err != nil {
|
||||
return err
|
||||
}
|
||||
cmdParams := child.Params[1:]
|
||||
|
||||
srv.ACMEIssuer.DNS01Solver = &certmagic.DNS01Solver{
|
||||
DNSProvider: &commandDNSProvider{
|
||||
Name: cmdName,
|
||||
Params: cmdParams,
|
||||
},
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("unknown %q directive", child.Name)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
package tlstunnel
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"github.com/caddyserver/certmagic"
|
||||
"github.com/libdns/libdns"
|
||||
)
|
||||
|
||||
type commandDNSProvider struct {
|
||||
Name string
|
||||
Params []string
|
||||
}
|
||||
|
||||
var _ certmagic.ACMEDNSProvider = (*commandDNSProvider)(nil)
|
||||
|
||||
func (provider *commandDNSProvider) exec(ctx context.Context, subcmd string, subargs ...string) error {
|
||||
var params []string
|
||||
params = append(params, provider.Params...)
|
||||
params = append(params, subcmd)
|
||||
params = append(params, subargs...)
|
||||
cmd := exec.CommandContext(ctx, provider.Name, params...)
|
||||
|
||||
if out, err := cmd.CombinedOutput(); err != nil {
|
||||
details := ""
|
||||
if len(out) > 0 {
|
||||
details = ": " + string(out)
|
||||
}
|
||||
return fmt.Errorf("failed to run DNS hook %v (%w)%v", subcmd, err, details)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (provider *commandDNSProvider) processRecords(ctx context.Context, zone string, recs []libdns.Record, subcmd string) ([]libdns.Record, error) {
|
||||
var (
|
||||
done []libdns.Record
|
||||
err error
|
||||
)
|
||||
for _, rec := range recs {
|
||||
var domain string
|
||||
if domain, err = domainFromACMEChallengeRecord(zone, &rec); err != nil {
|
||||
break
|
||||
}
|
||||
if err = provider.exec(ctx, subcmd, domain, "-", rec.Value); err != nil {
|
||||
break
|
||||
}
|
||||
done = append(done, rec)
|
||||
}
|
||||
return done, err
|
||||
}
|
||||
|
||||
func (provider *commandDNSProvider) AppendRecords(ctx context.Context, zone string, recs []libdns.Record) ([]libdns.Record, error) {
|
||||
return provider.processRecords(ctx, zone, recs, "deploy_challenge")
|
||||
}
|
||||
|
||||
func (provider *commandDNSProvider) DeleteRecords(ctx context.Context, zone string, recs []libdns.Record) ([]libdns.Record, error) {
|
||||
return provider.processRecords(ctx, zone, recs, "clean_challenge")
|
||||
}
|
||||
|
||||
func domainFromACMEChallengeRecord(zone string, rec *libdns.Record) (string, error) {
|
||||
if rec.Type != "TXT" || !strings.HasPrefix(rec.Name, "_acme-challenge.") {
|
||||
return "", fmt.Errorf("DNS record doesn't look like an ACME challenge: %v %v", rec.Type, rec.Name)
|
||||
}
|
||||
relName := strings.TrimPrefix(rec.Name, "_acme-challenge.")
|
||||
relZone := strings.TrimSuffix(zone, ".")
|
||||
return relName + "." + relZone, nil
|
||||
}
|
1
go.mod
1
go.mod
|
@ -6,6 +6,7 @@ require (
|
|||
git.sr.ht/~emersion/go-scfg v0.0.0-20211215104734-c2c7a15d6c99
|
||||
github.com/caddyserver/certmagic v0.17.2
|
||||
github.com/klauspost/cpuid/v2 v2.2.1 // indirect
|
||||
github.com/libdns/libdns v0.2.1
|
||||
github.com/pires/go-proxyproto v0.6.2
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
go.uber.org/atomic v1.10.0 // indirect
|
||||
|
|
|
@ -123,6 +123,13 @@ The following directives are supported:
|
|||
The environment will contain a *TLSTUNNEL_NAME* variable with the
|
||||
domain name to be validated.
|
||||
|
||||
*acme_dns_command* command [arguments...]
|
||||
Configure the ACME DNS challenge using the specified command.
|
||||
|
||||
The command must implement _deploy_challenge_ and _clean_challenge_
|
||||
as specified by dehydrated's hooks:
|
||||
https://github.com/dehydrated-io/dehydrated
|
||||
|
||||
# FILES
|
||||
|
||||
_/etc/tlstunnel/config_
|
||||
|
|
Loading…
Reference in New Issue