forked from TrueCloudLab/certificates
e1409349f3
* Pass the request context all the way down the ACME stack. * Save baseURL in context and use when generating ACME urls.
150 lines
3.8 KiB
Go
150 lines
3.8 KiB
Go
package acme
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/url"
|
|
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
// Directory represents an ACME directory for configuring clients.
|
|
type Directory struct {
|
|
NewNonce string `json:"newNonce,omitempty"`
|
|
NewAccount string `json:"newAccount,omitempty"`
|
|
NewOrder string `json:"newOrder,omitempty"`
|
|
NewAuthz string `json:"newAuthz,omitempty"`
|
|
RevokeCert string `json:"revokeCert,omitempty"`
|
|
KeyChange string `json:"keyChange,omitempty"`
|
|
}
|
|
|
|
// ToLog enables response logging for the Directory type.
|
|
func (d *Directory) ToLog() (interface{}, error) {
|
|
b, err := json.Marshal(d)
|
|
if err != nil {
|
|
return nil, ServerInternalErr(errors.Wrap(err, "error marshaling directory for logging"))
|
|
}
|
|
return string(b), nil
|
|
}
|
|
|
|
type directory struct {
|
|
prefix, dns string
|
|
}
|
|
|
|
// newDirectory returns a new Directory type.
|
|
func newDirectory(dns, prefix string) *directory {
|
|
return &directory{prefix: prefix, dns: dns}
|
|
}
|
|
|
|
// Link captures the link type.
|
|
type Link int
|
|
|
|
const (
|
|
// NewNonceLink new-nonce
|
|
NewNonceLink Link = iota
|
|
// NewAccountLink new-account
|
|
NewAccountLink
|
|
// AccountLink account
|
|
AccountLink
|
|
// OrderLink order
|
|
OrderLink
|
|
// NewOrderLink new-order
|
|
NewOrderLink
|
|
// OrdersByAccountLink list of orders owned by account
|
|
OrdersByAccountLink
|
|
// FinalizeLink finalize order
|
|
FinalizeLink
|
|
// NewAuthzLink authz
|
|
NewAuthzLink
|
|
// AuthzLink new-authz
|
|
AuthzLink
|
|
// ChallengeLink challenge
|
|
ChallengeLink
|
|
// CertificateLink certificate
|
|
CertificateLink
|
|
// DirectoryLink directory
|
|
DirectoryLink
|
|
// RevokeCertLink revoke certificate
|
|
RevokeCertLink
|
|
// KeyChangeLink key rollover
|
|
KeyChangeLink
|
|
)
|
|
|
|
func (l Link) String() string {
|
|
switch l {
|
|
case NewNonceLink:
|
|
return "new-nonce"
|
|
case NewAccountLink:
|
|
return "new-account"
|
|
case AccountLink:
|
|
return "account"
|
|
case NewOrderLink:
|
|
return "new-order"
|
|
case OrderLink:
|
|
return "order"
|
|
case NewAuthzLink:
|
|
return "new-authz"
|
|
case AuthzLink:
|
|
return "authz"
|
|
case ChallengeLink:
|
|
return "challenge"
|
|
case CertificateLink:
|
|
return "certificate"
|
|
case DirectoryLink:
|
|
return "directory"
|
|
case RevokeCertLink:
|
|
return "revoke-cert"
|
|
case KeyChangeLink:
|
|
return "key-change"
|
|
default:
|
|
return "unexpected"
|
|
}
|
|
}
|
|
|
|
func (d *directory) getLink(ctx context.Context, typ Link, abs bool, inputs ...string) string {
|
|
var provName string
|
|
if p, err := ProvisionerFromContext(ctx); err == nil && p != nil {
|
|
provName = p.GetName()
|
|
}
|
|
return d.getLinkExplicit(typ, provName, abs, BaseURLFromContext(ctx), inputs...)
|
|
}
|
|
|
|
// getLinkExplicit returns an absolute or partial path to the given resource and a base
|
|
// URL dynamically obtained from the request for which the link is being
|
|
// calculated.
|
|
func (d *directory) getLinkExplicit(typ Link, provisionerName string, abs bool, baseURL *url.URL, inputs ...string) string {
|
|
var link string
|
|
switch typ {
|
|
case NewNonceLink, NewAccountLink, NewOrderLink, NewAuthzLink, DirectoryLink, KeyChangeLink, RevokeCertLink:
|
|
link = fmt.Sprintf("/%s/%s", provisionerName, typ.String())
|
|
case AccountLink, OrderLink, AuthzLink, ChallengeLink, CertificateLink:
|
|
link = fmt.Sprintf("/%s/%s/%s", provisionerName, typ.String(), inputs[0])
|
|
case OrdersByAccountLink:
|
|
link = fmt.Sprintf("/%s/%s/%s/orders", provisionerName, AccountLink.String(), inputs[0])
|
|
case FinalizeLink:
|
|
link = fmt.Sprintf("/%s/%s/%s/finalize", provisionerName, OrderLink.String(), inputs[0])
|
|
}
|
|
|
|
if abs {
|
|
// Copy the baseURL value from the pointer. https://github.com/golang/go/issues/38351
|
|
u := url.URL{}
|
|
if baseURL != nil {
|
|
u = *baseURL
|
|
}
|
|
|
|
// If no Scheme is set, then default to https.
|
|
if u.Scheme == "" {
|
|
u.Scheme = "https"
|
|
}
|
|
|
|
// If no Host is set, then use the default (first DNS attr in the ca.json).
|
|
if u.Host == "" {
|
|
u.Host = d.dns
|
|
}
|
|
|
|
u.Path = d.prefix + link
|
|
return u.String()
|
|
}
|
|
return link
|
|
}
|