feat(challenge): add context

This commit is contained in:
Fernandez Ludovic 2026-01-18 16:21:48 +01:00
commit 01d91987af
8 changed files with 32 additions and 27 deletions

View file

@ -77,7 +77,7 @@ func (c *Challenge) PreSolve(ctx context.Context, authz acme.Authorization) erro
return err
}
err = c.provider.Present(authz.Identifier.Value, chlng.Token, keyAuth)
err = c.provider.Present(ctx, authz.Identifier.Value, chlng.Token, keyAuth)
if err != nil {
return fmt.Errorf("[%s] acme: error presenting token: %w", domain, err)
}
@ -134,7 +134,7 @@ func (c *Challenge) Solve(ctx context.Context, authz acme.Authorization) error {
}
// CleanUp cleans the challenge.
func (c *Challenge) CleanUp(authz acme.Authorization) error {
func (c *Challenge) CleanUp(ctx context.Context, authz acme.Authorization) error {
log.Info("acme: Cleaning DNS-01 challenge.", "domain", challenge.GetTargetedDomain(authz))
chlng, err := challenge.FindChallenge(challenge.DNS01, authz)
@ -147,7 +147,7 @@ func (c *Challenge) CleanUp(authz acme.Authorization) error {
return err
}
return c.provider.CleanUp(authz.Identifier.Value, chlng.Token, keyAuth)
return c.provider.CleanUp(ctx, authz.Identifier.Value, chlng.Token, keyAuth)
}
func (c *Challenge) Sequential() (bool, time.Duration) {

View file

@ -21,17 +21,17 @@ type providerMock struct {
present, cleanUp error
}
func (p *providerMock) Present(domain, token, keyAuth string) error { return p.present }
func (p *providerMock) CleanUp(domain, token, keyAuth string) error { return p.cleanUp }
func (p *providerMock) Present(_ context.Context, _, _, _ string) error { return p.present }
func (p *providerMock) CleanUp(_ context.Context, _, _, _ string) error { return p.cleanUp }
type providerTimeoutMock struct {
present, cleanUp error
timeout, interval time.Duration
}
func (p *providerTimeoutMock) Present(domain, token, keyAuth string) error { return p.present }
func (p *providerTimeoutMock) CleanUp(domain, token, keyAuth string) error { return p.cleanUp }
func (p *providerTimeoutMock) Timeout() (time.Duration, time.Duration) { return p.timeout, p.interval }
func (p *providerTimeoutMock) Present(_ context.Context, _, _, _ string) error { return p.present }
func (p *providerTimeoutMock) CleanUp(_ context.Context, _, _, _ string) error { return p.cleanUp }
func (p *providerTimeoutMock) Timeout() (time.Duration, time.Duration) { return p.timeout, p.interval }
func TestChallenge_PreSolve(t *testing.T) {
server := tester.MockACMEServer().BuildHTTPS(t)
@ -285,7 +285,7 @@ func TestChallenge_CleanUp(t *testing.T) {
},
}
err = chlg.CleanUp(authz)
err = chlg.CleanUp(t.Context(), authz)
if test.expectError {
require.Error(t, err)
} else {

View file

@ -67,13 +67,13 @@ func (c *Challenge) Solve(ctx context.Context, authz acme.Authorization) error {
return err
}
err = c.provider.Present(authz.Identifier.Value, chlng.Token, keyAuth)
err = c.provider.Present(ctx, authz.Identifier.Value, chlng.Token, keyAuth)
if err != nil {
return fmt.Errorf("[%s] acme: error presenting token: %w", domain, err)
}
defer func() {
err := c.provider.CleanUp(authz.Identifier.Value, chlng.Token, keyAuth)
err := c.provider.CleanUp(ctx, authz.Identifier.Value, chlng.Token, keyAuth)
if err != nil {
log.Warn("acme: cleaning up failed.", "domain", domain, "error", err)
}

View file

@ -1,6 +1,7 @@
package http01
import (
"context"
"fmt"
"io/fs"
"net"
@ -75,7 +76,7 @@ func NewUnixProviderServer(socketPath string, socketMode fs.FileMode) *ProviderS
}
// Present starts a web server and makes the token available at `ChallengePath(token)` for web requests.
func (s *ProviderServer) Present(domain, token, keyAuth string) error {
func (s *ProviderServer) Present(ctx context.Context, domain, token, keyAuth string) error {
var err error
s.listener, err = net.Listen(s.network, s.GetAddress())
@ -97,7 +98,7 @@ func (s *ProviderServer) Present(domain, token, keyAuth string) error {
}
// CleanUp closes the HTTP server and removes the token from `ChallengePath(token)`.
func (s *ProviderServer) CleanUp(domain, token, keyAuth string) error {
func (s *ProviderServer) CleanUp(ctx context.Context, domain, token, keyAuth string) error {
if s.listener == nil {
return nil
}

View file

@ -1,14 +1,17 @@
package challenge
import "time"
import (
"context"
"time"
)
// Provider enables implementing a custom challenge
// provider. Present presents the solution to a challenge available to
// be solved. CleanUp will be called by the challenge if Present ends
// in a non-error state.
type Provider interface {
Present(domain, token, keyAuth string) error
CleanUp(domain, token, keyAuth string) error
Present(ctx context.Context, domain, token, keyAuth string) error
CleanUp(ctx context.Context, domain, token, keyAuth string) error
}
// ProviderTimeout allows for implementing a

View file

@ -23,7 +23,7 @@ type preSolver interface {
// Interface for challenges like dns, where we can solve all the challenges before to delete them.
type cleanup interface {
CleanUp(authorization acme.Authorization) error
CleanUp(ctx context.Context, authorization acme.Authorization) error
}
type sequential interface {
@ -108,7 +108,7 @@ func sequentialSolve(ctx context.Context, authSolvers []*selectedAuthSolver, fai
if err != nil {
failures[domain] = err
cleanUp(authSolver.solver, authSolver.authz)
cleanUp(ctx, authSolver.solver, authSolver.authz)
continue
}
@ -119,13 +119,13 @@ func sequentialSolve(ctx context.Context, authSolvers []*selectedAuthSolver, fai
if err != nil {
failures[domain] = err
cleanUp(authSolver.solver, authSolver.authz)
cleanUp(ctx, authSolver.solver, authSolver.authz)
continue
}
// Clean challenge
cleanUp(authSolver.solver, authSolver.authz)
cleanUp(ctx, authSolver.solver, authSolver.authz)
if len(authSolvers)-1 > i {
solvr := authSolver.solver.(sequential)
@ -151,7 +151,7 @@ func parallelSolve(ctx context.Context, authSolvers []*selectedAuthSolver, failu
defer func() {
// Clean all created TXT records
for _, authSolver := range authSolvers {
cleanUp(authSolver.solver, authSolver.authz)
cleanUp(ctx, authSolver.solver, authSolver.authz)
}
}()
@ -172,11 +172,11 @@ func parallelSolve(ctx context.Context, authSolvers []*selectedAuthSolver, failu
}
}
func cleanUp(solvr solver, authz acme.Authorization) {
func cleanUp(ctx context.Context, solvr solver, authz acme.Authorization) {
if solvr, ok := solvr.(cleanup); ok {
domain := challenge.GetTargetedDomain(authz)
err := solvr.CleanUp(authz)
err := solvr.CleanUp(ctx, authz)
if err != nil {
log.Warn("acme: cleaning up failed.", "domain", domain, "error", err)
}

View file

@ -73,13 +73,13 @@ func (c *Challenge) Solve(ctx context.Context, authz acme.Authorization) error {
return err
}
err = c.provider.Present(domain, chlng.Token, keyAuth)
err = c.provider.Present(ctx, domain, chlng.Token, keyAuth)
if err != nil {
return fmt.Errorf("[%s] acme: error presenting token: %w", challenge.GetTargetedDomain(authz), err)
}
defer func() {
err := c.provider.CleanUp(domain, chlng.Token, keyAuth)
err := c.provider.CleanUp(ctx, domain, chlng.Token, keyAuth)
if err != nil {
log.Warn("acme: cleaning up failed.", "domain", challenge.GetTargetedDomain(authz), err)
}

View file

@ -1,6 +1,7 @@
package tlsalpn01
import (
"context"
"crypto/tls"
"errors"
"fmt"
@ -66,7 +67,7 @@ func NewProviderServer(host, port string) *ProviderServer {
// Present generates a certificate with an SHA-256 digest of the keyAuth provided
// as the acmeValidation-v1 extension value to conform to the ACME-TLS-ALPN spec.
func (s *ProviderServer) Present(domain, token, keyAuth string) error {
func (s *ProviderServer) Present(ctx context.Context, domain, token, keyAuth string) error {
// Generate the challenge certificate using the provided keyAuth and domain.
cert, err := ChallengeCert(domain, keyAuth)
if err != nil {
@ -101,7 +102,7 @@ func (s *ProviderServer) Present(domain, token, keyAuth string) error {
}
// CleanUp closes the HTTPS server.
func (s *ProviderServer) CleanUp(domain, token, keyAuth string) error {
func (s *ProviderServer) CleanUp(ctx context.Context, domain, token, keyAuth string) error {
if s.listener == nil {
return nil
}