From b401376829199e2196181c84781a4f72e0acd9dc Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Mon, 21 Mar 2022 19:21:40 -0700 Subject: [PATCH 01/21] Add current provisioner to AuthorizeSign SignOptions. The original provisioner cannot be retrieved from a certificate if a linked ra is used. --- authority/provisioner/acme.go | 1 + authority/provisioner/aws.go | 1 + authority/provisioner/azure.go | 1 + authority/provisioner/gcp.go | 1 + authority/provisioner/jwk.go | 1 + authority/provisioner/k8sSA.go | 1 + authority/provisioner/nebula.go | 1 + authority/provisioner/noop.go | 2 +- authority/provisioner/oidc.go | 1 + authority/provisioner/scep.go | 1 + authority/provisioner/x5c.go | 1 + 11 files changed, 11 insertions(+), 1 deletion(-) diff --git a/authority/provisioner/acme.go b/authority/provisioner/acme.go index 913d0ace..b5d806ab 100644 --- a/authority/provisioner/acme.go +++ b/authority/provisioner/acme.go @@ -89,6 +89,7 @@ func (p *ACME) Init(config Config) (err error) { // on the resulting certificate. func (p *ACME) AuthorizeSign(ctx context.Context, token string) ([]SignOption, error) { return []SignOption{ + p, // modifiers / withOptions newProvisionerExtensionOption(TypeACME, p.Name, ""), newForceCNOption(p.ForceCN), diff --git a/authority/provisioner/aws.go b/authority/provisioner/aws.go index 5f79d7d0..9d27e016 100644 --- a/authority/provisioner/aws.go +++ b/authority/provisioner/aws.go @@ -467,6 +467,7 @@ func (p *AWS) AuthorizeSign(ctx context.Context, token string) ([]SignOption, er } return append(so, + p, templateOptions, // modifiers / withOptions newProvisionerExtensionOption(TypeAWS, p.Name, doc.AccountID, "InstanceID", doc.InstanceID), diff --git a/authority/provisioner/azure.go b/authority/provisioner/azure.go index d9654566..58ce47b3 100644 --- a/authority/provisioner/azure.go +++ b/authority/provisioner/azure.go @@ -349,6 +349,7 @@ func (p *Azure) AuthorizeSign(ctx context.Context, token string) ([]SignOption, } return append(so, + p, templateOptions, // modifiers / withOptions newProvisionerExtensionOption(TypeAzure, p.Name, p.TenantID), diff --git a/authority/provisioner/gcp.go b/authority/provisioner/gcp.go index 6070b640..69d909a2 100644 --- a/authority/provisioner/gcp.go +++ b/authority/provisioner/gcp.go @@ -262,6 +262,7 @@ func (p *GCP) AuthorizeSign(ctx context.Context, token string) ([]SignOption, er } return append(so, + p, templateOptions, // modifiers / withOptions newProvisionerExtensionOption(TypeGCP, p.Name, claims.Subject, "InstanceID", ce.InstanceID, "InstanceName", ce.InstanceName), diff --git a/authority/provisioner/jwk.go b/authority/provisioner/jwk.go index c014bec0..3c5032fb 100644 --- a/authority/provisioner/jwk.go +++ b/authority/provisioner/jwk.go @@ -170,6 +170,7 @@ func (p *JWK) AuthorizeSign(ctx context.Context, token string) ([]SignOption, er } return []SignOption{ + p, templateOptions, // modifiers / withOptions newProvisionerExtensionOption(TypeJWK, p.Name, p.Key.KeyID), diff --git a/authority/provisioner/k8sSA.go b/authority/provisioner/k8sSA.go index 557d571a..083773e0 100644 --- a/authority/provisioner/k8sSA.go +++ b/authority/provisioner/k8sSA.go @@ -231,6 +231,7 @@ func (p *K8sSA) AuthorizeSign(ctx context.Context, token string) ([]SignOption, } return []SignOption{ + p, templateOptions, // modifiers / withOptions newProvisionerExtensionOption(TypeK8sSA, p.Name, ""), diff --git a/authority/provisioner/nebula.go b/authority/provisioner/nebula.go index 1a6eee3e..4216e997 100644 --- a/authority/provisioner/nebula.go +++ b/authority/provisioner/nebula.go @@ -144,6 +144,7 @@ func (p *Nebula) AuthorizeSign(ctx context.Context, token string) ([]SignOption, } return []SignOption{ + p, templateOptions, // modifiers / withOptions newProvisionerExtensionOption(TypeNebula, p.Name, ""), diff --git a/authority/provisioner/noop.go b/authority/provisioner/noop.go index 1709fbca..39661e54 100644 --- a/authority/provisioner/noop.go +++ b/authority/provisioner/noop.go @@ -38,7 +38,7 @@ func (p *noop) Init(config Config) error { } func (p *noop) AuthorizeSign(ctx context.Context, token string) ([]SignOption, error) { - return []SignOption{}, nil + return []SignOption{p}, nil } func (p *noop) AuthorizeRenew(ctx context.Context, cert *x509.Certificate) error { diff --git a/authority/provisioner/oidc.go b/authority/provisioner/oidc.go index 1fc9bb4b..3a9398a2 100644 --- a/authority/provisioner/oidc.go +++ b/authority/provisioner/oidc.go @@ -345,6 +345,7 @@ func (o *OIDC) AuthorizeSign(ctx context.Context, token string) ([]SignOption, e } return []SignOption{ + o, templateOptions, // modifiers / withOptions newProvisionerExtensionOption(TypeOIDC, o.Name, o.ClientID), diff --git a/authority/provisioner/scep.go b/authority/provisioner/scep.go index f4cffd78..9dc1edd8 100644 --- a/authority/provisioner/scep.go +++ b/authority/provisioner/scep.go @@ -121,6 +121,7 @@ func (s *SCEP) Init(config Config) (err error) { // on the resulting certificate. func (s *SCEP) AuthorizeSign(ctx context.Context, token string) ([]SignOption, error) { return []SignOption{ + s, // modifiers / withOptions newProvisionerExtensionOption(TypeSCEP, s.Name, ""), newForceCNOption(s.ForceCN), diff --git a/authority/provisioner/x5c.go b/authority/provisioner/x5c.go index 6f534c76..4f3e5899 100644 --- a/authority/provisioner/x5c.go +++ b/authority/provisioner/x5c.go @@ -218,6 +218,7 @@ func (p *X5C) AuthorizeSign(ctx context.Context, token string) ([]SignOption, er } return []SignOption{ + p, templateOptions, // modifiers / withOptions newProvisionerExtensionOption(TypeX5C, p.Name, ""), From 9d027c17d0a6154c3784df8b5b5fa8b425fc6f73 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Mon, 21 Mar 2022 19:24:05 -0700 Subject: [PATCH 02/21] Send current provisioner on PostCertificate --- authority/linkedca.go | 15 ++++++++++++++- authority/tls.go | 24 +++++++++++++++++++----- go.mod | 2 +- go.sum | 5 ++--- 4 files changed, 36 insertions(+), 10 deletions(-) diff --git a/authority/linkedca.go b/authority/linkedca.go index b568dcbb..00d5ceef 100644 --- a/authority/linkedca.go +++ b/authority/linkedca.go @@ -15,6 +15,7 @@ import ( "time" "github.com/pkg/errors" + "github.com/smallstep/certificates/authority/provisioner" "github.com/smallstep/certificates/db" "go.step.sm/crypto/jose" "go.step.sm/crypto/keyutil" @@ -228,12 +229,13 @@ func (c *linkedCaClient) DeleteAdmin(ctx context.Context, id string) error { return errors.Wrap(err, "error deleting admin") } -func (c *linkedCaClient) StoreCertificateChain(fullchain ...*x509.Certificate) error { +func (c *linkedCaClient) StoreCertificateChain(prov provisioner.Interface, fullchain ...*x509.Certificate) error { ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) defer cancel() _, err := c.client.PostCertificate(ctx, &linkedca.CertificateRequest{ PemCertificate: serializeCertificateChain(fullchain[0]), PemCertificateChain: serializeCertificateChain(fullchain[1:]...), + Provisioner: createProvisionerIdentity(prov), }) return errors.Wrap(err, "error posting certificate") } @@ -310,6 +312,17 @@ func (c *linkedCaClient) IsSSHRevoked(serial string) (bool, error) { return resp.Status != linkedca.RevocationStatus_ACTIVE, nil } +func createProvisionerIdentity(prov provisioner.Interface) *linkedca.ProvisionerIdentity { + if prov == nil { + return nil + } + return &linkedca.ProvisionerIdentity{ + Id: prov.GetID(), + Type: linkedca.Provisioner_Type(prov.GetType()), + Name: prov.GetName(), + } +} + func serializeCertificate(crt *x509.Certificate) string { if crt == nil { return "" diff --git a/authority/tls.go b/authority/tls.go index 58a1247c..93bc0408 100644 --- a/authority/tls.go +++ b/authority/tls.go @@ -89,8 +89,13 @@ func (a *Authority) Sign(csr *x509.CertificateRequest, signOpts provisioner.Sign // Set backdate with the configured value signOpts.Backdate = a.config.AuthorityConfig.Backdate.Duration + var prov provisioner.Interface for _, op := range extraOpts { switch k := op.(type) { + // Capture current provisioner + case provisioner.Interface: + prov = k + // Adds new options to NewCertificate case provisioner.CertificateOptions: certOptions = append(certOptions, k.Options(signOpts)...) @@ -204,7 +209,7 @@ func (a *Authority) Sign(csr *x509.CertificateRequest, signOpts provisioner.Sign } fullchain := append([]*x509.Certificate{resp.Certificate}, resp.CertificateChain...) - if err = a.storeCertificate(fullchain); err != nil { + if err = a.storeCertificate(prov, fullchain); err != nil { if err != db.ErrNotImplemented { return nil, errs.Wrap(http.StatusInternalServerError, err, "authority.Sign; error storing certificate in db", opts...) @@ -325,19 +330,28 @@ func (a *Authority) Rekey(oldCert *x509.Certificate, pk crypto.PublicKey) ([]*x5 // TODO: at some point we should replace the db.AuthDB interface to implement // `StoreCertificate(...*x509.Certificate) error` instead of just // `StoreCertificate(*x509.Certificate) error`. -func (a *Authority) storeCertificate(fullchain []*x509.Certificate) error { +func (a *Authority) storeCertificate(prov provisioner.Interface, fullchain []*x509.Certificate) error { + type linkedChainStorer interface { + StoreCertificateChain(provisioner.Interface, ...*x509.Certificate) error + } type certificateChainStorer interface { StoreCertificateChain(...*x509.Certificate) error } // Store certificate in linkedca - if s, ok := a.adminDB.(certificateChainStorer); ok { + switch s := a.adminDB.(type) { + case linkedChainStorer: + return s.StoreCertificateChain(prov, fullchain...) + case certificateChainStorer: return s.StoreCertificateChain(fullchain...) } + // Store certificate in local db - if s, ok := a.db.(certificateChainStorer); ok { + switch s := a.db.(type) { + case certificateChainStorer: return s.StoreCertificateChain(fullchain...) + default: + return a.db.StoreCertificate(fullchain[0]) } - return a.db.StoreCertificate(fullchain[0]) } // storeRenewedCertificate allows to use an extension of the db.AuthDB interface diff --git a/go.mod b/go.mod index 6033d05e..aad8e124 100644 --- a/go.mod +++ b/go.mod @@ -49,4 +49,4 @@ require ( // replace github.com/smallstep/nosql => ../nosql // replace go.step.sm/crypto => ../crypto // replace go.step.sm/cli-utils => ../cli-utils -// replace go.step.sm/linkedca => ../linkedca +replace go.step.sm/linkedca => ../linkedca diff --git a/go.sum b/go.sum index c7a18aad..f124df98 100644 --- a/go.sum +++ b/go.sum @@ -639,8 +639,9 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/thales-e-security/pool v0.0.2 h1:RAPs4q2EbWsTit6tpzuvTFlgFRJ3S8Evf5gtvVDbmPg= github.com/thales-e-security/pool v0.0.2/go.mod h1:qtpMm2+thHtqhLzTwgDBj/OuNnMpupY8mv0Phz0gjhU= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= @@ -685,8 +686,6 @@ go.step.sm/cli-utils v0.7.0/go.mod h1:Ur6bqA/yl636kCUJbp30J7Unv5JJ226eW2KqXPDwF/ go.step.sm/crypto v0.9.0/go.mod h1:+CYG05Mek1YDqi5WK0ERc6cOpKly2i/a5aZmU1sfGj0= go.step.sm/crypto v0.15.3 h1:f3GMl+aCydt294BZRjTYwpaXRqwwndvoTY2NLN4wu10= go.step.sm/crypto v0.15.3/go.mod h1:3G0yQr5lQqfEG0CMYz8apC/qMtjLRQlzflL2AxkcN+g= -go.step.sm/linkedca v0.11.0 h1:jkG5XDQz9VSz2PH+cGjDvJTwiIziN0SWExTnicWpb8o= -go.step.sm/linkedca v0.11.0/go.mod h1:5uTRjozEGSPAZal9xJqlaD38cvJcLe3o1VAFVjqcORo= 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= From 17d7fd70cd16c06dc523033f98eda1ffdb7fb9d1 Mon Sep 17 00:00:00 2001 From: Panagiotis Siatras Date: Tue, 22 Mar 2022 14:31:18 +0200 Subject: [PATCH 03/21] api/log: initial implementation of the package (#859) * api/log: initial implementation of the package * api: refactored to support api/log * scep/api: refactored to support api/log * api/log: documented the package * api: moved log-related tests to api/log --- api/errors.go | 3 ++- api/log/log.go | 47 +++++++++++++++++++++++++++++++++++++ api/log/log_test.go | 44 +++++++++++++++++++++++++++++++++++ api/utils.go | 56 ++++++++++----------------------------------- api/utils_test.go | 35 ---------------------------- scep/api/api.go | 14 ++++++------ 6 files changed, 112 insertions(+), 87 deletions(-) create mode 100644 api/log/log.go create mode 100644 api/log/log_test.go diff --git a/api/errors.go b/api/errors.go index 522fa955..49efd486 100644 --- a/api/errors.go +++ b/api/errors.go @@ -9,6 +9,7 @@ import ( "github.com/pkg/errors" "github.com/smallstep/certificates/acme" + "github.com/smallstep/certificates/api/log" "github.com/smallstep/certificates/authority/admin" "github.com/smallstep/certificates/errs" "github.com/smallstep/certificates/logging" @@ -60,6 +61,6 @@ func WriteError(w http.ResponseWriter, err error) { } if err := json.NewEncoder(w).Encode(err); err != nil { - LogError(w, err) + log.Error(w, err) } } diff --git a/api/log/log.go b/api/log/log.go new file mode 100644 index 00000000..78dae506 --- /dev/null +++ b/api/log/log.go @@ -0,0 +1,47 @@ +// Package log implements API-related logging helpers. +package log + +import ( + "log" + "net/http" + + "github.com/smallstep/certificates/logging" +) + +// Error adds to the response writer the given error if it implements +// logging.ResponseLogger. If it does not implement it, then writes the error +// using the log package. +func Error(rw http.ResponseWriter, err error) { + if rl, ok := rw.(logging.ResponseLogger); ok { + rl.WithFields(map[string]interface{}{ + "error": err, + }) + } else { + log.Println(err) + } +} + +// EnabledResponse log the response object if it implements the EnableLogger +// interface. +func EnabledResponse(rw http.ResponseWriter, v interface{}) { + type enableLogger interface { + ToLog() (interface{}, error) + } + + if el, ok := v.(enableLogger); ok { + out, err := el.ToLog() + if err != nil { + Error(rw, err) + + return + } + + if rl, ok := rw.(logging.ResponseLogger); ok { + rl.WithFields(map[string]interface{}{ + "response": out, + }) + } else { + log.Println(out) + } + } +} diff --git a/api/log/log_test.go b/api/log/log_test.go new file mode 100644 index 00000000..fcd3ea2b --- /dev/null +++ b/api/log/log_test.go @@ -0,0 +1,44 @@ +package log + +import ( + "errors" + "net/http" + "net/http/httptest" + "reflect" + "testing" + + "github.com/smallstep/certificates/logging" +) + +func TestError(t *testing.T) { + theError := errors.New("the error") + + type args struct { + rw http.ResponseWriter + err error + } + tests := []struct { + name string + args args + withFields bool + }{ + {"normalLogger", args{httptest.NewRecorder(), theError}, false}, + {"responseLogger", args{logging.NewResponseLogger(httptest.NewRecorder()), theError}, true}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + Error(tt.args.rw, tt.args.err) + if tt.withFields { + if rl, ok := tt.args.rw.(logging.ResponseLogger); ok { + fields := rl.Fields() + if !reflect.DeepEqual(fields["error"], theError) { + t.Errorf("ResponseLogger[\"error\"] = %s, wants %s", fields["error"], theError) + } + } else { + t.Error("ResponseWriter does not implement logging.ResponseLogger") + } + } + }) + } +} diff --git a/api/utils.go b/api/utils.go index 9daa0cd2..e3fcc9c4 100644 --- a/api/utils.go +++ b/api/utils.go @@ -2,52 +2,14 @@ package api import ( "encoding/json" - "log" "net/http" "google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/proto" - "github.com/smallstep/certificates/logging" + "github.com/smallstep/certificates/api/log" ) -// EnableLogger is an interface that enables response logging for an object. -type EnableLogger interface { - ToLog() (interface{}, error) -} - -// LogError adds to the response writer the given error if it implements -// logging.ResponseLogger. If it does not implement it, then writes the error -// using the log package. -func LogError(rw http.ResponseWriter, err error) { - if rl, ok := rw.(logging.ResponseLogger); ok { - rl.WithFields(map[string]interface{}{ - "error": err, - }) - } else { - log.Println(err) - } -} - -// LogEnabledResponse log the response object if it implements the EnableLogger -// interface. -func LogEnabledResponse(rw http.ResponseWriter, v interface{}) { - if el, ok := v.(EnableLogger); ok { - out, err := el.ToLog() - if err != nil { - LogError(rw, err) - return - } - if rl, ok := rw.(logging.ResponseLogger); ok { - rl.WithFields(map[string]interface{}{ - "response": out, - }) - } else { - log.Println(out) - } - } -} - // JSON writes the passed value into the http.ResponseWriter. func JSON(w http.ResponseWriter, v interface{}) { JSONStatus(w, v, http.StatusOK) @@ -59,10 +21,12 @@ func JSONStatus(w http.ResponseWriter, v interface{}, status int) { w.Header().Set("Content-Type", "application/json") w.WriteHeader(status) if err := json.NewEncoder(w).Encode(v); err != nil { - LogError(w, err) + log.Error(w, err) + return } - LogEnabledResponse(w, v) + + log.EnabledResponse(w, v) } // ProtoJSON writes the passed value into the http.ResponseWriter. @@ -78,12 +42,16 @@ func ProtoJSONStatus(w http.ResponseWriter, m proto.Message, status int) { b, err := protojson.Marshal(m) if err != nil { - LogError(w, err) + log.Error(w, err) + return } + if _, err := w.Write(b); err != nil { - LogError(w, err) + log.Error(w, err) + return } - //LogEnabledResponse(w, v) + + // log.EnabledResponse(w, v) } diff --git a/api/utils_test.go b/api/utils_test.go index 12350c97..f5e1e1cb 100644 --- a/api/utils_test.go +++ b/api/utils_test.go @@ -3,46 +3,11 @@ package api import ( "net/http" "net/http/httptest" - "reflect" "testing" - "github.com/pkg/errors" - "github.com/smallstep/certificates/logging" ) -func TestLogError(t *testing.T) { - theError := errors.New("the error") - type args struct { - rw http.ResponseWriter - err error - } - tests := []struct { - name string - args args - withFields bool - }{ - {"normalLogger", args{httptest.NewRecorder(), theError}, false}, - {"responseLogger", args{logging.NewResponseLogger(httptest.NewRecorder()), theError}, true}, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - LogError(tt.args.rw, tt.args.err) - if tt.withFields { - if rl, ok := tt.args.rw.(logging.ResponseLogger); ok { - fields := rl.Fields() - if !reflect.DeepEqual(fields["error"], theError) { - t.Errorf("ResponseLogger[\"error\"] = %s, wants %s", fields["error"], theError) - } - } else { - t.Error("ResponseWriter does not implement logging.ResponseLogger") - } - } - }) - } -} - func TestJSON(t *testing.T) { type args struct { rw http.ResponseWriter diff --git a/scep/api/api.go b/scep/api/api.go index 77c683ee..a326ea92 100644 --- a/scep/api/api.go +++ b/scep/api/api.go @@ -10,14 +10,14 @@ import ( "strings" "github.com/go-chi/chi" - "github.com/smallstep/certificates/api" - "github.com/smallstep/certificates/authority/provisioner" - "github.com/smallstep/certificates/scep" + microscep "github.com/micromdm/scep/v2/scep" + "github.com/pkg/errors" "go.mozilla.org/pkcs7" - "github.com/pkg/errors" - - microscep "github.com/micromdm/scep/v2/scep" + "github.com/smallstep/certificates/api" + "github.com/smallstep/certificates/api/log" + "github.com/smallstep/certificates/authority/provisioner" + "github.com/smallstep/certificates/scep" ) const ( @@ -337,7 +337,7 @@ func formatCapabilities(caps []string) []byte { func writeSCEPResponse(w http.ResponseWriter, response SCEPResponse) { if response.Error != nil { - api.LogError(w, response.Error) + log.Error(w, response.Error) } if response.Certificate != nil { From 76e53479238705a85986576ecffb1f330c141f2e Mon Sep 17 00:00:00 2001 From: Herman Slatman Date: Wed, 23 Mar 2022 23:14:04 +0100 Subject: [PATCH 04/21] Add armv5 build to GoReleaser configuration --- .goreleaser.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.goreleaser.yml b/.goreleaser.yml index 207c75bd..cd4826c9 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -19,6 +19,7 @@ builds: - linux_386 - linux_amd64 - linux_arm64 + - linux_arm_5 - linux_arm_6 - linux_arm_7 - windows_amd64 From c50800eb0166c9a7ca7ec09c85ab5aa6f3ac0b9e Mon Sep 17 00:00:00 2001 From: Herman Slatman Date: Thu, 24 Mar 2022 00:04:59 +0100 Subject: [PATCH 05/21] Add armv5 build for (cloud|aws)kms --- .goreleaser.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.goreleaser.yml b/.goreleaser.yml index cd4826c9..441d5785 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -40,6 +40,7 @@ builds: - linux_386 - linux_amd64 - linux_arm64 + - linux_arm_5 - linux_arm_6 - linux_arm_7 - windows_amd64 @@ -60,6 +61,7 @@ builds: - linux_386 - linux_amd64 - linux_arm64 + - linux_arm_5 - linux_arm_6 - linux_arm_7 - windows_amd64 From 161a4b28bedd5c89aad9134853a000ea3b7287ab Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Mon, 21 Mar 2022 16:22:26 -0700 Subject: [PATCH 06/21] Change go version to 1.17 and 1.18 --- .github/workflows/release.yml | 8 ++++---- .github/workflows/test.yml | 6 +++--- CHANGELOG.md | 1 + 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5d0416ef..2ab7084d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-20.04 strategy: matrix: - go: [ '1.15', '1.16', '1.17' ] + go: [ '1.17', '1.18' ] outputs: is_prerelease: ${{ steps.is_prerelease.outputs.IS_PRERELEASE }} steps: @@ -33,7 +33,7 @@ jobs: uses: golangci/golangci-lint-action@v2 with: # Optional: version of golangci-lint to use in form of v1.2 or v1.2.3 or `latest` to use the latest version - version: 'v1.44.0' + version: 'v1.45.0' # Optional: working directory, useful for monorepos # working-directory: somedir @@ -106,7 +106,7 @@ jobs: name: Set up Go uses: actions/setup-go@v2 with: - go-version: 1.17 + go-version: 1.18 - name: APT Install id: aptInstall @@ -159,7 +159,7 @@ jobs: name: Setup Go uses: actions/setup-go@v2 with: - go-version: '1.17' + go-version: '1.18' - name: Install cosign uses: sigstore/cosign-installer@v1.1.0 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f36e78ef..64cb64cd 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-20.04 strategy: matrix: - go: [ '1.16', '1.17' ] + go: [ '1.17', '1.18' ] steps: - name: Checkout @@ -33,7 +33,7 @@ jobs: uses: golangci/golangci-lint-action@v2 with: # Optional: version of golangci-lint to use in form of v1.2 or v1.2.3 or `latest` to use the latest version - version: 'v1.44.0' + version: 'v1.45.0' # Optional: working directory, useful for monorepos # working-directory: somedir @@ -58,7 +58,7 @@ jobs: run: V=1 make ci - name: Codecov - if: matrix.go == '1.17' + if: matrix.go == '1.18' uses: codecov/codecov-action@v1.2.1 with: file: ./coverage.out # optional diff --git a/CHANGELOG.md b/CHANGELOG.md index fc25c0ed..3164b3b6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Added support for renew after expiry using the claim `allowRenewAfterExpiry`. ### Changed - Made SCEP CA URL paths dynamic +- Support two latest versions of golang (1.17, 1.18) ### Deprecated ### Removed ### Fixed From 5ab79f53be3ab1c3ffa4b2a9db08831a6780b670 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Mon, 21 Mar 2022 16:53:57 -0700 Subject: [PATCH 07/21] Fix linter errors --- authority/provisioner/x5c.go | 4 +++- authority/provisioner/x5c_test.go | 2 ++ ca/ca.go | 3 --- ca/identity/client_test.go | 23 ++++++++++++++++++++++- ca/identity/identity_test.go | 2 ++ ca/tls.go | 2 -- ca/tls_options_test.go | 1 + 7 files changed, 30 insertions(+), 7 deletions(-) diff --git a/authority/provisioner/x5c.go b/authority/provisioner/x5c.go index 4f3e5899..295d81fb 100644 --- a/authority/provisioner/x5c.go +++ b/authority/provisioner/x5c.go @@ -100,6 +100,7 @@ func (p *X5C) Init(config Config) (err error) { var ( block *pem.Block rest = p.Roots + count int ) for rest != nil { block, rest = pem.Decode(rest) @@ -110,11 +111,12 @@ func (p *X5C) Init(config Config) (err error) { if err != nil { return errors.Wrap(err, "error parsing x509 certificate from PEM block") } + count++ p.rootPool.AddCert(cert) } // Verify that at least one root was found. - if len(p.rootPool.Subjects()) == 0 { + if count == 0 { return errors.Errorf("no x509 certificates found in roots attribute for provisioner '%s'", p.GetName()) } diff --git a/authority/provisioner/x5c_test.go b/authority/provisioner/x5c_test.go index 84e29b48..7932d045 100644 --- a/authority/provisioner/x5c_test.go +++ b/authority/provisioner/x5c_test.go @@ -118,6 +118,8 @@ M46l92gdOozT return ProvisionerValidateTest{ p: p, extraValid: func(p *X5C) error { + // nolint:staticcheck // We don't have a different way to + // check the number of certificates in the pool. numCerts := len(p.rootPool.Subjects()) if numCerts != 2 { return errors.Errorf("unexpected number of certs: want 2, but got %d", numCerts) diff --git a/ca/ca.go b/ca/ca.go index c95ba22f..dfb82731 100644 --- a/ca/ca.go +++ b/ca/ca.go @@ -450,9 +450,6 @@ func (ca *CA) getTLSConfig(auth *authority.Authority) (*tls.Config, error) { tlsConfig.ClientAuth = tls.VerifyClientCertIfGiven tlsConfig.ClientCAs = certPool - // Use server's most preferred ciphersuite - tlsConfig.PreferServerCipherSuites = true - return tlsConfig, nil } diff --git a/ca/identity/client_test.go b/ca/identity/client_test.go index 0f1234e9..9660a3bd 100644 --- a/ca/identity/client_test.go +++ b/ca/identity/client_test.go @@ -8,6 +8,7 @@ import ( "net/url" "os" "reflect" + "sort" "testing" ) @@ -196,7 +197,7 @@ func TestLoadClient(t *testing.T) { switch { case gotTransport.TLSClientConfig.GetClientCertificate == nil: t.Error("LoadClient() transport does not define GetClientCertificate") - case !reflect.DeepEqual(got.CaURL, tt.want.CaURL) || !reflect.DeepEqual(gotTransport.TLSClientConfig.RootCAs.Subjects(), wantTransport.TLSClientConfig.RootCAs.Subjects()): + case !reflect.DeepEqual(got.CaURL, tt.want.CaURL) || !equalPools(gotTransport.TLSClientConfig.RootCAs, wantTransport.TLSClientConfig.RootCAs): t.Errorf("LoadClient() = %#v, want %#v", got, tt.want) default: crt, err := gotTransport.TLSClientConfig.GetClientCertificate(nil) @@ -238,3 +239,23 @@ func Test_defaultsConfig_Validate(t *testing.T) { }) } } + +// nolint:staticcheck,gocritic +func equalPools(a, b *x509.CertPool) bool { + if reflect.DeepEqual(a, b) { + return true + } + subjects := a.Subjects() + sA := make([]string, len(subjects)) + for i := range subjects { + sA[i] = string(subjects[i]) + } + subjects = b.Subjects() + sB := make([]string, len(subjects)) + for i := range subjects { + sB[i] = string(subjects[i]) + } + sort.Strings(sA) + sort.Strings(sB) + return reflect.DeepEqual(sA, sB) +} diff --git a/ca/identity/identity_test.go b/ca/identity/identity_test.go index d3b1d541..55fc60fd 100644 --- a/ca/identity/identity_test.go +++ b/ca/identity/identity_test.go @@ -346,6 +346,8 @@ func TestIdentity_GetCertPool(t *testing.T) { return } if got != nil { + // nolint:staticcheck // we don't have a different way to check + // the certificates in the pool. subjects := got.Subjects() if !reflect.DeepEqual(subjects, tt.wantSubjects) { t.Errorf("Identity.GetCertPool() = %x, want %x", subjects, tt.wantSubjects) diff --git a/ca/tls.go b/ca/tls.go index 0738d0e0..7954cbdf 100644 --- a/ca/tls.go +++ b/ca/tls.go @@ -95,7 +95,6 @@ func (c *Client) getClientTLSConfig(ctx context.Context, sign *api.SignResponse, // Note that with GetClientCertificate tlsConfig.Certificates is not used. // Without tlsConfig.Certificates there's not need to use tlsConfig.BuildNameToCertificate() tlsConfig.GetClientCertificate = renewer.GetClientCertificate - tlsConfig.PreferServerCipherSuites = true // Apply options and initialize mutable tls.Config tlsCtx := newTLSOptionCtx(c, tlsConfig, sign) @@ -137,7 +136,6 @@ func (c *Client) GetServerTLSConfig(ctx context.Context, sign *api.SignResponse, // Without tlsConfig.Certificates there's not need to use tlsConfig.BuildNameToCertificate() tlsConfig.GetCertificate = renewer.GetCertificate tlsConfig.GetClientCertificate = renewer.GetClientCertificate - tlsConfig.PreferServerCipherSuites = true tlsConfig.ClientAuth = tls.RequireAndVerifyClientCert // Apply options and initialize mutable tls.Config diff --git a/ca/tls_options_test.go b/ca/tls_options_test.go index 7d94926b..ca5f80b8 100644 --- a/ca/tls_options_test.go +++ b/ca/tls_options_test.go @@ -542,6 +542,7 @@ func TestAddFederationToCAs(t *testing.T) { } } +// nolint:staticcheck,gocritic func equalPools(a, b *x509.CertPool) bool { if reflect.DeepEqual(a, b) { return true From 76ea1635a77e35885abb2502f00ea56837319007 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Mon, 21 Mar 2022 17:59:15 -0700 Subject: [PATCH 08/21] Change golang to Go --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3164b3b6..73c338f8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Added support for renew after expiry using the claim `allowRenewAfterExpiry`. ### Changed - Made SCEP CA URL paths dynamic -- Support two latest versions of golang (1.17, 1.18) +- Support two latest versions of Go (1.17, 1.18) ### Deprecated ### Removed ### Fixed From 7b605b2d16b8853fdad6739a9d61fa2f289bfe30 Mon Sep 17 00:00:00 2001 From: vijayjt <2975049+vijayjt@users.noreply.github.com> Date: Mon, 7 Mar 2022 11:24:58 +0000 Subject: [PATCH 09/21] Support Azure tokens from managed identities not associated with a VM --- authority/provisioner/azure.go | 14 +++++++++++--- authority/provisioner/azure_test.go | 22 +++++++++++----------- authority/provisioner/utils_test.go | 12 +++++++++--- 3 files changed, 31 insertions(+), 17 deletions(-) diff --git a/authority/provisioner/azure.go b/authority/provisioner/azure.go index 58ce47b3..eabc6efc 100644 --- a/authority/provisioner/azure.go +++ b/authority/provisioner/azure.go @@ -30,7 +30,7 @@ const azureDefaultAudience = "https://management.azure.com/" // azureXMSMirIDRegExp is the regular expression used to parse the xms_mirid claim. // Using case insensitive as resourceGroups appears as resourcegroups. -var azureXMSMirIDRegExp = regexp.MustCompile(`(?i)^/subscriptions/([^/]+)/resourceGroups/([^/]+)/providers/Microsoft.Compute/virtualMachines/([^/]+)$`) +var azureXMSMirIDRegExp = regexp.MustCompile(`(?i)^/subscriptions/([^/]+)/resourceGroups/([^/]+)/providers/Microsoft.(Compute/virtualMachines|ManagedIdentity/userAssignedIdentities)/([^/]+)$`) type azureConfig struct { oidcDiscoveryURL string @@ -260,11 +260,19 @@ func (p *Azure) authorizeToken(token string) (*azurePayload, string, string, str } re := azureXMSMirIDRegExp.FindStringSubmatch(claims.XMSMirID) - if len(re) != 4 { + if len(re) != 5 { return nil, "", "", "", "", errs.Unauthorized("azure.authorizeToken; error parsing xms_mirid claim - %s", claims.XMSMirID) } + + var subscription, group, name string identityObjectID := claims.ObjectID - subscription, group, name := re[1], re[2], re[3] + + if strings.Contains(claims.XMSMirID, "virtualMachines") { + subscription, group, name = re[1], re[2], re[4] + } else { + // This is not a VM resource ID so we don't have the VM name so set that to the empty string + subscription, group, name = re[1], re[2], "" + } return &claims, name, group, subscription, identityObjectID, nil } diff --git a/authority/provisioner/azure_test.go b/authority/provisioner/azure_test.go index c05685b7..40bb4698 100644 --- a/authority/provisioner/azure_test.go +++ b/authority/provisioner/azure_test.go @@ -95,7 +95,7 @@ func TestAzure_GetIdentityToken(t *testing.T) { assert.FatalError(t, err) t1, err := generateAzureToken("subject", p1.oidcConfig.Issuer, azureDefaultAudience, - p1.TenantID, "subscriptionID", "resourceGroup", "virtualMachine", + p1.TenantID, "subscriptionID", "resourceGroup", "virtualMachine", "vm", time.Now(), &p1.keyStore.keySet.Keys[0]) assert.FatalError(t, err) @@ -237,7 +237,7 @@ func TestAzure_authorizeToken(t *testing.T) { jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0) assert.FatalError(t, err) tok, err := generateAzureToken("subject", p.oidcConfig.Issuer, azureDefaultAudience, - p.TenantID, "subscriptionID", "resourceGroup", "virtualMachine", + p.TenantID, "subscriptionID", "resourceGroup", "virtualMachine", "vm", time.Now(), jwk) assert.FatalError(t, err) return test{ @@ -252,7 +252,7 @@ func TestAzure_authorizeToken(t *testing.T) { assert.FatalError(t, err) defer srv.Close() tok, err := generateAzureToken("subject", "bad-issuer", azureDefaultAudience, - p.TenantID, "subscriptionID", "resourceGroup", "virtualMachine", + p.TenantID, "subscriptionID", "resourceGroup", "virtualMachine", "vm", time.Now(), &p.keyStore.keySet.Keys[0]) assert.FatalError(t, err) return test{ @@ -267,7 +267,7 @@ func TestAzure_authorizeToken(t *testing.T) { assert.FatalError(t, err) defer srv.Close() tok, err := generateAzureToken("subject", p.oidcConfig.Issuer, azureDefaultAudience, - "foo", "subscriptionID", "resourceGroup", "virtualMachine", + "foo", "subscriptionID", "resourceGroup", "virtualMachine", "vm", time.Now(), &p.keyStore.keySet.Keys[0]) assert.FatalError(t, err) return test{ @@ -321,7 +321,7 @@ func TestAzure_authorizeToken(t *testing.T) { assert.FatalError(t, err) defer srv.Close() tok, err := generateAzureToken("subject", p.oidcConfig.Issuer, azureDefaultAudience, - p.TenantID, "subscriptionID", "resourceGroup", "virtualMachine", + p.TenantID, "subscriptionID", "resourceGroup", "virtualMachine", "vm", time.Now(), &p.keyStore.keySet.Keys[0]) assert.FatalError(t, err) return test{ @@ -437,28 +437,28 @@ func TestAzure_AuthorizeSign(t *testing.T) { assert.FatalError(t, err) t11, err := generateAzureToken("subject", p1.oidcConfig.Issuer, azureDefaultAudience, - p1.TenantID, "subscriptionID", "resourceGroup", "virtualMachine", + p1.TenantID, "subscriptionID", "resourceGroup", "virtualMachine", "vm", time.Now(), &p1.keyStore.keySet.Keys[0]) assert.FatalError(t, err) failIssuer, err := generateAzureToken("subject", "bad-issuer", azureDefaultAudience, - p1.TenantID, "subscriptionID", "resourceGroup", "virtualMachine", + p1.TenantID, "subscriptionID", "resourceGroup", "virtualMachine", "vm", time.Now(), &p1.keyStore.keySet.Keys[0]) assert.FatalError(t, err) failAudience, err := generateAzureToken("subject", p1.oidcConfig.Issuer, "bad-audience", - p1.TenantID, "subscriptionID", "resourceGroup", "virtualMachine", + p1.TenantID, "subscriptionID", "resourceGroup", "virtualMachine", "vm", time.Now(), &p1.keyStore.keySet.Keys[0]) assert.FatalError(t, err) failExp, err := generateAzureToken("subject", p1.oidcConfig.Issuer, azureDefaultAudience, - p1.TenantID, "subscriptionID", "resourceGroup", "virtualMachine", + p1.TenantID, "subscriptionID", "resourceGroup", "virtualMachine", "vm", time.Now().Add(-360*time.Second), &p1.keyStore.keySet.Keys[0]) assert.FatalError(t, err) failNbf, err := generateAzureToken("subject", p1.oidcConfig.Issuer, azureDefaultAudience, - p1.TenantID, "subscriptionID", "resourceGroup", "virtualMachine", + p1.TenantID, "subscriptionID", "resourceGroup", "virtualMachine", "vm", time.Now().Add(360*time.Second), &p1.keyStore.keySet.Keys[0]) assert.FatalError(t, err) failKey, err := generateAzureToken("subject", p1.oidcConfig.Issuer, azureDefaultAudience, - p1.TenantID, "subscriptionID", "resourceGroup", "virtualMachine", + p1.TenantID, "subscriptionID", "resourceGroup", "virtualMachine", "vm", time.Now(), badKey) assert.FatalError(t, err) diff --git a/authority/provisioner/utils_test.go b/authority/provisioner/utils_test.go index 669693d6..7e783c2a 100644 --- a/authority/provisioner/utils_test.go +++ b/authority/provisioner/utils_test.go @@ -656,7 +656,7 @@ func generateAzureWithServer() (*Azure, *httptest.Server, error) { w.Header().Add("Cache-Control", "max-age=5") writeJSON(w, getPublic(az.keyStore.keySet)) case "/metadata/identity/oauth2/token": - tok, err := generateAzureToken("subject", issuer, "https://management.azure.com/", az.TenantID, "subscriptionID", "resourceGroup", "virtualMachine", time.Now(), &az.keyStore.keySet.Keys[0]) + tok, err := generateAzureToken("subject", issuer, "https://management.azure.com/", az.TenantID, "subscriptionID", "resourceGroup", "virtualMachine", "vm", time.Now(), &az.keyStore.keySet.Keys[0]) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) } else { @@ -994,7 +994,7 @@ func generateAWSToken(p *AWS, sub, iss, aud, accountID, instanceID, privateIP, r return jose.Signed(sig).Claims(claims).CompactSerialize() } -func generateAzureToken(sub, iss, aud, tenantID, subscriptionID, resourceGroup, virtualMachine string, iat time.Time, jwk *jose.JSONWebKey) (string, error) { +func generateAzureToken(sub, iss, aud, tenantID, subscriptionID, resourceGroup, resourceName string, resourceType string, iat time.Time, jwk *jose.JSONWebKey) (string, error) { sig, err := jose.NewSigner( jose.SigningKey{Algorithm: jose.ES256, Key: jwk.Key}, new(jose.SignerOptions).WithType("JWT").WithHeader("kid", jwk.KeyID), @@ -1002,6 +1002,12 @@ func generateAzureToken(sub, iss, aud, tenantID, subscriptionID, resourceGroup, if err != nil { return "", err } + var xmsMirID string + if resourceType == "vm" { + xmsMirID = fmt.Sprintf("/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Compute/virtualMachines/%s", subscriptionID, resourceGroup, resourceName) + } else if resourceType == "uai" { + xmsMirID = fmt.Sprintf("/subscriptions/%s/resourceGroups/%s/providers/Microsoft.ManagedIdentity/userAssignedIdentities/%s", subscriptionID, resourceGroup, resourceName) + } claims := azurePayload{ Claims: jose.Claims{ @@ -1019,7 +1025,7 @@ func generateAzureToken(sub, iss, aud, tenantID, subscriptionID, resourceGroup, ObjectID: "the-oid", TenantID: tenantID, Version: "the-version", - XMSMirID: fmt.Sprintf("/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Compute/virtualMachines/%s", subscriptionID, resourceGroup, virtualMachine), + XMSMirID: xmsMirID, } return jose.Signed(sig).Claims(claims).CompactSerialize() } From 7e47c70af2eded79e4e94d3356d85abb337f1553 Mon Sep 17 00:00:00 2001 From: vijayjt <2975049+vijayjt@users.noreply.github.com> Date: Mon, 7 Mar 2022 12:07:48 +0000 Subject: [PATCH 10/21] Remove redundant parameter type declaration --- authority/provisioner/utils_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/authority/provisioner/utils_test.go b/authority/provisioner/utils_test.go index 7e783c2a..c55c58d2 100644 --- a/authority/provisioner/utils_test.go +++ b/authority/provisioner/utils_test.go @@ -994,7 +994,7 @@ func generateAWSToken(p *AWS, sub, iss, aud, accountID, instanceID, privateIP, r return jose.Signed(sig).Claims(claims).CompactSerialize() } -func generateAzureToken(sub, iss, aud, tenantID, subscriptionID, resourceGroup, resourceName string, resourceType string, iat time.Time, jwk *jose.JSONWebKey) (string, error) { +func generateAzureToken(sub, iss, aud, tenantID, subscriptionID, resourceGroup, resourceName, resourceType string, iat time.Time, jwk *jose.JSONWebKey) (string, error) { sig, err := jose.NewSigner( jose.SigningKey{Algorithm: jose.ES256, Key: jwk.Key}, new(jose.SignerOptions).WithType("JWT").WithHeader("kid", jwk.KeyID), From 37207793f9368a5e2a13e06ad36b150167713979 Mon Sep 17 00:00:00 2001 From: vijayjt <2975049+vijayjt@users.noreply.github.com> Date: Tue, 22 Mar 2022 00:10:43 +0000 Subject: [PATCH 11/21] Pass in the resource name regardless of if its a VM or managed identity --- authority/provisioner/azure.go | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/authority/provisioner/azure.go b/authority/provisioner/azure.go index eabc6efc..e6323e9f 100644 --- a/authority/provisioner/azure.go +++ b/authority/provisioner/azure.go @@ -266,13 +266,8 @@ func (p *Azure) authorizeToken(token string) (*azurePayload, string, string, str var subscription, group, name string identityObjectID := claims.ObjectID + subscription, group, name = re[1], re[2], re[4] - if strings.Contains(claims.XMSMirID, "virtualMachines") { - subscription, group, name = re[1], re[2], re[4] - } else { - // This is not a VM resource ID so we don't have the VM name so set that to the empty string - subscription, group, name = re[1], re[2], "" - } return &claims, name, group, subscription, identityObjectID, nil } From bca74cb6a734794284439a63219d6ece301b9a82 Mon Sep 17 00:00:00 2001 From: Panagiotis Siatras Date: Thu, 24 Mar 2022 14:58:50 +0200 Subject: [PATCH 12/21] scep: minor cleanup (#867) * api, scep: removed scep.Error * scep/api: replaced nextHTTP with http.HandlerFunc * scep/api: renamed writeSCEPResponse to writeResponse * scep/api: renamed decodeSCEPRequest to decodeRequest * scep/api: renamed writeError to fail * scep/api: replaced pkg/errors with errors * scep/api: formatted imports * scep/api: do not export SCEPRequest & SCEPResponse * scep/api: do not export Handler * api: flush errors better --- api/errors.go | 24 +++----- scep/api/api.go | 158 +++++++++++++++++++++++------------------------- scep/errors.go | 12 ---- 3 files changed, 86 insertions(+), 108 deletions(-) delete mode 100644 scep/errors.go diff --git a/api/errors.go b/api/errors.go index 49efd486..680e6578 100644 --- a/api/errors.go +++ b/api/errors.go @@ -13,7 +13,6 @@ import ( "github.com/smallstep/certificates/authority/admin" "github.com/smallstep/certificates/errs" "github.com/smallstep/certificates/logging" - "github.com/smallstep/certificates/scep" ) // WriteError writes to w a JSON representation of the given error. @@ -25,22 +24,9 @@ func WriteError(w http.ResponseWriter, err error) { case *admin.Error: admin.WriteError(w, k) return - case *scep.Error: - w.Header().Set("Content-Type", "text/plain") - default: - w.Header().Set("Content-Type", "application/json") } cause := errors.Cause(err) - if sc, ok := err.(errs.StatusCoder); ok { - w.WriteHeader(sc.StatusCode()) - } else { - if sc, ok := cause.(errs.StatusCoder); ok { - w.WriteHeader(sc.StatusCode()) - } else { - w.WriteHeader(http.StatusInternalServerError) - } - } // Write errors in the response writer if rl, ok := w.(logging.ResponseLogger); ok { @@ -60,6 +46,16 @@ func WriteError(w http.ResponseWriter, err error) { } } + code := http.StatusInternalServerError + if sc, ok := err.(errs.StatusCoder); ok { + code = sc.StatusCode() + } else if sc, ok := cause.(errs.StatusCoder); ok { + code = sc.StatusCode() + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(code) + if err := json.NewEncoder(w).Encode(err); err != nil { log.Error(w, err) } diff --git a/scep/api/api.go b/scep/api/api.go index a326ea92..91d337fe 100644 --- a/scep/api/api.go +++ b/scep/api/api.go @@ -4,6 +4,8 @@ import ( "context" "crypto/x509" "encoding/base64" + "errors" + "fmt" "io" "net/http" "net/url" @@ -11,7 +13,6 @@ import ( "github.com/go-chi/chi" microscep "github.com/micromdm/scep/v2/scep" - "github.com/pkg/errors" "go.mozilla.org/pkcs7" "github.com/smallstep/certificates/api" @@ -30,22 +31,20 @@ const ( const maxPayloadSize = 2 << 20 -type nextHTTP = func(http.ResponseWriter, *http.Request) - const ( certChainHeader = "application/x-x509-ca-ra-cert" leafHeader = "application/x-x509-ca-cert" pkiOperationHeader = "application/x-pki-message" ) -// SCEPRequest is a SCEP server request. -type SCEPRequest struct { +// request is a SCEP server request. +type request struct { Operation string Message []byte } -// SCEPResponse is a SCEP server response. -type SCEPResponse struct { +// response is a SCEP server response. +type response struct { Operation string CACertNum int Data []byte @@ -53,18 +52,18 @@ type SCEPResponse struct { Error error } -// Handler is the SCEP request handler. -type Handler struct { +// handler is the SCEP request handler. +type handler struct { Auth scep.Interface } // New returns a new SCEP API router. func New(scepAuth scep.Interface) api.RouterHandler { - return &Handler{scepAuth} + return &handler{scepAuth} } // Route traffic and implement the Router interface. -func (h *Handler) Route(r api.Router) { +func (h *handler) Route(r api.Router) { getLink := h.Auth.GetLinkExplicit r.MethodFunc(http.MethodGet, getLink("{provisionerName}/*", false, nil), h.lookupProvisioner(h.Get)) r.MethodFunc(http.MethodGet, getLink("{provisionerName}", false, nil), h.lookupProvisioner(h.Get)) @@ -73,64 +72,64 @@ func (h *Handler) Route(r api.Router) { } // Get handles all SCEP GET requests -func (h *Handler) Get(w http.ResponseWriter, r *http.Request) { +func (h *handler) Get(w http.ResponseWriter, r *http.Request) { - request, err := decodeSCEPRequest(r) + req, err := decodeRequest(r) if err != nil { - writeError(w, errors.Wrap(err, "invalid scep get request")) + fail(w, fmt.Errorf("invalid scep get request: %w", err)) return } ctx := r.Context() - var response SCEPResponse + var res response - switch request.Operation { + switch req.Operation { case opnGetCACert: - response, err = h.GetCACert(ctx) + res, err = h.GetCACert(ctx) case opnGetCACaps: - response, err = h.GetCACaps(ctx) + res, err = h.GetCACaps(ctx) case opnPKIOperation: // TODO: implement the GET for PKI operation? Default CACAPS doesn't specify this is in use, though default: - err = errors.Errorf("unknown operation: %s", request.Operation) + err = fmt.Errorf("unknown operation: %s", req.Operation) } if err != nil { - writeError(w, errors.Wrap(err, "scep get request failed")) + fail(w, fmt.Errorf("scep get request failed: %w", err)) return } - writeSCEPResponse(w, response) + writeResponse(w, res) } // Post handles all SCEP POST requests -func (h *Handler) Post(w http.ResponseWriter, r *http.Request) { +func (h *handler) Post(w http.ResponseWriter, r *http.Request) { - request, err := decodeSCEPRequest(r) + req, err := decodeRequest(r) if err != nil { - writeError(w, errors.Wrap(err, "invalid scep post request")) + fail(w, fmt.Errorf("invalid scep post request: %w", err)) return } ctx := r.Context() - var response SCEPResponse + var res response - switch request.Operation { + switch req.Operation { case opnPKIOperation: - response, err = h.PKIOperation(ctx, request) + res, err = h.PKIOperation(ctx, req) default: - err = errors.Errorf("unknown operation: %s", request.Operation) + err = fmt.Errorf("unknown operation: %s", req.Operation) } if err != nil { - writeError(w, errors.Wrap(err, "scep post request failed")) + fail(w, fmt.Errorf("scep post request failed: %w", err)) return } - writeSCEPResponse(w, response) + writeResponse(w, res) } -func decodeSCEPRequest(r *http.Request) (SCEPRequest, error) { +func decodeRequest(r *http.Request) (request, error) { defer r.Body.Close() @@ -146,7 +145,7 @@ func decodeSCEPRequest(r *http.Request) (SCEPRequest, error) { case http.MethodGet: switch operation { case opnGetCACert, opnGetCACaps: - return SCEPRequest{ + return request{ Operation: operation, Message: []byte{}, }, nil @@ -158,50 +157,50 @@ func decodeSCEPRequest(r *http.Request) (SCEPRequest, error) { // TODO: verify this; it seems like it should be StdEncoding instead of URLEncoding decodedMessage, err := base64.URLEncoding.DecodeString(message) if err != nil { - return SCEPRequest{}, err + return request{}, err } - return SCEPRequest{ + return request{ Operation: operation, Message: decodedMessage, }, nil default: - return SCEPRequest{}, errors.Errorf("unsupported operation: %s", operation) + return request{}, fmt.Errorf("unsupported operation: %s", operation) } case http.MethodPost: body, err := io.ReadAll(io.LimitReader(r.Body, maxPayloadSize)) if err != nil { - return SCEPRequest{}, err + return request{}, err } - return SCEPRequest{ + return request{ Operation: operation, Message: body, }, nil default: - return SCEPRequest{}, errors.Errorf("unsupported method: %s", method) + return request{}, fmt.Errorf("unsupported method: %s", method) } } // lookupProvisioner loads the provisioner associated with the request. // Responds 404 if the provisioner does not exist. -func (h *Handler) lookupProvisioner(next nextHTTP) nextHTTP { +func (h *handler) lookupProvisioner(next http.HandlerFunc) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { name := chi.URLParam(r, "provisionerName") provisionerName, err := url.PathUnescape(name) if err != nil { - api.WriteError(w, errors.Errorf("error url unescaping provisioner name '%s'", name)) + fail(w, fmt.Errorf("error url unescaping provisioner name '%s'", name)) return } p, err := h.Auth.LoadProvisionerByName(provisionerName) if err != nil { - api.WriteError(w, err) + fail(w, err) return } prov, ok := p.(*provisioner.SCEP) if !ok { - api.WriteError(w, errors.New("provisioner must be of type SCEP")) + fail(w, errors.New("provisioner must be of type SCEP")) return } @@ -212,59 +211,59 @@ func (h *Handler) lookupProvisioner(next nextHTTP) nextHTTP { } // GetCACert returns the CA certificates in a SCEP response -func (h *Handler) GetCACert(ctx context.Context) (SCEPResponse, error) { +func (h *handler) GetCACert(ctx context.Context) (response, error) { certs, err := h.Auth.GetCACertificates(ctx) if err != nil { - return SCEPResponse{}, err + return response{}, err } if len(certs) == 0 { - return SCEPResponse{}, errors.New("missing CA cert") + return response{}, errors.New("missing CA cert") } - response := SCEPResponse{ + res := response{ Operation: opnGetCACert, CACertNum: len(certs), } if len(certs) == 1 { - response.Data = certs[0].Raw + res.Data = certs[0].Raw } else { // create degenerate pkcs7 certificate structure, according to // https://tools.ietf.org/html/rfc8894#section-4.2.1.2, because // not signed or encrypted data has to be returned. data, err := microscep.DegenerateCertificates(certs) if err != nil { - return SCEPResponse{}, err + return response{}, err } - response.Data = data + res.Data = data } - return response, nil + return res, nil } // GetCACaps returns the CA capabilities in a SCEP response -func (h *Handler) GetCACaps(ctx context.Context) (SCEPResponse, error) { +func (h *handler) GetCACaps(ctx context.Context) (response, error) { caps := h.Auth.GetCACaps(ctx) - response := SCEPResponse{ + res := response{ Operation: opnGetCACaps, Data: formatCapabilities(caps), } - return response, nil + return res, nil } // PKIOperation performs PKI operations and returns a SCEP response -func (h *Handler) PKIOperation(ctx context.Context, request SCEPRequest) (SCEPResponse, error) { +func (h *handler) PKIOperation(ctx context.Context, req request) (response, error) { // parse the message using microscep implementation - microMsg, err := microscep.ParsePKIMessage(request.Message) + microMsg, err := microscep.ParsePKIMessage(req.Message) if err != nil { // return the error, because we can't use the msg for creating a CertRep - return SCEPResponse{}, err + return response{}, err } // this is essentially doing the same as microscep.ParsePKIMessage, but @@ -272,7 +271,7 @@ func (h *Handler) PKIOperation(ctx context.Context, request SCEPRequest) (SCEPRe // wrapper for the microscep implementation. p7, err := pkcs7.Parse(microMsg.Raw) if err != nil { - return SCEPResponse{}, err + return response{}, err } // copy over properties to our internal PKIMessage @@ -285,7 +284,7 @@ func (h *Handler) PKIOperation(ctx context.Context, request SCEPRequest) (SCEPRe } if err := h.Auth.DecryptPKIEnvelope(ctx, msg); err != nil { - return SCEPResponse{}, err + return response{}, err } // NOTE: at this point we have sufficient information for returning nicely signed CertReps @@ -317,61 +316,56 @@ func (h *Handler) PKIOperation(ctx context.Context, request SCEPRequest) (SCEPRe certRep, err := h.Auth.SignCSR(ctx, csr, msg) if err != nil { - return h.createFailureResponse(ctx, csr, msg, microscep.BadRequest, errors.Wrap(err, "error when signing new certificate")) + return h.createFailureResponse(ctx, csr, msg, microscep.BadRequest, fmt.Errorf("error when signing new certificate: %w", err)) } - response := SCEPResponse{ + res := response{ Operation: opnPKIOperation, Data: certRep.Raw, Certificate: certRep.Certificate, } - return response, nil + return res, nil } func formatCapabilities(caps []string) []byte { return []byte(strings.Join(caps, "\r\n")) } -// writeSCEPResponse writes a SCEP response back to the SCEP client. -func writeSCEPResponse(w http.ResponseWriter, response SCEPResponse) { +// writeResponse writes a SCEP response back to the SCEP client. +func writeResponse(w http.ResponseWriter, res response) { - if response.Error != nil { - log.Error(w, response.Error) + if res.Error != nil { + log.Error(w, res.Error) } - if response.Certificate != nil { - api.LogCertificate(w, response.Certificate) + if res.Certificate != nil { + api.LogCertificate(w, res.Certificate) } - w.Header().Set("Content-Type", contentHeader(response)) - _, err := w.Write(response.Data) - if err != nil { - writeError(w, errors.Wrap(err, "error when writing scep response")) // This could end up as an error again - } + w.Header().Set("Content-Type", contentHeader(res)) + _, _ = w.Write(res.Data) } -func writeError(w http.ResponseWriter, err error) { - scepError := &scep.Error{ - Message: err.Error(), - Status: http.StatusInternalServerError, // TODO: make this a param? - } - api.WriteError(w, scepError) +func fail(w http.ResponseWriter, err error) { + log.Error(w, err) + + http.Error(w, err.Error(), http.StatusInternalServerError) } -func (h *Handler) createFailureResponse(ctx context.Context, csr *x509.CertificateRequest, msg *scep.PKIMessage, info microscep.FailInfo, failError error) (SCEPResponse, error) { +func (h *handler) createFailureResponse(ctx context.Context, csr *x509.CertificateRequest, msg *scep.PKIMessage, info microscep.FailInfo, failError error) (response, error) { certRepMsg, err := h.Auth.CreateFailureResponse(ctx, csr, msg, scep.FailInfoName(info), failError.Error()) if err != nil { - return SCEPResponse{}, err + return response{}, err } - return SCEPResponse{ + return response{ Operation: opnPKIOperation, Data: certRepMsg.Raw, Error: failError, }, nil } -func contentHeader(r SCEPResponse) string { +func contentHeader(r response) string { switch r.Operation { case opnGetCACert: if r.CACertNum > 1 { diff --git a/scep/errors.go b/scep/errors.go deleted file mode 100644 index 4287403b..00000000 --- a/scep/errors.go +++ /dev/null @@ -1,12 +0,0 @@ -package scep - -// Error is an SCEP error type -type Error struct { - Message string `json:"message"` - Status int `json:"-"` -} - -// Error implements the error interface. -func (e *Error) Error() string { - return e.Message -} From a8522237172c4337076a4d1354a5ea94c0d09d47 Mon Sep 17 00:00:00 2001 From: Panagiotis Siatras Date: Thu, 24 Mar 2022 17:08:23 +0200 Subject: [PATCH 13/21] scep: remove Interface and the dependency to pkg/errors (#872) * scep: documented the package * scep/api: removed some top level constants * scep: removed dependency to pkg/errors * scep/api: documented the package --- scep/api/api.go | 45 +++++++++++++++++++++------------------------ scep/authority.go | 40 +++++++++++++--------------------------- scep/scep.go | 4 +--- 3 files changed, 35 insertions(+), 54 deletions(-) diff --git a/scep/api/api.go b/scep/api/api.go index 91d337fe..31f0f10d 100644 --- a/scep/api/api.go +++ b/scep/api/api.go @@ -1,3 +1,4 @@ +// Package api implements a SCEP HTTP server. package api import ( @@ -31,12 +32,6 @@ const ( const maxPayloadSize = 2 << 20 -const ( - certChainHeader = "application/x-x509-ca-ra-cert" - leafHeader = "application/x-x509-ca-cert" - pkiOperationHeader = "application/x-pki-message" -) - // request is a SCEP server request. type request struct { Operation string @@ -54,17 +49,19 @@ type response struct { // handler is the SCEP request handler. type handler struct { - Auth scep.Interface + auth *scep.Authority } // New returns a new SCEP API router. -func New(scepAuth scep.Interface) api.RouterHandler { - return &handler{scepAuth} +func New(auth *scep.Authority) api.RouterHandler { + return &handler{ + auth: auth, + } } // Route traffic and implement the Router interface. func (h *handler) Route(r api.Router) { - getLink := h.Auth.GetLinkExplicit + getLink := h.auth.GetLinkExplicit r.MethodFunc(http.MethodGet, getLink("{provisionerName}/*", false, nil), h.lookupProvisioner(h.Get)) r.MethodFunc(http.MethodGet, getLink("{provisionerName}", false, nil), h.lookupProvisioner(h.Get)) r.MethodFunc(http.MethodPost, getLink("{provisionerName}/*", false, nil), h.lookupProvisioner(h.Post)) @@ -192,7 +189,7 @@ func (h *handler) lookupProvisioner(next http.HandlerFunc) http.HandlerFunc { return } - p, err := h.Auth.LoadProvisionerByName(provisionerName) + p, err := h.auth.LoadProvisionerByName(provisionerName) if err != nil { fail(w, err) return @@ -213,7 +210,7 @@ func (h *handler) lookupProvisioner(next http.HandlerFunc) http.HandlerFunc { // GetCACert returns the CA certificates in a SCEP response func (h *handler) GetCACert(ctx context.Context) (response, error) { - certs, err := h.Auth.GetCACertificates(ctx) + certs, err := h.auth.GetCACertificates(ctx) if err != nil { return response{}, err } @@ -246,7 +243,7 @@ func (h *handler) GetCACert(ctx context.Context) (response, error) { // GetCACaps returns the CA capabilities in a SCEP response func (h *handler) GetCACaps(ctx context.Context) (response, error) { - caps := h.Auth.GetCACaps(ctx) + caps := h.auth.GetCACaps(ctx) res := response{ Operation: opnGetCACaps, @@ -283,7 +280,7 @@ func (h *handler) PKIOperation(ctx context.Context, req request) (response, erro P7: p7, } - if err := h.Auth.DecryptPKIEnvelope(ctx, msg); err != nil { + if err := h.auth.DecryptPKIEnvelope(ctx, msg); err != nil { return response{}, err } @@ -296,7 +293,7 @@ func (h *handler) PKIOperation(ctx context.Context, req request) (response, erro // a certificate exists; then it will use RenewalReq. Adding the challenge check here may be a small breaking change for clients. // We'll have to see how it works out. if msg.MessageType == microscep.PKCSReq || msg.MessageType == microscep.RenewalReq { - challengeMatches, err := h.Auth.MatchChallengePassword(ctx, msg.CSRReqMessage.ChallengePassword) + challengeMatches, err := h.auth.MatchChallengePassword(ctx, msg.CSRReqMessage.ChallengePassword) if err != nil { return h.createFailureResponse(ctx, csr, msg, microscep.BadRequest, errors.New("error when checking password")) } @@ -314,7 +311,7 @@ func (h *handler) PKIOperation(ctx context.Context, req request) (response, erro // Authentication by the (self-signed) certificate with an optional challenge is required; supporting renewals incl. verification // of the client cert is not. - certRep, err := h.Auth.SignCSR(ctx, csr, msg) + certRep, err := h.auth.SignCSR(ctx, csr, msg) if err != nil { return h.createFailureResponse(ctx, csr, msg, microscep.BadRequest, fmt.Errorf("error when signing new certificate: %w", err)) } @@ -354,7 +351,7 @@ func fail(w http.ResponseWriter, err error) { } func (h *handler) createFailureResponse(ctx context.Context, csr *x509.CertificateRequest, msg *scep.PKIMessage, info microscep.FailInfo, failError error) (response, error) { - certRepMsg, err := h.Auth.CreateFailureResponse(ctx, csr, msg, scep.FailInfoName(info), failError.Error()) + certRepMsg, err := h.auth.CreateFailureResponse(ctx, csr, msg, scep.FailInfoName(info), failError.Error()) if err != nil { return response{}, err } @@ -367,14 +364,14 @@ func (h *handler) createFailureResponse(ctx context.Context, csr *x509.Certifica func contentHeader(r response) string { switch r.Operation { - case opnGetCACert: - if r.CACertNum > 1 { - return certChainHeader - } - return leafHeader - case opnPKIOperation: - return pkiOperationHeader default: return "text/plain" + case opnGetCACert: + if r.CACertNum > 1 { + return "application/x-x509-ca-ra-cert" + } + return "application/x-x509-ca-cert" + case opnPKIOperation: + return "application/x-pki-message" } } diff --git a/scep/authority.go b/scep/authority.go index 269e3ae1..71f92152 100644 --- a/scep/authority.go +++ b/scep/authority.go @@ -4,33 +4,19 @@ import ( "context" "crypto/subtle" "crypto/x509" + "errors" + "fmt" "net/url" - "github.com/smallstep/certificates/authority/provisioner" - microx509util "github.com/micromdm/scep/v2/cryptoutil/x509util" microscep "github.com/micromdm/scep/v2/scep" - - "github.com/pkg/errors" - "go.mozilla.org/pkcs7" "go.step.sm/crypto/x509util" + + "github.com/smallstep/certificates/authority/provisioner" ) -// Interface is the SCEP authority interface. -type Interface interface { - LoadProvisionerByName(string) (provisioner.Interface, error) - GetLinkExplicit(provName string, absoluteLink bool, baseURL *url.URL, inputs ...string) string - - GetCACertificates(ctx context.Context) ([]*x509.Certificate, error) - DecryptPKIEnvelope(ctx context.Context, msg *PKIMessage) error - SignCSR(ctx context.Context, csr *x509.CertificateRequest, msg *PKIMessage) (*PKIMessage, error) - CreateFailureResponse(ctx context.Context, csr *x509.CertificateRequest, msg *PKIMessage, info FailInfoName, infoText string) (*PKIMessage, error) - MatchChallengePassword(ctx context.Context, password string) (bool, error) - GetCACaps(ctx context.Context) []string -} - // Authority is the layer that handles all SCEP interactions. type Authority struct { prefix string @@ -180,12 +166,12 @@ func (a *Authority) DecryptPKIEnvelope(ctx context.Context, msg *PKIMessage) err p7c, err := pkcs7.Parse(msg.P7.Content) if err != nil { - return errors.Wrap(err, "error parsing pkcs7 content") + return fmt.Errorf("error parsing pkcs7 content: %w", err) } envelope, err := p7c.Decrypt(a.intermediateCertificate, a.service.decrypter) if err != nil { - return errors.Wrap(err, "error decrypting encrypted pkcs7 content") + return fmt.Errorf("error decrypting encrypted pkcs7 content: %w", err) } msg.pkiEnvelope = envelope @@ -194,19 +180,19 @@ func (a *Authority) DecryptPKIEnvelope(ctx context.Context, msg *PKIMessage) err case microscep.CertRep: certs, err := microscep.CACerts(msg.pkiEnvelope) if err != nil { - return errors.Wrap(err, "error extracting CA certs from pkcs7 degenerate data") + return fmt.Errorf("error extracting CA certs from pkcs7 degenerate data: %w", err) } msg.CertRepMessage.Certificate = certs[0] return nil case microscep.PKCSReq, microscep.UpdateReq, microscep.RenewalReq: csr, err := x509.ParseCertificateRequest(msg.pkiEnvelope) if err != nil { - return errors.Wrap(err, "parse CSR from pkiEnvelope") + return fmt.Errorf("parse CSR from pkiEnvelope: %w", err) } // check for challengePassword cp, err := microx509util.ParseChallengePassword(msg.pkiEnvelope) if err != nil { - return errors.Wrap(err, "parse challenge password in pkiEnvelope") + return fmt.Errorf("parse challenge password in pkiEnvelope: %w", err) } msg.CSRReqMessage = µscep.CSRReqMessage{ RawDecrypted: msg.pkiEnvelope, @@ -215,7 +201,7 @@ func (a *Authority) DecryptPKIEnvelope(ctx context.Context, msg *PKIMessage) err } return nil case microscep.GetCRL, microscep.GetCert, microscep.CertPoll: - return errors.Errorf("not implemented") + return errors.New("not implemented") } return nil @@ -274,19 +260,19 @@ func (a *Authority) SignCSR(ctx context.Context, csr *x509.CertificateRequest, m ctx = provisioner.NewContextWithMethod(ctx, provisioner.SignMethod) signOps, err := p.AuthorizeSign(ctx, "") if err != nil { - return nil, errors.Wrap(err, "error retrieving authorization options from SCEP provisioner") + return nil, fmt.Errorf("error retrieving authorization options from SCEP provisioner: %w", err) } opts := provisioner.SignOptions{} templateOptions, err := provisioner.TemplateOptions(p.GetOptions(), data) if err != nil { - return nil, errors.Wrap(err, "error creating template options from SCEP provisioner") + return nil, fmt.Errorf("error creating template options from SCEP provisioner: %w", err) } signOps = append(signOps, templateOptions) certChain, err := a.signAuth.Sign(csr, opts, signOps...) if err != nil { - return nil, errors.Wrap(err, "error generating certificate for order") + return nil, fmt.Errorf("error generating certificate for order: %w", err) } // take the issued certificate (only); https://tools.ietf.org/html/rfc8894#section-3.3.2 diff --git a/scep/scep.go b/scep/scep.go index afabf368..372a5436 100644 --- a/scep/scep.go +++ b/scep/scep.go @@ -1,3 +1,4 @@ +// Package scep implements Simple Certificate Enrollment Protocol related functionality. package scep import ( @@ -5,9 +6,6 @@ import ( "encoding/asn1" microscep "github.com/micromdm/scep/v2/scep" - - //"github.com/smallstep/certificates/scep/pkcs7" - "go.mozilla.org/pkcs7" ) From 27c1d0afc33c5036ca2543454ea0ffaad58ed654 Mon Sep 17 00:00:00 2001 From: Panagiotis Siatras Date: Thu, 24 Mar 2022 18:18:51 +0200 Subject: [PATCH 14/21] add --context flag to step-ca command (#851) * added the --context flag * apply the context and allow for different ca.json * amended usage for consistency * added an extra example * added an extra example * reordered and reworded examples --- cmd/step-ca/main.go | 24 ++++++++++++++++++++++-- commands/app.go | 28 +++++++++++++++++++++------- 2 files changed, 43 insertions(+), 9 deletions(-) diff --git a/cmd/step-ca/main.go b/cmd/step-ca/main.go index fba5b792..96e7fbd5 100644 --- a/cmd/step-ca/main.go +++ b/cmd/step-ca/main.go @@ -117,7 +117,7 @@ func main() { app.HelpName = "step-ca" app.Version = step.Version() app.Usage = "an online certificate authority for secure automated certificate management" - app.UsageText = `**step-ca** [**--password-file**=] + app.UsageText = `**step-ca** [config] [**--context**=] [**--password-file**=] [**--ssh-host-password-file**=] [**--ssh-user-password-file**=] [**--issuer-password-file**=] [**--resolver**=] [**--help**] [**--version**]` app.Description = `**step-ca** runs the Step Online Certificate Authority @@ -133,6 +133,7 @@ This command will run indefinitely on success and return \>0 if any error occurs These examples assume that you have already initialized your PKI by running 'step ca init'. If you have not completed this step please see the 'Getting Started' section of the README. + Run the Step CA and prompt for password: ''' $ step-ca $STEPPATH/config/ca.json @@ -141,7 +142,26 @@ Run the Step CA and read the password from a file - this is useful for automating deployment: ''' $ step-ca $STEPPATH/config/ca.json --password-file ./password.txt -'''` +''' +Run the Step CA for the context selected with step and a custom password file: +''' +$ step context select ssh +$ step-ca --password-file ./password.txt +''' +Run the Step CA for the context named _mybiz_ and prompt for password: +''' +$ step-ca --context=mybiz +''' +Run the Step CA for the context named _mybiz_ and an alternate ca.json file: +''' +$ step-ca --context=mybiz other-ca.json +''' +Run the Step CA for the context named _mybiz_ and read the password from a file - this is useful for +automating deployment: +''' +$ step-ca --context=mybiz --password-file ./password.txt +''' +` app.Flags = append(app.Flags, commands.AppCommand.Flags...) app.Flags = append(app.Flags, cli.HelpFlag) app.Copyright = fmt.Sprintf("(c) 2018-%d Smallstep Labs, Inc.", time.Now().Year()) diff --git a/commands/app.go b/commands/app.go index 8c40de0e..fc9cd15b 100644 --- a/commands/app.go +++ b/commands/app.go @@ -16,6 +16,7 @@ import ( "github.com/smallstep/certificates/pki" "github.com/urfave/cli" "go.step.sm/cli-utils/errs" + "go.step.sm/cli-utils/step" ) // AppCommand is the action used as the top action. @@ -57,6 +58,11 @@ certificate issuer private key used in the RA mode.`, Usage: "token used to enable the linked ca.", EnvVar: "STEP_CA_TOKEN", }, + cli.StringFlag{ + Name: "context", + Usage: "The name of the authority's context.", + EnvVar: "STEP_CA_CONTEXT", + }, }, } @@ -69,15 +75,23 @@ func appAction(ctx *cli.Context) error { resolver := ctx.String("resolver") token := ctx.String("token") - // If zero cmd line args show help, if >1 cmd line args show error. - if ctx.NArg() == 0 { - return cli.ShowAppHelp(ctx) - } - if err := errs.NumberOfArguments(ctx, 1); err != nil { - return err + if ctx.NArg() > 1 { + return errs.TooManyArguments(ctx) + } + + if caCtx := ctx.String("context"); caCtx != "" { + if err := step.Contexts().SetCurrent(caCtx); err != nil { + return err + } + } + + var configFile string + if ctx.NArg() > 0 { + configFile = ctx.Args().Get(0) + } else { + configFile = step.CaConfigFile() } - configFile := ctx.Args().Get(0) cfg, err := config.LoadConfiguration(configFile) if err != nil { fatal(err) From 750e9ee2f86813f772167830994fd3228a8b1e63 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Wed, 23 Mar 2022 19:14:28 -0700 Subject: [PATCH 15/21] Attempt to fix TestBootstrapClientServerRotation This change attempts to fix the test TestBootstrapClientServerRotation. Due to the backdate, the renew options get too large, causing continuous renewals, and random errors. After experimenting with different options, truncating durations to seconds have shown better results than rounding or just use the plain time. --- ca/renew.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/ca/renew.go b/ca/renew.go index 915be787..27898993 100644 --- a/ca/renew.go +++ b/ca/renew.go @@ -60,7 +60,10 @@ func NewTLSRenewer(cert *tls.Certificate, fn RenewFunc, opts ...tlsRenewerOption } } - period := cert.Leaf.NotAfter.Sub(cert.Leaf.NotBefore) + // Use the current time to calculate the initial period. Using a notBefore + // in the past might set a renewBefore too large, causing continuous + // renewals due to the negative values in nextRenewDuration. + period := cert.Leaf.NotAfter.Sub(time.Now().Truncate(time.Second)) if period < minCertDuration { return nil, errors.Errorf("period must be greater than or equal to %s, but got %v.", minCertDuration, period) } @@ -181,7 +184,7 @@ func (r *TLSRenewer) renewCertificate() { } func (r *TLSRenewer) nextRenewDuration(notAfter time.Time) time.Duration { - d := time.Until(notAfter) - r.renewBefore + d := time.Until(notAfter).Truncate(time.Second) - r.renewBefore n := rand.Int63n(int64(r.renewJitter)) d -= time.Duration(n) if d < 0 { From 52d7f084d2917cf4f2a6839496e7726debb9ddab Mon Sep 17 00:00:00 2001 From: Andrew Reed Date: Mon, 28 Mar 2022 09:18:18 -0500 Subject: [PATCH 16/21] Add /roots.pem handler (#866) * Add /roots.pem handler * Review changes * Remove no peer cert test case --- api/api.go | 25 +++++++++++++++++++++++++ api/api_test.go | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/api/api.go b/api/api.go index 47d2fd27..1c47c03d 100644 --- a/api/api.go +++ b/api/api.go @@ -21,6 +21,7 @@ import ( "github.com/go-chi/chi" "github.com/pkg/errors" + "github.com/smallstep/certificates/api/log" "github.com/smallstep/certificates/authority" "github.com/smallstep/certificates/authority/config" "github.com/smallstep/certificates/authority/provisioner" @@ -259,6 +260,7 @@ func (h *caHandler) Route(r Router) { r.MethodFunc("GET", "/provisioners", h.Provisioners) r.MethodFunc("GET", "/provisioners/{kid}/encrypted-key", h.ProvisionerKey) r.MethodFunc("GET", "/roots", h.Roots) + r.MethodFunc("GET", "/roots.pem", h.RootsPEM) r.MethodFunc("GET", "/federation", h.Federation) // SSH CA r.MethodFunc("POST", "/ssh/sign", h.SSHSign) @@ -364,6 +366,29 @@ func (h *caHandler) Roots(w http.ResponseWriter, r *http.Request) { }, http.StatusCreated) } +// RootsPEM returns all the root certificates for the CA in PEM format. +func (h *caHandler) RootsPEM(w http.ResponseWriter, r *http.Request) { + roots, err := h.Authority.GetRoots() + if err != nil { + WriteError(w, errs.InternalServerErr(err)) + return + } + + w.Header().Set("Content-Type", "application/x-pem-file") + + for _, root := range roots { + block := pem.EncodeToMemory(&pem.Block{ + Type: "CERTIFICATE", + Bytes: root.Raw, + }) + + if _, err := w.Write(block); err != nil { + log.Error(w, err) + return + } + } +} + // Federation returns all the public certificates in the federation. func (h *caHandler) Federation(w http.ResponseWriter, r *http.Request) { federated, err := h.Authority.GetFederation() diff --git a/api/api_test.go b/api/api_test.go index 25abdeff..39c77de7 100644 --- a/api/api_test.go +++ b/api/api_test.go @@ -1344,6 +1344,46 @@ func Test_caHandler_Roots(t *testing.T) { } } +func Test_caHandler_RootsPEM(t *testing.T) { + parsedRoot := parseCertificate(rootPEM) + tests := []struct { + name string + roots []*x509.Certificate + err error + statusCode int + expect string + }{ + {"one root", []*x509.Certificate{parsedRoot}, nil, http.StatusOK, rootPEM}, + {"two roots", []*x509.Certificate{parsedRoot, parsedRoot}, nil, http.StatusOK, rootPEM + "\n" + rootPEM}, + {"fail", nil, errors.New("an error"), http.StatusInternalServerError, ""}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + h := New(&mockAuthority{ret1: tt.roots, err: tt.err}).(*caHandler) + req := httptest.NewRequest("GET", "https://example.com/roots", nil) + w := httptest.NewRecorder() + h.RootsPEM(w, req) + res := w.Result() + + if res.StatusCode != tt.statusCode { + t.Errorf("caHandler.RootsPEM StatusCode = %d, wants %d", res.StatusCode, tt.statusCode) + } + + body, err := io.ReadAll(res.Body) + res.Body.Close() + if err != nil { + t.Errorf("caHandler.RootsPEM unexpected error = %v", err) + } + if tt.statusCode < http.StatusBadRequest { + if !bytes.Equal(bytes.TrimSpace(body), []byte(tt.expect)) { + t.Errorf("caHandler.RootsPEM Body = %s, wants %s", body, tt.expect) + } + } + }) + } +} + func Test_caHandler_Federation(t *testing.T) { cs := &tls.ConnectionState{ PeerCertificates: []*x509.Certificate{parseCertificate(certPEM)}, From 4cde2696e5bd90a350f65878581a400e4caf7bb4 Mon Sep 17 00:00:00 2001 From: Herman Slatman Date: Sun, 27 Mar 2022 21:40:01 +0200 Subject: [PATCH 17/21] Update cloud.google.com/go/kms --- go.mod | 17 +++++----- go.sum | 101 +++++++++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 97 insertions(+), 21 deletions(-) diff --git a/go.mod b/go.mod index aad8e124..8f8c3143 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,9 @@ module github.com/smallstep/certificates go 1.16 require ( - cloud.google.com/go v0.83.0 + cloud.google.com/go v0.100.2 + cloud.google.com/go/kms v1.4.0 + cloud.google.com/go/security v1.3.0 github.com/Azure/azure-sdk-for-go v58.0.0+incompatible github.com/Azure/go-autorest/autorest v0.11.17 github.com/Azure/go-autorest/autorest/azure/auth v0.5.8 @@ -18,9 +20,9 @@ require ( github.com/go-kit/kit v0.10.0 // indirect github.com/go-piv/piv-go v1.7.0 github.com/golang/mock v1.6.0 - github.com/google/go-cmp v0.5.6 + github.com/google/go-cmp v0.5.7 github.com/google/uuid v1.3.0 - github.com/googleapis/gax-go/v2 v2.0.5 + github.com/googleapis/gax-go/v2 v2.1.1 github.com/mattn/go-colorable v0.1.8 // indirect github.com/mattn/go-isatty v0.0.13 // indirect github.com/micromdm/scep/v2 v2.1.0 @@ -37,11 +39,10 @@ require ( go.step.sm/crypto v0.15.3 go.step.sm/linkedca v0.11.0 golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 - golang.org/x/net v0.0.0-20220114011407-0dd24b26b47d - golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 // indirect - google.golang.org/api v0.47.0 - google.golang.org/genproto v0.0.0-20220118154757-00ab72f36ad5 - google.golang.org/grpc v1.43.0 + golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd + google.golang.org/api v0.70.0 + google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf + google.golang.org/grpc v1.44.0 google.golang.org/protobuf v1.27.1 gopkg.in/square/go-jose.v2 v2.6.0 ) diff --git a/go.sum b/go.sum index f124df98..47f84801 100644 --- a/go.sum +++ b/go.sum @@ -18,20 +18,38 @@ cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmW cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= -cloud.google.com/go v0.83.0 h1:bAMqZidYkmIsUqe6PtkEPT7Q+vfizScn+jfNA6jwK9c= cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY= +cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM= +cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY= +cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ= +cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= +cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4= +cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= +cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA= +cloud.google.com/go v0.100.1/go.mod h1:fs4QogzfH5n2pBXBP9vRiU+eCny7lD2vmFZy79Iuw1U= +cloud.google.com/go v0.100.2 h1:t9Iw5QH5v4XtlEQaCtUY7x6sCABps8sW0acw7e2WQ6Y= +cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow= +cloud.google.com/go/compute v1.3.0 h1:mPL/MzDDYHsh5tHRS9mhmhWlcgClCrCa6ApQCU6wnHI= +cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/iam v0.1.0 h1:W2vbGCrE3Z7J/x3WXLxxGl9LMSB2uhsAA7Ss/6u/qRY= +cloud.google.com/go/iam v0.1.0/go.mod h1:vcUNEa0pEm0qRVpmWepWaFMIAI8/hjB9mO8rNCJtF6c= +cloud.google.com/go/kms v1.4.0 h1:iElbfoE61VeLhnZcGOltqL8HIly8Nhbe5t6JlH9GXjo= +cloud.google.com/go/kms v1.4.0/go.mod h1:fajBHndQ+6ubNw6Ss2sSd+SWvjL26RNo/dr7uxsnnOA= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/security v1.3.0 h1:BhCl33x+KQI4qiZnFrfr2gAGhb2aZ0ZvKB3Y4QlEfgo= +cloud.google.com/go/security v1.3.0/go.mod h1:pQsnLAXfMzuWVJdctBs8BV3tGd3Jr0SMYu6KK3QXYAs= cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= @@ -294,8 +312,9 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= +github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= @@ -314,6 +333,8 @@ github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -321,8 +342,10 @@ github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+ github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= +github.com/googleapis/gax-go/v2 v2.1.1 h1:dp3bWCh+PPO1zjRRiCSczJav13sBvG4UhNyVTa1KqdU= +github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/context v0.0.0-20160226214623-1ea25387ff6f/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= @@ -804,8 +827,8 @@ golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20211020060615-d418f374d309/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220114011407-0dd24b26b47d h1:1n1fc535VhN8SYtD4cDUyNlfpAF2ROMM9+11equK3hs= -golang.org/x/net v0.0.0-20220114011407-0dd24b26b47d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd h1:O7DYs+zxREGLKzKoMQrtrEacpb0ZVXA5rIwylE2Xchk= +golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -817,8 +840,12 @@ golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c h1:pkQiBZBvdos9qq4wBAHqlzuZHEXo07pqV06ef90u1WI= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 h1:RerP+noqYHUQ8CMRcPlC2nvTa4dcBIjegkuWdcUDuqg= +golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -897,14 +924,24 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +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-20210915083310-ed5796bab164/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211031064116-611d5d643895/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 h1:XfKQ4OlFl8okEOr5UvAqFRVj8pY/4yfcXrddB8qAbU0= -golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220209214540-3681064d5158 h1:rm+CHSpPEEW2IsXUib1ThaHIjuBVZjxNgSKmBLFfD4c= +golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= @@ -982,6 +1019,9 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= 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= @@ -1014,8 +1054,19 @@ google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34q google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= -google.golang.org/api v0.47.0 h1:sQLWZQvP6jPGIP4JGPkJu4zHswrv81iobiyszr3b/0I= google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= +google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= +google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= +google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU= +google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k= +google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= +google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= +google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI= +google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I= +google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo= +google.golang.org/api v0.67.0/go.mod h1:ShHKP8E60yPsKNw/w8w+VYaj9H6buA5UqDp8dhbQZ6g= +google.golang.org/api v0.70.0 h1:67zQnAE0T2rB0A3CwLSas0K+SbVzSxP+zTLkQLexeiw= +google.golang.org/api v0.70.0/go.mod h1:Bs4ZM2HGifEvXwd50TtW70ovgJffJYw2oRCOFU/SkfA= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -1068,8 +1119,29 @@ google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20220118154757-00ab72f36ad5 h1:zzNejm+EgrbLfDZ6lu9Uud2IVvHySPl8vQzf04laR5Q= -google.golang.org/genproto v0.0.0-20220118154757-00ab72f36ad5/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= +google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= +google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= +google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= +google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= +google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w= +google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211221195035-429b39de9b1c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220207164111-0872dc986b00/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf h1:SVYXkUz2yZS9FWb2Gm8ivSlbNQzL2Z/NpPKE3RG2jWk= +google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= @@ -1097,9 +1169,12 @@ google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAG google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= +google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.43.0 h1:Eeu7bZtDZ2DpRCsLhUlcrLnvYaMK1Gz86a+hMVvELmM= -google.golang.org/grpc v1.43.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= +google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc v1.44.0 h1:weqSxi/TMs1SqFRMHCtBgXRs8k3X39QIDEZ0pRcttUg= +google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= From 580a9c14762aab8adde8433441d04e282f4abc74 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Wed, 23 Mar 2022 14:56:39 -0700 Subject: [PATCH 18/21] Get linked RA configuration using the linked ca client. --- authority/authority.go | 48 ++++++++++++++++++++++++++++++------------ authority/linkedca.go | 18 ++++++++++------ 2 files changed, 46 insertions(+), 20 deletions(-) diff --git a/authority/authority.go b/authority/authority.go index cc26635e..1aac594a 100644 --- a/authority/authority.go +++ b/authority/authority.go @@ -253,6 +253,21 @@ func (a *Authority) init() error { } } + // Initialize linkedca client if necessary. On a linked RA, the issuer + // configuration might come from majordomo. + var linkedcaClient *linkedCaClient + if a.config.AuthorityConfig.EnableAdmin && a.linkedCAToken != "" && a.adminDB == nil { + linkedcaClient, err = newLinkedCAClient(a.linkedCAToken) + if err != nil { + return err + } + // If authorityId is configured make sure it matches the one in the token + if id := a.config.AuthorityConfig.AuthorityID; id != "" && !strings.EqualFold(id, linkedcaClient.authorityID) { + return errors.New("error initializing linkedca: token authority and configured authority do not match") + } + linkedcaClient.Run() + } + // Initialize the X.509 CA Service if it has not been set in the options. if a.x509CAService == nil { var options casapi.Options @@ -260,6 +275,22 @@ func (a *Authority) init() error { options = *a.config.AuthorityConfig.Options } + // Configure linked RA + if linkedcaClient != nil && options.CertificateAuthority == "" { + conf, err := linkedcaClient.GetConfiguration(context.Background()) + if err != nil { + return err + } + if conf.RaConfig != nil { + options.CertificateAuthority = conf.RaConfig.CaUrl + options.CertificateAuthorityFingerprint = conf.RaConfig.Fingerprint + options.CertificateIssuer = &casapi.CertificateIssuer{ + Type: conf.RaConfig.Provisioner.Type.String(), + Provisioner: conf.RaConfig.Provisioner.Name, + } + } + } + // Set the issuer password if passed in the flags. if options.CertificateIssuer != nil && a.issuerPassword != nil { options.CertificateIssuer.Password = string(a.issuerPassword) @@ -481,24 +512,13 @@ func (a *Authority) init() error { // Initialize step-ca Admin Database if it's not already initialized using // WithAdminDB. if a.adminDB == nil { - if a.linkedCAToken == "" { - // Check if AuthConfig already exists + if linkedcaClient != nil { + a.adminDB = linkedcaClient + } else { a.adminDB, err = adminDBNosql.New(a.db.(nosql.DB), admin.DefaultAuthorityID) if err != nil { return err } - } else { - // Use the linkedca client as the admindb. - client, err := newLinkedCAClient(a.linkedCAToken) - if err != nil { - return err - } - // If authorityId is configured make sure it matches the one in the token - if id := a.config.AuthorityConfig.AuthorityID; id != "" && !strings.EqualFold(id, client.authorityID) { - return errors.New("error initializing linkedca: token authority and configured authority do not match") - } - client.Run() - a.adminDB = client } } diff --git a/authority/linkedca.go b/authority/linkedca.go index 00d5ceef..6a0800c2 100644 --- a/authority/linkedca.go +++ b/authority/linkedca.go @@ -152,13 +152,21 @@ func (c *linkedCaClient) GetProvisioner(ctx context.Context, id string) (*linked } func (c *linkedCaClient) GetProvisioners(ctx context.Context) ([]*linkedca.Provisioner, error) { + resp, err := c.GetConfiguration(ctx) + if err != nil { + return nil, err + } + return resp.Provisioners, nil +} + +func (c *linkedCaClient) GetConfiguration(ctx context.Context) (*linkedca.ConfigurationResponse, error) { resp, err := c.client.GetConfiguration(ctx, &linkedca.ConfigurationRequest{ AuthorityId: c.authorityID, }) if err != nil { - return nil, errors.Wrap(err, "error getting provisioners") + return nil, errors.Wrap(err, "error getting configuration") } - return resp.Provisioners, nil + return resp, nil } func (c *linkedCaClient) UpdateProvisioner(ctx context.Context, prov *linkedca.Provisioner) error { @@ -205,11 +213,9 @@ func (c *linkedCaClient) GetAdmin(ctx context.Context, id string) (*linkedca.Adm } func (c *linkedCaClient) GetAdmins(ctx context.Context) ([]*linkedca.Admin, error) { - resp, err := c.client.GetConfiguration(ctx, &linkedca.ConfigurationRequest{ - AuthorityId: c.authorityID, - }) + resp, err := c.GetConfiguration(ctx) if err != nil { - return nil, errors.Wrap(err, "error getting admins") + return nil, err } return resp.Admins, nil } From 6851842841732cd8bf220bf82af09f240ff89335 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Mon, 28 Mar 2022 15:06:56 -0700 Subject: [PATCH 19/21] Fix unit tests. --- authority/authorize_test.go | 2 +- authority/provisioner/acme_test.go | 3 ++- authority/provisioner/aws_test.go | 11 ++++++----- authority/provisioner/azure_test.go | 11 ++++++----- authority/provisioner/gcp_test.go | 7 ++++--- authority/provisioner/jwk_test.go | 3 ++- authority/provisioner/k8sSA_test.go | 3 ++- authority/provisioner/noop_test.go | 2 +- authority/provisioner/oidc_test.go | 3 ++- authority/provisioner/x5c_test.go | 3 ++- 10 files changed, 28 insertions(+), 20 deletions(-) diff --git a/authority/authorize_test.go b/authority/authorize_test.go index b631741a..6a35c4e1 100644 --- a/authority/authorize_test.go +++ b/authority/authorize_test.go @@ -488,7 +488,7 @@ func TestAuthority_authorizeSign(t *testing.T) { } } else { if assert.Nil(t, tc.err) { - assert.Len(t, 7, got) + assert.Len(t, 8, got) } } }) diff --git a/authority/provisioner/acme_test.go b/authority/provisioner/acme_test.go index bc4e97e0..8ab29b26 100644 --- a/authority/provisioner/acme_test.go +++ b/authority/provisioner/acme_test.go @@ -175,9 +175,10 @@ func TestACME_AuthorizeSign(t *testing.T) { } } else { if assert.Nil(t, tc.err) && assert.NotNil(t, opts) { - assert.Len(t, 5, opts) + assert.Len(t, 6, opts) for _, o := range opts { switch v := o.(type) { + case *ACME: case *provisionerExtensionOption: assert.Equals(t, v.Type, TypeACME) assert.Equals(t, v.Name, tc.p.GetName()) diff --git a/authority/provisioner/aws_test.go b/authority/provisioner/aws_test.go index 559a48f1..f17ec231 100644 --- a/authority/provisioner/aws_test.go +++ b/authority/provisioner/aws_test.go @@ -641,11 +641,11 @@ func TestAWS_AuthorizeSign(t *testing.T) { code int wantErr bool }{ - {"ok", p1, args{t1, "foo.local"}, 6, http.StatusOK, false}, - {"ok", p2, args{t2, "instance-id"}, 10, http.StatusOK, false}, - {"ok", p2, args{t2Hostname, "ip-127-0-0-1.us-west-1.compute.internal"}, 10, http.StatusOK, false}, - {"ok", p2, args{t2PrivateIP, "127.0.0.1"}, 10, http.StatusOK, false}, - {"ok", p1, args{t4, "instance-id"}, 6, http.StatusOK, false}, + {"ok", p1, args{t1, "foo.local"}, 7, http.StatusOK, false}, + {"ok", p2, args{t2, "instance-id"}, 11, http.StatusOK, false}, + {"ok", p2, args{t2Hostname, "ip-127-0-0-1.us-west-1.compute.internal"}, 11, http.StatusOK, false}, + {"ok", p2, args{t2PrivateIP, "127.0.0.1"}, 11, http.StatusOK, false}, + {"ok", p1, args{t4, "instance-id"}, 7, http.StatusOK, false}, {"fail account", p3, args{token: t3}, 0, http.StatusUnauthorized, true}, {"fail token", p1, args{token: "token"}, 0, http.StatusUnauthorized, true}, {"fail subject", p1, args{token: failSubject}, 0, http.StatusUnauthorized, true}, @@ -675,6 +675,7 @@ func TestAWS_AuthorizeSign(t *testing.T) { assert.Len(t, tt.wantLen, got) for _, o := range got { switch v := o.(type) { + case *AWS: case certificateOptionsFunc: case *provisionerExtensionOption: assert.Equals(t, v.Type, TypeAWS) diff --git a/authority/provisioner/azure_test.go b/authority/provisioner/azure_test.go index 40bb4698..28de642c 100644 --- a/authority/provisioner/azure_test.go +++ b/authority/provisioner/azure_test.go @@ -473,11 +473,11 @@ func TestAzure_AuthorizeSign(t *testing.T) { code int wantErr bool }{ - {"ok", p1, args{t1}, 5, http.StatusOK, false}, - {"ok", p2, args{t2}, 10, http.StatusOK, false}, - {"ok", p1, args{t11}, 5, http.StatusOK, false}, - {"ok", p5, args{t5}, 5, http.StatusOK, false}, - {"ok", p7, args{t7}, 5, http.StatusOK, false}, + {"ok", p1, args{t1}, 6, http.StatusOK, false}, + {"ok", p2, args{t2}, 11, http.StatusOK, false}, + {"ok", p1, args{t11}, 6, http.StatusOK, false}, + {"ok", p5, args{t5}, 6, http.StatusOK, false}, + {"ok", p7, args{t7}, 6, http.StatusOK, false}, {"fail tenant", p3, args{t3}, 0, http.StatusUnauthorized, true}, {"fail resource group", p4, args{t4}, 0, http.StatusUnauthorized, true}, {"fail subscription", p6, args{t6}, 0, http.StatusUnauthorized, true}, @@ -504,6 +504,7 @@ func TestAzure_AuthorizeSign(t *testing.T) { assert.Len(t, tt.wantLen, got) for _, o := range got { switch v := o.(type) { + case *Azure: case certificateOptionsFunc: case *provisionerExtensionOption: assert.Equals(t, v.Type, TypeAzure) diff --git a/authority/provisioner/gcp_test.go b/authority/provisioner/gcp_test.go index b8c437c3..7d3bd073 100644 --- a/authority/provisioner/gcp_test.go +++ b/authority/provisioner/gcp_test.go @@ -515,9 +515,9 @@ func TestGCP_AuthorizeSign(t *testing.T) { code int wantErr bool }{ - {"ok", p1, args{t1}, 5, http.StatusOK, false}, - {"ok", p2, args{t2}, 10, http.StatusOK, false}, - {"ok", p3, args{t3}, 5, http.StatusOK, false}, + {"ok", p1, args{t1}, 6, http.StatusOK, false}, + {"ok", p2, args{t2}, 11, http.StatusOK, false}, + {"ok", p3, args{t3}, 6, http.StatusOK, false}, {"fail token", p1, args{"token"}, 0, http.StatusUnauthorized, true}, {"fail key", p1, args{failKey}, 0, http.StatusUnauthorized, true}, {"fail iss", p1, args{failIss}, 0, http.StatusUnauthorized, true}, @@ -547,6 +547,7 @@ func TestGCP_AuthorizeSign(t *testing.T) { assert.Len(t, tt.wantLen, got) for _, o := range got { switch v := o.(type) { + case *GCP: case certificateOptionsFunc: case *provisionerExtensionOption: assert.Equals(t, v.Type, TypeGCP) diff --git a/authority/provisioner/jwk_test.go b/authority/provisioner/jwk_test.go index dde2f836..f9000961 100644 --- a/authority/provisioner/jwk_test.go +++ b/authority/provisioner/jwk_test.go @@ -295,9 +295,10 @@ func TestJWK_AuthorizeSign(t *testing.T) { } } else { if assert.NotNil(t, got) { - assert.Len(t, 7, got) + assert.Len(t, 8, got) for _, o := range got { switch v := o.(type) { + case *JWK: case certificateOptionsFunc: case *provisionerExtensionOption: assert.Equals(t, v.Type, TypeJWK) diff --git a/authority/provisioner/k8sSA_test.go b/authority/provisioner/k8sSA_test.go index 378d4471..e6305f6e 100644 --- a/authority/provisioner/k8sSA_test.go +++ b/authority/provisioner/k8sSA_test.go @@ -281,6 +281,7 @@ func TestK8sSA_AuthorizeSign(t *testing.T) { tot := 0 for _, o := range opts { switch v := o.(type) { + case *K8sSA: case certificateOptionsFunc: case *provisionerExtensionOption: assert.Equals(t, v.Type, TypeK8sSA) @@ -298,7 +299,7 @@ func TestK8sSA_AuthorizeSign(t *testing.T) { } tot++ } - assert.Equals(t, tot, 5) + assert.Equals(t, tot, 6) } } } diff --git a/authority/provisioner/noop_test.go b/authority/provisioner/noop_test.go index 19e4d235..b10d1d29 100644 --- a/authority/provisioner/noop_test.go +++ b/authority/provisioner/noop_test.go @@ -24,6 +24,6 @@ func Test_noop(t *testing.T) { ctx := NewContextWithMethod(context.Background(), SignMethod) sigOptions, err := p.AuthorizeSign(ctx, "foo") - assert.Equals(t, []SignOption{}, sigOptions) + assert.Equals(t, []SignOption{&p}, sigOptions) assert.Equals(t, nil, err) } diff --git a/authority/provisioner/oidc_test.go b/authority/provisioner/oidc_test.go index c1a94b1d..bfa46027 100644 --- a/authority/provisioner/oidc_test.go +++ b/authority/provisioner/oidc_test.go @@ -322,9 +322,10 @@ func TestOIDC_AuthorizeSign(t *testing.T) { assert.Equals(t, sc.StatusCode(), tt.code) assert.Nil(t, got) } else if assert.NotNil(t, got) { - assert.Len(t, 5, got) + assert.Len(t, 6, got) for _, o := range got { switch v := o.(type) { + case *OIDC: case certificateOptionsFunc: case *provisionerExtensionOption: assert.Equals(t, v.Type, TypeOIDC) diff --git a/authority/provisioner/x5c_test.go b/authority/provisioner/x5c_test.go index 7932d045..91e789a1 100644 --- a/authority/provisioner/x5c_test.go +++ b/authority/provisioner/x5c_test.go @@ -466,9 +466,10 @@ func TestX5C_AuthorizeSign(t *testing.T) { } else { if assert.Nil(t, tc.err) { if assert.NotNil(t, opts) { - assert.Equals(t, len(opts), 7) + assert.Equals(t, len(opts), 8) for _, o := range opts { switch v := o.(type) { + case *X5C: case certificateOptionsFunc: case *provisionerExtensionOption: assert.Equals(t, v.Type, TypeX5C) From 0b388942e8a7cdc2ed1a530f007aeee77051f015 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Mon, 28 Mar 2022 18:23:36 -0700 Subject: [PATCH 20/21] Upgrade linkedca package. --- go.mod | 4 ++-- go.sum | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index 8f8c3143..16007f5b 100644 --- a/go.mod +++ b/go.mod @@ -37,7 +37,7 @@ require ( go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352 go.step.sm/cli-utils v0.7.0 go.step.sm/crypto v0.15.3 - go.step.sm/linkedca v0.11.0 + go.step.sm/linkedca v0.12.0 golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd google.golang.org/api v0.70.0 @@ -50,4 +50,4 @@ require ( // replace github.com/smallstep/nosql => ../nosql // replace go.step.sm/crypto => ../crypto // replace go.step.sm/cli-utils => ../cli-utils -replace go.step.sm/linkedca => ../linkedca +// replace go.step.sm/linkedca => ../linkedca diff --git a/go.sum b/go.sum index 47f84801..108cfec9 100644 --- a/go.sum +++ b/go.sum @@ -709,6 +709,8 @@ go.step.sm/cli-utils v0.7.0/go.mod h1:Ur6bqA/yl636kCUJbp30J7Unv5JJ226eW2KqXPDwF/ go.step.sm/crypto v0.9.0/go.mod h1:+CYG05Mek1YDqi5WK0ERc6cOpKly2i/a5aZmU1sfGj0= go.step.sm/crypto v0.15.3 h1:f3GMl+aCydt294BZRjTYwpaXRqwwndvoTY2NLN4wu10= go.step.sm/crypto v0.15.3/go.mod h1:3G0yQr5lQqfEG0CMYz8apC/qMtjLRQlzflL2AxkcN+g= +go.step.sm/linkedca v0.12.0 h1:FA18uJO5P6W2pklcezMs+w+N3dVbpKEE1LP9HLsJgg4= +go.step.sm/linkedca v0.12.0/go.mod h1:W59ucS4vFpuR0g4PtkGbbtXAwxbDEnNCg+ovkej1ANM= 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= From d4013f0df63820728f9a515eedeba5c984e20e34 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Thu, 7 Apr 2022 18:19:56 -0700 Subject: [PATCH 21/21] Update linkedca --- go.mod | 4 ++-- go.sum | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index 17ea33fe..01ea550b 100644 --- a/go.mod +++ b/go.mod @@ -33,12 +33,12 @@ require ( github.com/slackhq/nebula v1.5.2 github.com/smallstep/assert v0.0.0-20200723003110-82e2b9b3b262 github.com/smallstep/nosql v0.4.0 - github.com/stretchr/testify v1.7.0 + github.com/stretchr/testify v1.7.1 github.com/urfave/cli v1.22.4 go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352 go.step.sm/cli-utils v0.7.0 go.step.sm/crypto v0.16.1 - go.step.sm/linkedca v0.11.0 + go.step.sm/linkedca v0.12.0 golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd google.golang.org/api v0.70.0 diff --git a/go.sum b/go.sum index e7ddd660..42577048 100644 --- a/go.sum +++ b/go.sum @@ -664,8 +664,9 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/thales-e-security/pool v0.0.2 h1:RAPs4q2EbWsTit6tpzuvTFlgFRJ3S8Evf5gtvVDbmPg= github.com/thales-e-security/pool v0.0.2/go.mod h1:qtpMm2+thHtqhLzTwgDBj/OuNnMpupY8mv0Phz0gjhU= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= @@ -710,8 +711,8 @@ go.step.sm/cli-utils v0.7.0/go.mod h1:Ur6bqA/yl636kCUJbp30J7Unv5JJ226eW2KqXPDwF/ go.step.sm/crypto v0.9.0/go.mod h1:+CYG05Mek1YDqi5WK0ERc6cOpKly2i/a5aZmU1sfGj0= go.step.sm/crypto v0.16.1 h1:4mnZk21cSxyMGxsEpJwZKKvJvDu1PN09UVrWWFNUBdk= go.step.sm/crypto v0.16.1/go.mod h1:3G0yQr5lQqfEG0CMYz8apC/qMtjLRQlzflL2AxkcN+g= -go.step.sm/linkedca v0.11.0 h1:jkG5XDQz9VSz2PH+cGjDvJTwiIziN0SWExTnicWpb8o= -go.step.sm/linkedca v0.11.0/go.mod h1:5uTRjozEGSPAZal9xJqlaD38cvJcLe3o1VAFVjqcORo= +go.step.sm/linkedca v0.12.0 h1:FA18uJO5P6W2pklcezMs+w+N3dVbpKEE1LP9HLsJgg4= +go.step.sm/linkedca v0.12.0/go.mod h1:W59ucS4vFpuR0g4PtkGbbtXAwxbDEnNCg+ovkej1ANM= 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=