From bca311b05eb5e0ea558dc18fe2794b02d5a487ac Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Tue, 23 Aug 2022 17:11:40 -0700 Subject: [PATCH] Add acme property to enable challenges Fixes #1027 --- acme/api/account_test.go | 11 ++++----- acme/api/order.go | 12 +++++++--- acme/api/order_test.go | 1 + acme/common.go | 10 +++++++++ authority/provisioner/acme.go | 25 ++++++++++++++++++++- authority/provisioners.go | 42 ++++++++++++++++++++++++++++++++++- go.mod | 4 ++-- go.sum | 14 +++++++++--- 8 files changed, 104 insertions(+), 15 deletions(-) diff --git a/acme/api/account_test.go b/acme/api/account_test.go index d81553d2..0aea6107 100644 --- a/acme/api/account_test.go +++ b/acme/api/account_test.go @@ -41,11 +41,12 @@ func (*fakeProvisioner) AuthorizeSign(ctx context.Context, token string) ([]prov return nil, nil } -func (*fakeProvisioner) AuthorizeRevoke(ctx context.Context, token string) error { return nil } -func (*fakeProvisioner) GetID() string { return "" } -func (*fakeProvisioner) GetName() string { return "" } -func (*fakeProvisioner) DefaultTLSCertDuration() time.Duration { return 0 } -func (*fakeProvisioner) GetOptions() *provisioner.Options { return nil } +func (*fakeProvisioner) AuthorizeRevoke(ctx context.Context, token string) error { return nil } +func (*fakeProvisioner) AuthorizeChallenge(ctx context.Context, challenge string) error { return nil } +func (*fakeProvisioner) GetID() string { return "" } +func (*fakeProvisioner) GetName() string { return "" } +func (*fakeProvisioner) DefaultTLSCertDuration() time.Duration { return 0 } +func (*fakeProvisioner) GetOptions() *provisioner.Options { return nil } func newProv() acme.Provisioner { // Initialize provisioners diff --git a/acme/api/order.go b/acme/api/order.go index b88b56fb..90541d79 100644 --- a/acme/api/order.go +++ b/acme/api/order.go @@ -255,8 +255,14 @@ func newAuthorization(ctx context.Context, az *acme.Authorization) error { } db := acme.MustDatabaseFromContext(ctx) - az.Challenges = make([]*acme.Challenge, len(chTypes)) - for i, typ := range chTypes { + prov := acme.MustProvisionerFromContext(ctx) + az.Challenges = make([]*acme.Challenge, 0, len(chTypes)) + for _, typ := range chTypes { + // Make sure the challenge is enabled + if err := prov.AuthorizeChallenge(ctx, string(typ)); err != nil { + continue + } + ch := &acme.Challenge{ AccountID: az.AccountID, Value: az.Identifier.Value, @@ -267,7 +273,7 @@ func newAuthorization(ctx context.Context, az *acme.Authorization) error { if err := db.CreateChallenge(ctx, ch); err != nil { return acme.WrapErrorISE(err, "error creating challenge") } - az.Challenges[i] = ch + az.Challenges = append(az.Challenges, ch) } if err = db.CreateAuthorization(ctx, az); err != nil { return acme.WrapErrorISE(err, "error creating authorization") diff --git a/acme/api/order_test.go b/acme/api/order_test.go index 724357d8..6ce330c0 100644 --- a/acme/api/order_test.go +++ b/acme/api/order_test.go @@ -681,6 +681,7 @@ func TestHandler_newAuthorization(t *testing.T) { t.Run(name, func(t *testing.T) { tc := run(t) ctx := newBaseContext(context.Background(), tc.db) + ctx = acme.NewProvisionerContext(ctx, newProv()) if err := newAuthorization(ctx, tc.az); err != nil { if assert.NotNil(t, tc.err) { switch k := err.(type) { diff --git a/acme/common.go b/acme/common.go index 3054abe1..3a1e7a8f 100644 --- a/acme/common.go +++ b/acme/common.go @@ -71,6 +71,7 @@ type Provisioner interface { AuthorizeOrderIdentifier(ctx context.Context, identifier provisioner.ACMEIdentifier) error AuthorizeSign(ctx context.Context, token string) ([]provisioner.SignOption, error) AuthorizeRevoke(ctx context.Context, token string) error + AuthorizeChallenge(ctx context.Context, challenge string) error GetID() string GetName() string DefaultTLSCertDuration() time.Duration @@ -109,6 +110,7 @@ type MockProvisioner struct { MauthorizeOrderIdentifier func(ctx context.Context, identifier provisioner.ACMEIdentifier) error MauthorizeSign func(ctx context.Context, ott string) ([]provisioner.SignOption, error) MauthorizeRevoke func(ctx context.Context, token string) error + MauthorizeChallenge func(Ctx context.Context, challenge string) error MdefaultTLSCertDuration func() time.Duration MgetOptions func() *provisioner.Options } @@ -145,6 +147,14 @@ func (m *MockProvisioner) AuthorizeRevoke(ctx context.Context, token string) err return m.Merr } +// AuthorizeChallenge mock +func (m *MockProvisioner) AuthorizeChallenge(ctx context.Context, challenge string) error { + if m.MauthorizeChallenge != nil { + return m.MauthorizeChallenge(ctx, challenge) + } + return m.Merr +} + // DefaultTLSCertDuration mock func (m *MockProvisioner) DefaultTLSCertDuration() time.Duration { if m.MdefaultTLSCertDuration != nil { diff --git a/authority/provisioner/acme.go b/authority/provisioner/acme.go index 9374d985..dc7533e5 100644 --- a/authority/provisioner/acme.go +++ b/authority/provisioner/acme.go @@ -5,6 +5,7 @@ import ( "crypto/x509" "fmt" "net" + "strings" "time" "github.com/pkg/errors" @@ -22,7 +23,11 @@ type ACME struct { // by clients when creating a new Account. If set to true, the provided // EAB will be verified. If set to false and an EAB is provided, it is // not verified. Defaults to false. - RequireEAB bool `json:"requireEAB,omitempty"` + RequireEAB bool `json:"requireEAB,omitempty"` + // Challenges contains the enabled challenges for this provisioner. If this + // value is not set the default http-01, dns-01 and tls-alpn-01 challenges + // will be enabled, device-attest-01 will be disabled. + Challenges []string `json:"challenges,omitempty"` Claims *Claims `json:"claims,omitempty"` Options *Options `json:"options,omitempty"` @@ -163,3 +168,21 @@ func (p *ACME) AuthorizeRevoke(ctx context.Context, token string) error { func (p *ACME) AuthorizeRenew(ctx context.Context, cert *x509.Certificate) error { return p.ctl.AuthorizeRenew(ctx, cert) } + +// AuthorizeChallenge checks if the given challenge is enabled. By default +// http-01, dns-01 and tls-alpn-01 are enabled, to disable any of them the +// Challenge provisioner property should have at least one element. +func (p *ACME) AuthorizeChallenge(ctx context.Context, challenge string) error { + enabledChallenges := []string{ + "http-01", "dns-01", "tls-alpn-01", + } + if len(p.Challenges) > 0 { + enabledChallenges = p.Challenges + } + for _, ch := range enabledChallenges { + if strings.EqualFold(ch, challenge) { + return nil + } + } + return fmt.Errorf("acme challenge %q is disabled", challenge) +} diff --git a/authority/provisioners.go b/authority/provisioners.go index 1fd34ef0..1fb31321 100644 --- a/authority/provisioners.go +++ b/authority/provisioners.go @@ -753,6 +753,7 @@ func ProvisionerToCertificates(p *linkedca.Provisioner) (provisioner.Interface, Name: p.Name, ForceCN: cfg.ForceCn, RequireEAB: cfg.RequireEab, + Challenges: challengesToCertificates(cfg.Challenges), Claims: claims, Options: options, }, nil @@ -1001,7 +1002,8 @@ func ProvisionerToLinkedca(p provisioner.Interface) (*linkedca.Provisioner, erro Details: &linkedca.ProvisionerDetails{ Data: &linkedca.ProvisionerDetails_ACME{ ACME: &linkedca.ACMEProvisioner{ - ForceCn: p.ForceCN, + ForceCn: p.ForceCN, + Challenges: challengesToLinkedca(p.Challenges), }, }, }, @@ -1122,3 +1124,41 @@ func parseInstanceAge(age string) (provisioner.Duration, error) { } return instanceAge, nil } + +func challengesToCertificates(challenges []linkedca.ACMEProvisioner_ChallengeType) []string { + ret := make([]string, len(challenges)) + for i, ch := range challenges { + switch ch { + case linkedca.ACMEProvisioner_HTTP_01: + ret[i] = "http-01" + case linkedca.ACMEProvisioner_DNS_01: + ret[i] = "dns-01" + case linkedca.ACMEProvisioner_TLS_ALPN_O1: + ret[i] = "tls-alpn-01" + case linkedca.ACMEProvisioner_DEVICE_ATTEST_01: + ret[i] = "device-attest-01" + default: + ret[i] = "unknown" + } + } + return ret +} + +func challengesToLinkedca(challenges []string) []linkedca.ACMEProvisioner_ChallengeType { + ret := make([]linkedca.ACMEProvisioner_ChallengeType, len(challenges)) + for i, ch := range challenges { + switch ch { + case "http-01": + ret[i] = linkedca.ACMEProvisioner_DNS_01 + case "dns-01": + ret[i] = linkedca.ACMEProvisioner_DNS_01 + case "tls-alpn-01": + ret[i] = linkedca.ACMEProvisioner_TLS_ALPN_O1 + case "device-attest-01": + ret[i] = linkedca.ACMEProvisioner_DEVICE_ATTEST_01 + default: + ret[i] = linkedca.ACMEProvisioner_UNKNOWN + } + } + return ret +} diff --git a/go.mod b/go.mod index 464d5007..525de75a 100644 --- a/go.mod +++ b/go.mod @@ -37,8 +37,8 @@ require ( github.com/urfave/cli v1.22.4 go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352 go.step.sm/cli-utils v0.7.3 - go.step.sm/crypto v0.17.3 - go.step.sm/linkedca v0.18.0 + go.step.sm/crypto v0.17.4-0.20220823173825-938e5638a882 + go.step.sm/linkedca v0.18.1-0.20220824000236-47827c8eb300 golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 golang.org/x/net v0.0.0-20220607020251-c690dde0001d google.golang.org/api v0.84.0 diff --git a/go.sum b/go.sum index 0098a132..653a8c32 100644 --- a/go.sum +++ b/go.sum @@ -247,6 +247,7 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9 github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0 h1:TrB8swr/68K7m9CcGut2g3UOihhbcbiMAYiuTXdEih4= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-piv/piv-go v1.9.0/go.mod h1:NZ2zmjVkfFaL/CF8cVQ/pXdXtuj110zEKGdJM6fJZZM= github.com/go-piv/piv-go v1.10.0 h1:P1Y1VjBI5DnXW0+YkKmTuh5opWnMIrKriUaIOblee9Q= github.com/go-piv/piv-go v1.10.0/go.mod h1:NZ2zmjVkfFaL/CF8cVQ/pXdXtuj110zEKGdJM6fJZZM= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= @@ -570,6 +571,7 @@ github.com/micromdm/scep/v2 v2.1.0 h1:2fS9Rla7qRR266hvUoEauBJ7J6FhgssEiq2OkSKXma github.com/micromdm/scep/v2 v2.1.0/go.mod h1:BkF7TkPPhmgJAMtHfP+sFTKXmgzNJgLQlvvGoOExBcc= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/pkcs11 v1.0.3-0.20190429190417-a667d056470f/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= +github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= github.com/miekg/pkcs11 v1.1.1 h1:Ugu9pdy6vAYku5DEpVWVFPYnzV+bxB+iRdbuFSu7TvU= github.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= @@ -751,6 +753,7 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= @@ -771,10 +774,11 @@ go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqe go.step.sm/cli-utils v0.7.3 h1:IA12IaiXVCI18yOFVQuvMpyvjL8wuwUn1yO+KhAVAr0= go.step.sm/cli-utils v0.7.3/go.mod h1:RJRwbBLqzs5nrepQLAV9FuT3fVpWz66tKzLIB7Izpfk= go.step.sm/crypto v0.9.0/go.mod h1:+CYG05Mek1YDqi5WK0ERc6cOpKly2i/a5aZmU1sfGj0= -go.step.sm/crypto v0.17.3 h1:YxrRVGmtY4PObl8YD9bU0/nx7F29GjnFR9Ef+Z+cILk= -go.step.sm/crypto v0.17.3/go.mod h1:FXFiLBUsoE0OGz8JTjxhYU1rwKKNgVIb5izZTUMdc/8= -go.step.sm/linkedca v0.18.0 h1:uxRBd2WDvJNZ2i0nJm/QmG4lkRxWoebYKJinchX7T7o= +go.step.sm/crypto v0.17.4-0.20220823173825-938e5638a882 h1:nNG9b4hUh1vN6yxqzQ/Q4Ex/s4di1qoMESxrGC4pMsY= +go.step.sm/crypto v0.17.4-0.20220823173825-938e5638a882/go.mod h1:FXFiLBUsoE0OGz8JTjxhYU1rwKKNgVIb5izZTUMdc/8= go.step.sm/linkedca v0.18.0/go.mod h1:qSuYlIIhvPmA2+DSSS03E2IXhbXWTLW61Xh9zDQJ3VM= +go.step.sm/linkedca v0.18.1-0.20220824000236-47827c8eb300 h1:kDqCHUh4jqqqf+m5IXjFjlwsTXuIXpf5ciGKigqJH14= +go.step.sm/linkedca v0.18.1-0.20220824000236-47827c8eb300/go.mod h1:qSuYlIIhvPmA2+DSSS03E2IXhbXWTLW61Xh9zDQJ3VM= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= @@ -887,6 +891,7 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= @@ -992,6 +997,7 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211031064116-611d5d643895/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1090,6 +1096,7 @@ golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1306,6 +1313,7 @@ gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0 h1:hjy8E9ON/egN1tAYqKb61G10WtihqetD4sz2H+8nIeA= gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=