diff --git a/pkg/issuer/acme/http/http.go b/pkg/issuer/acme/http/http.go index f688a912e..8d6fc5305 100644 --- a/pkg/issuer/acme/http/http.go +++ b/pkg/issuer/acme/http/http.go @@ -2,15 +2,55 @@ package http import ( "fmt" + "log" "net/http" "path" "strings" "sync" + "time" + + "github.com/jetstack/cert-manager/pkg/apis/certmanager/v1alpha1" + "github.com/jetstack/cert-manager/pkg/controller" ) +// Solver is an implementation of the acme http-01 challenge solver protocol +type Solver struct { + solver *httpSolver +} + +func NewSolver() *Solver { + handler := &httpSolver{ + ListenPort: 8080, + } + + // todo: provide a way to stop this goroutine + go func() { + for { + err := handler.listen() + + if err != nil { + log.Printf("error listening for acme challenges: %s", err.Error()) + } + + time.Sleep(time.Second * 5) + } + }() + return &Solver{handler} +} + +func (s *Solver) Present(ctx controller.Context, crt *v1alpha1.Certificate, domain, token, key string) error { + s.solver.addChallenge(challenge{domain, token, key}) + return nil +} + +// todo +func (s *Solver) Cleanup(ctx controller.Context, crt *v1alpha1.Certificate, domain, token string) error { + return nil +} + // Challenge is a Host/Token pair that is used for verify ownership of domains type challenge struct { - host, token string + host, token, key string } // httpSolver is an ACME HTTP-01 challenge solver. It will listen on a given @@ -46,13 +86,16 @@ func (h *httpSolver) listen() error { basePath := path.Dir(r.URL.EscapedPath()) token := path.Base(r.URL.EscapedPath()) + log.Printf("got request for host %s, basePath %s, token %s", host, basePath, token) // verify the base path is correct if basePath != HTTPChallengePath { + log.Printf("invalid basePath - expected %s", HTTPChallengePath) http.NotFound(w, r) return } for i, c := range h.challenges { + log.Printf("comparing host %s against %s", host, c.host) // if either the host or the token don't match what is expected, // we should continue to the next loop iteration if c.host != host || c.token != token { @@ -61,6 +104,8 @@ func (h *httpSolver) listen() error { // otherwise, this is a valid request and we're going to approve it w.WriteHeader(http.StatusOK) + fmt.Fprint(w, c.key) + // remove this challenge from the list so we don't store indefinitely h.challenges = append(h.challenges[:i], h.challenges[i+1:]...) return diff --git a/pkg/issuer/acme/interface.go b/pkg/issuer/acme/interface.go index 1b1a8f61f..ac8986263 100644 --- a/pkg/issuer/acme/interface.go +++ b/pkg/issuer/acme/interface.go @@ -5,6 +5,7 @@ import ( "github.com/jetstack/cert-manager/pkg/apis/certmanager/v1alpha1" "github.com/jetstack/cert-manager/pkg/controller" + http01 "github.com/jetstack/cert-manager/pkg/issuer/acme/http" ) type solver interface { @@ -12,6 +13,12 @@ type solver interface { Cleanup(ctx controller.Context, crt *v1alpha1.Certificate, domain, token string) error } +var httpSolver = http01.NewSolver() + func solverFor(challengeType string) (solver, error) { + switch challengeType { + case "http-01": + return httpSolver, nil + } return nil, fmt.Errorf("no solver implemented") }