package acme import ( "encoding/json" "fmt" "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" } } // getLink returns an absolute or partial path to the given resource. func (d *directory) getLink(typ Link, provisionerName string, abs bool, inputs ...string) string { return d.getLinkFromBaseURL(typ, provisionerName, abs, "", inputs...) } // getLinkFromBaseURL 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) getLinkFromBaseURL(typ Link, provisionerName string, abs bool, baseURLFromRequest string, 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 { baseURL := baseURLFromRequest if baseURL == "" { baseURL = "https://" + d.dns } return fmt.Sprintf("%s/%s%s", baseURL, d.prefix, link) } return link }