first commit
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
package acme
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Obtain drives the complete ACME issuance flow for one or more domains:
|
||||
// bootstrap, account registration, order, HTTP-01 challenge response via
|
||||
// responder, finalize, download. The caller is responsible for mounting
|
||||
// responder on a listener the CA's HTTP-01 validator can reach at
|
||||
// http://{domain}/.well-known/acme-challenge/{token} — this function only
|
||||
// populates the token->response map, it doesn't start any listener itself.
|
||||
func Obtain(directoryURL, contactEmail string, domains []string, accountKey *AccountKey, responder *ChallengeResponder) (certPEM, keyPEM []byte, err error) {
|
||||
client := NewClient(directoryURL, accountKey)
|
||||
if err := client.Bootstrap(); err != nil {
|
||||
return nil, nil, fmt.Errorf("bootstrap: %w", err)
|
||||
}
|
||||
if err := client.NewAccount(contactEmail); err != nil {
|
||||
return nil, nil, fmt.Errorf("account registration: %w", err)
|
||||
}
|
||||
|
||||
order, err := client.NewOrder(domains)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("creating order: %w", err)
|
||||
}
|
||||
|
||||
for _, authzURL := range order.Authorizations {
|
||||
authz, err := client.GetAuthorization(authzURL)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("fetching authorization: %w", err)
|
||||
}
|
||||
if authz.Status == "valid" {
|
||||
continue // already satisfied (e.g. from a very recent prior order)
|
||||
}
|
||||
|
||||
var httpChallenge *Challenge
|
||||
for i := range authz.Challenges {
|
||||
if authz.Challenges[i].Type == "http-01" {
|
||||
httpChallenge = &authz.Challenges[i]
|
||||
break
|
||||
}
|
||||
}
|
||||
if httpChallenge == nil {
|
||||
return nil, nil, fmt.Errorf("no http-01 challenge offered for %s", authz.Identifier.Value)
|
||||
}
|
||||
|
||||
keyAuth := client.KeyAuthorization(httpChallenge.Token)
|
||||
responder.Set(httpChallenge.Token, keyAuth)
|
||||
|
||||
if err := client.RespondToChallenge(httpChallenge.URL); err != nil {
|
||||
responder.Remove(httpChallenge.Token)
|
||||
return nil, nil, fmt.Errorf("responding to challenge for %s: %w", authz.Identifier.Value, err)
|
||||
}
|
||||
waitErr := client.WaitForAuthorizationValid(authzURL, 30*time.Second)
|
||||
responder.Remove(httpChallenge.Token)
|
||||
if waitErr != nil {
|
||||
return nil, nil, fmt.Errorf("waiting for validation of %s: %w", authz.Identifier.Value, waitErr)
|
||||
}
|
||||
}
|
||||
|
||||
certPEM, keyPEM, err = client.FinalizeAndDownload(order, domains, 30*time.Second)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("finalize/download: %w", err)
|
||||
}
|
||||
return certPEM, keyPEM, nil
|
||||
}
|
||||
Reference in New Issue
Block a user