diff --git a/Makefile b/Makefile index bd341e1a..6dfcbfa6 100644 --- a/Makefile +++ b/Makefile @@ -39,16 +39,16 @@ checks: .PHONY: patch minor major detach patch: - go run internal/release.go release -m patch + go run ./internal/useragent/ release -m patch minor: - go run internal/release.go release -m minor + go run ./internal/useragent/ release -m minor major: - go run internal/release.go release -m major + go run ./internal/useragent/ release -m major detach: - go run internal/release.go detach + go run ./internal/useragent/ detach # Docs .PHONY: docs-build docs-serve docs-themes diff --git a/acme/api/internal/sender/useragent.go b/acme/api/internal/sender/useragent.go index 2dc84fc2..7fb4a94e 100644 --- a/acme/api/internal/sender/useragent.go +++ b/acme/api/internal/sender/useragent.go @@ -1,7 +1,6 @@ -package sender +// Code generated by 'internal/useragent'; DO NOT EDIT. -// CODE GENERATED AUTOMATICALLY -// THIS FILE MUST NOT BE EDITED BY HAND +package sender const ( // ourUserAgent is the User-Agent of this underlying library package. diff --git a/internal/useragent/data_dns.go b/internal/useragent/data_dns.go new file mode 100644 index 00000000..2ce8a322 --- /dev/null +++ b/internal/useragent/data_dns.go @@ -0,0 +1,36 @@ +package main + +const dnsBaseUserAgent = "goacme-lego/" + +const dnsSourceFile = "./providers/dns/internal/useragent/useragent.go" + +const dnsTemplate = `// Code generated by 'internal/useragent'; DO NOT EDIT. + +package useragent + +import ( + "fmt" + "net/http" + "runtime" +) + +const ( + // ourUserAgent is the User-Agent of this underlying library package. + ourUserAgent = "goacme-lego/{{ .version }}" + + // ourUserAgentComment is part of the UA comment linked to the version status of this underlying library package. + // values: detach|release + // NOTE: Update this with each tagged release. + ourUserAgentComment = "{{ .comment }}" +) + +// Get builds and returns the User-Agent string. +func Get() string { + return fmt.Sprintf("%s (%s; %s; %s)", ourUserAgent, ourUserAgentComment, runtime.GOOS, runtime.GOARCH) +} + +// SetHeader sets the User-Agent header. +func SetHeader(h http.Header) { + h.Set("User-Agent", Get()) +} +` diff --git a/internal/useragent/data_sender.go b/internal/useragent/data_sender.go new file mode 100644 index 00000000..5da2d853 --- /dev/null +++ b/internal/useragent/data_sender.go @@ -0,0 +1,21 @@ +package main + +const senderBaseUserAgent = "xenolf-acme/" + +const senderSourceFile = "./acme/api/internal/sender/useragent.go" + +const senderTemplate = `// Code generated by 'internal/useragent'; DO NOT EDIT. + +package sender + +const ( + // ourUserAgent is the User-Agent of this underlying library package. + ourUserAgent = "xenolf-acme/{{ .version }}" + + // ourUserAgentComment is part of the UA comment linked to the version status of this underlying library package. + // values: detach|release + // NOTE: Update this with each tagged release. + ourUserAgentComment = "{{ .comment }}" +) + +` diff --git a/internal/release.go b/internal/useragent/generator.go similarity index 54% rename from internal/release.go rename to internal/useragent/generator.go index b03e62b2..bfa2e406 100644 --- a/internal/release.go +++ b/internal/useragent/generator.go @@ -7,107 +7,123 @@ import ( "go/format" "go/parser" "go/token" - "log" "os" "regexp" "strconv" "strings" "text/template" - - "github.com/urfave/cli/v2" ) -const sourceFile = "./acme/api/internal/sender/useragent.go" - -const uaTemplate = `package sender - -// CODE GENERATED AUTOMATICALLY -// THIS FILE MUST NOT BE EDITED BY HAND - -const ( - // ourUserAgent is the User-Agent of this underlying library package. - ourUserAgent = "xenolf-acme/{{ .version }}" - - // ourUserAgentComment is part of the UA comment linked to the version status of this underlying library package. - // values: detach|release - // NOTE: Update this with each tagged release. - ourUserAgentComment = "{{ .comment }}" -) - -` - -func main() { - app := cli.NewApp() - app.Name = "lego-releaser" - app.Usage = "Lego releaser" - app.HelpName = "releaser" - app.Commands = []*cli.Command{ - { - Name: "release", - Usage: "Update file for a release", - Action: release, - Before: func(ctx *cli.Context) error { - mode := ctx.String("mode") - switch mode { - case "patch", "minor", "major": - return nil - default: - return fmt.Errorf("invalid mode: %s", mode) - } - }, - Flags: []cli.Flag{ - &cli.StringFlag{ - Name: "mode", - Aliases: []string{"m"}, - Value: "patch", - Usage: "The release mode: patch|minor|major", - }, - }, - }, - { - Name: "detach", - Usage: "Update file post release", - Action: detach, - }, - } - - err := app.Run(os.Args) - if err != nil { - log.Fatal(err) - } +type Generator struct { + baseUserAgent string + template string + sourcePath string } -func release(ctx *cli.Context) error { - mode := ctx.String("mode") +func NewGenerator(baseUserAgent string, tmpl string, sourcePath string) *Generator { + return &Generator{baseUserAgent: baseUserAgent, template: tmpl, sourcePath: sourcePath} +} +func (g *Generator) Release(mode string) error { // Read file - data, err := readUserAgentFile(sourceFile) + data, err := readUserAgentFile(g.sourcePath) if err != nil { return err } // Bump version - newVersion, err := bumpVersion(data["ourUserAgent"], mode) + newVersion, err := g.bumpVersion(data["ourUserAgent"], mode) if err != nil { return err } // Write file comment := "release" // detach|release - return writeUserAgentFile(sourceFile, newVersion, comment) + + return g.writeUserAgentFile(g.sourcePath, newVersion, comment) } -func detach(_ *cli.Context) error { +func (g *Generator) Detach() error { // Read file - data, err := readUserAgentFile(sourceFile) + data, err := readUserAgentFile(g.sourcePath) if err != nil { return err } // Write file - version := strings.TrimPrefix(data["ourUserAgent"], "xenolf-acme/") + version := strings.TrimPrefix(data["ourUserAgent"], g.baseUserAgent) comment := "detach" - return writeUserAgentFile(sourceFile, version, comment) + + return g.writeUserAgentFile(g.sourcePath, version, comment) +} + +func (g *Generator) writeUserAgentFile(filename, version, comment string) error { + tmpl, err := template.New("ua").Parse(g.template) + if err != nil { + return err + } + + b := &bytes.Buffer{} + err = tmpl.Execute(b, map[string]string{ + "version": version, + "comment": comment, + }) + if err != nil { + return err + } + + source, err := format.Source(b.Bytes()) + if err != nil { + return err + } + + return os.WriteFile(filename, source, 0o644) +} + +func (g *Generator) bumpVersion(userAgent, mode string) (string, error) { + prevVersion := strings.TrimPrefix(userAgent, g.baseUserAgent) + + allString := regexp.MustCompile(`(\d+)\.(\d+)\.(\d+)`).FindStringSubmatch(prevVersion) + + if len(allString) != 4 { + return "", fmt.Errorf("invalid version format: %s", prevVersion) + } + + switch mode { + case "patch": + patch, err := strconv.Atoi(allString[3]) + if err != nil { + return "", err + } + return fmt.Sprintf("%s.%s.%d", allString[1], allString[2], patch+1), nil + case "minor": + minor, err := strconv.Atoi(allString[2]) + if err != nil { + return "", err + } + return fmt.Sprintf("%s.%d.0", allString[1], minor+1), nil + case "major": + major, err := strconv.Atoi(allString[1]) + if err != nil { + return "", err + } + return fmt.Sprintf("%d.0.0", major+1), nil + default: + return "", fmt.Errorf("invalid mode: %s", mode) + } +} + +func readUserAgentFile(filename string) (map[string]string, error) { + fset := token.NewFileSet() + file, err := parser.ParseFile(fset, filename, nil, parser.AllErrors) + if err != nil { + return nil, err + } + + v := visitor{data: make(map[string]string)} + ast.Walk(v, file) + + return v.data, nil } type visitor struct { @@ -152,72 +168,3 @@ func (v visitor) Visit(n ast.Node) ast.Visitor { } return v } - -func readUserAgentFile(filename string) (map[string]string, error) { - fset := token.NewFileSet() - file, err := parser.ParseFile(fset, filename, nil, parser.AllErrors) - if err != nil { - return nil, err - } - - v := visitor{data: make(map[string]string)} - ast.Walk(v, file) - - return v.data, nil -} - -func writeUserAgentFile(filename, version, comment string) error { - tmpl, err := template.New("ua").Parse(uaTemplate) - if err != nil { - return err - } - - b := &bytes.Buffer{} - err = tmpl.Execute(b, map[string]string{ - "version": version, - "comment": comment, - }) - if err != nil { - return err - } - - source, err := format.Source(b.Bytes()) - if err != nil { - return err - } - - return os.WriteFile(filename, source, 0o644) -} - -func bumpVersion(userAgent, mode string) (string, error) { - prevVersion := strings.TrimPrefix(userAgent, "xenolf-acme/") - - allString := regexp.MustCompile(`(\d+)\.(\d+)\.(\d+)`).FindStringSubmatch(prevVersion) - - if len(allString) != 4 { - return "", fmt.Errorf("invalid version format: %s", prevVersion) - } - - switch mode { - case "patch": - patch, err := strconv.Atoi(allString[3]) - if err != nil { - return "", err - } - return fmt.Sprintf("%s.%s.%d", allString[1], allString[2], patch+1), nil - case "minor": - minor, err := strconv.Atoi(allString[2]) - if err != nil { - return "", err - } - return fmt.Sprintf("%s.%d.0", allString[1], minor+1), nil - case "major": - major, err := strconv.Atoi(allString[1]) - if err != nil { - return "", err - } - return fmt.Sprintf("%d.0.0", major+1), nil - default: - return "", fmt.Errorf("invalid mode: %s", mode) - } -} diff --git a/internal/useragent/main.go b/internal/useragent/main.go new file mode 100644 index 00000000..9add82aa --- /dev/null +++ b/internal/useragent/main.go @@ -0,0 +1,84 @@ +package main + +import ( + "fmt" + "log" + "os" + + "github.com/urfave/cli/v2" +) + +func main() { + app := cli.NewApp() + app.Name = "lego-releaser" + app.Usage = "Lego releaser" + app.HelpName = "releaser" + app.Commands = []*cli.Command{ + { + Name: "release", + Usage: "Update file for a release", + Action: release, + Before: func(ctx *cli.Context) error { + mode := ctx.String("mode") + switch mode { + case "patch", "minor", "major": + return nil + default: + return fmt.Errorf("invalid mode: %s", mode) + } + }, + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "mode", + Aliases: []string{"m"}, + Value: "patch", + Usage: "The release mode: patch|minor|major", + }, + }, + }, + { + Name: "detach", + Usage: "Update file post release", + Action: detach, + }, + } + + err := app.Run(os.Args) + if err != nil { + log.Fatal(err) + } +} + +func release(ctx *cli.Context) error { + mode := ctx.String("mode") + + generators := []*Generator{ + NewGenerator(senderBaseUserAgent, senderTemplate, senderSourceFile), + NewGenerator(dnsBaseUserAgent, dnsTemplate, dnsSourceFile), + } + + for _, generator := range generators { + err := generator.Release(mode) + if err != nil { + return err + } + } + + return nil +} + +func detach(_ *cli.Context) error { + generators := []*Generator{ + NewGenerator(senderBaseUserAgent, senderTemplate, senderSourceFile), + NewGenerator(dnsBaseUserAgent, dnsTemplate, dnsSourceFile), + } + + for _, generator := range generators { + err := generator.Detach() + if err != nil { + return err + } + } + + return nil +} diff --git a/providers/dns/dnsimple/dnsimple.go b/providers/dns/dnsimple/dnsimple.go index 4a5b8788..0c1d3067 100644 --- a/providers/dns/dnsimple/dnsimple.go +++ b/providers/dns/dnsimple/dnsimple.go @@ -11,6 +11,7 @@ import ( "github.com/dnsimple/dnsimple-go/dnsimple" "github.com/go-acme/lego/v4/challenge/dns01" "github.com/go-acme/lego/v4/platform/config/env" + "github.com/go-acme/lego/v4/providers/dns/internal/useragent" "golang.org/x/oauth2" ) @@ -77,7 +78,7 @@ func NewDNSProviderConfig(config *Config) (*DNSProvider, error) { ts := oauth2.StaticTokenSource(&oauth2.Token{AccessToken: config.AccessToken}) client := dnsimple.NewClient(oauth2.NewClient(context.Background(), ts)) - client.SetUserAgent("go-acme/lego") + client.SetUserAgent(useragent.Get()) if config.BaseURL != "" { client.BaseURL = config.BaseURL diff --git a/providers/dns/epik/internal/client.go b/providers/dns/epik/internal/client.go index 1a802dfd..9a538545 100644 --- a/providers/dns/epik/internal/client.go +++ b/providers/dns/epik/internal/client.go @@ -11,14 +11,11 @@ import ( "time" "github.com/go-acme/lego/v4/providers/dns/internal/errutils" + "github.com/go-acme/lego/v4/providers/dns/internal/useragent" ) const defaultBaseURL = "https://usersapiv2.epik.com/v2" -// The API server don't support User-Agent starting with `go-`, then this User-Agent is different from the other implementation. -// https://github.com/go-acme/lego/issues/2268#issuecomment-2394007004 -const defaultUserAgent = "goacme/lego" - // Client the Epik API client. type Client struct { signature string @@ -101,7 +98,7 @@ func (c Client) RemoveHostRecord(ctx context.Context, domain string, recordID st } func (c Client) do(req *http.Request, result any) error { - req.Header.Set("User-Agent", defaultUserAgent) + useragent.SetHeader(req.Header) resp, err := c.HTTPClient.Do(req) if err != nil { diff --git a/providers/dns/exoscale/exoscale.go b/providers/dns/exoscale/exoscale.go index 6e7c026a..c9402a75 100644 --- a/providers/dns/exoscale/exoscale.go +++ b/providers/dns/exoscale/exoscale.go @@ -12,6 +12,7 @@ import ( "github.com/exoscale/egoscale/v3/credentials" "github.com/go-acme/lego/v4/challenge/dns01" "github.com/go-acme/lego/v4/platform/config/env" + "github.com/go-acme/lego/v4/providers/dns/internal/useragent" ) // Environment variables names. @@ -85,7 +86,7 @@ func NewDNSProviderConfig(config *Config) (*DNSProvider, error) { credentials.NewStaticCredentials(config.APIKey, config.APISecret), egoscale.ClientOptWithEndpoint(egoscale.Endpoint(config.Endpoint)), egoscale.ClientOptWithHTTPClient(&http.Client{Timeout: config.HTTPTimeout}), - egoscale.ClientOptWithUserAgent("go-acme/lego"), + egoscale.ClientOptWithUserAgent(useragent.Get()), ) if err != nil { return nil, fmt.Errorf("exoscale: initializing client: %w", err) diff --git a/providers/dns/infoblox/infoblox.go b/providers/dns/infoblox/infoblox.go index 6eda174d..87a443e4 100644 --- a/providers/dns/infoblox/infoblox.go +++ b/providers/dns/infoblox/infoblox.go @@ -10,6 +10,7 @@ import ( "github.com/go-acme/lego/v4/challenge/dns01" "github.com/go-acme/lego/v4/platform/config/env" + "github.com/go-acme/lego/v4/providers/dns/internal/useragent" infoblox "github.com/infobloxopen/infoblox-go-client" ) @@ -31,10 +32,7 @@ const ( EnvHTTPTimeout = envNamespace + "HTTP_TIMEOUT" ) -const ( - defaultPoolConnections = 10 - defaultUserAgent = "go-acme/lego" -) +const defaultPoolConnections = 10 // Config is used to configure the creation of the DNSProvider. type Config struct { @@ -151,7 +149,7 @@ func (d *DNSProvider) Present(domain, token, keyAuth string) error { defer func() { _ = connector.Logout() }() - objectManager := infoblox.NewObjectManager(connector, defaultUserAgent, "") + objectManager := infoblox.NewObjectManager(connector, useragent.Get(), "") record, err := objectManager.CreateTXTRecord(dns01.UnFqdn(info.EffectiveFQDN), info.Value, uint(d.config.TTL), d.config.DNSView) if err != nil { @@ -176,7 +174,7 @@ func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error { defer func() { _ = connector.Logout() }() - objectManager := infoblox.NewObjectManager(connector, defaultUserAgent, "") + objectManager := infoblox.NewObjectManager(connector, useragent.Get(), "") // gets the record's unique ref from when we created it d.recordRefsMu.Lock() diff --git a/providers/dns/internal/useragent/useragent.go b/providers/dns/internal/useragent/useragent.go new file mode 100644 index 00000000..8ecbfccc --- /dev/null +++ b/providers/dns/internal/useragent/useragent.go @@ -0,0 +1,29 @@ +// Code generated by 'internal/useragent'; DO NOT EDIT. + +package useragent + +import ( + "fmt" + "net/http" + "runtime" +) + +const ( + // ourUserAgent is the User-Agent of this underlying library package. + ourUserAgent = "goacme-lego/4.19.2" + + // ourUserAgentComment is part of the UA comment linked to the version status of this underlying library package. + // values: detach|release + // NOTE: Update this with each tagged release. + ourUserAgentComment = "detach" +) + +// Get builds and returns the User-Agent string. +func Get() string { + return fmt.Sprintf("%s (%s; %s; %s)", ourUserAgent, ourUserAgentComment, runtime.GOOS, runtime.GOARCH) +} + +// SetHeader sets the User-Agent header. +func SetHeader(h http.Header) { + h.Set("User-Agent", Get()) +} diff --git a/providers/dns/linode/linode.go b/providers/dns/linode/linode.go index 54af31e2..f9d77ebc 100644 --- a/providers/dns/linode/linode.go +++ b/providers/dns/linode/linode.go @@ -11,6 +11,7 @@ import ( "github.com/go-acme/lego/v4/challenge/dns01" "github.com/go-acme/lego/v4/platform/config/env" + "github.com/go-acme/lego/v4/providers/dns/internal/useragent" "github.com/linode/linodego" "golang.org/x/oauth2" ) @@ -99,7 +100,7 @@ func NewDNSProviderConfig(config *Config) (*DNSProvider, error) { } client := linodego.NewClient(oauth2Client) - client.SetUserAgent("go-acme/lego https://github.com/linode/linodego") + client.SetUserAgent(useragent.Get()) return &DNSProvider{config: config, client: &client}, nil } diff --git a/providers/dns/ovh/ovh.go b/providers/dns/ovh/ovh.go index a35b80c8..c86d6129 100644 --- a/providers/dns/ovh/ovh.go +++ b/providers/dns/ovh/ovh.go @@ -10,6 +10,7 @@ import ( "github.com/go-acme/lego/v4/challenge/dns01" "github.com/go-acme/lego/v4/platform/config/env" + "github.com/go-acme/lego/v4/providers/dns/internal/useragent" "github.com/ovh/go-ovh/ovh" ) @@ -271,7 +272,7 @@ func newClient(config *Config) (*ovh.Client, error) { return nil, fmt.Errorf("new client: %w", err) } - client.UserAgent = "go-acme/lego" + client.UserAgent = useragent.Get() return client, nil } diff --git a/providers/dns/sakuracloud/sakuracloud.go b/providers/dns/sakuracloud/sakuracloud.go index f0c8dc92..0b919968 100644 --- a/providers/dns/sakuracloud/sakuracloud.go +++ b/providers/dns/sakuracloud/sakuracloud.go @@ -9,6 +9,7 @@ import ( "github.com/go-acme/lego/v4/challenge/dns01" "github.com/go-acme/lego/v4/platform/config/env" + "github.com/go-acme/lego/v4/providers/dns/internal/useragent" client "github.com/sacloud/api-client-go" "github.com/sacloud/iaas-api-go" "github.com/sacloud/iaas-api-go/helper/api" @@ -95,7 +96,7 @@ func NewDNSProviderConfig(config *Config) (*DNSProvider, error) { AccessToken: config.Token, AccessTokenSecret: config.Secret, HttpClient: config.HTTPClient, - UserAgent: fmt.Sprintf("go-acme/lego %s", iaas.DefaultUserAgent), + UserAgent: fmt.Sprintf("%s %s", iaas.DefaultUserAgent, useragent.Get()), }, } diff --git a/providers/dns/scaleway/scaleway.go b/providers/dns/scaleway/scaleway.go index 70b8a8ea..d3d027d9 100644 --- a/providers/dns/scaleway/scaleway.go +++ b/providers/dns/scaleway/scaleway.go @@ -11,6 +11,7 @@ import ( "github.com/go-acme/lego/v4/challenge/dns01" "github.com/go-acme/lego/v4/platform/config/env" + "github.com/go-acme/lego/v4/providers/dns/internal/useragent" scwdomain "github.com/scaleway/scaleway-sdk-go/api/domain/v2beta1" "github.com/scaleway/scaleway-sdk-go/scw" ) @@ -100,7 +101,7 @@ func NewDNSProviderConfig(config *Config) (*DNSProvider, error) { configuration := []scw.ClientOption{ scw.WithAuth(config.AccessKey, config.Token), - scw.WithUserAgent("Scaleway Lego's provider"), + scw.WithUserAgent(useragent.Get()), } if config.ProjectID != "" { diff --git a/providers/dns/selectelv2/selectelv2.go b/providers/dns/selectelv2/selectelv2.go index 4cc6e941..8e114e24 100644 --- a/providers/dns/selectelv2/selectelv2.go +++ b/providers/dns/selectelv2/selectelv2.go @@ -11,6 +11,7 @@ import ( "github.com/go-acme/lego/v4/challenge/dns01" "github.com/go-acme/lego/v4/platform/config/env" + "github.com/go-acme/lego/v4/providers/dns/internal/useragent" selectelapi "github.com/selectel/domains-go/pkg/v2" "github.com/selectel/go-selvpcclient/v3/selvpcclient" ) @@ -25,8 +26,6 @@ const ( defaultHTTPTimeout = 30 * time.Second ) -const defaultUserAgent = "go-acme/lego" - const ( envNamespace = "SELECTELV2_" @@ -114,7 +113,7 @@ func NewDNSProviderConfig(config *Config) (*DNSProvider, error) { } headers := http.Header{} - headers.Set("User-Agent", defaultUserAgent) + useragent.SetHeader(headers) return &DNSProvider{ baseClient: selectelapi.NewClient(config.BaseURL, config.HTTPClient, headers), diff --git a/providers/dns/ultradns/ultradns.go b/providers/dns/ultradns/ultradns.go index 95cf9569..369af456 100644 --- a/providers/dns/ultradns/ultradns.go +++ b/providers/dns/ultradns/ultradns.go @@ -8,6 +8,7 @@ import ( "github.com/go-acme/lego/v4/challenge/dns01" "github.com/go-acme/lego/v4/platform/config/env" + "github.com/go-acme/lego/v4/providers/dns/internal/useragent" "github.com/ultradns/ultradns-go-sdk/pkg/client" "github.com/ultradns/ultradns-go-sdk/pkg/record" "github.com/ultradns/ultradns-go-sdk/pkg/rrset" @@ -24,12 +25,10 @@ const ( EnvTTL = envNamespace + "TTL" EnvPropagationTimeout = envNamespace + "PROPAGATION_TIMEOUT" EnvPollingInterval = envNamespace + "POLLING_INTERVAL" - - // Default variables names. - defaultEndpoint = "https://api.ultradns.com/" - defaultUserAgent = "go-acme/lego" ) +const defaultEndpoint = "https://api.ultradns.com/" + // DNSProvider implements the challenge.Provider interface. type DNSProvider struct { config *Config @@ -83,7 +82,7 @@ func NewDNSProviderConfig(config *Config) (*DNSProvider, error) { Username: config.Username, Password: config.Password, HostURL: config.Endpoint, - UserAgent: defaultUserAgent, + UserAgent: useragent.Get(), } uClient, err := client.NewClient(ultraConfig) diff --git a/providers/dns/vinyldns/vinyldns.go b/providers/dns/vinyldns/vinyldns.go index dca58fb9..f5f0d233 100644 --- a/providers/dns/vinyldns/vinyldns.go +++ b/providers/dns/vinyldns/vinyldns.go @@ -8,6 +8,7 @@ import ( "github.com/go-acme/lego/v4/challenge/dns01" "github.com/go-acme/lego/v4/platform/config/env" + "github.com/go-acme/lego/v4/providers/dns/internal/useragent" "github.com/vinyldns/go-vinyldns/vinyldns" ) @@ -84,7 +85,7 @@ func NewDNSProviderConfig(config *Config) (*DNSProvider, error) { AccessKey: config.AccessKey, SecretKey: config.SecretKey, Host: config.Host, - UserAgent: "go-acme/lego", + UserAgent: useragent.Get(), }) client.HTTPClient.Timeout = 30 * time.Second