chore: unexpose some plumbing functions

This commit is contained in:
Fernandez Ludovic 2026-02-25 18:12:15 +01:00
commit 1b6962633f
5 changed files with 40 additions and 24 deletions

View file

@ -171,7 +171,7 @@ func (c *Challenge) selectIssuerDomainName(challIssuers []string, records []TXTR
func (c *Challenge) hasMatchingRecord(records []TXTRecord, issuerDomainName string, wildcard bool) bool {
for _, record := range records {
parsed, err := ParseIssueValue(record.Value)
parsed, err := parseIssueValue(record.Value)
if err != nil {
continue
}
@ -217,7 +217,7 @@ func GetChallengeInfo(authz acme.Authorization, issuerDomainName, accountURI str
return ChallengeInfo{}, errors.New("dnspersist01: domain cannot be empty")
}
value, err := BuildIssueValue(issuerDomainName, accountURI, authz.Wildcard, persistUntil)
value, err := buildIssueValue(issuerDomainName, accountURI, authz.Wildcard, persistUntil)
if err != nil {
return ChallengeInfo{}, err
}

View file

@ -23,10 +23,10 @@ type IssueValue struct {
PersistUntil time.Time
}
// BuildIssueValue constructs an RFC 8659 issue-value for a dns-persist-01 TXT record.
// buildIssueValue constructs an RFC 8659 issue-value for a dns-persist-01 TXT record.
// issuerDomainName and accountURI are required.
// wildcard and persistUntil are optional.
func BuildIssueValue(issuerDomainName, accountURI string, wildcard bool, persistUntil time.Time) (string, error) {
func buildIssueValue(issuerDomainName, accountURI string, wildcard bool, persistUntil time.Time) (string, error) {
if accountURI == "" {
return "", errors.New("dnspersist01: ACME account URI cannot be empty")
}
@ -49,20 +49,12 @@ func BuildIssueValue(issuerDomainName, accountURI string, wildcard bool, persist
return value, nil
}
// trimWSP trims RFC 5234 WSP (SP / HTAB) characters from both ends of a string,
// as referenced by RFC 8659.
func trimWSP(s string) string {
return strings.TrimFunc(s, func(r rune) bool {
return r == ' ' || r == '\t'
})
}
// ParseIssueValue parses the issuer-domain-name and parameters
// parseIssueValue parses the issuer-domain-name and parameters
// for an RFC 8659 issue-value TXT record and returns the extracted fields.
// It returns an error if any portion of the value is malformed.
//
//nolint:gocyclo // parsing and validating tagged parameters requires branching
func ParseIssueValue(value string) (IssueValue, error) {
func parseIssueValue(value string) (IssueValue, error) {
fields := strings.Split(value, ";")
issuerDomainName := trimWSP(fields[0])
@ -150,3 +142,11 @@ func ParseIssueValue(value string) (IssueValue, error) {
return parsed, nil
}
// trimWSP trims RFC 5234 WSP (SP / HTAB) characters from both ends of a string,
// as referenced by RFC 8659.
func trimWSP(s string) string {
return strings.TrimFunc(s, func(r rune) bool {
return r == ' ' || r == '\t'
})
}

View file

@ -8,7 +8,7 @@ import (
"github.com/stretchr/testify/require"
)
func TestBuildIssueValue(t *testing.T) {
func Test_buildIssueValue(t *testing.T) {
testCases := []struct {
desc string
issuer string
@ -49,7 +49,7 @@ func TestBuildIssueValue(t *testing.T) {
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
actual, err := BuildIssueValue(test.issuer, test.accountURI, test.wildcard, test.persistUTC)
actual, err := buildIssueValue(test.issuer, test.accountURI, test.wildcard, test.persistUTC)
if test.expectErrContains != "" {
require.Error(t, err)
assert.ErrorContains(t, err, test.expectErrContains)
@ -63,7 +63,7 @@ func TestBuildIssueValue(t *testing.T) {
}
}
func TestParseIssueValue(t *testing.T) {
func Test_parseIssueValue(t *testing.T) {
testCases := []struct {
desc string
value string
@ -192,7 +192,7 @@ func TestParseIssueValue(t *testing.T) {
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
parsed, err := ParseIssueValue(test.value)
parsed, err := parseIssueValue(test.value)
if test.expectErrContains != "" {
require.Error(t, err)
assert.ErrorContains(t, err, test.expectErrContains)

View file

@ -14,6 +14,7 @@ import (
"time"
"github.com/cenkalti/backoff/v5"
"github.com/go-acme/lego/v5/acme"
"github.com/go-acme/lego/v5/certcrypto"
"github.com/go-acme/lego/v5/certificate"
"github.com/go-acme/lego/v5/challenge/dnspersist01"
@ -141,10 +142,17 @@ func TestChallengeDNSPersist_Run_NewAccount(t *testing.T) {
return
}
txtValue, err := dnspersist01.BuildIssueValue(testPersistIssuer, accountURI, true, time.Time{})
authz := acme.Authorization{
Identifier: acme.Identifier{
Value: testPersistCLIDomain,
},
Wildcard: true,
}
info, err := dnspersist01.GetChallengeInfo(authz, testPersistIssuer, accountURI, time.Time{})
require.NoError(t, err)
err = client.SetPersistRecord(testPersistCLIDomain, txtValue)
err = client.SetPersistRecord(testPersistCLIDomain, info.Value)
if err != nil {
errChan <- fmt.Errorf("set TXT record: %w", err)
return

View file

@ -10,25 +10,33 @@ import (
"testing"
"time"
"github.com/go-acme/lego/v5/acme"
"github.com/go-acme/lego/v5/challenge/dnspersist01"
"github.com/stretchr/testify/require"
)
const persistLabel = "_validation-persist."
func updateDNS(t *testing.T, accountURI, domain string) {
func updateDNS(t *testing.T, accountURI, issuerDomainName string) {
t.Helper()
value, err := dnspersist01.BuildIssueValue(testPersistIssuer, accountURI, true, time.Time{})
authz := acme.Authorization{
Identifier: acme.Identifier{
Value: "example.net", // Note: unused inside the tests.
},
Wildcard: true,
}
info, err := dnspersist01.GetChallengeInfo(authz, testPersistIssuer, accountURI, time.Time{})
require.NoError(t, err)
client := newChallTestSrvClient()
err = client.SetPersistRecord(domain, value)
err = client.SetPersistRecord(issuerDomainName, info.Value)
require.NoError(t, err)
t.Cleanup(func() {
err = client.ClearPersistRecord(domain)
err = client.ClearPersistRecord(issuerDomainName)
require.NoError(t, err)
})
}