summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/mholt/acmez/acme/challenge.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/mholt/acmez/acme/challenge.go')
-rw-r--r--vendor/github.com/mholt/acmez/acme/challenge.go133
1 files changed, 133 insertions, 0 deletions
diff --git a/vendor/github.com/mholt/acmez/acme/challenge.go b/vendor/github.com/mholt/acmez/acme/challenge.go
new file mode 100644
index 0000000000..ccb264cf52
--- /dev/null
+++ b/vendor/github.com/mholt/acmez/acme/challenge.go
@@ -0,0 +1,133 @@
+// Copyright 2020 Matthew Holt
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package acme
+
+import (
+ "context"
+ "crypto/sha256"
+ "encoding/base64"
+)
+
+// Challenge holds information about an ACME challenge.
+//
+// "An ACME challenge object represents a server's offer to validate a
+// client's possession of an identifier in a specific way. Unlike the
+// other objects listed above, there is not a single standard structure
+// for a challenge object. The contents of a challenge object depend on
+// the validation method being used. The general structure of challenge
+// objects and an initial set of validation methods are described in
+// Section 8." §7.1.5
+type Challenge struct {
+ // "Challenge objects all contain the following basic fields..." §8
+
+ // type (required, string): The type of challenge encoded in the
+ // object.
+ Type string `json:"type"`
+
+ // url (required, string): The URL to which a response can be posted.
+ URL string `json:"url"`
+
+ // status (required, string): The status of this challenge. Possible
+ // values are "pending", "processing", "valid", and "invalid" (see
+ // Section 7.1.6).
+ Status string `json:"status"`
+
+ // validated (optional, string): The time at which the server validated
+ // this challenge, encoded in the format specified in [RFC3339].
+ // This field is REQUIRED if the "status" field is "valid".
+ Validated string `json:"validated,omitempty"`
+
+ // error (optional, object): Error that occurred while the server was
+ // validating the challenge, if any, structured as a problem document
+ // [RFC7807]. Multiple errors can be indicated by using subproblems
+ // Section 6.7.1. A challenge object with an error MUST have status
+ // equal to "invalid".
+ Error *Problem `json:"error,omitempty"`
+
+ // "All additional fields are specified by the challenge type." §8
+ // (We also add our own for convenience.)
+
+ // "The token for a challenge is a string comprised entirely of
+ // characters in the URL-safe base64 alphabet." §8.1
+ //
+ // Used by the http-01, tls-alpn-01, and dns-01 challenges.
+ Token string `json:"token,omitempty"`
+
+ // A key authorization is a string that concatenates the token for the
+ // challenge with a key fingerprint, separated by a "." character (§8.1):
+ //
+ // keyAuthorization = token || '.' || base64url(Thumbprint(accountKey))
+ //
+ // This client package automatically assembles and sets this value for you.
+ KeyAuthorization string `json:"keyAuthorization,omitempty"`
+
+ // We attach the identifier that this challenge is associated with, which
+ // may be useful information for solving a challenge. It is not part of the
+ // structure as defined by the spec but is added by us to provide enough
+ // information to solve the DNS-01 challenge.
+ Identifier Identifier `json:"identifier,omitempty"`
+}
+
+// HTTP01ResourcePath returns the URI path for solving the http-01 challenge.
+//
+// "The path at which the resource is provisioned is comprised of the
+// fixed prefix '/.well-known/acme-challenge/', followed by the 'token'
+// value in the challenge." §8.3
+func (c Challenge) HTTP01ResourcePath() string {
+ return "/.well-known/acme-challenge/" + c.Token
+}
+
+// DNS01TXTRecordName returns the name of the TXT record to create for
+// solving the dns-01 challenge.
+//
+// "The client constructs the validation domain name by prepending the
+// label '_acme-challenge' to the domain name being validated, then
+// provisions a TXT record with the digest value under that name." §8.4
+func (c Challenge) DNS01TXTRecordName() string {
+ return "_acme-challenge." + c.Identifier.Value
+}
+
+// DNS01KeyAuthorization encodes a key authorization value to be used
+// in a TXT record for the _acme-challenge DNS record.
+//
+// "A client fulfills this challenge by constructing a key authorization
+// from the 'token' value provided in the challenge and the client's
+// account key. The client then computes the SHA-256 digest [FIPS180-4]
+// of the key authorization.
+//
+// The record provisioned to the DNS contains the base64url encoding of
+// this digest." §8.4
+func (c Challenge) DNS01KeyAuthorization() string {
+ h := sha256.Sum256([]byte(c.KeyAuthorization))
+ return base64.RawURLEncoding.EncodeToString(h[:])
+}
+
+// InitiateChallenge "indicates to the server that it is ready for the challenge
+// validation by sending an empty JSON body ('{}') carried in a POST request to
+// the challenge URL (not the authorization URL)." §7.5.1
+func (c *Client) InitiateChallenge(ctx context.Context, account Account, challenge Challenge) (Challenge, error) {
+ if err := c.provision(ctx); err != nil {
+ return Challenge{}, err
+ }
+ _, err := c.httpPostJWS(ctx, account.PrivateKey, account.Location, challenge.URL, struct{}{}, &challenge)
+ return challenge, err
+}
+
+// The standard or well-known ACME challenge types.
+const (
+ ChallengeTypeHTTP01 = "http-01" // RFC 8555 §8.3
+ ChallengeTypeDNS01 = "dns-01" // RFC 8555 §8.4
+ ChallengeTypeTLSALPN01 = "tls-alpn-01" // RFC 8737 §3
+)