Switch to the cert-manager/crypto fork which contains @sigmavirus24's ACME profiles patch
Signed-off-by: Richard Wall <richard.wall@cyberark.com>
This commit is contained in:
parent
5dbcc7571c
commit
0631f8c596
10
third_party/forked/acme/acme.go
vendored
10
third_party/forked/acme/acme.go
vendored
@ -186,10 +186,11 @@ func (c *Client) Discover(ctx context.Context) (Directory, error) {
|
||||
Nonce string `json:"newNonce"`
|
||||
KeyChange string `json:"keyChange"`
|
||||
Meta struct {
|
||||
Terms string `json:"termsOfService"`
|
||||
Website string `json:"website"`
|
||||
CAA []string `json:"caaIdentities"`
|
||||
ExternalAcct bool `json:"externalAccountRequired"`
|
||||
Terms string `json:"termsOfService"`
|
||||
Website string `json:"website"`
|
||||
CAA []string `json:"caaIdentities"`
|
||||
ExternalAcct bool `json:"externalAccountRequired"`
|
||||
Profiles map[string]string `json:"profiles"`
|
||||
}
|
||||
}
|
||||
if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
|
||||
@ -209,6 +210,7 @@ func (c *Client) Discover(ctx context.Context) (Directory, error) {
|
||||
Website: v.Meta.Website,
|
||||
CAA: v.Meta.CAA,
|
||||
ExternalAccountRequired: v.Meta.ExternalAcct,
|
||||
Profiles: v.Meta.Profiles,
|
||||
}
|
||||
return *c.dir, nil
|
||||
}
|
||||
|
||||
10
third_party/forked/acme/rfc8555.go
vendored
10
third_party/forked/acme/rfc8555.go
vendored
@ -205,6 +205,7 @@ func (c *Client) AuthorizeOrder(ctx context.Context, id []AuthzID, opt ...OrderO
|
||||
Identifiers []wireAuthzID `json:"identifiers"`
|
||||
NotBefore string `json:"notBefore,omitempty"`
|
||||
NotAfter string `json:"notAfter,omitempty"`
|
||||
Profile string `json:"profile,omitempty"`
|
||||
}{}
|
||||
for _, v := range id {
|
||||
req.Identifiers = append(req.Identifiers, wireAuthzID{
|
||||
@ -218,6 +219,15 @@ func (c *Client) AuthorizeOrder(ctx context.Context, id []AuthzID, opt ...OrderO
|
||||
req.NotBefore = time.Time(o).Format(time.RFC3339)
|
||||
case orderNotAfterOpt:
|
||||
req.NotAfter = time.Time(o).Format(time.RFC3339)
|
||||
case orderProfileOpt:
|
||||
if !dir.Profiles.isSupported() {
|
||||
return nil, ErrCADoesNotSupportProfiles
|
||||
}
|
||||
profileName := string(o)
|
||||
if !dir.Profiles.Has(profileName) {
|
||||
return nil, fmt.Errorf("%w %s", ErrProfileNotInSetOfSupportedProfiles, profileName)
|
||||
}
|
||||
req.Profile = profileName
|
||||
default:
|
||||
// Package's fault if we let this happen.
|
||||
panic(fmt.Sprintf("unsupported order option type %T", o))
|
||||
|
||||
121
third_party/forked/acme/rfc8555_test.go
vendored
121
third_party/forked/acme/rfc8555_test.go
vendored
@ -99,6 +99,61 @@ func TestRFC_Discover(t *testing.T) {
|
||||
if !dir.ExternalAccountRequired {
|
||||
t.Error("dir.Meta.ExternalAccountRequired is false")
|
||||
}
|
||||
if dir.Profiles != nil {
|
||||
t.Errorf("dir.Profiles is expected to be nil, got %+v", dir.Profiles)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDiscover_WithProfiles(t *testing.T) {
|
||||
const (
|
||||
nonce = "https://example.com/acme/new-nonce"
|
||||
reg = "https://example.com/acme/new-acct"
|
||||
order = "https://example.com/acme/new-order"
|
||||
authz = "https://example.com/acme/new-authz"
|
||||
revoke = "https://example.com/acme/revoke-cert"
|
||||
keychange = "https://example.com/acme/key-change"
|
||||
metaTerms = "https://example.com/acme/terms/2017-5-30"
|
||||
metaWebsite = "https://www.example.com/"
|
||||
metaCAA = "example.com"
|
||||
)
|
||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
fmt.Fprintf(w, `{
|
||||
"newNonce": %q,
|
||||
"newAccount": %q,
|
||||
"newOrder": %q,
|
||||
"newAuthz": %q,
|
||||
"revokeCert": %q,
|
||||
"keyChange": %q,
|
||||
"meta": {
|
||||
"termsOfService": %q,
|
||||
"website": %q,
|
||||
"caaIdentities": [%q],
|
||||
"externalAccountRequired": true,
|
||||
"profiles": {
|
||||
"default": "Your favorite default profile",
|
||||
"tlsserver": "New and improved",
|
||||
"client": "For all your mutual TLS needs"
|
||||
}
|
||||
}
|
||||
}`, nonce, reg, order, authz, revoke, keychange, metaTerms, metaWebsite, metaCAA)
|
||||
}))
|
||||
defer ts.Close()
|
||||
c := &Client{DirectoryURL: ts.URL}
|
||||
dir, err := c.Discover(context.Background())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
expected := Profiles(map[string]string{"default": "Your favorite default profile", "tlsserver": "New and improved", "client": "For all your mutual TLS needs"})
|
||||
if dir.Profiles == nil {
|
||||
t.Errorf("expected directory to be %+v; got nil", expected)
|
||||
}
|
||||
|
||||
for key, value := range dir.Profiles {
|
||||
if expValue := expected.GetDescription(key); value != expValue {
|
||||
t.Errorf("expected key %+q to have description %+q; got %+q", key, expected, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestRFC_popNonce(t *testing.T) {
|
||||
@ -247,6 +302,27 @@ func (s *acmeServer) start() {
|
||||
return
|
||||
}
|
||||
|
||||
if r.URL.Path == "/directory-with-profiles" {
|
||||
fmt.Fprintf(w, `{
|
||||
"newNonce": %q,
|
||||
"newAccount": %q,
|
||||
"newOrder": %q,
|
||||
"newAuthz": %q,
|
||||
"revokeCert": %q,
|
||||
"keyChange": %q,
|
||||
"meta": {"termsOfService": %q, "profiles": {"default": "Default", "server": "Server", "client": "Client"}}
|
||||
}`,
|
||||
s.url("/acme/new-nonce"),
|
||||
s.url("/acme/new-account"),
|
||||
s.url("/acme/new-order"),
|
||||
s.url("/acme/new-authz"),
|
||||
s.url("/acme/revoke-cert"),
|
||||
s.url("/acme/key-change"),
|
||||
s.url("/terms"),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
// All other responses contain a nonce value unconditionally.
|
||||
w.Header().Set("Replay-Nonce", s.nonce())
|
||||
if r.URL.Path == "/acme/new-nonce" {
|
||||
@ -788,6 +864,51 @@ func TestRFC_AuthorizeOrder(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRFC_AuthorizeOrder_WithOrderProfile(t *testing.T) {
|
||||
s := newACMEServer()
|
||||
s.handle("/acme/new-account", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Location", s.url("/accounts/1"))
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write([]byte(`{"status": "valid"}`))
|
||||
})
|
||||
s.handle("/acme/new-order", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Location", s.url("/orders/1"))
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
fmt.Fprintf(w, `{
|
||||
"status": "pending",
|
||||
"expires": "2019-09-01T00:00:00Z",
|
||||
"notBefore": "2019-08-31T00:00:00Z",
|
||||
"notAfter": "2019-09-02T00:00:00Z",
|
||||
"identifiers": [{"type":"dns", "value":"example.org"}],
|
||||
"authorizations": [%q]
|
||||
}`, s.url("/authz/1"))
|
||||
})
|
||||
s.start()
|
||||
defer s.close()
|
||||
|
||||
cl := &Client{Key: testKeyEC, DirectoryURL: s.url("/directory-with-profiles")}
|
||||
o, err := cl.AuthorizeOrder(context.Background(), DomainIDs("example.org"),
|
||||
WithOrderNotBefore(time.Date(2019, 8, 31, 0, 0, 0, 0, time.UTC)),
|
||||
WithOrderNotAfter(time.Date(2019, 9, 2, 0, 0, 0, 0, time.UTC)),
|
||||
WithOrderProfile("server"),
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
okOrder := &Order{
|
||||
URI: s.url("/orders/1"),
|
||||
Status: StatusPending,
|
||||
Expires: time.Date(2019, 9, 1, 0, 0, 0, 0, time.UTC),
|
||||
NotBefore: time.Date(2019, 8, 31, 0, 0, 0, 0, time.UTC),
|
||||
NotAfter: time.Date(2019, 9, 2, 0, 0, 0, 0, time.UTC),
|
||||
Identifiers: []AuthzID{{Type: "dns", Value: "example.org"}},
|
||||
AuthzURLs: []string{s.url("/authz/1")},
|
||||
}
|
||||
if !reflect.DeepEqual(o, okOrder) {
|
||||
t.Errorf("AuthorizeOrder = %+v; want %+v", o, okOrder)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRFC_GetOrder(t *testing.T) {
|
||||
s := newACMEServer()
|
||||
s.handle("/acme/new-account", func(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
41
third_party/forked/acme/types.go
vendored
41
third_party/forked/acme/types.go
vendored
@ -60,6 +60,15 @@ var (
|
||||
// errPreAuthorizationNotSupported indicates that the server does not
|
||||
// support pre-authorization of identifiers.
|
||||
errPreAuthorizationNotSupported = errors.New("acme: pre-authorization is not supported")
|
||||
|
||||
// ErrCADoesNotSupportProfiles indicates that [WithOrderProfile] was
|
||||
// included with a CA that does not advertise support for profiles in
|
||||
// their directory.
|
||||
ErrCADoesNotSupportProfiles = errors.New("acme: certificate authority does not support profiles")
|
||||
|
||||
// ErrProfileNotInSetOfSupportedProfiles indicates that the profile
|
||||
// specified with [WithOrderProfile} is not one supported by the CA
|
||||
ErrProfileNotInSetOfSupportedProfiles = errors.New("acme: certificate authority does not advertise a profile with name")
|
||||
)
|
||||
|
||||
// A Subproblem describes an ACME subproblem as reported in an Error.
|
||||
@ -308,6 +317,10 @@ type Directory struct {
|
||||
// ExternalAccountRequired indicates that the CA requires for all account-related
|
||||
// requests to include external account binding information.
|
||||
ExternalAccountRequired bool
|
||||
|
||||
// Profiles indicates that the CA supports specifying a profile for an
|
||||
// order. See also [WithOrderNotAfter].
|
||||
Profiles Profiles
|
||||
}
|
||||
|
||||
// Order represents a client's request for a certificate.
|
||||
@ -383,6 +396,15 @@ func WithOrderNotAfter(t time.Time) OrderOption {
|
||||
return orderNotAfterOpt(t)
|
||||
}
|
||||
|
||||
// WithOrderProfile sets an order's Profile field for servers which support
|
||||
// profiles.
|
||||
// See also:
|
||||
// * https://datatracker.ietf.org/doc/draft-aaron-acme-profiles/
|
||||
// * https://letsencrypt.org/docs/profiles/
|
||||
func WithOrderProfile(name string) OrderOption {
|
||||
return orderProfileOpt(name)
|
||||
}
|
||||
|
||||
type orderNotBeforeOpt time.Time
|
||||
|
||||
func (orderNotBeforeOpt) privateOrderOpt() {}
|
||||
@ -391,6 +413,10 @@ type orderNotAfterOpt time.Time
|
||||
|
||||
func (orderNotAfterOpt) privateOrderOpt() {}
|
||||
|
||||
type orderProfileOpt string
|
||||
|
||||
func (orderProfileOpt) privateOrderOpt() {}
|
||||
|
||||
// Authorization encodes an authorization response.
|
||||
type Authorization struct {
|
||||
// URI uniquely identifies a authorization.
|
||||
@ -627,3 +653,18 @@ func WithTemplate(t *x509.Certificate) CertOption {
|
||||
type certOptTemplate x509.Certificate
|
||||
|
||||
func (*certOptTemplate) privateCertOpt() {}
|
||||
|
||||
type Profiles map[string]string
|
||||
|
||||
func (ps Profiles) isSupported() bool {
|
||||
return len(ps) > 0
|
||||
}
|
||||
|
||||
func (ps Profiles) GetDescription(name string) string {
|
||||
return ps[name]
|
||||
}
|
||||
|
||||
func (ps Profiles) Has(name string) bool {
|
||||
_, ok := ps[name]
|
||||
return ok
|
||||
}
|
||||
|
||||
12
third_party/klone.yaml
vendored
12
third_party/klone.yaml
vendored
@ -1,9 +1,15 @@
|
||||
# Clone folders from third_party repos and forks.
|
||||
# More info can be found here: https://github.com/cert-manager/klone
|
||||
#
|
||||
# - acme
|
||||
# We vendor just the acme package, from a cert-manager fork of
|
||||
# golang.org/x/crypto. The acme-profiles branch has a patch by @sigmavirus24,
|
||||
# with support for ACME profiles.
|
||||
# See https://github.com/golang/go/issues/73101#issuecomment-2764923702
|
||||
targets:
|
||||
forked:
|
||||
- folder_name: acme
|
||||
repo_url: https://go.googlesource.com/crypto
|
||||
repo_ref: v0.38.0
|
||||
repo_hash: aae6e61070421a51c1ba3bd9bba4b9b3979ed488
|
||||
repo_url: https://github.com/cert-manager/crypto
|
||||
repo_ref: acme-profiles
|
||||
repo_hash: 20ccc126e2ac0b2d9da2e78f84f5bb7649d8100a
|
||||
repo_path: acme
|
||||
|
||||
Loading…
Reference in New Issue
Block a user