From 0369151bfad6d95e5efdc27040c7ea1408eacc52 Mon Sep 17 00:00:00 2001 From: Joe Julian Date: Tue, 27 Apr 2021 08:18:35 -0700 Subject: [PATCH 001/195] use InsecureSkipVerify for validation The server will not yet have a valid certificate so we need to disable certificate validation in the HTTPGetter. --- acme/api/handler.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/acme/api/handler.go b/acme/api/handler.go index 2a6d3a02..b05bd0c4 100644 --- a/acme/api/handler.go +++ b/acme/api/handler.go @@ -64,8 +64,14 @@ type HandlerOptions struct { // NewHandler returns a new ACME API handler. func NewHandler(ops HandlerOptions) api.RouterHandler { + transport := &http.Transport{ + TLSClientConfig: &tls.Config{ + InsecureSkipVerify: true, + }, + } client := http.Client{ - Timeout: 30 * time.Second, + Timeout: 30 * time.Second, + Transport: transport, } dialer := &net.Dialer{ Timeout: 30 * time.Second, From 2ac53f7c69e22ef86b43ae367db259178ef90796 Mon Sep 17 00:00:00 2001 From: Kevin Chen <49530888+devadvocado@users.noreply.github.com> Date: Tue, 8 Jun 2021 09:42:20 -0700 Subject: [PATCH 002/195] update gitter to discord --- docs/CONTRIBUTING.md | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md index 93749026..d7356fd9 100644 --- a/docs/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -7,12 +7,20 @@ to manage issues, etc. ## Table of Contents -* [Building From Source](#building-from-source) -* [Asking Support Questions](#asking-support-questions) -* [Reporting Issues](#reporting-issues) -* [Submitting Patches](#submitting-patches) - * [Code Contribution Guidelines](#code-contribution-guidelines) - * [Git Commit Message Guidelines](#git-commit-message-guidelines) +- [Contributing to `step certificates`](#contributing-to-step-certificates) + - [Table of Contents](#table-of-contents) + - [Building From Source](#building-from-source) + - [Build a standard `step-ca`](#build-a-standard-step-ca) + - [Build `step-ca` using CGO](#build-step-ca-using-cgo) + - [The CGO build enables PKCS #11 and YubiKey PIV support](#the-cgo-build-enables-pkcs-11-and-yubikey-piv-support) + - [1. Install PCSC support](#1-install-pcsc-support) + - [2. Build `step-ca`](#2-build-step-ca) + - [Asking Support Questions](#asking-support-questions) + - [Reporting Issues](#reporting-issues) + - [Code Contribution](#code-contribution) + - [Submitting Patches](#submitting-patches) + - [Code Contribution Guidelines](#code-contribution-guidelines) + - [Git Commit Message Guidelines](#git-commit-message-guidelines) ## Building From Source @@ -73,7 +81,7 @@ When the build is complete, you will find binaries in `bin/`. ## Asking Support Questions -Feel free to post a question on our [GitHub Discussions](https://github.com/smallstep/certificates/discussions) page, or find us on [Gitter](https://gitter.im/smallstep/community). +Feel free to post a question on our [GitHub Discussions](https://github.com/smallstep/certificates/discussions) page, or find us on [Discord](https://bit.ly/stepdiscord). ## Reporting Issues From be89459524a4d74edd7e2375ae98d00095bd55f5 Mon Sep 17 00:00:00 2001 From: Gary Belvin Date: Thu, 17 Jun 2021 09:06:35 -0400 Subject: [PATCH 003/195] Set key export bit --- cmd/step-pkcs11-init/main.go | 4 ++++ go.mod | 1 + kms/apiv1/requests.go | 4 ++++ kms/pkcs11/pkcs11.go | 24 ++++++++++++++++++++---- 4 files changed, 29 insertions(+), 4 deletions(-) diff --git a/cmd/step-pkcs11-init/main.go b/cmd/step-pkcs11-init/main.go index 34f9f8f8..b190c261 100644 --- a/cmd/step-pkcs11-init/main.go +++ b/cmd/step-pkcs11-init/main.go @@ -50,6 +50,7 @@ type Config struct { NoCerts bool EnableSSH bool Force bool + Extractable bool } // Validate checks the flags in the config. @@ -117,6 +118,7 @@ func main() { flag.BoolVar(&c.EnableSSH, "ssh", false, "Enable the creation of ssh keys.") flag.BoolVar(&c.NoCerts, "no-certs", false, "Do not store certificates in the module.") flag.BoolVar(&c.Force, "force", false, "Force the delete of previous keys.") + flag.BoolVar(&c.Extractable, "extractable", false, "Allow export of private keys under wrap.") flag.Usage = usage flag.Parse() @@ -286,6 +288,7 @@ func createPKI(k kms.KeyManager, c Config) error { resp, err := k.CreateKey(&apiv1.CreateKeyRequest{ Name: c.RootKeyObject, SignatureAlgorithm: apiv1.ECDSAWithSHA256, + Extractable: c.Extractable, }) if err != nil { return err @@ -366,6 +369,7 @@ func createPKI(k kms.KeyManager, c Config) error { resp, err := k.CreateKey(&apiv1.CreateKeyRequest{ Name: c.CrtKeyObject, SignatureAlgorithm: apiv1.ECDSAWithSHA256, + Extractable: c.Extractable, }) if err != nil { return err diff --git a/go.mod b/go.mod index ac3d54fb..74aa56e9 100644 --- a/go.mod +++ b/go.mod @@ -15,6 +15,7 @@ require ( github.com/googleapis/gax-go/v2 v2.0.5 github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect github.com/micromdm/scep/v2 v2.0.0 + github.com/miekg/pkcs11 v1.0.3-0.20190429190417-a667d056470f github.com/newrelic/go-agent v2.15.0+incompatible github.com/pkg/errors v0.9.1 github.com/rs/xid v1.2.1 diff --git a/kms/apiv1/requests.go b/kms/apiv1/requests.go index f6fe7dd2..321b308b 100644 --- a/kms/apiv1/requests.go +++ b/kms/apiv1/requests.go @@ -112,6 +112,10 @@ type CreateKeyRequest struct { // ProtectionLevel specifies how cryptographic operations are performed. // Used by: cloudkms ProtectionLevel ProtectionLevel + + // Whether the key may be exported from the HSM under a wrap key. + // Sets the CKA_EXTRACTABLE bit. + Extractable bool } // CreateKeyResponse is the response value of the kms.CreateKey method. diff --git a/kms/pkcs11/pkcs11.go b/kms/pkcs11/pkcs11.go index 47c298a5..f6a86a0d 100644 --- a/kms/pkcs11/pkcs11.go +++ b/kms/pkcs11/pkcs11.go @@ -14,6 +14,7 @@ import ( "sync" "github.com/ThalesIgnite/crypto11" + "github.com/miekg/pkcs11" "github.com/pkg/errors" "github.com/smallstep/certificates/kms/apiv1" "github.com/smallstep/certificates/kms/uri" @@ -35,6 +36,7 @@ type P11 interface { DeleteCertificate(id, label []byte, serial *big.Int) error GenerateRSAKeyPairWithLabel(id, label []byte, bits int) (crypto11.SignerDecrypter, error) GenerateECDSAKeyPairWithLabel(id, label []byte, curve elliptic.Curve) (crypto11.Signer, error) + GenerateECDSAKeyPairWithAttributes(public, private crypto11.AttributeSet, curve elliptic.Curve) (crypto11.Signer, error) Close() error } @@ -291,17 +293,17 @@ func generateKey(ctx P11, req *apiv1.CreateKeyRequest) (crypto11.Signer, error) switch req.SignatureAlgorithm { case apiv1.UnspecifiedSignAlgorithm: - return ctx.GenerateECDSAKeyPairWithLabel(id, object, elliptic.P256()) + return GenerateECDSAKeyPairWithLabel(ctx, id, object, elliptic.P256(), req.Extractable) case apiv1.SHA256WithRSA, apiv1.SHA384WithRSA, apiv1.SHA512WithRSA: return ctx.GenerateRSAKeyPairWithLabel(id, object, bits) case apiv1.SHA256WithRSAPSS, apiv1.SHA384WithRSAPSS, apiv1.SHA512WithRSAPSS: return ctx.GenerateRSAKeyPairWithLabel(id, object, bits) case apiv1.ECDSAWithSHA256: - return ctx.GenerateECDSAKeyPairWithLabel(id, object, elliptic.P256()) + return GenerateECDSAKeyPairWithLabel(ctx, id, object, elliptic.P256(), req.Extractable) case apiv1.ECDSAWithSHA384: - return ctx.GenerateECDSAKeyPairWithLabel(id, object, elliptic.P384()) + return GenerateECDSAKeyPairWithLabel(ctx, id, object, elliptic.P384(), req.Extractable) case apiv1.ECDSAWithSHA512: - return ctx.GenerateECDSAKeyPairWithLabel(id, object, elliptic.P521()) + return GenerateECDSAKeyPairWithLabel(ctx, id, object, elliptic.P521(), req.Extractable) case apiv1.PureEd25519: return nil, fmt.Errorf("signature algorithm %s is not supported", req.SignatureAlgorithm) default: @@ -309,6 +311,20 @@ func generateKey(ctx P11, req *apiv1.CreateKeyRequest) (crypto11.Signer, error) } } +func GenerateECDSAKeyPairWithLabel(ctx P11, id, label []byte, curve elliptic.Curve, extractable bool) (crypto11.Signer, error) { + public, err := crypto11.NewAttributeSetWithIDAndLabel(id, label) + if err != nil { + return nil, err + } + // Copy the AttributeSet to allow modifications. + private := public.Copy() + private.AddIfNotPresent([]*pkcs11.Attribute{ + pkcs11.NewAttribute(pkcs11.CKA_EXTRACTABLE, extractable), + }) + + return ctx.GenerateECDSAKeyPairWithAttributes(public, private, curve) +} + func findSigner(ctx P11, rawuri string) (crypto11.Signer, error) { id, object, err := parseObject(rawuri) if err != nil { From 22b471acf92035180fedb98a144c3db3261659ae Mon Sep 17 00:00:00 2001 From: Gary Belvin Date: Thu, 17 Jun 2021 09:23:22 -0400 Subject: [PATCH 004/195] Extractable certs --- cmd/step-pkcs11-init/main.go | 2 ++ kms/apiv1/requests.go | 4 ++++ kms/pkcs11/pkcs11.go | 21 ++++++++++++++++++++- 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/cmd/step-pkcs11-init/main.go b/cmd/step-pkcs11-init/main.go index b190c261..c7ac9b0f 100644 --- a/cmd/step-pkcs11-init/main.go +++ b/cmd/step-pkcs11-init/main.go @@ -328,6 +328,7 @@ func createPKI(k kms.KeyManager, c Config) error { if err = cm.StoreCertificate(&apiv1.StoreCertificateRequest{ Name: c.RootObject, Certificate: root, + Extractable: c.Extractable, }); err != nil { return err } @@ -406,6 +407,7 @@ func createPKI(k kms.KeyManager, c Config) error { if err = cm.StoreCertificate(&apiv1.StoreCertificateRequest{ Name: c.CrtObject, Certificate: intermediate, + Extractable: c.Extractable, }); err != nil { return err } diff --git a/kms/apiv1/requests.go b/kms/apiv1/requests.go index 321b308b..94d832f9 100644 --- a/kms/apiv1/requests.go +++ b/kms/apiv1/requests.go @@ -156,4 +156,8 @@ type LoadCertificateRequest struct { type StoreCertificateRequest struct { Name string Certificate *x509.Certificate + + // Whether the key may be exported from the HSM under a wrap key. + // Sets the CKA_EXTRACTABLE bit. + Extractable bool } diff --git a/kms/pkcs11/pkcs11.go b/kms/pkcs11/pkcs11.go index f6a86a0d..98b08c58 100644 --- a/kms/pkcs11/pkcs11.go +++ b/kms/pkcs11/pkcs11.go @@ -33,6 +33,7 @@ type P11 interface { FindKeyPair(id, label []byte) (crypto11.Signer, error) FindCertificate(id, label []byte, serial *big.Int) (*x509.Certificate, error) ImportCertificateWithLabel(id, label []byte, cert *x509.Certificate) error + ImportCertificateWithAttributes(template crypto11.AttributeSet, certificate *x509.Certificate) error DeleteCertificate(id, label []byte, serial *big.Int) error GenerateRSAKeyPairWithLabel(id, label []byte, bits int) (crypto11.SignerDecrypter, error) GenerateECDSAKeyPairWithLabel(id, label []byte, curve elliptic.Curve) (crypto11.Signer, error) @@ -197,13 +198,31 @@ func (k *PKCS11) StoreCertificate(req *apiv1.StoreCertificateRequest) error { }, "storeCertificate failed") } - if err := k.p11.ImportCertificateWithLabel(id, object, req.Certificate); err != nil { + if err := ImportCertificateWithLabel(k.p11, id, object, req.Certificate, req.Extractable); err != nil { return errors.Wrap(err, "storeCertificate failed") } return nil } +func ImportCertificateWithLabel(ctx P11, id []byte, label []byte, certificate *x509.Certificate, extractable bool) error { + if id == nil { + return errors.New("id cannot be nil") + } + if label == nil { + return errors.New("label cannot be nil") + } + + template, err := crypto11.NewAttributeSetWithIDAndLabel(id, label) + if err != nil { + return err + } + template.AddIfNotPresent([]*pkcs11.Attribute{ + pkcs11.NewAttribute(pkcs11.CKA_EXTRACTABLE, extractable), + }) + return ctx.ImportCertificateWithAttributes(template, certificate) +} + // DeleteKey is a utility function to delete a key given an uri. func (k *PKCS11) DeleteKey(uri string) error { id, object, err := parseObject(uri) From 9d4e6e315a4a1caefc64b3ba9e3b1216517ca12f Mon Sep 17 00:00:00 2001 From: Kevin Chen <49530888+devadvocado@users.noreply.github.com> Date: Tue, 29 Jun 2021 11:01:53 -0700 Subject: [PATCH 005/195] update readme page --- docs/CONTRIBUTING.md | 2 +- docs/revocation.md | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md index d7356fd9..35f75159 100644 --- a/docs/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -81,7 +81,7 @@ When the build is complete, you will find binaries in `bin/`. ## Asking Support Questions -Feel free to post a question on our [GitHub Discussions](https://github.com/smallstep/certificates/discussions) page, or find us on [Discord](https://bit.ly/stepdiscord). +Feel free to post a question on our [GitHub Discussions](https://github.com/smallstep/certificates/discussions) page, or find us on [Discord](https://bit.ly/step-discord). ## Reporting Issues diff --git a/docs/revocation.md b/docs/revocation.md index e994940d..4f3a7d5e 100644 --- a/docs/revocation.md +++ b/docs/revocation.md @@ -202,7 +202,8 @@ through an example. [Use TLS Everywhere](https://smallstep.com/blog/use-tls.html) and let us know what you think of our tools. Get in touch over [Twitter](twitter.com/smallsteplabs) or through our -[GitHub Discussions](https://github.com/smallstep/certificates/discussions) to chat with us in real time. +[GitHub Discussions](https://github.com/smallstep/certificates/discussions) to find answers to frequently asked questions. +[Discord](https://bit.ly/step-discord) to chat with us in real time. ## Further Reading From f7e09af9dfbaee897dd78e48b61c48d74b06f917 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Mon, 12 Jul 2021 15:28:13 +0200 Subject: [PATCH 006/195] Implement the login command. The login commands creates a new certificate for the linked ca. This certificate will be used to sync data with the linkedca endpoint. --- commands/login.go | 219 ++++++++++++++++++++++++++++++++++++++++++++++ go.mod | 11 +-- go.sum | 210 +++++--------------------------------------- 3 files changed, 247 insertions(+), 193 deletions(-) create mode 100644 commands/login.go diff --git a/commands/login.go b/commands/login.go new file mode 100644 index 00000000..0206d073 --- /dev/null +++ b/commands/login.go @@ -0,0 +1,219 @@ +package commands + +import ( + "context" + "crypto/tls" + "crypto/x509" + "encoding/pem" + "io/ioutil" + "os" + "path/filepath" + "regexp" + "time" + + "github.com/pkg/errors" + "github.com/urfave/cli" + "go.step.sm/cli-utils/command" + "go.step.sm/cli-utils/config" + "go.step.sm/cli-utils/errs" + "go.step.sm/cli-utils/ui" + "go.step.sm/crypto/jose" + "go.step.sm/crypto/keyutil" + "go.step.sm/crypto/pemutil" + "go.step.sm/crypto/x509util" + "go.step.sm/linkedca" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials" +) + +const loginEndpoint = "linkedca.smallstep.com:443" +const uuidPattern = "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$" + +type linkedCAClaims struct { + jose.Claims + SANs []string `json:"sans"` +} + +func init() { + command.Register(cli.Command{ + Name: "login", + Usage: "create the certificates to authorize your Linked CA instance", + UsageText: `**step-ca login** **--token*= + [**--linkedca**=] [**--root**=]`, + Action: loginAction, + Description: `**step-ca login** ... + +## POSITIONAL ARGUMENTS + + +: The authority uuid provided by the web app.`, + Flags: []cli.Flag{ + cli.StringFlag{ + Name: "token", + Usage: "The one-time used to authenticate with the Linked CA in order to create the initial credentials", + }, + cli.StringFlag{ + Name: "linkedca", + Usage: "The linkedca to connect to.", + Value: loginEndpoint, + }, + cli.StringFlag{ + Name: "root", + Usage: "The root certificate used to authenticate with the linkedca endpoint.", + }, + }, + }) +} + +func loginAction(ctx *cli.Context) error { + if err := errs.NumberOfArguments(ctx, 1); err != nil { + return err + } + + args := ctx.Args() + authority := args[0] + token := ctx.String("token") + endpoint := ctx.String("linkedca") + rx := regexp.MustCompile(uuidPattern) + switch { + case !rx.MatchString(authority): + return errors.Errorf("positional argument %s is not a valid uuid", authority) + case token == "": + return errs.RequiredFlag(ctx, "token") + case endpoint == "": + return errs.RequiredFlag(ctx, "linkedca") + } + + var claims linkedCAClaims + tok, err := jose.ParseSigned(token) + if err != nil { + return errors.Wrap(err, "error parsing token") + } + if err := tok.UnsafeClaimsWithoutVerification(&claims); err != nil { + return errors.Wrap(err, "error parsing payload") + } + + signer, err := keyutil.GenerateDefaultSigner() + if err != nil { + return err + } + + csr, err := x509util.CreateCertificateRequest(claims.Subject, claims.SANs, signer) + if err != nil { + return err + } + block, err := pemutil.Serialize(csr) + if err != nil { + return err + } + + var options []grpc.DialOption + if root := ctx.String("root"); root != "" { + b, err := ioutil.ReadFile(root) + if err != nil { + return errors.Wrap(err, "error reading file") + } + + pool := x509.NewCertPool() + if !pool.AppendCertsFromPEM(b) { + return errors.Errorf("error reading %s: no certificates were found", root) + } + + options = append(options, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + RootCAs: pool, + }))) + } else { + options = append(options, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{}))) + } + + gctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) + defer cancel() + + conn, err := grpc.DialContext(gctx, endpoint, options...) + if err != nil { + return errors.Wrapf(err, "error connecting %s", endpoint) + } + + client := linkedca.NewMajordomoClient(conn) + gctx, cancel = context.WithTimeout(context.Background(), 15*time.Second) + defer cancel() + resp, err := client.Login(gctx, &linkedca.LoginRequest{ + AuthorityId: authority, + Token: token, + PemCertificateRequest: string(pem.EncodeToMemory(block)), + }) + if err != nil { + return errors.Wrap(err, "error doing login") + } + + certData, rootData, err := parseLoginResponse(resp) + if err != nil { + return err + } + block, err = pemutil.Serialize(signer, pemutil.WithPKCS8(true)) + if err != nil { + return err + } + keyData := pem.EncodeToMemory(block) + + base := filepath.Join(config.StepPath(), "linkedca") + if err := os.MkdirAll(base, 0700); err != nil { + return errors.Wrap(err, "error creating linkedca directory") + } + rootFile := filepath.Join(base, "root_ca.crt") + certFile := filepath.Join(base, "linkedca.crt") + keyFile := filepath.Join(base, "linkedca.key") + + if err := ioutil.WriteFile(rootFile, []byte(rootData), 0600); err != nil { + return errors.Wrap(err, "error writing file") + } + if err := ioutil.WriteFile(certFile, []byte(certData), 0600); err != nil { + return errors.Wrap(err, "error writing file") + } + if err := ioutil.WriteFile(keyFile, []byte(keyData), 0600); err != nil { + return errors.Wrap(err, "error writing file") + } + + ui.PrintSelected("Certificate", certFile) + ui.PrintSelected("Key", keyFile) + ui.PrintSelected("Root", rootFile) + return nil +} + +func parseLoginResponse(resp *linkedca.LoginResponse) ([]byte, []byte, error) { + var block *pem.Block + var bundle []*x509.Certificate + b := []byte(resp.PemCertificateChain) + for len(b) > 0 { + block, b = pem.Decode(b) + if block == nil { + break + } + if block.Type != "CERTIFICATE" { + return nil, nil, errors.New("error decoding login response: pemCertificateChain is not a certificate bundle") + } + crt, err := x509.ParseCertificate(block.Bytes) + if err != nil { + return nil, nil, errors.Wrap(err, "error parsing login response") + } + bundle = append(bundle, crt) + } + if len(bundle) == 0 { + return nil, nil, errors.New("error decoding login response: pemCertificateChain should not be empty") + } + + last := len(bundle) - 1 + + certBytes := []byte(resp.PemCertificate) + for i := 0; i < last; i++ { + certBytes = append(certBytes, pem.EncodeToMemory(&pem.Block{ + Type: "CERTIFICATE", + Bytes: bundle[i].Raw, + })...) + } + + return certBytes, pem.EncodeToMemory(&pem.Block{ + Type: "CERTIFICATE", + Bytes: bundle[last].Raw, + }), nil +} diff --git a/go.mod b/go.mod index 58228557..591c35ce 100644 --- a/go.mod +++ b/go.mod @@ -28,13 +28,14 @@ require ( go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1 go.step.sm/cli-utils v0.4.1 go.step.sm/crypto v0.9.0 - go.step.sm/linkedca v0.0.0-20210611183751-27424aae8d25 + go.step.sm/linkedca v0.0.0-20210712083753-ce3a4a62479a golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 - golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420 + golang.org/x/net v0.0.0-20210614182718-04defd469f4e + golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c // indirect google.golang.org/api v0.47.0 - google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c - google.golang.org/grpc v1.38.0 - google.golang.org/protobuf v1.26.0 + google.golang.org/genproto v0.0.0-20210708141623-e76da96a951f + google.golang.org/grpc v1.39.0 + google.golang.org/protobuf v1.27.1 gopkg.in/square/go-jose.v2 v2.5.1 ) diff --git a/go.sum b/go.sum index e2e71580..2688662a 100644 --- a/go.sum +++ b/go.sum @@ -45,7 +45,6 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym github.com/DataDog/zstd v1.4.1/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= github.com/DataDog/zstd v1.4.5 h1:EndNeuB0l9syBZhut0wns3gV1hL8zX8LIu6ZiVHWLIQ= github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= -github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible h1:1G1pk05UrOh0NlF1oeaaix1x8XzrfjIDK47TY0Zehcw= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/Masterminds/goutils v1.1.0 h1:zukEsf/1JZwCMgHiK3GZftabmxiCw4apj3a28RPBiVg= github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= @@ -55,77 +54,57 @@ github.com/Masterminds/sprig/v3 v3.1.0 h1:j7GpgZ7PdFqNsmncycTHsLmVPf5/3wJtlgW9TN github.com/Masterminds/sprig/v3 v3.1.0/go.mod h1:ONGMf7UfYGAbMXCZmQLy8x3lCDIPrEZE/rU8pmrbihA= github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/Shopify/sarama v1.19.0 h1:9oksLxC6uxVPHPVYUmq6xhr1BOF/hHobWH2UzO67z1s= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= -github.com/Shopify/toxiproxy v2.1.4+incompatible h1:TKdv8HiTLgE5wdJuEML90aBgNWsokNbMijUGhmcoBJc= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= github.com/ThalesIgnite/crypto11 v1.2.4 h1:3MebRK/U0mA2SmSthXAIZAdUA9w8+ZuKem2O6HuR1f8= github.com/ThalesIgnite/crypto11 v1.2.4 h1:3MebRK/U0mA2SmSthXAIZAdUA9w8+ZuKem2O6HuR1f8= github.com/ThalesIgnite/crypto11 v1.2.4/go.mod h1:ILDKtnCKiQ7zRoNxcp36Y1ZR8LBPmR2E23+wTQe/MlE= github.com/ThalesIgnite/crypto11 v1.2.4/go.mod h1:ILDKtnCKiQ7zRoNxcp36Y1ZR8LBPmR2E23+wTQe/MlE= -github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE= github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= -github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5 h1:rFw4nCn9iMW+Vajsk51NtYIcwSTkXr+JGrMd36kTDJw= github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4 h1:Hs82Z41s6SdL1CELW+XaDYmOH4hkBN4/N9og/AsOv7E= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= -github.com/apache/thrift v0.13.0 h1:5hryIiq9gtn+MiLVn0wP37kb/uTeRZgN08WoCsAhIhI= github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= -github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e h1:QEF07wC0T1rKkctt1RINW/+RMTVmiwxETico2l3gxJA= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= -github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6 h1:G1bPvciwNyF7IUmKXNt9Ak3m6u9DE1rF+RmtIkBpVdA= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= -github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da h1:8GUt8eRujhVEGZFFEjBj46YV4rDjvGrNxb0KMWYkL2I= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= -github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310 h1:BUAU3CGlLvorLI26FmByPp2eC2qla6E1Tw+scpcg/to= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a h1:pv34s756C4pEXnjgPfGYgdhg/ZdajGhyOvzx8k+23nw= github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= -github.com/aws/aws-lambda-go v1.13.3 h1:SuCy7H3NLyp+1Mrfp+m80jcbi9KYWAs9/BXwppwRDzY= github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.30.29 h1:NXNqBS9hjOCpDL8SyCyl38gZX3LLLunKOJc5E7vJ8P0= github.com/aws/aws-sdk-go v1.30.29/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= -github.com/aws/aws-sdk-go-v2 v0.18.0 h1:qZ+woO4SamnH/eEbjM2IDLhRNwIwND/RQyVlBLp3Jqg= github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= -github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4= github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= -github.com/casbin/casbin/v2 v2.1.2 h1:bTwon/ECRx9dwBy2ewRVr5OiqjeXSGiTUY74sDPQi/g= github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= -github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= -github.com/census-instrumentation/opencensus-proto v0.2.1 h1:glEXhBS5PSLLv4IXzLA5yPRVX4bilULVyxxbrfOtDAk= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= @@ -133,32 +112,24 @@ github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5O github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 h1:q763qf9huN11kDQavWsoZXJNW3xEE4JJyHa5Q25/sd8= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec h1:EdRZT3IeKQmfCSrgo8SZ8V3MEnskuJP0wCYNpe+aiXo= github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= -github.com/client9/misspell v0.3.4 h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403 h1:cqQfy1jclcSy/FwLjemeg3SR1yaINm74aQyupQ0Bl8M= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa h1:OaNxuTZr7kxeODyLWsRMC+OD03aFUH+mW6r2d+MWa5Y= +github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= -github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd h1:qMd81Ts1T2OTKmB4acZcyKaMtRnY5Y44NuXGX2GFJ1w= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= -github.com/coreos/etcd v3.3.10+incompatible h1:jFneRYjIvLMLhDLCzuTuU4rSJUjRplcJQ7pD7MnhC04= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7 h1:u9SHYsPQNyt5tgDm3YN7+9dYrpK96E5wFilTFWIDZOM= github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf h1:CAKfRE2YtTUIjjh1bkBtyYFaUT/WmOqsJjgtihT0vMI= github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/creack/pty v1.1.7 h1:6pwm8kMQKCmgUg0ZHTm5+/YvRK0s3THD/28+T6/kk4A= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -170,7 +141,6 @@ github.com/dgraph-io/badger/v2 v2.0.1-rc1.0.20201003150343-5d1bab4fc658/go.mod h github.com/dgraph-io/ristretto v0.0.2/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E= github.com/dgraph-io/ristretto v0.0.4-0.20200906165740-41ebdbffecfd h1:KoJOtZf+6wpQaDTuOWGuo61GxcPBIfhwRxRTaTWGCTc= github.com/dgraph-io/ristretto v0.0.4-0.20200906165740-41ebdbffecfd/go.mod h1:YylP9MpCYGVZQrly/j/diqcdUetCRRePeBB0c2VGXsA= -github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y= @@ -178,13 +148,9 @@ github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUn github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/eapache/go-resiliency v1.1.0 h1:1NtRmCAqadE2FN4ZcN6g90TP3uk8cg9rn9eNK2197aU= github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= -github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21 h1:YEetp8/yCZMuEPMUDHG0CW/brkkEp8mzqk2+ODEitlw= github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= -github.com/eapache/queue v1.1.0 h1:YOEu7KNc61ntiQlcEeUIoDTJ2o8mQznoNvUhiigpIqc= github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= -github.com/edsrzf/mmap-go v1.0.0 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw= github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -192,32 +158,24 @@ github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.m github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d h1:QyzYnTnPE15SQyUeqU6qLbWxMkwyAyu+vGksa0b7j00= github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/protoc-gen-validate v0.1.0 h1:EQciDnbrYxy13PgWoY8AqoxGiPrpgBZ1R8UNe3ddc+A= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db h1:gb2Z18BhTPJPpLQWj4T+rfKHYCHxRHCtRxhKKjRidVw= github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= -github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8 h1:a9ENSRDFBUPkJ5lCgVZh26+ZbGyoVJG7yb5SSzF5H54= github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= -github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-chi/chi v4.0.2+incompatible h1:maB6vn6FqCxrpz4FqWdh4+lwpyZIQS7YEAUcHlgXVRs= github.com/go-chi/chi v4.0.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-kit/kit v0.4.0 h1:KeVK+Emj3c3S4eRztFuzbFYb2BAgf2jmwDwyXEri7Lo= github.com/go-kit/kit v0.4.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.10.0 h1:dXFJfIHVvUcpSgDOV+Ne6t7jXri8Tfv2uOLHUZ2XNuo= github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= -github.com/go-logfmt/logfmt v0.3.0 h1:8HUsc87TaSWLKwrnumgC8/YconD2fJQsRJAsWaPg2ic= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0 h1:TrB8swr/68K7m9CcGut2g3UOihhbcbiMAYiuTXdEih4= @@ -227,17 +185,13 @@ github.com/go-piv/piv-go v1.7.0/go.mod h1:ON2WvQncm7dIkCQ7kYJs+nc3V4jHGfrrJnSF8H github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= -github.com/go-stack/stack v1.6.0 h1:MmJCxYVKTJ0SplGKqFVX3SBnmaUhODHZrrFF6jMbpZk= github.com/go-stack/stack v1.6.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/gogo/googleapis v1.1.0 h1:kFkMAZBNAn4j7K0GiZr8cRYzejq68VbheufiV3YuyFI= github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -267,7 +221,6 @@ github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvq github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.5.0 h1:LUVKkCeviFUMKqHa4tXIIij/lbhnMbP7Fn5wKdKkRh4= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= @@ -289,13 +242,10 @@ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 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 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= 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/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= @@ -320,101 +270,67 @@ github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+ 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/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= 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 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/mux v1.4.0/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw= github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c h1:Lh2aW+HnU2Nbe1gqD9SOJLJxW1jBMmQOktN2acDyJk8= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= -github.com/groob/finalizer v0.0.0-20170707115354-4c2ed49aabda h1:5ikpG9mYCMFiZX0nkxoV6aU2IpCHPdws3gCNgdZeEV0= github.com/groob/finalizer v0.0.0-20170707115354-4c2ed49aabda/go.mod h1:MyndkAZd5rUMdNogn35MWXBX1UiBigrU8eTj8DoAC2c= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4 h1:z53tR0945TRRQO/fLEVPI6SMv7ZflF0TEaTAoU7tOzg= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway v1.9.5 h1:UImYN5qQ8tuGpGE16ZmjvcTtTw24zw1QAp/SlnNrZhI= github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/hashicorp/consul/api v1.3.0 h1:HXNYlRkkM/t+Y/Yhxtwcy02dlYwIaoxzvxPnS+cqy78= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= -github.com/hashicorp/consul/sdk v0.3.0 h1:UOxjlb4xVNF93jak1mzzoBatyFju9nrkxpVwIp/QqxQ= github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= -github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-cleanhttp v0.5.1 h1:dH3aiDG9Jvb5r5+bYHsikaOUIpcM0xvgMXVoDkXMzJM= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-immutable-radix v1.0.0 h1:AKDB1HM5PWEA7i4nhcpwOrO2byshxBjXVn/J/3+z5/0= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-msgpack v0.5.3 h1:zKjpN5BK/P5lMYrLmBHdBULWbJ0XpYR+7NGzqkZzoD4= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= -github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= -github.com/hashicorp/go-rootcerts v1.0.0 h1:Rqb66Oo1X/eSV1x66xbDccZjhJigjg0+e82kpwzSwCI= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= -github.com/hashicorp/go-sockaddr v1.0.0 h1:GeH6tui99pF4NJgfnhp+L6+FfobzVW3Ah46sLo0ICXs= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= -github.com/hashicorp/go-syslog v1.0.0 h1:KaodqZuhUoZereWVIYmpUgZysurB1kBLX2j0MwMrUAE= github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-version v1.2.0 h1:3vNe/fWF5CBgRIguda1meWhsZHy3m8gCJ5wx+dIzX/E= github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/go.net v0.0.1 h1:sNCoNyDEvN1xa+X0baata4RdcpKwcMS6DH+xwfqPgjw= github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/hashicorp/logutils v1.0.0 h1:dLEQVugN8vlakKOUE3ihGLTZJRB4j+M2cdTm/ORI65Y= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= -github.com/hashicorp/mdns v1.0.0 h1:WhIgCr5a7AaVH6jPUwjtRuuE7/RDufnUvzIr48smyxs= github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= -github.com/hashicorp/memberlist v0.1.3 h1:EmmoJme1matNzb+hMpDuR/0sbJSUisxyqBGG676r31M= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= -github.com/hashicorp/serf v0.8.2 h1:YZ7UKsJv+hKjqGVUUbtE3HNj79Eln2oQ75tniF6iPt0= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= -github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huandu/xstrings v1.3.1 h1:4jgBlKK6tLKFvO8u5pmYjG91cqytmDCDvGh7ECVFfFs= github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= -github.com/hudl/fargo v1.3.0 h1:0U6+BtN6LhaYuTnIJq4Wyq5cpn6O2kWrxAtcqBmYY6w= github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.8 h1:CGgOkSJeqMRmt0D9XLWExdT4m4F1vd3FV3VPt+0VxkQ= github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d h1:/WZQPMZNsjZ7IlCpsLGdQBINg5bxKQ1K1sh6awxLtkA= github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.3.0 h1:OS12ieG61fsCg5+qLJ+SsW9NicxNkg3b25OyT2yCeUc= github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik= -github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.8 h1:QiWkFLKq0T7mpzwOTu6BzNDbfTE8OLrYhVKYMLF46Ok= github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a h1:FaWFmfWdAUKbSCtOU2QjDaorUexogfaMgbipgYATUMU= github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a/go.mod h1:UJSiEoRfvx3hP73CvoARgeLjaIOjybY9vj8PUPPFGeU= -github.com/julienschmidt/httprouter v1.2.0 h1:TDTW5Yz1mjftljbcKqRcrYhd4XeOoI98t+9HbQbYf7g= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/kisielk/errcheck v1.1.0 h1:ZqfnKyx9KGpRcW04j5nnPDgRgoXUeLh2YFBeFzphcA0= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= -github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515 h1:T+h1c/A9Gawja4Y9mFVWj2vyii2bbUNDw3kt9VxK2EY= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs= @@ -422,16 +338,12 @@ github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfn github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743 h1:143Bb8f8DuGWck/xpNUOckBVYfFbBTnLevfRZ1aVVqo= github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= -github.com/lightstep/lightstep-tracer-go v0.18.1 h1:vi1F1IQ8N7hNWytK9DpJsUfQhGuNSc19z330K6vl4zk= github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= github.com/lunixbochs/vtclean v0.0.0-20180621232353-2d01aacdc34a/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= github.com/lunixbochs/vtclean v1.0.0 h1:xu2sLAri4lGiovBDQKxl5mrXyESr3gUr5m5SM5+LVb8= github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= -github.com/lyft/protoc-gen-validate v0.0.13 h1:KNt/RhmQTOLr7Aj8PsJ7mTronaFyx80mRTT9qF261dA= github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= -github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/manifoldco/promptui v0.8.0 h1:R95mMF+McvXZQ7j1g8ucVZE1gLP3Sv6j9vlF9kyRqQo= github.com/manifoldco/promptui v0.8.0/go.mod h1:n4zTdgP0vr0S3w7/O/g98U+e0gwLScEXGwov2nIKuGQ= @@ -446,132 +358,90 @@ github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOA github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.13 h1:qdl+GuBjcsKKDco5BsxPJlId98mSWNKqYA+Co0SC1yA= github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-runewidth v0.0.2 h1:UnlwIPBGaTZfPQ6T1IGzPI0EkYAQmT9fAEJ/poFC63o= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/micromdm/scep/v2 v2.0.0 h1:cRzcY0S5QX+0+J+7YC4P2uZSnfMup8S8zJu/bLFgOkA= github.com/micromdm/scep/v2 v2.0.0/go.mod h1:ouaDs5tcjOjdHD/h8BGaQsWE87MUnQ/wMTMgfMMIpPc= -github.com/miekg/dns v1.0.14 h1:9jZdLNd/P4+SfEJ0TNyxYpsK8N4GtfylBLqtbYN1sbA= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/pkcs11 v1.0.3-0.20190429190417-a667d056470f h1:eVB9ELsoq5ouItQBr5Tj334bhPJG/MX+m7rTchmzVUQ= github.com/miekg/pkcs11 v1.0.3-0.20190429190417-a667d056470f/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= -github.com/mitchellh/cli v1.0.0 h1:iGBIsUe3+HZ/AD/Vd7DErOt5sU9fa8Uj7A2s1aggv1Y= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ= github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdIPrefOvVG1VZ96U0= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= -github.com/mitchellh/gox v0.4.0 h1:lfGJxY7ToLJQjHHwi0EX6uYBdK78egf954SQl13PQJc= github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= -github.com/mitchellh/iochan v1.0.0 h1:C+X3KsSTLFVBr/tK1eYN/vs4rJcvsiLU338UhYPJWeY= github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY= github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223 h1:F9x/1yl3T2AeKLr2AMdilSD8+f9bvMnNN8VS5iDtovc= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= -github.com/nats-io/jwt v0.3.2 h1:+RB5hMpXUUA2dfxuhBTEkMOrYmM+gKIZYS1KjSostMI= github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= -github.com/nats-io/nats-server/v2 v2.1.2 h1:i2Ly0B+1+rzNZHHWtD4ZwKi+OU5l+uQo1iDHZ2PmiIc= github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= -github.com/nats-io/nats.go v1.9.1 h1:ik3HbLhZ0YABLto7iX80pZLPw/6dx3T+++MZJwLnMrQ= github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= -github.com/nats-io/nkeys v0.1.3 h1:6JrEfig+HzTH85yxzhSVbjHRJv9cn0p6n3IngIcM5/k= github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= -github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/newrelic/go-agent v2.15.0+incompatible h1:IB0Fy+dClpBq9aEoIrLyQXzU34JyI1xVTanPLB/+jvU= github.com/newrelic/go-agent v2.15.0+incompatible/go.mod h1:a8Fv1b/fYhFSReoTU6HDkTYIMZeSVNffmoS726Y0LzQ= -github.com/oklog/oklog v0.3.2 h1:wVfs8F+in6nTBMkA7CbRw+zZMIB7nNM825cM1wuzoTk= github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= -github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= -github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5 h1:58+kh9C6jJVXYjt8IE48G2eWl6BjwU5Gj0gqY84fy78= github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/omorsi/pkcs7 v0.0.0-20210217142924-a7b80a2a8568 h1:+MPqEswjYiS0S1FCTg8MIhMBMzxiVQ94rooFwvPPiWk= github.com/omorsi/pkcs7 v0.0.0-20210217142924-a7b80a2a8568/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 h1:lDH9UUVJtmYCjyT0CI4q8xvlXPxeZ0gYCVvWbmPlp88= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= -github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492 h1:lM6RxxfUMrYL/f8bWEUqdXrANWtrL7Nndbm9iFN0DlU= github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= -github.com/opentracing/basictracer-go v1.0.0 h1:YyUAhaEfjoWXclZVJ9sGoNct7j4TVk7lZWlQw5UXuoo= github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5 h1:ZCnq+JUrvXcDVhX/xRolRBZifmabN1HcS1wrPSvxhrU= github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= -github.com/openzipkin/zipkin-go v0.2.2 h1:nY8Hti+WKaP0cRsSeQ026wU03QsM762XBeCXBb9NAWI= github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= -github.com/pact-foundation/pact-go v1.0.4 h1:OYkFijGHoZAYbOIb1LWXrwKQbMMRUv1oQ89blD2Mh2Q= github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= -github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c h1:Lgl0gzECD8GnQ5QCWA8o6BtfL6mDH5rQgM4/fX3avOs= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= -github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/performancecopilot/speed v3.0.0+incompatible h1:2WnRzIquHa5QxaJKShDkLM+sc0JPuwhXzK8OYOyt3Vg= github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= -github.com/pierrec/lz4 v2.0.5+incompatible h1:2xWsjqPFWcplujydGg4WmhC/6fZqK42wMM8aXeqhl0I= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/profile v1.2.1 h1:F++O52m40owAmADcojzM+9gyjmMOY/T4oYJkgFDH8RE= github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/posener/complete v1.1.1 h1:ccV59UEOTzVDnDUEFdT95ZzHVZ+5+158q8+SJb2QV5w= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.3.0 h1:miYCvYqFXtl/J9FIy8eNpBfYthAEFg+Ys0XyUVEcDsc= github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.1.0 h1:ElTg5tNp4DqfV7UQjDqv2+RJlNzsDtvNAWccbItceIE= github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.7.0 h1:L+1lyG48J1zAQXA3RBX/nG/B3gjlHq0zTt2tlbJLyCY= github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.8 h1:+fpWZdT24pJBiqJdAwYBjPSk+5YmQzYNPYzQsdzLkt8= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= -github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a h1:9ZKAASQSHhDYGoxY8uLVpewe1GDZ2vu2Tr/vTdVAkFQ= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af h1:gu+uRPtBe88sKxUCEXRoeCvVG90TJmwhiqRpvdhQFng= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= -github.com/rogpeppe/go-internal v1.3.0 h1:RR9dF3JtopPvtkroDZuVD7qquD0bnHlKSqaQhgwt8yk= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rs/xid v1.2.1 h1:mhH9Nq+C1fY2l1XIpgxIiUOfNpRBYH1kKcr+qfKgjRc= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= @@ -579,13 +449,10 @@ github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNue github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f h1:UFr9zpz4xgTnIE5yIMtWAMngCdZ9p/+q6lTbgelo80M= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/samfoo/ansi v0.0.0-20160124022901-b6bd2ded7189 h1:CmSpbxmewNQbzqztaY0bke1qzHhyNyC29wYgh17Gxfo= github.com/samfoo/ansi v0.0.0-20160124022901-b6bd2ded7189/go.mod h1:UUwuHEJ9zkkPDxspIHOa59PUeSkGFljESGzbxntLmIg= -github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da h1:p3Vo3i64TCLY7gIfzeQaUJ+kppEO5WQG3cL8iE8tGHU= github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= -github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= @@ -597,13 +464,9 @@ github.com/smallstep/assert v0.0.0-20200723003110-82e2b9b3b262 h1:unQFBIznI+VYD1 github.com/smallstep/assert v0.0.0-20200723003110-82e2b9b3b262/go.mod h1:MyOHs9Po2fbM1LHej6sBUT8ozbxmMOFG+E+rx/GSGuc= github.com/smallstep/nosql v0.3.6 h1:cq6a3NwjFJxkVlWU1T4qGskcfEXr0fO1WqQrraDO1Po= github.com/smallstep/nosql v0.3.6/go.mod h1:h1zC/Z54uNHc8euquLED4qJNCrMHd3nytA141ZZh4qQ= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= -github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/soheilhy/cmux v0.1.4 h1:0HKaf1o97UwFjHH9o5XsHUOF+tqmdA7KEzXLpiyaw0E= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= -github.com/sony/gobreaker v0.4.1 h1:oMnRNZXX5j85zso6xCPRNPtmAycat+WcoKbklScLDgQ= github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= @@ -613,17 +476,13 @@ github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkU github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng= github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= -github.com/spf13/cobra v0.0.5 h1:f0B+LkLX6DtmRH1isoNA9VTtNUK9K8xYd28JNNfOv/s= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= -github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271 h1:WhxRHzgeVGETMlmVfqhRn8RIeeNoPr2Czh33I4Zdccw= github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= -github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a h1:AhmOdSHeswKHBjhsLs/7+1voOxT+LLrSk/Nxvk35fug= github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -636,18 +495,14 @@ github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5Cc github.com/stretchr/testify v1.7.0/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 h1:ndzgwNDnKIqyCvHTXaCqh9KlOWKvBry6nuXMJmonVsE= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8 h1:3SVOIvH7Ae1KRYyQWRjXWJEA9sS/c/pjvH++55Gr648= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli v1.22.4 h1:u7tSpNPPswAFymm8IehJhy4uJMlUuU/GmqSkvJ1InXA= github.com/urfave/cli v1.22.4/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= -github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77 h1:ESFSdwYZvkeru3RtdrYueztKhOBCSAAzS4Gf+k0tEow= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -657,7 +512,6 @@ github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1 go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.5 h1:XAzx9gjCb0Rxj7EoqcClPD1d5ZBxZJk0jbuoPHenBt0= go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= -go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738 h1:VcrIfasaLFkyjk6KNlXQSzO+B0fZcnECiDrKJsfxka0= go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= @@ -669,31 +523,19 @@ go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= -go.step.sm/cli-utils v0.2.0 h1:hpVu9+6dpv/7/Bd8nGJFc3V+gQ+TciSJRTu9TavDUQ4= -go.step.sm/cli-utils v0.2.0/go.mod h1:+t4qCp5NO+080DdGkJxEh3xL5S4TcYC2JTPLMM72b6Y= -go.step.sm/cli-utils v0.4.0 h1:dni6gR/6/LOqfbzm/yUdgz5O12tkxX17SxA9+pRMidI= -go.step.sm/cli-utils v0.4.0/go.mod h1:1zFgatDqEJ1Y4MNStdWa0b1NPc1fvSHbDJC+wZ6iQlE= +go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.step.sm/cli-utils v0.4.1 h1:QztRUhGYjOPM1I2Nmi7V6XejQyVtcESmo+sbegxvX7Q= go.step.sm/cli-utils v0.4.1/go.mod h1:hWYVOSlw8W9Pd+BwIbs/aftVVMRms3EG7Q2qLRwc0WA= -go.step.sm/crypto v0.6.1/go.mod h1:AKS4yMZVZD4EGjpSkY4eibuMenrvKCscb+BpWMet8c0= -go.step.sm/crypto v0.8.3 h1:TO/OPlaUrYXhs8srGEFNyL6OWVQvRmEPCUONNnQUuEM= -go.step.sm/crypto v0.8.3/go.mod h1:+CYG05Mek1YDqi5WK0ERc6cOpKly2i/a5aZmU1sfGj0= go.step.sm/crypto v0.9.0 h1:q2AllTSnVj4NRtyEPkGW2ohArLmbGbe6ZAL/VIOKDzA= go.step.sm/crypto v0.9.0/go.mod h1:+CYG05Mek1YDqi5WK0ERc6cOpKly2i/a5aZmU1sfGj0= -go.step.sm/linkedca v0.0.0-20210610014030-59b16916c7e7 h1:hAfzUm80XWGtFnxyVgeT/gc/3XnlVNnHD5HrLbk4Fc0= -go.step.sm/linkedca v0.0.0-20210610014030-59b16916c7e7/go.mod h1:5uTRjozEGSPAZal9xJqlaD38cvJcLe3o1VAFVjqcORo= -go.step.sm/linkedca v0.0.0-20210611183751-27424aae8d25 h1:ncJqviWswJT19IdnfOYQGKG1zL7IDy4lAJz1PuM3fgw= -go.step.sm/linkedca v0.0.0-20210611183751-27424aae8d25/go.mod h1:5uTRjozEGSPAZal9xJqlaD38cvJcLe3o1VAFVjqcORo= +go.step.sm/linkedca v0.0.0-20210712083753-ce3a4a62479a h1:bu8HRqaJeZpXyAdULY3lptl1U0TrwAfm0WMwxWtG0JY= +go.step.sm/linkedca v0.0.0-20210712083753-ce3a4a62479a/go.mod h1:5uTRjozEGSPAZal9xJqlaD38cvJcLe3o1VAFVjqcORo= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.5.0 h1:OI5t8sDa1Or+q8AeE+yKeB/SDYioSHAgcVljj9JIETY= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/multierr v1.3.0 h1:sFPn2GLc3poCkfrpIXGhBD2X0CMIo4Q/zSULXrj/+uc= go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= -go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.13.0 h1:nR6NoDBgAf67s68NhaXbsojM+2gxp3S1hWkHDl27pVU= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -786,10 +628,9 @@ golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420 h1:a8jGStKg0XqKDlKqjLrXn0ioF5MH36pT7Z0BRTqLhbk= golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210525063256-abc453219eb5 h1:wjuX4b5yYQnEQHzd+CBcrcC6OVR2J1CN6mUy0oSxIPo= -golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210614182718-04defd469f4e h1:XpT3nA5TvE525Ne3hInMh6+GETgn27Zfm9dxsThnX2Q= +golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 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= @@ -870,11 +711,9 @@ golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210514084401-e8d321eab015 h1:hZR0X1kPW+nwyJ9xRxqZk1vx5RUObAPBdKVvXPDUH/E= golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210616094352-59db8d763f22 h1:RqytpXGR1iVNX7psjB3ff8y7sNFinVFvkx1c8SjBkio= -golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -943,6 +782,7 @@ golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/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.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1005,6 +845,7 @@ google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfG google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= @@ -1022,10 +863,9 @@ google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 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 h1:wtujag7C+4D6KMoulW9YauvK2lgdvCMS260jsqqBXr0= google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d h1:KzwjikDymrEmYYbdyfievTwjEeGlu+OM6oiKBkF3Jfg= -google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210708141623-e76da96a951f h1:khwpF3oSk7GIab/7DDMDyE8cPQEO6FAfOcWHIRAhO20= +google.golang.org/genproto v0.0.0-20210708141623-e76da96a951f/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= 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= @@ -1044,6 +884,7 @@ google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3Iji google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= @@ -1051,8 +892,9 @@ google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAG google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= 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 h1:/9BgsAsa5nWe26HqOlvlgJnqBuktYOLCgjCPqsa56W0= google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.39.0 h1:Klz8I9kdtkIN6EpHHUOMLCYhTn/2WAe5a0s1hcBkdTI= +google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= 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= @@ -1065,33 +907,27 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc= +google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/cheggaaa/pb.v1 v1.0.25 h1:Ev7yu1/f6+d+b3pi5vPdRPc6nNtP1umSfcWiEfRqv6I= gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= -gopkg.in/errgo.v2 v2.1.0 h1:0vLT13EuvQ0hNvakwLuFZ/jYrLp5F3kcWHXdRggjCE8= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/gcfg.v1 v1.2.3 h1:m8OOJ4ccYHnx2f4gQwpno8nAX5OGOh7RLaaz0pj3Ogs= gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= -gopkg.in/resty.v1 v1.12.0 h1:CuXP0Pjfw9rOuY6EP+UvtNvt5DSqHpIxILZKT/quCZI= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/square/go-jose.v2 v2.5.1 h1:7odma5RETjNHWJnR32wx8t+Io4djHE1PqxCFx3iiZ2w= gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.7 h1:VUgggvou5XRW9mHwD/yXxIYSMtY0zoKQf/v226p2nyo= gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= @@ -1107,7 +943,5 @@ honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9 rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= -sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= -sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0 h1:ucqkfpjg9WzSUubAO62csmucvxl4/JeW3F4I4909XkM= sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= From 49c1427d1576edd1cd62db6bb6688f7749706d46 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Mon, 12 Jul 2021 15:31:05 +0200 Subject: [PATCH 007/195] Use authorityId instead of authorityID. In json or javascript world authorityId, userId, ... are more common than authorityID, ... --- authority/config/config.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/authority/config/config.go b/authority/config/config.go index 9ad1ff5f..fabd3f91 100644 --- a/authority/config/config.go +++ b/authority/config/config.go @@ -83,7 +83,7 @@ type ASN1DN struct { // cas.Options. type AuthConfig struct { *cas.Options - AuthorityID string `json:"authorityID,omitempty"` + AuthorityID string `json:"authorityId,omitempty"` Provisioners provisioner.List `json:"provisioners"` Admins []*linkedca.Admin `json:"-"` Template *ASN1DN `json:"template,omitempty"` From dd9850ce4c0a5843714cc2320ba84cbd8a49fa22 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Mon, 12 Jul 2021 18:11:00 +0200 Subject: [PATCH 008/195] Add working implementation of the linkedca. Replaces the authority adminDB with a new impmentation that users the linkedca client to retrieve the data. Note that this implementation still hardcodes the endpoint to localhost. --- authority/authority.go | 15 +++- authority/linkedca.go | 171 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 182 insertions(+), 4 deletions(-) create mode 100644 authority/linkedca.go diff --git a/authority/authority.go b/authority/authority.go index 0f171fa7..48b7a566 100644 --- a/authority/authority.go +++ b/authority/authority.go @@ -442,10 +442,17 @@ func (a *Authority) init() error { // Initialize step-ca Admin Database if it's not already initialized using // WithAdminDB. if a.adminDB == nil { - // Check if AuthConfig already exists - a.adminDB, err = adminDBNosql.New(a.db.(nosql.DB), admin.DefaultAuthorityID) - if err != nil { - return err + if a.config.AuthorityConfig.AuthorityID == "" { + // Check if AuthConfig already exists + a.adminDB, err = adminDBNosql.New(a.db.(nosql.DB), admin.DefaultAuthorityID) + if err != nil { + return err + } + } else { + a.adminDB, err = createLinkedCAClient(a.config.AuthorityConfig.AuthorityID, "localhost:6040") + if err != nil { + return err + } } } diff --git a/authority/linkedca.go b/authority/linkedca.go new file mode 100644 index 00000000..0d9a748f --- /dev/null +++ b/authority/linkedca.go @@ -0,0 +1,171 @@ +package authority + +import ( + "context" + "crypto/tls" + "crypto/x509" + "io/ioutil" + "path/filepath" + + "github.com/pkg/errors" + "github.com/smallstep/certificates/errs" + "go.step.sm/cli-utils/config" + "go.step.sm/linkedca" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials" +) + +type linkedCaClient struct { + client linkedca.MajordomoClient + authorityID string +} + +func createLinkedCAClient(authorityID, endpoint string) (*linkedCaClient, error) { + base := filepath.Join(config.StepPath(), "linkedca") + rootFile := filepath.Join(base, "root_ca.crt") + certFile := filepath.Join(base, "linkedca.crt") + keyFile := filepath.Join(base, "linkedca.key") + + b, err := ioutil.ReadFile(rootFile) + if err != nil { + return nil, errors.Wrap(err, "error reading linkedca root") + } + pool := x509.NewCertPool() + if !pool.AppendCertsFromPEM(b) { + return nil, errors.Errorf("error reading %s: no certificates were found", rootFile) + } + + conn, err := grpc.Dial(endpoint, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + RootCAs: pool, + GetClientCertificate: func(*tls.CertificateRequestInfo) (*tls.Certificate, error) { + cert, err := tls.LoadX509KeyPair(certFile, keyFile) + if err != nil { + return nil, errors.Wrap(err, "error reading linkedca certificate") + } + return &cert, nil + }, + }))) + if err != nil { + return nil, errors.Wrapf(err, "error connecting %s", endpoint) + } + + return &linkedCaClient{ + client: linkedca.NewMajordomoClient(conn), + authorityID: authorityID, + }, nil +} + +func (c *linkedCaClient) CreateProvisioner(ctx context.Context, prov *linkedca.Provisioner) error { + resp, err := c.client.CreateProvisioner(ctx, &linkedca.CreateProvisionerRequest{ + Type: prov.Type, + Name: prov.Name, + Details: prov.Details, + Claims: prov.Claims, + X509Template: prov.X509Template, + SshTemplate: prov.SshTemplate, + }) + if err != nil { + return errors.Wrap(err, "error creating provisioner") + } + prov.Id = resp.Id + prov.AuthorityId = resp.AuthorityId + return nil +} + +func (c *linkedCaClient) GetProvisioner(ctx context.Context, id string) (*linkedca.Provisioner, error) { + resp, err := c.client.GetConfiguration(ctx, &linkedca.ConfigurationRequest{ + AuthorityId: c.authorityID, + }) + if err != nil { + return nil, errors.Wrap(err, "error getting provisioners") + } + for _, p := range resp.Provisioners { + if p.Id == id { + return p, nil + } + } + return nil, errs.NotFound("provisioner not found") +} + +func (c *linkedCaClient) GetProvisioners(ctx context.Context) ([]*linkedca.Provisioner, error) { + resp, err := c.client.GetConfiguration(ctx, &linkedca.ConfigurationRequest{ + AuthorityId: c.authorityID, + }) + if err != nil { + return nil, errors.Wrap(err, "error getting provisioners") + } + return resp.Provisioners, nil +} + +func (c *linkedCaClient) UpdateProvisioner(ctx context.Context, prov *linkedca.Provisioner) error { + _, err := c.client.UpdateProvisioner(ctx, &linkedca.UpdateProvisionerRequest{ + Id: prov.Id, + Name: prov.Name, + Details: prov.Details, + Claims: prov.Claims, + X509Template: prov.X509Template, + SshTemplate: prov.SshTemplate, + }) + return errors.Wrap(err, "error updating provisioner") +} + +func (c *linkedCaClient) DeleteProvisioner(ctx context.Context, id string) error { + _, err := c.client.DeleteProvisioner(ctx, &linkedca.DeleteProvisionerRequest{ + Id: id, + }) + return errors.Wrap(err, "error deleting provisioner") +} + +func (c *linkedCaClient) CreateAdmin(ctx context.Context, adm *linkedca.Admin) error { + resp, err := c.client.CreateAdmin(ctx, &linkedca.CreateAdminRequest{ + Subject: adm.Subject, + ProvisionerId: adm.ProvisionerId, + Type: adm.Type, + }) + if err != nil { + return errors.Wrap(err, "error creating admin") + } + adm.Id = resp.Id + adm.AuthorityId = resp.AuthorityId + return nil +} + +func (c *linkedCaClient) GetAdmin(ctx context.Context, id string) (*linkedca.Admin, error) { + resp, err := c.client.GetConfiguration(ctx, &linkedca.ConfigurationRequest{ + AuthorityId: c.authorityID, + }) + if err != nil { + return nil, errors.Wrap(err, "error getting admins") + } + for _, a := range resp.Admins { + if a.Id == id { + return a, nil + } + } + return nil, errs.NotFound("admin not found") +} + +func (c *linkedCaClient) GetAdmins(ctx context.Context) ([]*linkedca.Admin, error) { + resp, err := c.client.GetConfiguration(ctx, &linkedca.ConfigurationRequest{ + AuthorityId: c.authorityID, + }) + if err != nil { + return nil, errors.Wrap(err, "error getting admins") + } + return resp.Admins, nil +} + +func (c *linkedCaClient) UpdateAdmin(ctx context.Context, adm *linkedca.Admin) error { + _, err := c.client.UpdateAdmin(ctx, &linkedca.UpdateAdminRequest{ + Id: adm.Id, + Type: adm.Type, + }) + return errors.Wrap(err, "error updating admin") +} + +func (c *linkedCaClient) DeleteAdmin(ctx context.Context, id string) error { + _, err := c.client.DeleteAdmin(ctx, &linkedca.DeleteAdminRequest{ + Id: id, + }) + return errors.Wrap(err, "error deleting admin") +} From 3e5b90b6fac1e33a0bf6db24ec9a2af87dec234f Mon Sep 17 00:00:00 2001 From: Carl Tashian Date: Mon, 19 Jul 2021 08:34:22 -0500 Subject: [PATCH 009/195] systemd cert renewer can now use 'step certificate needs-renewal' --- systemd/cert-renewer@.service | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/systemd/cert-renewer@.service b/systemd/cert-renewer@.service index f38951b5..7c4c4e3c 100644 --- a/systemd/cert-renewer@.service +++ b/systemd/cert-renewer@.service @@ -15,11 +15,7 @@ Environment=STEPPATH=/etc/step-ca \ ; ExecStartPre checks if the certificate is ready for renewal, ; based on the exit status of the command. ; (In systemd 243 and above, you can use ExecCondition= here.) -ExecStartPre=/usr/bin/env bash -c \ - 'step certificate inspect $CERT_LOCATION --format json --roots "$STEPPATH/certs/root_ca.crt" | \ - jq -e "(((.validity.start | fromdate) + \ - ((.validity.end | fromdate) - (.validity.start | fromdate)) * 0.66) \ - - now) <= 0" > /dev/null' +ExecStartPre=/usr/bin/step certificate needs-renewal $CERT_LOCATION --roots $STEPPATH/certs/root_ca.crt ; ExecStart renews the certificate, if ExecStartPre was successful. ExecStart=/usr/bin/step ca renew --force $CERT_LOCATION $KEY_LOCATION From 0dd6564b1e16627b160e491f9e4b4395221e2d90 Mon Sep 17 00:00:00 2001 From: Carl Tashian Date: Mon, 19 Jul 2021 13:05:01 -0500 Subject: [PATCH 010/195] README link fixes --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f0649175..544dd5b5 100644 --- a/README.md +++ b/README.md @@ -58,10 +58,10 @@ You can issue certificates in exchange for: - ID tokens from Okta, GSuite, Azure AD, Auth0. - ID tokens from an OAuth OIDC service that you host, like [Keycloak](https://www.keycloak.org/) or [Dex](https://github.com/dexidp/dex) - [Cloud instance identity documents](https://smallstep.com/blog/embarrassingly-easy-certificates-on-aws-azure-gcp/), for VMs on AWS, GCP, and Azure -- [Single-use, short-lived JWK tokens]() issued by your CD tool — Puppet, Chef, Ansible, Terraform, etc. +- [Single-use, short-lived JWK tokens](https://smallstep.com/docs/step-ca/provisioners#jwk) issued by your CD tool — Puppet, Chef, Ansible, Terraform, etc. - A trusted X.509 certificate (X5C provisioner) - Expiring SSH host certificates needing rotation (the SSHPOP provisioner) -- Learn more in our [provisioner documentation](https://smallstep.com/docs/step-ca/configuration#jwk) +- Learn more in our [provisioner documentation](https://smallstep.com/docs/step-ca/provisioners) ### 🏔 Your own private ACME server From 8fb5340dc9aa779dab96cb3d5b8672a572759ca6 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Mon, 19 Jul 2021 19:28:06 -0700 Subject: [PATCH 011/195] Use a token at start time to configure linkedca. Instead of using `step-ca login` we will use a new token provided as a flag to configure and start linkedca. Certificates will be kept in memory and refreshed automatically. --- authority/authority.go | 30 +++-- authority/linkedca.go | 266 +++++++++++++++++++++++++++++++++++++---- authority/options.go | 9 ++ ca/ca.go | 13 ++ commands/app.go | 8 +- commands/login.go | 155 ++++++++++++++++-------- go.mod | 3 +- 7 files changed, 399 insertions(+), 85 deletions(-) diff --git a/authority/authority.go b/authority/authority.go index 48b7a566..80242e8b 100644 --- a/authority/authority.go +++ b/authority/authority.go @@ -7,6 +7,7 @@ import ( "crypto/x509" "encoding/hex" "log" + "strings" "sync" "time" @@ -33,13 +34,14 @@ import ( // Authority implements the Certificate Authority internal interface. type Authority struct { - config *config.Config - keyManager kms.KeyManager - provisioners *provisioner.Collection - admins *administrator.Collection - db db.AuthDB - adminDB admin.DB - templates *templates.Templates + config *config.Config + keyManager kms.KeyManager + provisioners *provisioner.Collection + admins *administrator.Collection + db db.AuthDB + adminDB admin.DB + templates *templates.Templates + linkedCAToken string // X509 CA x509CAService cas.CertificateAuthorityService @@ -442,17 +444,24 @@ func (a *Authority) init() error { // Initialize step-ca Admin Database if it's not already initialized using // WithAdminDB. if a.adminDB == nil { - if a.config.AuthorityConfig.AuthorityID == "" { + if a.linkedCAToken == "" { // Check if AuthConfig already exists a.adminDB, err = adminDBNosql.New(a.db.(nosql.DB), admin.DefaultAuthorityID) if err != nil { return err } } else { - a.adminDB, err = createLinkedCAClient(a.config.AuthorityConfig.AuthorityID, "localhost:6040") + // 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 } } @@ -534,6 +543,9 @@ func (a *Authority) CloseForReload() { if err := a.keyManager.Close(); err != nil { log.Printf("error closing the key manager: %v", err) } + if client, ok := a.adminDB.(*linkedCaClient); ok { + client.Stop() + } } // requiresDecrypter returns whether the Authority diff --git a/authority/linkedca.go b/authority/linkedca.go index 0d9a748f..4e67f246 100644 --- a/authority/linkedca.go +++ b/authority/linkedca.go @@ -2,59 +2,126 @@ package authority import ( "context" + "crypto" + "crypto/sha256" "crypto/tls" "crypto/x509" - "io/ioutil" - "path/filepath" + "encoding/hex" + "encoding/pem" + "fmt" + "net/url" + "regexp" + "strings" + "time" "github.com/pkg/errors" "github.com/smallstep/certificates/errs" - "go.step.sm/cli-utils/config" + "go.step.sm/crypto/jose" + "go.step.sm/crypto/keyutil" + "go.step.sm/crypto/tlsutil" + "go.step.sm/crypto/x509util" "go.step.sm/linkedca" "google.golang.org/grpc" "google.golang.org/grpc/credentials" ) +const uuidPattern = "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$" + type linkedCaClient struct { + renewer *tlsutil.Renewer client linkedca.MajordomoClient authorityID string } -func createLinkedCAClient(authorityID, endpoint string) (*linkedCaClient, error) { - base := filepath.Join(config.StepPath(), "linkedca") - rootFile := filepath.Join(base, "root_ca.crt") - certFile := filepath.Join(base, "linkedca.crt") - keyFile := filepath.Join(base, "linkedca.key") +type linkedCAClaims struct { + jose.Claims + SANs []string `json:"sans"` + SHA string `json:"sha"` +} - b, err := ioutil.ReadFile(rootFile) +func newLinkedCAClient(token string) (*linkedCaClient, error) { + tok, err := jose.ParseSigned(token) if err != nil { - return nil, errors.Wrap(err, "error reading linkedca root") + return nil, errors.Wrap(err, "error parsing token") } + + var claims linkedCAClaims + if err := tok.UnsafeClaimsWithoutVerification(&claims); err != nil { + return nil, errors.Wrap(err, "error parsing token") + } + // Validate claims + if len(claims.Audience) != 1 { + return nil, errors.New("error parsing token: invalid aud claim") + } + if claims.SHA == "" { + return nil, errors.New("error parsing token: invalid sha claim") + } + // Get linkedCA endpoint from audience. + u, err := url.Parse(claims.Audience[0]) + if err != nil { + return nil, errors.New("error parsing token: invalid aud claim") + } + // Get authority from SANs + authority, err := getAuthority(claims.SANs) + if err != nil { + return nil, err + } + + // Create csr to login with + signer, err := keyutil.GenerateDefaultSigner() + if err != nil { + return nil, err + } + csr, err := x509util.CreateCertificateRequest(claims.Subject, claims.SANs, signer) + if err != nil { + return nil, err + } + + // Get and verify root certificate + root, err := getRootCertificate(u.Host, claims.SHA) + if err != nil { + return nil, err + } + pool := x509.NewCertPool() - if !pool.AppendCertsFromPEM(b) { - return nil, errors.Errorf("error reading %s: no certificates were found", rootFile) + pool.AddCert(root) + + // Login with majordomo and get certificates + cert, tlsConfig, err := login(authority, token, csr, signer, u.Host, pool) + if err != nil { + return nil, err } - conn, err := grpc.Dial(endpoint, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ - RootCAs: pool, - GetClientCertificate: func(*tls.CertificateRequestInfo) (*tls.Certificate, error) { - cert, err := tls.LoadX509KeyPair(certFile, keyFile) - if err != nil { - return nil, errors.Wrap(err, "error reading linkedca certificate") - } - return &cert, nil - }, - }))) + // Start TLS renewer and set the GetClientCertificate callback to it. + renewer, err := tlsutil.NewRenewer(cert, tlsConfig, func() (*tls.Certificate, *tls.Config, error) { + return login(authority, token, csr, signer, u.Host, pool) + }) if err != nil { - return nil, errors.Wrapf(err, "error connecting %s", endpoint) + return nil, err + } + tlsConfig.GetClientCertificate = renewer.GetClientCertificate + + // Start mTLS client + conn, err := grpc.Dial(u.Host, grpc.WithTransportCredentials(credentials.NewTLS(tlsConfig))) + if err != nil { + return nil, errors.Wrapf(err, "error connecting %s", u.Host) } return &linkedCaClient{ + renewer: renewer, client: linkedca.NewMajordomoClient(conn), - authorityID: authorityID, + authorityID: authority, }, nil } +func (c *linkedCaClient) Run() { + c.renewer.Run() +} + +func (c *linkedCaClient) Stop() { + c.renewer.Stop() +} + func (c *linkedCaClient) CreateProvisioner(ctx context.Context, prov *linkedca.Provisioner) error { resp, err := c.client.CreateProvisioner(ctx, &linkedca.CreateProvisionerRequest{ Type: prov.Type, @@ -169,3 +236,154 @@ func (c *linkedCaClient) DeleteAdmin(ctx context.Context, id string) error { }) return errors.Wrap(err, "error deleting admin") } + +func getAuthority(sans []string) (string, error) { + for _, s := range sans { + if strings.HasPrefix(s, "urn:smallstep:authority:") { + if regexp.MustCompile(uuidPattern).MatchString(s[24:]) { + return s[24:], nil + } + } + } + return "", fmt.Errorf("error parsing token: invalid sans claim") +} + +// getRootCertificate creates an insecure majordomo client and returns the +// verified root certificate. +func getRootCertificate(endpoint, fingerprint string) (*x509.Certificate, error) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + conn, err := grpc.DialContext(ctx, endpoint, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + InsecureSkipVerify: true, + }))) + if err != nil { + return nil, errors.Wrapf(err, "error connecting %s", endpoint) + } + + ctx, cancel = context.WithTimeout(context.Background(), 15*time.Second) + defer cancel() + + client := linkedca.NewMajordomoClient(conn) + resp, err := client.GetRootCertificate(ctx, &linkedca.GetRootCertificateRequest{ + Fingerprint: fingerprint, + }) + if err != nil { + return nil, fmt.Errorf("error getting root certificate: %w", err) + } + + var block *pem.Block + b := []byte(resp.PemCertificate) + for len(b) > 0 { + block, b = pem.Decode(b) + if block == nil { + break + } + if block.Type != "CERTIFICATE" || len(block.Headers) != 0 { + continue + } + + cert, err := x509.ParseCertificate(block.Bytes) + if err != nil { + return nil, fmt.Errorf("error parsing certificate: %w", err) + } + + // verify the sha256 + sum := sha256.Sum256(cert.Raw) + if !strings.EqualFold(fingerprint, hex.EncodeToString(sum[:])) { + return nil, fmt.Errorf("error verifying certificate: SHA256 fingerprint does not match") + } + + return cert, nil + } + + return nil, fmt.Errorf("error getting root certificate: certificate not found") +} + +// login creates a new majordomo client with just the root ca pool and returns +// the signed certificate and tls configuration. +func login(authority, token string, csr *x509.CertificateRequest, signer crypto.PrivateKey, endpoint string, rootCAs *x509.CertPool) (*tls.Certificate, *tls.Config, error) { + // Connect to majordomo + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + conn, err := grpc.DialContext(ctx, endpoint, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + RootCAs: rootCAs, + }))) + if err != nil { + return nil, nil, errors.Wrapf(err, "error connecting %s", endpoint) + } + + // Login to get the signed certificate + ctx, cancel = context.WithTimeout(context.Background(), 15*time.Second) + defer cancel() + + client := linkedca.NewMajordomoClient(conn) + resp, err := client.Login(ctx, &linkedca.LoginRequest{ + AuthorityId: authority, + Token: token, + PemCertificateRequest: string(pem.EncodeToMemory(&pem.Block{ + Type: "CERTIFICATE REQUEST", + Bytes: csr.Raw, + })), + }) + if err != nil { + return nil, nil, errors.Wrapf(err, "error logging in %s", endpoint) + } + + // Parse login response + var block *pem.Block + var bundle []*x509.Certificate + rest := []byte(resp.PemCertificateChain) + for { + block, rest = pem.Decode(rest) + if block == nil { + break + } + if block.Type != "CERTIFICATE" { + return nil, nil, errors.New("error decoding login response: pemCertificateChain is not a certificate bundle") + } + crt, err := x509.ParseCertificate(block.Bytes) + if err != nil { + return nil, nil, errors.Wrap(err, "error parsing login response") + } + bundle = append(bundle, crt) + } + if len(bundle) == 0 { + return nil, nil, errors.New("error decoding login response: pemCertificateChain should not be empty") + } + + // Build tls.Certificate with PemCertificate and intermediates in the + // PemCertificateChain + cert := &tls.Certificate{ + PrivateKey: signer, + } + rest = []byte(resp.PemCertificate) + for { + block, rest = pem.Decode(rest) + if block == nil { + break + } + if block.Type == "CERTIFICATE" { + leaf, err := x509.ParseCertificate(block.Bytes) + if err != nil { + return nil, nil, errors.Wrap(err, "error parsing pemCertificate") + } + cert.Certificate = append(cert.Certificate, block.Bytes) + cert.Leaf = leaf + } + } + + // Add intermediates to the tls.Certificate + last := len(bundle) - 1 + for i := 0; i < last; i++ { + cert.Certificate = append(cert.Certificate, bundle[i].Raw) + } + + // Add root to the pool if it's not there yet + rootCAs.AddCert(bundle[last]) + + return cert, &tls.Config{ + RootCAs: rootCAs, + }, nil +} diff --git a/authority/options.go b/authority/options.go index 4e9fbdbc..6baeb2bc 100644 --- a/authority/options.go +++ b/authority/options.go @@ -196,6 +196,15 @@ func WithAdminDB(db admin.DB) Option { } } +// WithLinkedCAToken is an option to set the authentication token used to enable +// linked ca. +func WithLinkedCAToken(token string) Option { + return func(a *Authority) error { + a.linkedCAToken = token + return nil + } +} + func readCertificateBundle(pemCerts []byte) ([]*x509.Certificate, error) { var block *pem.Block var certs []*x509.Certificate diff --git a/ca/ca.go b/ca/ca.go index 4551286b..51d15bec 100644 --- a/ca/ca.go +++ b/ca/ca.go @@ -30,6 +30,7 @@ import ( type options struct { configFile string + linkedCAToken string password []byte issuerPassword []byte database db.AuthDB @@ -75,6 +76,13 @@ func WithDatabase(db db.AuthDB) Option { } } +// WithLinkedCAToken sets the token used to authenticate with the linkedca. +func WithLinkedCAToken(token string) Option { + return func(o *options) { + o.linkedCAToken = token + } +} + // CA is the type used to build the complete certificate authority. It builds // the HTTP server, set ups the middlewares and the HTTP handlers. type CA struct { @@ -111,6 +119,10 @@ func (ca *CA) Init(config *config.Config) (*CA, error) { } var opts []authority.Option + if ca.opts.linkedCAToken != "" { + opts = append(opts, authority.WithLinkedCAToken(ca.opts.linkedCAToken)) + } + if ca.opts.database != nil { opts = append(opts, authority.WithDatabase(ca.opts.database)) } @@ -326,6 +338,7 @@ func (ca *CA) Reload() error { newCA, err := New(config, WithPassword(ca.opts.password), WithIssuerPassword(ca.opts.issuerPassword), + WithLinkedCAToken(ca.opts.linkedCAToken), WithConfigFile(ca.opts.configFile), WithDatabase(ca.auth.GetDatabase()), ) diff --git a/commands/app.go b/commands/app.go index 8833726c..3b874ae8 100644 --- a/commands/app.go +++ b/commands/app.go @@ -38,6 +38,10 @@ certificate issuer private key used in the RA mode.`, Name: "resolver", Usage: "address of a DNS resolver to be used instead of the default.", }, + cli.StringFlag{ + Name: "token", + Usage: "token used to enable the linked ca.", + }, }, } @@ -46,6 +50,7 @@ func appAction(ctx *cli.Context) error { passFile := ctx.String("password-file") issuerPassFile := ctx.String("issuer-password-file") 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 { @@ -88,7 +93,8 @@ func appAction(ctx *cli.Context) error { srv, err := ca.New(config, ca.WithConfigFile(configFile), ca.WithPassword(password), - ca.WithIssuerPassword(issuerPassword)) + ca.WithIssuerPassword(issuerPassword), + ca.WithLinkedCAToken(token)) if err != nil { fatal(err) } diff --git a/commands/login.go b/commands/login.go index 0206d073..8c0049ee 100644 --- a/commands/login.go +++ b/commands/login.go @@ -2,13 +2,18 @@ package commands import ( "context" + "crypto/sha256" "crypto/tls" "crypto/x509" + "encoding/hex" "encoding/pem" + "fmt" "io/ioutil" + "net/url" "os" "path/filepath" "regexp" + "strings" "time" "github.com/pkg/errors" @@ -32,13 +37,14 @@ const uuidPattern = "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4 type linkedCAClaims struct { jose.Claims SANs []string `json:"sans"` + SHA string `json:"sha"` } func init() { command.Register(cli.Command{ Name: "login", Usage: "create the certificates to authorize your Linked CA instance", - UsageText: `**step-ca login** **--token*= + UsageText: `**step-ca login** **--token*= [**--linkedca**=] [**--root**=]`, Action: loginAction, Description: `**step-ca login** ... @@ -50,16 +56,7 @@ func init() { Flags: []cli.Flag{ cli.StringFlag{ Name: "token", - Usage: "The one-time used to authenticate with the Linked CA in order to create the initial credentials", - }, - cli.StringFlag{ - Name: "linkedca", - Usage: "The linkedca to connect to.", - Value: loginEndpoint, - }, - cli.StringFlag{ - Name: "root", - Usage: "The root certificate used to authenticate with the linkedca endpoint.", + Usage: "The used to authenticate with the Linked CA in order to create the initial credentials", }, }, }) @@ -70,18 +67,9 @@ func loginAction(ctx *cli.Context) error { return err } - args := ctx.Args() - authority := args[0] token := ctx.String("token") - endpoint := ctx.String("linkedca") - rx := regexp.MustCompile(uuidPattern) - switch { - case !rx.MatchString(authority): - return errors.Errorf("positional argument %s is not a valid uuid", authority) - case token == "": + if token == "" { return errs.RequiredFlag(ctx, "token") - case endpoint == "": - return errs.RequiredFlag(ctx, "linkedca") } var claims linkedCAClaims @@ -90,9 +78,43 @@ func loginAction(ctx *cli.Context) error { return errors.Wrap(err, "error parsing token") } if err := tok.UnsafeClaimsWithoutVerification(&claims); err != nil { - return errors.Wrap(err, "error parsing payload") + return errors.Wrap(err, "error parsing token") + } + if len(claims.Audience) != 0 { + return errors.Wrap(err, "error parsing token: invalid aud claim") + } + u, err := url.Parse(claims.Audience[0]) + if err != nil { + return errors.Wrap(err, "error parsing token: invalid aud claim") + } + if claims.SHA == "" { + return errors.Wrap(err, "error parsing token: invalid sha claim") + } + authority, err := getAuthority(claims.SANs) + if err != nil { + return err } + // Get and verify root certificate + root, err := getRootCertificate(u.Host, claims.SHA) + if err != nil { + return err + } + + pool := x509.NewCertPool() + pool.AddCert(root) + + gctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + conn, err := grpc.DialContext(gctx, u.Host, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + RootCAs: pool, + }))) + if err != nil { + return errors.Wrapf(err, "error connecting %s", u.Host) + } + + // Create csr signer, err := keyutil.GenerateDefaultSigner() if err != nil { return err @@ -107,33 +129,7 @@ func loginAction(ctx *cli.Context) error { return err } - var options []grpc.DialOption - if root := ctx.String("root"); root != "" { - b, err := ioutil.ReadFile(root) - if err != nil { - return errors.Wrap(err, "error reading file") - } - - pool := x509.NewCertPool() - if !pool.AppendCertsFromPEM(b) { - return errors.Errorf("error reading %s: no certificates were found", root) - } - - options = append(options, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ - RootCAs: pool, - }))) - } else { - options = append(options, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{}))) - } - - gctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) - defer cancel() - - conn, err := grpc.DialContext(gctx, endpoint, options...) - if err != nil { - return errors.Wrapf(err, "error connecting %s", endpoint) - } - + // Perform login and get signed certificate client := linkedca.NewMajordomoClient(conn) gctx, cancel = context.WithTimeout(context.Background(), 15*time.Second) defer cancel() @@ -180,6 +176,67 @@ func loginAction(ctx *cli.Context) error { return nil } +func getAuthority(sans []string) (string, error) { + for _, s := range sans { + if strings.HasPrefix(s, "urn:smallstep:authority:") { + if regexp.MustCompile(uuidPattern).MatchString(s[24:]) { + return s[24:], nil + } + } + } + return "", fmt.Errorf("error parsing token: invalid sans claim") +} + +func getRootCertificate(endpoint, fingerprint string) (*x509.Certificate, error) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + conn, err := grpc.DialContext(ctx, endpoint, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + InsecureSkipVerify: true, + }))) + if err != nil { + return nil, errors.Wrapf(err, "error connecting %s", endpoint) + } + + ctx, cancel = context.WithTimeout(context.Background(), 15*time.Second) + defer cancel() + + client := linkedca.NewMajordomoClient(conn) + resp, err := client.GetRootCertificate(ctx, &linkedca.GetRootCertificateRequest{ + Fingerprint: fingerprint, + }) + if err != nil { + return nil, fmt.Errorf("error getting root certificate: %w", err) + } + + var block *pem.Block + b := []byte(resp.PemCertificate) + for len(b) > 0 { + block, b = pem.Decode(b) + if block == nil { + break + } + if block.Type != "CERTIFICATE" || len(block.Headers) != 0 { + continue + } + + cert, err := x509.ParseCertificate(block.Bytes) + if err != nil { + return nil, fmt.Errorf("error parsing certificate: %w", err) + } + + // verify the sha256 + sum := sha256.Sum256(cert.Raw) + if !strings.EqualFold(fingerprint, hex.EncodeToString(sum[:])) { + return nil, fmt.Errorf("error verifying certificate: SHA256 fingerprint does not match") + } + + return cert, nil + } + + return nil, fmt.Errorf("error getting root certificate: certificate not found") +} + func parseLoginResponse(resp *linkedca.LoginResponse) ([]byte, []byte, error) { var block *pem.Block var bundle []*x509.Certificate diff --git a/go.mod b/go.mod index 591c35ce..86e0db73 100644 --- a/go.mod +++ b/go.mod @@ -40,9 +40,8 @@ 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.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1 => github.com/omorsi/pkcs7 v0.0.0-20210217142924-a7b80a2a8568 From f8c137af4ff0530400683ea24922e67d56cd07c3 Mon Sep 17 00:00:00 2001 From: Carl Tashian Date: Tue, 20 Jul 2021 10:32:18 -0500 Subject: [PATCH 012/195] Update provisioners.md --- docs/provisioners.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/provisioners.md b/docs/provisioners.md index 7ee9af50..18010f88 100644 --- a/docs/provisioners.md +++ b/docs/provisioners.md @@ -1,7 +1,7 @@ # Provisioners > Note: The canonical documentation for `step-ca` provisioners now lives at -> https://smallstep.com/docs/step-ca/configuration#provisioners. Documentation +> https://smallstep.com/docs/step-ca/provisioners. Documentation > found on this page may be out of date. Provisioners are people or code that are registered with the CA and authorized From 7c0faab73e1ae372c3612dca55cb6ffad94b0223 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Tue, 20 Jul 2021 12:57:34 -0700 Subject: [PATCH 013/195] Remove now unused step-ca login. --- commands/login.go | 276 ---------------------------------------------- 1 file changed, 276 deletions(-) delete mode 100644 commands/login.go diff --git a/commands/login.go b/commands/login.go deleted file mode 100644 index 8c0049ee..00000000 --- a/commands/login.go +++ /dev/null @@ -1,276 +0,0 @@ -package commands - -import ( - "context" - "crypto/sha256" - "crypto/tls" - "crypto/x509" - "encoding/hex" - "encoding/pem" - "fmt" - "io/ioutil" - "net/url" - "os" - "path/filepath" - "regexp" - "strings" - "time" - - "github.com/pkg/errors" - "github.com/urfave/cli" - "go.step.sm/cli-utils/command" - "go.step.sm/cli-utils/config" - "go.step.sm/cli-utils/errs" - "go.step.sm/cli-utils/ui" - "go.step.sm/crypto/jose" - "go.step.sm/crypto/keyutil" - "go.step.sm/crypto/pemutil" - "go.step.sm/crypto/x509util" - "go.step.sm/linkedca" - "google.golang.org/grpc" - "google.golang.org/grpc/credentials" -) - -const loginEndpoint = "linkedca.smallstep.com:443" -const uuidPattern = "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$" - -type linkedCAClaims struct { - jose.Claims - SANs []string `json:"sans"` - SHA string `json:"sha"` -} - -func init() { - command.Register(cli.Command{ - Name: "login", - Usage: "create the certificates to authorize your Linked CA instance", - UsageText: `**step-ca login** **--token*= - [**--linkedca**=] [**--root**=]`, - Action: loginAction, - Description: `**step-ca login** ... - -## POSITIONAL ARGUMENTS - - -: The authority uuid provided by the web app.`, - Flags: []cli.Flag{ - cli.StringFlag{ - Name: "token", - Usage: "The used to authenticate with the Linked CA in order to create the initial credentials", - }, - }, - }) -} - -func loginAction(ctx *cli.Context) error { - if err := errs.NumberOfArguments(ctx, 1); err != nil { - return err - } - - token := ctx.String("token") - if token == "" { - return errs.RequiredFlag(ctx, "token") - } - - var claims linkedCAClaims - tok, err := jose.ParseSigned(token) - if err != nil { - return errors.Wrap(err, "error parsing token") - } - if err := tok.UnsafeClaimsWithoutVerification(&claims); err != nil { - return errors.Wrap(err, "error parsing token") - } - if len(claims.Audience) != 0 { - return errors.Wrap(err, "error parsing token: invalid aud claim") - } - u, err := url.Parse(claims.Audience[0]) - if err != nil { - return errors.Wrap(err, "error parsing token: invalid aud claim") - } - if claims.SHA == "" { - return errors.Wrap(err, "error parsing token: invalid sha claim") - } - authority, err := getAuthority(claims.SANs) - if err != nil { - return err - } - - // Get and verify root certificate - root, err := getRootCertificate(u.Host, claims.SHA) - if err != nil { - return err - } - - pool := x509.NewCertPool() - pool.AddCert(root) - - gctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - conn, err := grpc.DialContext(gctx, u.Host, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ - RootCAs: pool, - }))) - if err != nil { - return errors.Wrapf(err, "error connecting %s", u.Host) - } - - // Create csr - signer, err := keyutil.GenerateDefaultSigner() - if err != nil { - return err - } - - csr, err := x509util.CreateCertificateRequest(claims.Subject, claims.SANs, signer) - if err != nil { - return err - } - block, err := pemutil.Serialize(csr) - if err != nil { - return err - } - - // Perform login and get signed certificate - client := linkedca.NewMajordomoClient(conn) - gctx, cancel = context.WithTimeout(context.Background(), 15*time.Second) - defer cancel() - resp, err := client.Login(gctx, &linkedca.LoginRequest{ - AuthorityId: authority, - Token: token, - PemCertificateRequest: string(pem.EncodeToMemory(block)), - }) - if err != nil { - return errors.Wrap(err, "error doing login") - } - - certData, rootData, err := parseLoginResponse(resp) - if err != nil { - return err - } - block, err = pemutil.Serialize(signer, pemutil.WithPKCS8(true)) - if err != nil { - return err - } - keyData := pem.EncodeToMemory(block) - - base := filepath.Join(config.StepPath(), "linkedca") - if err := os.MkdirAll(base, 0700); err != nil { - return errors.Wrap(err, "error creating linkedca directory") - } - rootFile := filepath.Join(base, "root_ca.crt") - certFile := filepath.Join(base, "linkedca.crt") - keyFile := filepath.Join(base, "linkedca.key") - - if err := ioutil.WriteFile(rootFile, []byte(rootData), 0600); err != nil { - return errors.Wrap(err, "error writing file") - } - if err := ioutil.WriteFile(certFile, []byte(certData), 0600); err != nil { - return errors.Wrap(err, "error writing file") - } - if err := ioutil.WriteFile(keyFile, []byte(keyData), 0600); err != nil { - return errors.Wrap(err, "error writing file") - } - - ui.PrintSelected("Certificate", certFile) - ui.PrintSelected("Key", keyFile) - ui.PrintSelected("Root", rootFile) - return nil -} - -func getAuthority(sans []string) (string, error) { - for _, s := range sans { - if strings.HasPrefix(s, "urn:smallstep:authority:") { - if regexp.MustCompile(uuidPattern).MatchString(s[24:]) { - return s[24:], nil - } - } - } - return "", fmt.Errorf("error parsing token: invalid sans claim") -} - -func getRootCertificate(endpoint, fingerprint string) (*x509.Certificate, error) { - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - conn, err := grpc.DialContext(ctx, endpoint, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ - InsecureSkipVerify: true, - }))) - if err != nil { - return nil, errors.Wrapf(err, "error connecting %s", endpoint) - } - - ctx, cancel = context.WithTimeout(context.Background(), 15*time.Second) - defer cancel() - - client := linkedca.NewMajordomoClient(conn) - resp, err := client.GetRootCertificate(ctx, &linkedca.GetRootCertificateRequest{ - Fingerprint: fingerprint, - }) - if err != nil { - return nil, fmt.Errorf("error getting root certificate: %w", err) - } - - var block *pem.Block - b := []byte(resp.PemCertificate) - for len(b) > 0 { - block, b = pem.Decode(b) - if block == nil { - break - } - if block.Type != "CERTIFICATE" || len(block.Headers) != 0 { - continue - } - - cert, err := x509.ParseCertificate(block.Bytes) - if err != nil { - return nil, fmt.Errorf("error parsing certificate: %w", err) - } - - // verify the sha256 - sum := sha256.Sum256(cert.Raw) - if !strings.EqualFold(fingerprint, hex.EncodeToString(sum[:])) { - return nil, fmt.Errorf("error verifying certificate: SHA256 fingerprint does not match") - } - - return cert, nil - } - - return nil, fmt.Errorf("error getting root certificate: certificate not found") -} - -func parseLoginResponse(resp *linkedca.LoginResponse) ([]byte, []byte, error) { - var block *pem.Block - var bundle []*x509.Certificate - b := []byte(resp.PemCertificateChain) - for len(b) > 0 { - block, b = pem.Decode(b) - if block == nil { - break - } - if block.Type != "CERTIFICATE" { - return nil, nil, errors.New("error decoding login response: pemCertificateChain is not a certificate bundle") - } - crt, err := x509.ParseCertificate(block.Bytes) - if err != nil { - return nil, nil, errors.Wrap(err, "error parsing login response") - } - bundle = append(bundle, crt) - } - if len(bundle) == 0 { - return nil, nil, errors.New("error decoding login response: pemCertificateChain should not be empty") - } - - last := len(bundle) - 1 - - certBytes := []byte(resp.PemCertificate) - for i := 0; i < last; i++ { - certBytes = append(certBytes, pem.EncodeToMemory(&pem.Block{ - Type: "CERTIFICATE", - Bytes: bundle[i].Raw, - })...) - } - - return certBytes, pem.EncodeToMemory(&pem.Block{ - Type: "CERTIFICATE", - Bytes: bundle[last].Raw, - }), nil -} From a72eab915b920290b184ef1e13b47649d493cb3e Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Tue, 20 Jul 2021 12:59:59 -0700 Subject: [PATCH 014/195] Use linkedca v0.1.0 --- go.mod | 6 +++--- go.sum | 12 +++++------- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/go.mod b/go.mod index 86e0db73..8ebffc43 100644 --- a/go.mod +++ b/go.mod @@ -28,12 +28,12 @@ require ( go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1 go.step.sm/cli-utils v0.4.1 go.step.sm/crypto v0.9.0 - go.step.sm/linkedca v0.0.0-20210712083753-ce3a4a62479a + go.step.sm/linkedca v0.1.0 golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 - golang.org/x/net v0.0.0-20210614182718-04defd469f4e + golang.org/x/net v0.0.0-20210716203947-853a461950ff golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c // indirect google.golang.org/api v0.47.0 - google.golang.org/genproto v0.0.0-20210708141623-e76da96a951f + google.golang.org/genproto v0.0.0-20210719143636-1d5a45f8e492 google.golang.org/grpc v1.39.0 google.golang.org/protobuf v1.27.1 gopkg.in/square/go-jose.v2 v2.5.1 diff --git a/go.sum b/go.sum index 2688662a..d3435218 100644 --- a/go.sum +++ b/go.sum @@ -528,8 +528,6 @@ go.step.sm/cli-utils v0.4.1 h1:QztRUhGYjOPM1I2Nmi7V6XejQyVtcESmo+sbegxvX7Q= go.step.sm/cli-utils v0.4.1/go.mod h1:hWYVOSlw8W9Pd+BwIbs/aftVVMRms3EG7Q2qLRwc0WA= go.step.sm/crypto v0.9.0 h1:q2AllTSnVj4NRtyEPkGW2ohArLmbGbe6ZAL/VIOKDzA= go.step.sm/crypto v0.9.0/go.mod h1:+CYG05Mek1YDqi5WK0ERc6cOpKly2i/a5aZmU1sfGj0= -go.step.sm/linkedca v0.0.0-20210712083753-ce3a4a62479a h1:bu8HRqaJeZpXyAdULY3lptl1U0TrwAfm0WMwxWtG0JY= -go.step.sm/linkedca v0.0.0-20210712083753-ce3a4a62479a/go.mod h1:5uTRjozEGSPAZal9xJqlaD38cvJcLe3o1VAFVjqcORo= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= @@ -629,8 +627,8 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210614182718-04defd469f4e h1:XpT3nA5TvE525Ne3hInMh6+GETgn27Zfm9dxsThnX2Q= -golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210716203947-853a461950ff h1:j2EK/QoxYNBsXI4R7fQkkRUk8y6wnOBI+6hgPdP/6Ds= +golang.org/x/net v0.0.0-20210716203947-853a461950ff/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 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= @@ -782,7 +780,7 @@ golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/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.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -864,8 +862,8 @@ 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-20210708141623-e76da96a951f h1:khwpF3oSk7GIab/7DDMDyE8cPQEO6FAfOcWHIRAhO20= -google.golang.org/genproto v0.0.0-20210708141623-e76da96a951f/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= +google.golang.org/genproto v0.0.0-20210719143636-1d5a45f8e492 h1:7yQQsvnwjfEahbNNEKcBHv3mR+HnB1ctGY/z1JXzx8M= +google.golang.org/genproto v0.0.0-20210719143636-1d5a45f8e492/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= 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= From 17eef81c916b080db8555bd22c0cbfcdb6f2874d Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Tue, 20 Jul 2021 14:55:07 -0700 Subject: [PATCH 015/195] Remove linkerd replace. --- go.mod | 6 +++--- go.sum | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 8ebffc43..c3fdb002 100644 --- a/go.mod +++ b/go.mod @@ -40,8 +40,8 @@ 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/crypto => ../crypto +// replace go.step.sm/cli-utils => ../cli-utils +// replace go.step.sm/linkedca => ../linkedca replace go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1 => github.com/omorsi/pkcs7 v0.0.0-20210217142924-a7b80a2a8568 diff --git a/go.sum b/go.sum index d3435218..140557ba 100644 --- a/go.sum +++ b/go.sum @@ -528,6 +528,8 @@ go.step.sm/cli-utils v0.4.1 h1:QztRUhGYjOPM1I2Nmi7V6XejQyVtcESmo+sbegxvX7Q= go.step.sm/cli-utils v0.4.1/go.mod h1:hWYVOSlw8W9Pd+BwIbs/aftVVMRms3EG7Q2qLRwc0WA= go.step.sm/crypto v0.9.0 h1:q2AllTSnVj4NRtyEPkGW2ohArLmbGbe6ZAL/VIOKDzA= go.step.sm/crypto v0.9.0/go.mod h1:+CYG05Mek1YDqi5WK0ERc6cOpKly2i/a5aZmU1sfGj0= +go.step.sm/linkedca v0.1.0 h1:2kVdQZi37pIijm1thSYVOQ/mKoREPYNXulUZj/G0azM= +go.step.sm/linkedca v0.1.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.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= From 71f8019243e201fe48c9c0b782fdee3cc9abd32e Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Tue, 20 Jul 2021 18:16:24 -0700 Subject: [PATCH 016/195] Store x509 and ssh certificates on linkedca if enabled. --- authority/linkedca.go | 43 +++++++++++++++++++++++++++++++++++++++++++ authority/ssh.go | 18 ++++++++++++++---- authority/tls.go | 20 ++++++++++++++++---- go.mod | 2 +- 4 files changed, 74 insertions(+), 9 deletions(-) diff --git a/authority/linkedca.go b/authority/linkedca.go index 4e67f246..117f19ef 100644 --- a/authority/linkedca.go +++ b/authority/linkedca.go @@ -6,6 +6,7 @@ import ( "crypto/sha256" "crypto/tls" "crypto/x509" + "encoding/base64" "encoding/hex" "encoding/pem" "fmt" @@ -21,6 +22,7 @@ import ( "go.step.sm/crypto/tlsutil" "go.step.sm/crypto/x509util" "go.step.sm/linkedca" + "golang.org/x/crypto/ssh" "google.golang.org/grpc" "google.golang.org/grpc/credentials" ) @@ -237,6 +239,47 @@ 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 { + 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:]...), + }) + return errors.Wrap(err, "error posting certificate") +} + +func (c *linkedCaClient) StoreRenewedCertificate(parent *x509.Certificate, 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:]...), + PemParentCertificate: serializeCertificateChain(parent), + }) + return errors.Wrap(err, "error posting certificate") +} + +func (c *linkedCaClient) StoreSSHCertificate(crt *ssh.Certificate) error { + ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) + defer cancel() + _, err := c.client.PostSSHCertificate(ctx, &linkedca.SSHCertificateRequest{ + Certificate: base64.StdEncoding.EncodeToString(crt.Marshal()), + }) + return errors.Wrap(err, "error posting ssh certificate") +} + +func serializeCertificateChain(fullchain ...*x509.Certificate) string { + var chain string + for _, crt := range fullchain { + chain += string(pem.EncodeToMemory(&pem.Block{ + Type: "CERTIFICATE", + Bytes: crt.Raw, + })) + } + return chain +} + func getAuthority(sans []string) (string, error) { for _, s := range sans { if strings.HasPrefix(s, "urn:smallstep:authority:") { diff --git a/authority/ssh.go b/authority/ssh.go index 335b6702..3b03fd7e 100644 --- a/authority/ssh.go +++ b/authority/ssh.go @@ -239,7 +239,7 @@ func (a *Authority) SignSSH(ctx context.Context, key ssh.PublicKey, opts provisi } } - if err = a.db.StoreSSHCertificate(cert); err != nil && err != db.ErrNotImplemented { + if err = a.storeSSHCertificate(cert); err != nil && err != db.ErrNotImplemented { return nil, errs.Wrap(http.StatusInternalServerError, err, "authority.SignSSH: error storing certificate in db") } @@ -294,7 +294,7 @@ func (a *Authority) RenewSSH(ctx context.Context, oldCert *ssh.Certificate) (*ss return nil, errs.Wrap(http.StatusInternalServerError, err, "signSSH: error signing certificate") } - if err = a.db.StoreSSHCertificate(cert); err != nil && err != db.ErrNotImplemented { + if err = a.storeSSHCertificate(cert); err != nil && err != db.ErrNotImplemented { return nil, errs.Wrap(http.StatusInternalServerError, err, "renewSSH: error storing certificate in db") } @@ -369,13 +369,23 @@ func (a *Authority) RekeySSH(ctx context.Context, oldCert *ssh.Certificate, pub } } - if err = a.db.StoreSSHCertificate(cert); err != nil && err != db.ErrNotImplemented { + if err = a.storeSSHCertificate(cert); err != nil && err != db.ErrNotImplemented { return nil, errs.Wrap(http.StatusInternalServerError, err, "rekeySSH; error storing certificate in db") } return cert, nil } +func (a *Authority) storeSSHCertificate(cert *ssh.Certificate) error { + type sshCertificateStorer interface { + StoreSSHCertificate(crt *ssh.Certificate) error + } + if s, ok := a.adminDB.(sshCertificateStorer); ok { + return s.StoreSSHCertificate(cert) + } + return a.db.StoreSSHCertificate(cert) +} + // IsValidForAddUser checks if a user provisioner certificate can be issued to // the given certificate. func IsValidForAddUser(cert *ssh.Certificate) error { @@ -451,7 +461,7 @@ func (a *Authority) SignSSHAddUser(ctx context.Context, key ssh.PublicKey, subje } cert.Signature = sig - if err = a.db.StoreSSHCertificate(cert); err != nil && err != db.ErrNotImplemented { + if err = a.storeSSHCertificate(cert); err != nil && err != db.ErrNotImplemented { return nil, errs.Wrap(http.StatusInternalServerError, err, "signSSHAddUser: error storing certificate in db") } diff --git a/authority/tls.go b/authority/tls.go index 4c3420df..b2dc4c92 100644 --- a/authority/tls.go +++ b/authority/tls.go @@ -280,9 +280,15 @@ func (a *Authority) Rekey(oldCert *x509.Certificate, pk crypto.PublicKey) ([]*x5 // `StoreCertificate(...*x509.Certificate) error` instead of just // `StoreCertificate(*x509.Certificate) error`. func (a *Authority) storeCertificate(fullchain []*x509.Certificate) error { - if s, ok := a.db.(interface { + type certificateChainStorer interface { StoreCertificateChain(...*x509.Certificate) error - }); ok { + } + // Store certificate in linkedca + if s, ok := a.adminDB.(certificateChainStorer); ok { + return s.StoreCertificateChain(fullchain...) + } + // Store certificate in local db + if s, ok := a.db.(certificateChainStorer); ok { return s.StoreCertificateChain(fullchain...) } return a.db.StoreCertificate(fullchain[0]) @@ -293,9 +299,15 @@ func (a *Authority) storeCertificate(fullchain []*x509.Certificate) error { // // TODO: at some point we should implement this in the standard implementation. func (a *Authority) storeRenewedCertificate(oldCert *x509.Certificate, fullchain []*x509.Certificate) error { - if s, ok := a.db.(interface { + type renewedCertificateChainStorer interface { StoreRenewedCertificate(*x509.Certificate, ...*x509.Certificate) error - }); ok { + } + // Store certificate in linkedca + if s, ok := a.adminDB.(renewedCertificateChainStorer); ok { + return s.StoreRenewedCertificate(oldCert, fullchain...) + } + // Store certificate in local db + if s, ok := a.db.(renewedCertificateChainStorer); ok { return s.StoreRenewedCertificate(oldCert, fullchain...) } return a.db.StoreCertificate(fullchain[0]) diff --git a/go.mod b/go.mod index c3fdb002..6957cc83 100644 --- a/go.mod +++ b/go.mod @@ -42,6 +42,6 @@ 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 replace go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1 => github.com/omorsi/pkcs7 v0.0.0-20210217142924-a7b80a2a8568 From 22ef324534cee45f3b231b32347155ca818377d0 Mon Sep 17 00:00:00 2001 From: Carl Tashian Date: Wed, 21 Jul 2021 11:49:10 -0500 Subject: [PATCH 017/195] Fix needs-renewal condition and switch to using ExecCondition --- systemd/cert-renewer@.service | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/systemd/cert-renewer@.service b/systemd/cert-renewer@.service index 7c4c4e3c..5b56f5fc 100644 --- a/systemd/cert-renewer@.service +++ b/systemd/cert-renewer@.service @@ -12,10 +12,10 @@ Environment=STEPPATH=/etc/step-ca \ CERT_LOCATION=/etc/step/certs/%i.crt \ KEY_LOCATION=/etc/step/certs/%i.key -; ExecStartPre checks if the certificate is ready for renewal, +; ExecCondition checks if the certificate is ready for renewal, ; based on the exit status of the command. -; (In systemd 243 and above, you can use ExecCondition= here.) -ExecStartPre=/usr/bin/step certificate needs-renewal $CERT_LOCATION --roots $STEPPATH/certs/root_ca.crt +; (In systemd 242 or below, you can use ExecStartPre= here.) +ExecCondition=/usr/bin/step certificate needs-renewal $CERT_LOCATION ; ExecStart renews the certificate, if ExecStartPre was successful. ExecStart=/usr/bin/step ca renew --force $CERT_LOCATION $KEY_LOCATION From f7542a5bd9037c570e0ba4ad87b26cd47670f85e Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Wed, 21 Jul 2021 15:22:57 -0700 Subject: [PATCH 018/195] Move check of ssh revocation from provisioner to the authority. --- authority/authorize.go | 14 ++++ authority/provisioner/sshpop.go | 13 +--- authority/provisioner/sshpop_test.go | 109 --------------------------- authority/ssh.go | 10 ++- authority/ssh_test.go | 58 ++++++++++++++ 5 files changed, 83 insertions(+), 121 deletions(-) diff --git a/authority/authorize.go b/authority/authorize.go index 8d1f878a..91a07353 100644 --- a/authority/authorize.go +++ b/authority/authorize.go @@ -6,6 +6,7 @@ import ( "crypto/x509" "encoding/hex" "net/http" + "strconv" "strings" "time" @@ -291,6 +292,19 @@ func (a *Authority) authorizeRenew(cert *x509.Certificate) error { return nil } +// authorizeSSHCertificate returns an error if the given certificate is revoked. +func (a *Authority) authorizeSSHCertificate(ctx context.Context, cert *ssh.Certificate) error { + serial := strconv.FormatUint(cert.Serial, 10) + isRevoked, err := a.db.IsSSHRevoked(serial) + if err != nil { + return errs.Wrap(http.StatusInternalServerError, err, "authority.authorizeSSHCertificate", errs.WithKeyVal("serialNumber", serial)) + } + if isRevoked { + return errs.Unauthorized("authority.authorizeSSHCertificate: certificate has been revoked", errs.WithKeyVal("serialNumber", serial)) + } + return nil +} + // authorizeSSHSign loads the provisioner from the token, checks that it has not // been used again and calls the provisioner AuthorizeSSHSign method. Returns a // list of methods to apply to the signing flow. diff --git a/authority/provisioner/sshpop.go b/authority/provisioner/sshpop.go index 8bc76edf..99974ff1 100644 --- a/authority/provisioner/sshpop.go +++ b/authority/provisioner/sshpop.go @@ -8,7 +8,6 @@ import ( "time" "github.com/pkg/errors" - "github.com/smallstep/certificates/db" "github.com/smallstep/certificates/errs" "go.step.sm/crypto/jose" "golang.org/x/crypto/ssh" @@ -30,7 +29,6 @@ type SSHPOP struct { Type string `json:"type"` Name string `json:"name"` Claims *Claims `json:"claims,omitempty"` - db db.AuthDB claimer *Claimer audiences Audiences sshPubKeys *SSHKeys @@ -102,7 +100,6 @@ func (p *SSHPOP) Init(config Config) error { } p.audiences = config.Audiences.WithFragment(p.GetIDForToken()) - p.db = config.DB p.sshPubKeys = config.SSHKeys return nil } @@ -110,6 +107,8 @@ func (p *SSHPOP) Init(config Config) error { // authorizeToken performs common jwt authorization actions and returns the // claims for case specific downstream parsing. // e.g. a Sign request will auth/validate different fields than a Revoke request. +// +// Checking for certificate revocation has been moved to the authority package. func (p *SSHPOP) authorizeToken(token string, audiences []string) (*sshPOPPayload, error) { sshCert, jwt, err := ExtractSSHPOPCert(token) if err != nil { @@ -117,14 +116,6 @@ func (p *SSHPOP) authorizeToken(token string, audiences []string) (*sshPOPPayloa "sshpop.authorizeToken; error extracting sshpop header from token") } - // Check for revocation. - if isRevoked, err := p.db.IsSSHRevoked(strconv.FormatUint(sshCert.Serial, 10)); err != nil { - return nil, errs.Wrap(http.StatusInternalServerError, err, - "sshpop.authorizeToken; error checking checking sshpop cert revocation") - } else if isRevoked { - return nil, errs.Unauthorized("sshpop.authorizeToken; sshpop certificate is revoked") - } - // Check validity period of the certificate. n := time.Now() if sshCert.ValidAfter != 0 && time.Unix(int64(sshCert.ValidAfter), 0).After(n) { diff --git a/authority/provisioner/sshpop_test.go b/authority/provisioner/sshpop_test.go index 5d51b90e..79d82e00 100644 --- a/authority/provisioner/sshpop_test.go +++ b/authority/provisioner/sshpop_test.go @@ -11,7 +11,6 @@ import ( "github.com/pkg/errors" "github.com/smallstep/assert" - "github.com/smallstep/certificates/db" "github.com/smallstep/certificates/errs" "go.step.sm/crypto/jose" "go.step.sm/crypto/pemutil" @@ -83,52 +82,9 @@ func TestSSHPOP_authorizeToken(t *testing.T) { err: errors.New("sshpop.authorizeToken; error extracting sshpop header from token: extractSSHPOPCert; error parsing token: "), } }, - "fail/error-revoked-db-check": func(t *testing.T) test { - p, err := generateSSHPOP() - assert.FatalError(t, err) - p.db = &db.MockAuthDB{ - MIsSSHRevoked: func(sn string) (bool, error) { - return false, errors.New("force") - }, - } - cert, jwk, err := createSSHCert(&ssh.Certificate{CertType: ssh.UserCert}, sshSigner) - assert.FatalError(t, err) - tok, err := generateSSHPOPToken(p, cert, jwk) - assert.FatalError(t, err) - return test{ - p: p, - token: tok, - code: http.StatusInternalServerError, - err: errors.New("sshpop.authorizeToken; error checking checking sshpop cert revocation: force"), - } - }, - "fail/cert-already-revoked": func(t *testing.T) test { - p, err := generateSSHPOP() - assert.FatalError(t, err) - p.db = &db.MockAuthDB{ - MIsSSHRevoked: func(sn string) (bool, error) { - return true, nil - }, - } - cert, jwk, err := createSSHCert(&ssh.Certificate{CertType: ssh.UserCert}, sshSigner) - assert.FatalError(t, err) - tok, err := generateSSHPOPToken(p, cert, jwk) - assert.FatalError(t, err) - return test{ - p: p, - token: tok, - code: http.StatusUnauthorized, - err: errors.New("sshpop.authorizeToken; sshpop certificate is revoked"), - } - }, "fail/cert-not-yet-valid": func(t *testing.T) test { p, err := generateSSHPOP() assert.FatalError(t, err) - p.db = &db.MockAuthDB{ - MIsSSHRevoked: func(sn string) (bool, error) { - return false, nil - }, - } cert, jwk, err := createSSHCert(&ssh.Certificate{ CertType: ssh.UserCert, ValidAfter: uint64(time.Now().Add(time.Minute).Unix()), @@ -146,11 +102,6 @@ func TestSSHPOP_authorizeToken(t *testing.T) { "fail/cert-past-validity": func(t *testing.T) test { p, err := generateSSHPOP() assert.FatalError(t, err) - p.db = &db.MockAuthDB{ - MIsSSHRevoked: func(sn string) (bool, error) { - return false, nil - }, - } cert, jwk, err := createSSHCert(&ssh.Certificate{ CertType: ssh.UserCert, ValidBefore: uint64(time.Now().Add(-time.Minute).Unix()), @@ -168,11 +119,6 @@ func TestSSHPOP_authorizeToken(t *testing.T) { "fail/no-signer-found": func(t *testing.T) test { p, err := generateSSHPOP() assert.FatalError(t, err) - p.db = &db.MockAuthDB{ - MIsSSHRevoked: func(sn string) (bool, error) { - return false, nil - }, - } cert, jwk, err := createSSHCert(&ssh.Certificate{CertType: ssh.HostCert}, sshSigner) assert.FatalError(t, err) tok, err := generateSSHPOPToken(p, cert, jwk) @@ -187,11 +133,6 @@ func TestSSHPOP_authorizeToken(t *testing.T) { "fail/error-parsing-claims-bad-sig": func(t *testing.T) test { p, err := generateSSHPOP() assert.FatalError(t, err) - p.db = &db.MockAuthDB{ - MIsSSHRevoked: func(sn string) (bool, error) { - return false, nil - }, - } cert, _, err := createSSHCert(&ssh.Certificate{CertType: ssh.UserCert}, sshSigner) assert.FatalError(t, err) otherJWK, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0) @@ -208,11 +149,6 @@ func TestSSHPOP_authorizeToken(t *testing.T) { "fail/invalid-claims-issuer": func(t *testing.T) test { p, err := generateSSHPOP() assert.FatalError(t, err) - p.db = &db.MockAuthDB{ - MIsSSHRevoked: func(sn string) (bool, error) { - return false, nil - }, - } cert, jwk, err := createSSHCert(&ssh.Certificate{CertType: ssh.UserCert}, sshSigner) assert.FatalError(t, err) tok, err := generateToken("foo", "bar", testAudiences.Sign[0], "", @@ -228,11 +164,6 @@ func TestSSHPOP_authorizeToken(t *testing.T) { "fail/invalid-audience": func(t *testing.T) test { p, err := generateSSHPOP() assert.FatalError(t, err) - p.db = &db.MockAuthDB{ - MIsSSHRevoked: func(sn string) (bool, error) { - return false, nil - }, - } cert, jwk, err := createSSHCert(&ssh.Certificate{CertType: ssh.UserCert}, sshSigner) assert.FatalError(t, err) tok, err := generateToken("foo", p.GetName(), "invalid-aud", "", @@ -248,11 +179,6 @@ func TestSSHPOP_authorizeToken(t *testing.T) { "fail/empty-subject": func(t *testing.T) test { p, err := generateSSHPOP() assert.FatalError(t, err) - p.db = &db.MockAuthDB{ - MIsSSHRevoked: func(sn string) (bool, error) { - return false, nil - }, - } cert, jwk, err := createSSHCert(&ssh.Certificate{CertType: ssh.UserCert}, sshSigner) assert.FatalError(t, err) tok, err := generateToken("", p.GetName(), testAudiences.Sign[0], "", @@ -268,11 +194,6 @@ func TestSSHPOP_authorizeToken(t *testing.T) { "ok": func(t *testing.T) test { p, err := generateSSHPOP() assert.FatalError(t, err) - p.db = &db.MockAuthDB{ - MIsSSHRevoked: func(sn string) (bool, error) { - return false, nil - }, - } cert, jwk, err := createSSHCert(&ssh.Certificate{CertType: ssh.UserCert}, sshSigner) assert.FatalError(t, err) tok, err := generateSSHPOPToken(p, cert, jwk) @@ -330,11 +251,6 @@ func TestSSHPOP_AuthorizeSSHRevoke(t *testing.T) { "fail/subject-not-equal-serial": func(t *testing.T) test { p, err := generateSSHPOP() assert.FatalError(t, err) - p.db = &db.MockAuthDB{ - MIsSSHRevoked: func(sn string) (bool, error) { - return false, nil - }, - } cert, jwk, err := createSSHCert(&ssh.Certificate{CertType: ssh.UserCert}, sshSigner) assert.FatalError(t, err) tok, err := generateToken("foo", p.GetName(), testAudiences.SSHRevoke[0], "", @@ -350,11 +266,6 @@ func TestSSHPOP_AuthorizeSSHRevoke(t *testing.T) { "ok": func(t *testing.T) test { p, err := generateSSHPOP() assert.FatalError(t, err) - p.db = &db.MockAuthDB{ - MIsSSHRevoked: func(sn string) (bool, error) { - return false, nil - }, - } cert, jwk, err := createSSHCert(&ssh.Certificate{Serial: 123455, CertType: ssh.UserCert}, sshSigner) assert.FatalError(t, err) tok, err := generateToken("123455", p.GetName(), testAudiences.SSHRevoke[0], "", @@ -419,11 +330,6 @@ func TestSSHPOP_AuthorizeSSHRenew(t *testing.T) { "fail/not-host-cert": func(t *testing.T) test { p, err := generateSSHPOP() assert.FatalError(t, err) - p.db = &db.MockAuthDB{ - MIsSSHRevoked: func(sn string) (bool, error) { - return false, nil - }, - } cert, jwk, err := createSSHCert(&ssh.Certificate{CertType: ssh.UserCert}, sshUserSigner) assert.FatalError(t, err) tok, err := generateToken("foo", p.GetName(), testAudiences.SSHRenew[0], "", @@ -439,11 +345,6 @@ func TestSSHPOP_AuthorizeSSHRenew(t *testing.T) { "ok": func(t *testing.T) test { p, err := generateSSHPOP() assert.FatalError(t, err) - p.db = &db.MockAuthDB{ - MIsSSHRevoked: func(sn string) (bool, error) { - return false, nil - }, - } cert, jwk, err := createSSHCert(&ssh.Certificate{Serial: 123455, CertType: ssh.HostCert}, sshHostSigner) assert.FatalError(t, err) tok, err := generateToken("123455", p.GetName(), testAudiences.SSHRenew[0], "", @@ -511,11 +412,6 @@ func TestSSHPOP_AuthorizeSSHRekey(t *testing.T) { "fail/not-host-cert": func(t *testing.T) test { p, err := generateSSHPOP() assert.FatalError(t, err) - p.db = &db.MockAuthDB{ - MIsSSHRevoked: func(sn string) (bool, error) { - return false, nil - }, - } cert, jwk, err := createSSHCert(&ssh.Certificate{CertType: ssh.UserCert}, sshUserSigner) assert.FatalError(t, err) tok, err := generateToken("foo", p.GetName(), testAudiences.SSHRekey[0], "", @@ -531,11 +427,6 @@ func TestSSHPOP_AuthorizeSSHRekey(t *testing.T) { "ok": func(t *testing.T) test { p, err := generateSSHPOP() assert.FatalError(t, err) - p.db = &db.MockAuthDB{ - MIsSSHRevoked: func(sn string) (bool, error) { - return false, nil - }, - } cert, jwk, err := createSSHCert(&ssh.Certificate{Serial: 123455, CertType: ssh.HostCert}, sshHostSigner) assert.FatalError(t, err) tok, err := generateToken("123455", p.GetName(), testAudiences.SSHRekey[0], "", diff --git a/authority/ssh.go b/authority/ssh.go index 3b03fd7e..1c873279 100644 --- a/authority/ssh.go +++ b/authority/ssh.go @@ -249,7 +249,11 @@ func (a *Authority) SignSSH(ctx context.Context, key ssh.PublicKey, opts provisi // RenewSSH creates a signed SSH certificate using the old SSH certificate as a template. func (a *Authority) RenewSSH(ctx context.Context, oldCert *ssh.Certificate) (*ssh.Certificate, error) { if oldCert.ValidAfter == 0 || oldCert.ValidBefore == 0 { - return nil, errs.BadRequest("rewnewSSH: cannot renew certificate without validity period") + return nil, errs.BadRequest("renewSSH: cannot renew certificate without validity period") + } + + if err := a.authorizeSSHCertificate(ctx, oldCert); err != nil { + return nil, err } backdate := a.config.AuthorityConfig.Backdate.Duration @@ -319,6 +323,10 @@ func (a *Authority) RekeySSH(ctx context.Context, oldCert *ssh.Certificate, pub return nil, errs.BadRequest("rekeySSH; cannot rekey certificate without validity period") } + if err := a.authorizeSSHCertificate(ctx, oldCert); err != nil { + return nil, err + } + backdate := a.config.AuthorityConfig.Backdate.Duration duration := time.Duration(oldCert.ValidBefore-oldCert.ValidAfter) * time.Second now := time.Now() diff --git a/authority/ssh_test.go b/authority/ssh_test.go index 8ca26af0..e468ecf0 100644 --- a/authority/ssh_test.go +++ b/authority/ssh_test.go @@ -750,6 +750,11 @@ func TestAuthority_RekeySSH(t *testing.T) { now := time.Now().UTC() a := testAuthority(t) + a.db = &db.MockAuthDB{ + MIsSSHRevoked: func(sn string) (bool, error) { + return false, nil + }, + } type test struct { auth *Authority @@ -763,6 +768,56 @@ func TestAuthority_RekeySSH(t *testing.T) { code int } tests := map[string]func(t *testing.T) *test{ + "fail/is-revoked": func(t *testing.T) *test { + auth := testAuthority(t) + auth.db = &db.MockAuthDB{ + MIsSSHRevoked: func(sn string) (bool, error) { + return true, nil + }, + } + return &test{ + auth: auth, + userSigner: signer, + hostSigner: signer, + cert: &ssh.Certificate{ + Serial: 1234567890, + ValidAfter: uint64(now.Unix()), + ValidBefore: uint64(now.Add(time.Hour).Unix()), + CertType: ssh.UserCert, + ValidPrincipals: []string{"foo", "bar"}, + KeyId: "foo", + }, + key: pub, + signOpts: []provisioner.SignOption{}, + err: errors.New("authority.authorizeSSHCertificate: certificate has been revoked"), + code: http.StatusUnauthorized, + } + }, + "fail/is-revoked-error": func(t *testing.T) *test { + auth := testAuthority(t) + auth.db = &db.MockAuthDB{ + MIsSSHRevoked: func(sn string) (bool, error) { + return false, errors.New("an error") + }, + } + return &test{ + auth: auth, + userSigner: signer, + hostSigner: signer, + cert: &ssh.Certificate{ + Serial: 1234567890, + ValidAfter: uint64(now.Unix()), + ValidBefore: uint64(now.Add(time.Hour).Unix()), + CertType: ssh.UserCert, + ValidPrincipals: []string{"foo", "bar"}, + KeyId: "foo", + }, + key: pub, + signOpts: []provisioner.SignOption{}, + err: errors.New("authority.authorizeSSHCertificate: an error"), + code: http.StatusInternalServerError, + } + }, "fail/opts-type": func(t *testing.T) *test { return &test{ userSigner: signer, @@ -831,6 +886,9 @@ func TestAuthority_RekeySSH(t *testing.T) { "fail/db-store": func(t *testing.T) *test { return &test{ auth: testAuthority(t, WithDatabase(&db.MockAuthDB{ + MIsSSHRevoked: func(sn string) (bool, error) { + return false, nil + }, MStoreSSHCertificate: func(cert *ssh.Certificate) error { return errors.New("force") }, From 4ad82a2f769c96a55b8dc1cbf886dbb0142e4803 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Fri, 23 Jul 2021 16:10:13 -0700 Subject: [PATCH 019/195] Check linkedca for revocation. --- authority/authorize.go | 22 ++++++++++++++++++++-- authority/linkedca.go | 24 ++++++++++++++++++++++++ go.mod | 2 +- 3 files changed, 45 insertions(+), 3 deletions(-) diff --git a/authority/authorize.go b/authority/authorize.go index 91a07353..8555db9b 100644 --- a/authority/authorize.go +++ b/authority/authorize.go @@ -271,10 +271,19 @@ func (a *Authority) authorizeRevoke(ctx context.Context, token string) error { // // TODO(mariano): should we authorize by default? func (a *Authority) authorizeRenew(cert *x509.Certificate) error { + var err error + var isRevoked bool var opts = []interface{}{errs.WithKeyVal("serialNumber", cert.SerialNumber.String())} // Check the passive revocation table. - isRevoked, err := a.db.IsRevoked(cert.SerialNumber.String()) + serial := cert.SerialNumber.String() + if lca, ok := a.adminDB.(interface { + IsRevoked(string) (bool, error) + }); ok { + isRevoked, err = lca.IsRevoked(serial) + } else { + isRevoked, err = a.db.IsRevoked(serial) + } if err != nil { return errs.Wrap(http.StatusInternalServerError, err, "authority.authorizeRenew", opts...) } @@ -294,8 +303,17 @@ func (a *Authority) authorizeRenew(cert *x509.Certificate) error { // authorizeSSHCertificate returns an error if the given certificate is revoked. func (a *Authority) authorizeSSHCertificate(ctx context.Context, cert *ssh.Certificate) error { + var err error + var isRevoked bool + serial := strconv.FormatUint(cert.Serial, 10) - isRevoked, err := a.db.IsSSHRevoked(serial) + if lca, ok := a.adminDB.(interface { + IsSSHRevoked(string) (bool, error) + }); ok { + isRevoked, err = lca.IsSSHRevoked(serial) + } else { + isRevoked, err = a.db.IsSSHRevoked(serial) + } if err != nil { return errs.Wrap(http.StatusInternalServerError, err, "authority.authorizeSSHCertificate", errs.WithKeyVal("serialNumber", serial)) } diff --git a/authority/linkedca.go b/authority/linkedca.go index 117f19ef..79427c5c 100644 --- a/authority/linkedca.go +++ b/authority/linkedca.go @@ -269,6 +269,30 @@ func (c *linkedCaClient) StoreSSHCertificate(crt *ssh.Certificate) error { return errors.Wrap(err, "error posting ssh certificate") } +func (c *linkedCaClient) IsRevoked(serial string) (bool, error) { + ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) + defer cancel() + resp, err := c.client.GetCertificateStatus(ctx, &linkedca.GetCertificateStatusRequest{ + Serial: serial, + }) + if err != nil { + return false, errors.Wrap(err, "error getting certificate status") + } + return resp.Status != linkedca.RevocationStatus_ACTIVE, nil +} + +func (c *linkedCaClient) IsSSHRevoked(serial string) (bool, error) { + ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) + defer cancel() + resp, err := c.client.GetSSHCertificateStatus(ctx, &linkedca.GetSSHCertificateStatusRequest{ + Serial: serial, + }) + if err != nil { + return false, errors.Wrap(err, "error getting certificate status") + } + return resp.Status != linkedca.RevocationStatus_ACTIVE, nil +} + func serializeCertificateChain(fullchain ...*x509.Certificate) string { var chain string for _, crt := range fullchain { diff --git a/go.mod b/go.mod index 6957cc83..98e7dbdb 100644 --- a/go.mod +++ b/go.mod @@ -28,7 +28,7 @@ require ( go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1 go.step.sm/cli-utils v0.4.1 go.step.sm/crypto v0.9.0 - go.step.sm/linkedca v0.1.0 + go.step.sm/linkedca v0.3.0 golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 golang.org/x/net v0.0.0-20210716203947-853a461950ff golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c // indirect From 3a00b6b39656fb8bba385cdada98b35f56a8f0ed Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Mon, 26 Jul 2021 14:31:42 -0700 Subject: [PATCH 020/195] Properly marshal a certificate when we send it to linkedca. --- authority/linkedca.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/authority/linkedca.go b/authority/linkedca.go index 79427c5c..75bc6e1a 100644 --- a/authority/linkedca.go +++ b/authority/linkedca.go @@ -6,7 +6,6 @@ import ( "crypto/sha256" "crypto/tls" "crypto/x509" - "encoding/base64" "encoding/hex" "encoding/pem" "fmt" @@ -264,7 +263,7 @@ func (c *linkedCaClient) StoreSSHCertificate(crt *ssh.Certificate) error { ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) defer cancel() _, err := c.client.PostSSHCertificate(ctx, &linkedca.SSHCertificateRequest{ - Certificate: base64.StdEncoding.EncodeToString(crt.Marshal()), + Certificate: string(ssh.MarshalAuthorizedKey(crt)), }) return errors.Wrap(err, "error posting ssh certificate") } From d0c1530f894ce9f5189de950b81c054fc64cf2a6 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Mon, 26 Jul 2021 14:48:01 -0700 Subject: [PATCH 021/195] Remove replace of linkedca package. --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 98e7dbdb..2c7a0687 100644 --- a/go.mod +++ b/go.mod @@ -42,6 +42,6 @@ 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 replace go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1 => github.com/omorsi/pkcs7 v0.0.0-20210217142924-a7b80a2a8568 diff --git a/go.sum b/go.sum index 140557ba..9310efc5 100644 --- a/go.sum +++ b/go.sum @@ -528,8 +528,8 @@ go.step.sm/cli-utils v0.4.1 h1:QztRUhGYjOPM1I2Nmi7V6XejQyVtcESmo+sbegxvX7Q= go.step.sm/cli-utils v0.4.1/go.mod h1:hWYVOSlw8W9Pd+BwIbs/aftVVMRms3EG7Q2qLRwc0WA= go.step.sm/crypto v0.9.0 h1:q2AllTSnVj4NRtyEPkGW2ohArLmbGbe6ZAL/VIOKDzA= go.step.sm/crypto v0.9.0/go.mod h1:+CYG05Mek1YDqi5WK0ERc6cOpKly2i/a5aZmU1sfGj0= -go.step.sm/linkedca v0.1.0 h1:2kVdQZi37pIijm1thSYVOQ/mKoREPYNXulUZj/G0azM= -go.step.sm/linkedca v0.1.0/go.mod h1:5uTRjozEGSPAZal9xJqlaD38cvJcLe3o1VAFVjqcORo= +go.step.sm/linkedca v0.3.0 h1:6jyghg/ErVTJ/J23DrbWhGyWbWX2b4aJkPQEGL4xZ40= +go.step.sm/linkedca v0.3.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.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= From dc1ec18b52287d09e68082c1ec7bc5b469b55916 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Mon, 26 Jul 2021 19:01:56 -0700 Subject: [PATCH 022/195] Create a way to export ca configurations. --- authority/export.go | 39 +++++ authority/provisioners.go | 331 ++++++++++++++++++++++++++++++++++++++ commands/export.go | 74 +++++++++ go.mod | 2 +- 4 files changed, 445 insertions(+), 1 deletion(-) create mode 100644 authority/export.go create mode 100644 commands/export.go diff --git a/authority/export.go b/authority/export.go new file mode 100644 index 00000000..e8f7298e --- /dev/null +++ b/authority/export.go @@ -0,0 +1,39 @@ +package authority + +import "go.step.sm/linkedca" + +func (a *Authority) Export() (*linkedca.Configuration, error) { + var admins []*linkedca.Admin + var provisioners []*linkedca.Provisioner + + for { + list, cursor := a.admins.Find("", 100) + admins = append(admins, list...) + if cursor == "" { + break + } + } + + for { + list, cursor := a.provisioners.Find("", 100) + for _, p := range list { + lp, err := ProvisionerToLinkedca(p) + if err != nil { + return nil, err + } + provisioners = append(provisioners, lp) + } + if cursor == "" { + break + } + } + + // Global claims for all provisioners. + claims := claimsToLinkedca(a.config.AuthorityConfig.Claims) + + return &linkedca.Configuration{ + Admins: admins, + Provisioners: provisioners, + Claims: claims, + }, nil +} diff --git a/authority/provisioners.go b/authority/provisioners.go index d2581e76..3e2d1276 100644 --- a/authority/provisioners.go +++ b/authority/provisioners.go @@ -4,12 +4,16 @@ import ( "context" "crypto/x509" "encoding/json" + "encoding/pem" "fmt" + "io/ioutil" + "github.com/pkg/errors" "github.com/smallstep/certificates/authority/admin" "github.com/smallstep/certificates/authority/config" "github.com/smallstep/certificates/authority/provisioner" "github.com/smallstep/certificates/errs" + step "go.step.sm/cli-utils/config" "go.step.sm/crypto/jose" "go.step.sm/linkedca" "gopkg.in/square/go-jose.v2/jwt" @@ -398,6 +402,13 @@ func durationsToCertificates(d *linkedca.Durations) (min, max, def *provisioner. return } +func durationsToLinkedca(d *provisioner.Duration) string { + if d == nil { + return "" + } + return d.Duration.String() +} + // claimsToCertificates converts the linkedca provisioner claims type to the // certifictes claims type. func claimsToCertificates(c *linkedca.Claims) (*provisioner.Claims, error) { @@ -438,6 +449,109 @@ func claimsToCertificates(c *linkedca.Claims) (*provisioner.Claims, error) { return pc, nil } +func claimsToLinkedca(c *provisioner.Claims) *linkedca.Claims { + if c == nil { + return nil + } + + disableRenewal := config.DefaultDisableRenewal + if c.DisableRenewal != nil { + disableRenewal = *c.DisableRenewal + } + + lc := &linkedca.Claims{ + DisableRenewal: disableRenewal, + } + + if c.DefaultTLSDur != nil || c.MinTLSDur != nil || c.MaxTLSDur != nil { + lc.X509 = &linkedca.X509Claims{ + Enabled: true, + Durations: &linkedca.Durations{ + Default: durationsToLinkedca(c.DefaultTLSDur), + Min: durationsToLinkedca(c.MinTLSDur), + Max: durationsToLinkedca(c.MaxTLSDur), + }, + } + } + + if c.EnableSSHCA != nil && *c.EnableSSHCA { + lc.Ssh = &linkedca.SSHClaims{ + Enabled: true, + } + if c.DefaultUserSSHDur != nil || c.MinUserSSHDur != nil || c.MaxUserSSHDur != nil { + lc.Ssh.UserDurations = &linkedca.Durations{ + Default: durationsToLinkedca(c.DefaultUserSSHDur), + Min: durationsToLinkedca(c.MinUserSSHDur), + Max: durationsToLinkedca(c.MaxUserSSHDur), + } + } + if c.DefaultHostSSHDur != nil || c.MinHostSSHDur != nil || c.MaxHostSSHDur != nil { + lc.Ssh.HostDurations = &linkedca.Durations{ + Default: durationsToLinkedca(c.DefaultHostSSHDur), + Min: durationsToLinkedca(c.MinHostSSHDur), + Max: durationsToLinkedca(c.MaxHostSSHDur), + } + } + } + + return lc +} + +func provisionerOptionsToLinkedca(p *provisioner.Options) (*linkedca.Template, *linkedca.Template, error) { + var err error + var x509Template, sshTemplate *linkedca.Template + + if p == nil { + return nil, nil, nil + } + + if p.X509 != nil && p.X509.HasTemplate() { + x509Template = &linkedca.Template{ + Template: nil, + Data: nil, + } + + if p.X509.Template != "" { + x509Template.Template = []byte(p.SSH.Template) + } else if p.X509.TemplateFile != "" { + filename := step.StepAbs(p.X509.TemplateFile) + if x509Template.Template, err = ioutil.ReadFile(filename); err != nil { + return nil, nil, errors.Wrap(err, "error reading x509 template") + } + } + } + + if p.SSH != nil && p.SSH.HasTemplate() { + sshTemplate = &linkedca.Template{ + Template: nil, + Data: nil, + } + + if p.SSH.Template != "" { + sshTemplate.Template = []byte(p.SSH.Template) + } else if p.SSH.TemplateFile != "" { + filename := step.StepAbs(p.SSH.TemplateFile) + if sshTemplate.Template, err = ioutil.ReadFile(filename); err != nil { + return nil, nil, errors.Wrap(err, "error reading ssh template") + } + } + } + + return x509Template, sshTemplate, nil +} + +func provisionerPEMToLinkedca(b []byte) [][]byte { + var roots [][]byte + var block *pem.Block + for { + if block, b = pem.Decode(b); block == nil { + break + } + roots = append(roots, pem.EncodeToMemory(block)) + } + return roots +} + // ProvisionerToCertificates converts the linkedca provisioner type to the certificates provisioner // interface. func ProvisionerToCertificates(p *linkedca.Provisioner) (provisioner.Interface, error) { @@ -588,6 +702,223 @@ func ProvisionerToCertificates(p *linkedca.Provisioner) (provisioner.Interface, } } +// ProvisionerToLinkedca converts a provisioner.Interface to a +// linkedca.Provisioner type. +func ProvisionerToLinkedca(p provisioner.Interface) (*linkedca.Provisioner, error) { + switch p := p.(type) { + case *provisioner.JWK: + x509Template, sshTemplate, err := provisionerOptionsToLinkedca(p.Options) + if err != nil { + return nil, err + } + publicKey, err := json.Marshal(p.Key) + if err != nil { + return nil, errors.Wrap(err, "error marshaling key") + } + return &linkedca.Provisioner{ + Type: linkedca.Provisioner_JWK, + Name: p.GetName(), + Details: &linkedca.ProvisionerDetails{ + Data: &linkedca.ProvisionerDetails_JWK{ + JWK: &linkedca.JWKProvisioner{ + PublicKey: publicKey, + EncryptedPrivateKey: []byte(p.EncryptedKey), + }, + }, + }, + Claims: claimsToLinkedca(p.Claims), + X509Template: x509Template, + SshTemplate: sshTemplate, + }, nil + case *provisioner.OIDC: + x509Template, sshTemplate, err := provisionerOptionsToLinkedca(p.Options) + if err != nil { + return nil, err + } + return &linkedca.Provisioner{ + Type: linkedca.Provisioner_OIDC, + Name: p.GetName(), + Details: &linkedca.ProvisionerDetails{ + Data: &linkedca.ProvisionerDetails_OIDC{ + OIDC: &linkedca.OIDCProvisioner{ + ClientId: p.ClientID, + ClientSecret: p.ClientSecret, + ConfigurationEndpoint: p.ConfigurationEndpoint, + Admins: p.Admins, + Domains: p.Domains, + Groups: p.Groups, + ListenAddress: p.ListenAddress, + TenantId: p.TenantID, + }, + }, + }, + Claims: claimsToLinkedca(p.Claims), + X509Template: x509Template, + SshTemplate: sshTemplate, + }, nil + case *provisioner.GCP: + x509Template, sshTemplate, err := provisionerOptionsToLinkedca(p.Options) + if err != nil { + return nil, err + } + return &linkedca.Provisioner{ + Type: linkedca.Provisioner_GCP, + Name: p.GetName(), + Details: &linkedca.ProvisionerDetails{ + Data: &linkedca.ProvisionerDetails_GCP{ + GCP: &linkedca.GCPProvisioner{ + ServiceAccounts: p.ServiceAccounts, + ProjectIds: p.ProjectIDs, + DisableCustomSans: p.DisableCustomSANs, + DisableTrustOnFirstUse: p.DisableTrustOnFirstUse, + InstanceAge: p.InstanceAge.String(), + }, + }, + }, + Claims: claimsToLinkedca(p.Claims), + X509Template: x509Template, + SshTemplate: sshTemplate, + }, nil + case *provisioner.AWS: + x509Template, sshTemplate, err := provisionerOptionsToLinkedca(p.Options) + if err != nil { + return nil, err + } + return &linkedca.Provisioner{ + Type: linkedca.Provisioner_AWS, + Name: p.GetName(), + Details: &linkedca.ProvisionerDetails{ + Data: &linkedca.ProvisionerDetails_AWS{ + AWS: &linkedca.AWSProvisioner{ + Accounts: p.Accounts, + DisableCustomSans: p.DisableCustomSANs, + DisableTrustOnFirstUse: p.DisableTrustOnFirstUse, + InstanceAge: p.InstanceAge.String(), + }, + }, + }, + Claims: claimsToLinkedca(p.Claims), + X509Template: x509Template, + SshTemplate: sshTemplate, + }, nil + case *provisioner.Azure: + x509Template, sshTemplate, err := provisionerOptionsToLinkedca(p.Options) + if err != nil { + return nil, err + } + return &linkedca.Provisioner{ + Type: linkedca.Provisioner_AZURE, + Name: p.GetName(), + Details: &linkedca.ProvisionerDetails{ + Data: &linkedca.ProvisionerDetails_Azure{ + Azure: &linkedca.AzureProvisioner{ + TenantId: p.TenantID, + ResourceGroups: p.ResourceGroups, + Audience: p.Audience, + DisableCustomSans: p.DisableCustomSANs, + DisableTrustOnFirstUse: p.DisableTrustOnFirstUse, + }, + }, + }, + Claims: claimsToLinkedca(p.Claims), + X509Template: x509Template, + SshTemplate: sshTemplate, + }, nil + case *provisioner.ACME: + x509Template, sshTemplate, err := provisionerOptionsToLinkedca(p.Options) + if err != nil { + return nil, err + } + return &linkedca.Provisioner{ + Type: linkedca.Provisioner_ACME, + Name: p.GetName(), + Details: &linkedca.ProvisionerDetails{ + Data: &linkedca.ProvisionerDetails_ACME{ + ACME: &linkedca.ACMEProvisioner{ + ForceCn: p.ForceCN, + }, + }, + }, + Claims: claimsToLinkedca(p.Claims), + X509Template: x509Template, + SshTemplate: sshTemplate, + }, nil + case *provisioner.X5C: + x509Template, sshTemplate, err := provisionerOptionsToLinkedca(p.Options) + if err != nil { + return nil, err + } + return &linkedca.Provisioner{ + Type: linkedca.Provisioner_X5C, + Name: p.GetName(), + Details: &linkedca.ProvisionerDetails{ + Data: &linkedca.ProvisionerDetails_X5C{ + X5C: &linkedca.X5CProvisioner{ + Roots: provisionerPEMToLinkedca(p.Roots), + }, + }, + }, + Claims: claimsToLinkedca(p.Claims), + X509Template: x509Template, + SshTemplate: sshTemplate, + }, nil + case *provisioner.K8sSA: + x509Template, sshTemplate, err := provisionerOptionsToLinkedca(p.Options) + if err != nil { + return nil, err + } + return &linkedca.Provisioner{ + Type: linkedca.Provisioner_K8SSA, + Name: p.GetName(), + Details: &linkedca.ProvisionerDetails{ + Data: &linkedca.ProvisionerDetails_K8SSA{ + K8SSA: &linkedca.K8SSAProvisioner{ + PublicKeys: provisionerPEMToLinkedca(p.PubKeys), + }, + }, + }, + Claims: claimsToLinkedca(p.Claims), + X509Template: x509Template, + SshTemplate: sshTemplate, + }, nil + case *provisioner.SSHPOP: + return &linkedca.Provisioner{ + Type: linkedca.Provisioner_SSHPOP, + Name: p.GetName(), + Details: &linkedca.ProvisionerDetails{ + Data: &linkedca.ProvisionerDetails_SSHPOP{ + SSHPOP: &linkedca.SSHPOPProvisioner{}, + }, + }, + Claims: claimsToLinkedca(p.Claims), + }, nil + case *provisioner.SCEP: + x509Template, sshTemplate, err := provisionerOptionsToLinkedca(p.Options) + if err != nil { + return nil, err + } + return &linkedca.Provisioner{ + Type: linkedca.Provisioner_SCEP, + Name: p.GetName(), + Details: &linkedca.ProvisionerDetails{ + Data: &linkedca.ProvisionerDetails_SCEP{ + SCEP: &linkedca.SCEPProvisioner{ + ForceCn: p.ForceCN, + Challenge: p.GetChallengePassword(), + Capabilities: p.Capabilities, + MinimumPublicKeyLength: int32(p.MinimumPublicKeyLength), + }, + }, + }, + Claims: claimsToLinkedca(p.Claims), + X509Template: x509Template, + SshTemplate: sshTemplate, + }, nil + default: + return nil, fmt.Errorf("provisioner %s not implemented", p.GetType()) + } +} + func parseInstanceAge(age string) (provisioner.Duration, error) { var instanceAge provisioner.Duration if age != "" { diff --git a/commands/export.go b/commands/export.go new file mode 100644 index 00000000..bb11fea7 --- /dev/null +++ b/commands/export.go @@ -0,0 +1,74 @@ +package commands + +import ( + "bytes" + "encoding/json" + "fmt" + + "github.com/pkg/errors" + "github.com/smallstep/certificates/authority" + "github.com/smallstep/certificates/authority/config" + "github.com/urfave/cli" + "google.golang.org/protobuf/encoding/protojson" + + "go.step.sm/cli-utils/command" + "go.step.sm/cli-utils/errs" +) + +func init() { + command.Register(cli.Command{ + Name: "export", + Usage: "export the current configuration of step-ca", + UsageText: "**step-ca export** ", + Action: exportAction, + Description: `**step-ca export** exports the current configuration of step-ca. + +## POSITIONAL ARGUMENTS + + +: The ca.json that contains the step-ca configuration. + +## EXAMPLES + +Export the current configuration: +''' +$ step-ca export $(step path)/config/ca.json +'''`, + }) +} + +func exportAction(ctx *cli.Context) error { + if err := errs.NumberOfArguments(ctx, 1); err != nil { + return err + } + + configFile := ctx.Args().Get(0) + + config, err := config.LoadConfiguration(configFile) + if err != nil { + return err + } + + auth, err := authority.New(config) + if err != nil { + return err + } + + export, err := auth.Export() + if err != nil { + return err + } + + b, err := protojson.Marshal(export) + if err != nil { + return errors.Wrap(err, "error marshaling export") + } + + var buf bytes.Buffer + if err := json.Indent(&buf, b, "", "\t"); err != nil { + return errors.Wrap(err, "error indenting export") + } + + fmt.Println(buf.String()) + return nil +} diff --git a/go.mod b/go.mod index 2c7a0687..98e7dbdb 100644 --- a/go.mod +++ b/go.mod @@ -42,6 +42,6 @@ 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 replace go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1 => github.com/omorsi/pkcs7 v0.0.0-20210217142924-a7b80a2a8568 From 8f4c833845bf59610f0f805574c8ca3232b8c942 Mon Sep 17 00:00:00 2001 From: Carl Tashian Date: Tue, 27 Jul 2021 12:01:50 -0700 Subject: [PATCH 023/195] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 544dd5b5..ca08cbe5 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ You can use it to: Whatever your use case, `step-ca` is easy to use and hard to misuse, thanks to [safe, sane defaults](https://smallstep.com/docs/step-ca/certificate-authority-server-production#sane-cryptographic-defaults). -**Questions? Find us in [Discussions](https://github.com/smallstep/certificates/discussions).** +**Questions? Find us in [Discussions](https://github.com/smallstep/certificates/discussions) or [Join our Discord](https://bit.ly/stepdiscord).** [Website](https://smallstep.com/certificates) | [Documentation](https://smallstep.com/docs) | From 53d08e1f5c97261f424dec68184536d67fed4ea9 Mon Sep 17 00:00:00 2001 From: Carl Tashian Date: Tue, 27 Jul 2021 12:03:52 -0700 Subject: [PATCH 024/195] Remove microbadger.com (the website is gone) --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index ca08cbe5..79e567ab 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,6 @@ Whatever your use case, `step-ca` is easy to use and hard to misuse, thanks to [ [Contributor's Guide](./docs/CONTRIBUTING.md) [![GitHub release](https://img.shields.io/github/release/smallstep/certificates.svg)](https://github.com/smallstep/certificates/releases/latest) -[![CA Image](https://images.microbadger.com/badges/image/smallstep/step-ca.svg)](https://microbadger.com/images/smallstep/step-ca) [![Go Report Card](https://goreportcard.com/badge/github.com/smallstep/certificates)](https://goreportcard.com/report/github.com/smallstep/certificates) [![Build Status](https://travis-ci.com/smallstep/certificates.svg?branch=master)](https://travis-ci.com/smallstep/certificates) [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) From 887423ee6e520466c2c2b75abb53f62c84de1755 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Tue, 27 Jul 2021 18:29:10 -0700 Subject: [PATCH 025/195] Update TLS cipher suites. --- authority/config/tls_options.go | 53 ++++++++++++++++++++------------- 1 file changed, 32 insertions(+), 21 deletions(-) diff --git a/authority/config/tls_options.go b/authority/config/tls_options.go index 996b5834..ed61cfc9 100644 --- a/authority/config/tls_options.go +++ b/authority/config/tls_options.go @@ -119,27 +119,38 @@ func (c CipherSuites) Value() []uint16 { // cipherSuites has the list of supported cipher suites. var cipherSuites = map[string]uint16{ - "TLS_RSA_WITH_RC4_128_SHA": tls.TLS_RSA_WITH_RC4_128_SHA, - "TLS_RSA_WITH_3DES_EDE_CBC_SHA": tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA, - "TLS_RSA_WITH_AES_128_CBC_SHA": tls.TLS_RSA_WITH_AES_128_CBC_SHA, - "TLS_RSA_WITH_AES_256_CBC_SHA": tls.TLS_RSA_WITH_AES_256_CBC_SHA, - "TLS_RSA_WITH_AES_128_CBC_SHA256": tls.TLS_RSA_WITH_AES_128_CBC_SHA256, - "TLS_RSA_WITH_AES_128_GCM_SHA256": tls.TLS_RSA_WITH_AES_128_GCM_SHA256, - "TLS_RSA_WITH_AES_256_GCM_SHA384": tls.TLS_RSA_WITH_AES_256_GCM_SHA384, - "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA": tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, - "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA": tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, - "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256": tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, - "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256": tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, - "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA": tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, - "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384": tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, - "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305": tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, - "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA": tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, - "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA": tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, - "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256": tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, - "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256": tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, - "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA": tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, - "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384": tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, - "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305": tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, + // TLS 1.0 - 1.2 cipher suites. + "TLS_RSA_WITH_RC4_128_SHA": tls.TLS_RSA_WITH_RC4_128_SHA, + "TLS_RSA_WITH_3DES_EDE_CBC_SHA": tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA, + "TLS_RSA_WITH_AES_128_CBC_SHA": tls.TLS_RSA_WITH_AES_128_CBC_SHA, + "TLS_RSA_WITH_AES_256_CBC_SHA": tls.TLS_RSA_WITH_AES_256_CBC_SHA, + "TLS_RSA_WITH_AES_128_CBC_SHA256": tls.TLS_RSA_WITH_AES_128_CBC_SHA256, + "TLS_RSA_WITH_AES_128_GCM_SHA256": tls.TLS_RSA_WITH_AES_128_GCM_SHA256, + "TLS_RSA_WITH_AES_256_GCM_SHA384": tls.TLS_RSA_WITH_AES_256_GCM_SHA384, + "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA": tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, + "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA": tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, + "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA": tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, + "TLS_ECDHE_RSA_WITH_RC4_128_SHA": tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA, + "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA": tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, + "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA": tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, + "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA": tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, + "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256": tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, + "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256": tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, + "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256": tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256": tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384": tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384": tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256": tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, + "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256": tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, + + // TLS 1.3 cipher sutes. + "TLS_AES_128_GCM_SHA256": tls.TLS_AES_128_GCM_SHA256, + "TLS_AES_256_GCM_SHA384": tls.TLS_AES_256_GCM_SHA384, + "TLS_CHACHA20_POLY1305_SHA256": tls.TLS_CHACHA20_POLY1305_SHA256, + + // Legacy names. + "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305": tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, + "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305": tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, } // TLSOptions represents the TLS options that can be specified on *tls.Config From c7f8516142bed7ce577f7a439629f31321fcb684 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Tue, 27 Jul 2021 18:29:29 -0700 Subject: [PATCH 026/195] Add to export all the information in the ca.json --- authority/export.go | 235 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 222 insertions(+), 13 deletions(-) diff --git a/authority/export.go b/authority/export.go index e8f7298e..f78f7fbb 100644 --- a/authority/export.go +++ b/authority/export.go @@ -1,19 +1,118 @@ package authority -import "go.step.sm/linkedca" +import ( + "encoding/json" + "io/ioutil" + "net/url" + "strings" -func (a *Authority) Export() (*linkedca.Configuration, error) { - var admins []*linkedca.Admin - var provisioners []*linkedca.Provisioner + "github.com/pkg/errors" + step "go.step.sm/cli-utils/config" + "go.step.sm/linkedca/config" + "google.golang.org/protobuf/types/known/structpb" +) +func (a *Authority) Export() (c *config.Configuration, err error) { + // Recover from panics + defer func() { + if r := recover(); r != nil { + err = r.(error) + } + }() + + c = &config.Configuration{ + Root: mustReadFilesOrUris(a.config.Root), + FederatedRoots: mustReadFilesOrUris(a.config.FederatedRoots), + Intermediate: mustReadFileOrUri(a.config.IntermediateCert), + IntermediateKey: mustReadFileOrUri(a.config.IntermediateKey), + Address: a.config.Address, + InsecureAddress: a.config.InsecureAddress, + DnsNames: a.config.DNSNames, + Db: mustMarshalToStruct(a.config.DB), + Logger: mustMarshalToStruct(a.config.Logger), + Monitoring: mustMarshalToStruct(a.config.Monitoring), + Authority: &config.Authority{}, + Password: mustPassword(a.config.Password), + } + + // SSH + if v := a.config.SSH; v != nil { + c.Ssh = &config.SSH{ + HostKey: mustReadFileOrUri(v.HostKey), + UserKey: mustReadFileOrUri(v.UserKey), + AddUserPrincipal: v.AddUserPrincipal, + AddUserCommand: v.AddUserCommand, + } + for _, k := range v.Keys { + typ, ok := config.SSHPublicKey_Type_value[strings.ToUpper(k.Type)] + if !ok { + return nil, errors.Errorf("unsupported ssh key type %s", k.Type) + } + c.Ssh.Keys = append(c.Ssh.Keys, &config.SSHPublicKey{ + Type: config.SSHPublicKey_Type(typ), + Federated: k.Federated, + Key: mustMarshalToStruct(k), + }) + } + } + + // KMS + if v := a.config.KMS; v != nil { + var typ int32 + var ok bool + if v.Type == "" { + typ = int32(config.KMS_SOFTKMS) + } else { + typ, ok = config.KMS_Type_value[strings.ToUpper(v.Type)] + if !ok { + return nil, errors.Errorf("unsupported kms type %s", v.Type) + } + } + c.Kms = &config.KMS{ + Type: config.KMS_Type(typ), + CredentialsFile: v.CredentialsFile, + Uri: v.URI, + Pin: v.Pin, + ManagementKey: v.ManagementKey, + Region: v.Region, + Profile: v.Profile, + } + } + + // Authority + c.Authority.Id = a.config.AuthorityConfig.AuthorityID + + // cas options + if v := a.config.AuthorityConfig.Options; v != nil { + c.Authority.Type = 0 + c.Authority.CertificateAuthority = v.CertificateAuthority + c.Authority.CertificateAuthorityFingerprint = v.CertificateAuthorityFingerprint + c.Authority.CredentialsFile = v.CredentialsFile + if iss := v.CertificateIssuer; iss != nil { + typ, ok := config.CertificateIssuer_Type_value[strings.ToUpper(iss.Type)] + if !ok { + return nil, errors.Errorf("unknown certificate issuer type %s", iss.Type) + } + c.Authority.CertificateIssuer = &config.CertificateIssuer{ + Type: config.CertificateIssuer_Type(typ), + Provisioner: iss.Provisioner, + Certificate: mustReadFileOrUri(iss.Certificate), + Key: mustReadFileOrUri(iss.Key), + Password: mustPassword(iss.Password), + } + } + } + + // admins for { list, cursor := a.admins.Find("", 100) - admins = append(admins, list...) + c.Authority.Admins = append(c.Authority.Admins, list...) if cursor == "" { break } } + // provisioners for { list, cursor := a.provisioners.Find("", 100) for _, p := range list { @@ -21,19 +120,129 @@ func (a *Authority) Export() (*linkedca.Configuration, error) { if err != nil { return nil, err } - provisioners = append(provisioners, lp) + c.Authority.Provisioners = append(c.Authority.Provisioners, lp) } if cursor == "" { break } } + c.Authority.Claims = claimsToLinkedca(a.config.AuthorityConfig.Claims) - // Global claims for all provisioners. - claims := claimsToLinkedca(a.config.AuthorityConfig.Claims) + // TLS + if v := a.config.TLS; v != nil { + c.Tls = &config.TLS{ + MinVersion: v.MinVersion.String(), + MaxVersion: v.MaxVersion.String(), + Renegotiation: v.Renegotiation, + } + for _, cs := range v.CipherSuites.Value() { + c.Tls.CipherSuites = append(c.Tls.CipherSuites, config.TLS_CiperSuite(cs)) + } + } - return &linkedca.Configuration{ - Admins: admins, - Provisioners: provisioners, - Claims: claims, - }, nil + // Templates + if v := a.config.Templates; v != nil { + c.Templates = &config.Templates{ + Ssh: &config.SSHTemplate{}, + Data: mustMarshalToStruct(v.Data), + } + // Remove automatically loaded vars + if c.Templates.Data != nil && c.Templates.Data.Fields != nil { + delete(c.Templates.Data.Fields, "Step") + } + for _, t := range v.SSH.Host { + typ, ok := config.Template_Type_value[strings.ToUpper(string(t.Type))] + if !ok { + return nil, errors.Errorf("unsupported template type %s", t.Type) + } + content := t.Content + if len(content) == 0 { + content = mustReadFileOrUri(t.TemplatePath) + } + c.Templates.Ssh.Hosts = append(c.Templates.Ssh.Hosts, &config.Template{ + Type: config.Template_Type(typ), + Name: t.Name, + Template: t.TemplatePath, + Path: t.Path, + Comment: t.Comment, + Requires: t.RequiredData, + Content: content, + }) + } + for _, t := range v.SSH.User { + typ, ok := config.Template_Type_value[strings.ToUpper(string(t.Type))] + if !ok { + return nil, errors.Errorf("unsupported template type %s", t.Type) + } + content := t.Content + if len(content) == 0 { + content = mustReadFileOrUri(t.TemplatePath) + } + c.Templates.Ssh.Users = append(c.Templates.Ssh.Users, &config.Template{ + Type: config.Template_Type(typ), + Name: t.Name, + Template: t.TemplatePath, + Path: t.Path, + Comment: t.Comment, + Requires: t.RequiredData, + Content: content, + }) + } + } + + return c, nil +} + +func mustPassword(s string) []byte { + if s == "" { + return nil + } + return []byte(s) +} + +func mustMarshalToStruct(v interface{}) *structpb.Struct { + b, err := json.Marshal(v) + if err != nil { + panic(errors.Wrapf(err, "error marshaling %T", v)) + } + var r *structpb.Struct + if err := json.Unmarshal(b, &r); err != nil { + panic(errors.Wrapf(err, "error unmarshaling %T", v)) + } + return r +} + +func mustReadFileOrUri(fn string) []byte { + if fn == "" { + return nil + } + + ok, err := isFilename(fn) + if err != nil { + panic(err) + } + if ok { + b, err := ioutil.ReadFile(step.StepAbs(fn)) + if err != nil { + panic(errors.Wrapf(err, "error reading %s", fn)) + } + return b + } + return []byte(fn) +} + +func mustReadFilesOrUris(fns []string) [][]byte { + var result [][]byte + for _, fn := range fns { + result = append(result, mustReadFileOrUri(fn)) + } + return result +} + +func isFilename(fn string) (bool, error) { + u, err := url.Parse(fn) + if err != nil { + return false, errors.Wrapf(err, "error parsing %s", fn) + } + return u.Scheme == "" || u.Scheme == "file", nil } From 0730a165fd5d0a79c3881613235cae6c423381bf Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Tue, 27 Jul 2021 19:19:58 -0700 Subject: [PATCH 027/195] Add collection of files and authority template. --- authority/config/config.go | 1 + authority/export.go | 85 +++++++++++++++++++++++--------------- authority/tls.go | 8 +++- 3 files changed, 59 insertions(+), 35 deletions(-) diff --git a/authority/config/config.go b/authority/config/config.go index fabd3f91..4d7592ac 100644 --- a/authority/config/config.go +++ b/authority/config/config.go @@ -75,6 +75,7 @@ type ASN1DN struct { Locality string `json:"locality,omitempty"` Province string `json:"province,omitempty"` StreetAddress string `json:"streetAddress,omitempty"` + SerialNumber string `json:"serialNumber,omitempty"` CommonName string `json:"commonName,omitempty"` } diff --git a/authority/export.go b/authority/export.go index f78f7fbb..316ede0e 100644 --- a/authority/export.go +++ b/authority/export.go @@ -4,6 +4,7 @@ import ( "encoding/json" "io/ioutil" "net/url" + "path/filepath" "strings" "github.com/pkg/errors" @@ -20,26 +21,34 @@ func (a *Authority) Export() (c *config.Configuration, err error) { } }() + files := make(map[string][]byte) c = &config.Configuration{ - Root: mustReadFilesOrUris(a.config.Root), - FederatedRoots: mustReadFilesOrUris(a.config.FederatedRoots), - Intermediate: mustReadFileOrUri(a.config.IntermediateCert), - IntermediateKey: mustReadFileOrUri(a.config.IntermediateKey), + Version: "1.0", + Root: mustReadFilesOrUris(a.config.Root, files), + FederatedRoots: mustReadFilesOrUris(a.config.FederatedRoots, files), + Intermediate: mustReadFileOrUri(a.config.IntermediateCert, files), + IntermediateKey: mustReadFileOrUri(a.config.IntermediateKey, files), Address: a.config.Address, InsecureAddress: a.config.InsecureAddress, DnsNames: a.config.DNSNames, Db: mustMarshalToStruct(a.config.DB), Logger: mustMarshalToStruct(a.config.Logger), Monitoring: mustMarshalToStruct(a.config.Monitoring), - Authority: &config.Authority{}, - Password: mustPassword(a.config.Password), + Authority: &config.Authority{ + Id: a.config.AuthorityConfig.AuthorityID, + EnableAdmin: a.config.AuthorityConfig.EnableAdmin, + DisableIssuedAtCheck: a.config.AuthorityConfig.DisableIssuedAtCheck, + Backdate: a.config.AuthorityConfig.Backdate.String(), + }, + Password: mustPassword(a.config.Password), + Files: files, } // SSH if v := a.config.SSH; v != nil { c.Ssh = &config.SSH{ - HostKey: mustReadFileOrUri(v.HostKey), - UserKey: mustReadFileOrUri(v.UserKey), + HostKey: mustReadFileOrUri(v.HostKey, files), + UserKey: mustReadFileOrUri(v.UserKey, files), AddUserPrincipal: v.AddUserPrincipal, AddUserCommand: v.AddUserCommand, } @@ -80,8 +89,6 @@ func (a *Authority) Export() (c *config.Configuration, err error) { } // Authority - c.Authority.Id = a.config.AuthorityConfig.AuthorityID - // cas options if v := a.config.AuthorityConfig.Options; v != nil { c.Authority.Type = 0 @@ -96,13 +103,12 @@ func (a *Authority) Export() (c *config.Configuration, err error) { c.Authority.CertificateIssuer = &config.CertificateIssuer{ Type: config.CertificateIssuer_Type(typ), Provisioner: iss.Provisioner, - Certificate: mustReadFileOrUri(iss.Certificate), - Key: mustReadFileOrUri(iss.Key), + Certificate: mustReadFileOrUri(iss.Certificate, files), + Key: mustReadFileOrUri(iss.Key, files), Password: mustPassword(iss.Password), } } } - // admins for { list, cursor := a.admins.Find("", 100) @@ -111,7 +117,6 @@ func (a *Authority) Export() (c *config.Configuration, err error) { break } } - // provisioners for { list, cursor := a.provisioners.Find("", 100) @@ -126,7 +131,21 @@ func (a *Authority) Export() (c *config.Configuration, err error) { break } } + // global claims c.Authority.Claims = claimsToLinkedca(a.config.AuthorityConfig.Claims) + // Distiguised names template + if v := a.config.AuthorityConfig.Template; v != nil { + c.Authority.Template = &config.DistinguishedName{ + Country: v.Country, + Organization: v.Organization, + OrganizationalUnit: v.OrganizationalUnit, + Locality: v.Locality, + Province: v.Province, + StreetAddress: v.StreetAddress, + SerialNumber: v.SerialNumber, + CommonName: v.CommonName, + } + } // TLS if v := a.config.TLS; v != nil { @@ -155,18 +174,14 @@ func (a *Authority) Export() (c *config.Configuration, err error) { if !ok { return nil, errors.Errorf("unsupported template type %s", t.Type) } - content := t.Content - if len(content) == 0 { - content = mustReadFileOrUri(t.TemplatePath) - } c.Templates.Ssh.Hosts = append(c.Templates.Ssh.Hosts, &config.Template{ Type: config.Template_Type(typ), Name: t.Name, - Template: t.TemplatePath, + Template: mustReadFileOrUri(t.TemplatePath, files), Path: t.Path, Comment: t.Comment, Requires: t.RequiredData, - Content: content, + Content: t.Content, }) } for _, t := range v.SSH.User { @@ -174,18 +189,14 @@ func (a *Authority) Export() (c *config.Configuration, err error) { if !ok { return nil, errors.Errorf("unsupported template type %s", t.Type) } - content := t.Content - if len(content) == 0 { - content = mustReadFileOrUri(t.TemplatePath) - } c.Templates.Ssh.Users = append(c.Templates.Ssh.Users, &config.Template{ Type: config.Template_Type(typ), Name: t.Name, - Template: t.TemplatePath, + Template: mustReadFileOrUri(t.TemplatePath, files), Path: t.Path, Comment: t.Comment, Requires: t.RequiredData, - Content: content, + Content: t.Content, }) } } @@ -212,11 +223,18 @@ func mustMarshalToStruct(v interface{}) *structpb.Struct { return r } -func mustReadFileOrUri(fn string) []byte { +func mustReadFileOrUri(fn string, m map[string][]byte) string { if fn == "" { - return nil + return "" } + stepPath := filepath.ToSlash(step.StepPath()) + if !strings.HasSuffix(stepPath, "/") { + stepPath += "/" + } + + fn = strings.TrimPrefix(filepath.ToSlash(fn), stepPath) + ok, err := isFilename(fn) if err != nil { panic(err) @@ -226,15 +244,16 @@ func mustReadFileOrUri(fn string) []byte { if err != nil { panic(errors.Wrapf(err, "error reading %s", fn)) } - return b + m[fn] = b + return fn } - return []byte(fn) + return fn } -func mustReadFilesOrUris(fns []string) [][]byte { - var result [][]byte +func mustReadFilesOrUris(fns []string, m map[string][]byte) []string { + var result []string for _, fn := range fns { - result = append(result, mustReadFileOrUri(fn)) + result = append(result, mustReadFileOrUri(fn, m)) } return result } diff --git a/authority/tls.go b/authority/tls.go index b2dc4c92..32d6f3c6 100644 --- a/authority/tls.go +++ b/authority/tls.go @@ -36,7 +36,6 @@ func withDefaultASN1DN(def *config.ASN1DN) provisioner.CertificateModifierFunc { if def == nil { return errors.New("default ASN1DN template cannot be nil") } - if len(crt.Subject.Country) == 0 && def.Country != "" { crt.Subject.Country = append(crt.Subject.Country, def.Country) } @@ -55,7 +54,12 @@ func withDefaultASN1DN(def *config.ASN1DN) provisioner.CertificateModifierFunc { if len(crt.Subject.StreetAddress) == 0 && def.StreetAddress != "" { crt.Subject.StreetAddress = append(crt.Subject.StreetAddress, def.StreetAddress) } - + if len(crt.Subject.SerialNumber) == 0 && def.SerialNumber != "" { + crt.Subject.SerialNumber = def.SerialNumber + } + if len(crt.Subject.CommonName) == 0 && def.CommonName != "" { + crt.Subject.CommonName = def.CommonName + } return nil } } From 07f7316851117a8aa4245e92c5385781a8554f78 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Tue, 27 Jul 2021 19:22:29 -0700 Subject: [PATCH 028/195] Add bastion to export. --- authority/export.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/authority/export.go b/authority/export.go index 316ede0e..4c5059ea 100644 --- a/authority/export.go +++ b/authority/export.go @@ -63,6 +63,15 @@ func (a *Authority) Export() (c *config.Configuration, err error) { Key: mustMarshalToStruct(k), }) } + if b := v.Bastion; b != nil { + c.Ssh.Bastion = &config.Bastion{ + Hostname: b.Hostname, + User: b.User, + Port: b.Port, + Command: b.Command, + Flags: b.Flags, + } + } } // KMS From 97af829805588967243297c3e31f13dcc1b52259 Mon Sep 17 00:00:00 2001 From: Carl Tashian Date: Wed, 28 Jul 2021 13:55:35 -0700 Subject: [PATCH 029/195] RA install script --- scripts/README.md | 4 + scripts/install-step-ra.sh | 253 +++++++++++++++++++++++++++++++++++++ 2 files changed, 257 insertions(+) create mode 100644 scripts/README.md create mode 100644 scripts/install-step-ra.sh diff --git a/scripts/README.md b/scripts/README.md new file mode 100644 index 00000000..80d3cdba --- /dev/null +++ b/scripts/README.md @@ -0,0 +1,4 @@ +# Scripts folder + +Please note that `install-step-ra.sh` is referenced on the `files.smallstep.com` S3 website bucket as a redirect to `raw.githubusercontent.com`. If you move it, please update the S3 redirect. + diff --git a/scripts/install-step-ra.sh b/scripts/install-step-ra.sh new file mode 100644 index 00000000..a24f6ea4 --- /dev/null +++ b/scripts/install-step-ra.sh @@ -0,0 +1,253 @@ +#!/bin/bash +set -e + +echo "This script will install and start a step-ca server running in Registration Authority (RA) mode." +echo "" +echo "You will need an upstream CA (URL and fingerprint)" +echo "Don't have a CA? Sign up for a hosted CA at smallstep.com — or run your own." +echo "" + +# Fail if this script is not run as root. +if ! [ $(id -u) = 0 ]; then + echo "This script must be run as root" + exit 1 +fi + +# Architecture detection +arch=$(uname -m) +case $arch in + x86_64) arch="amd64" ;; + x86) arch="386" ;; + i686) arch="386" ;; + i386) arch="386" ;; + aarch64) arch="arm64" ;; + armv5*) arch="armv5" ;; + armv6*) arch="armv6" ;; + armv7*) arch="armv7" ;; +esac + +if [ "$arch" = "armv5" ]; then + echo "This script doesn't work on armv5 machines" + exit 1 +fi + +if ! hash jq &> /dev/null; then + echo "This script requires the jq commmand; please install it." + exit 1 +fi + +if ! hash curl &> /dev/null; then + echo "This script requires the curl commmand; please install it." + exit 1 +fi + +if ! hash tar &> /dev/null; then + echo "This script requires the tar commmand; please install it." + exit 1 +fi + +while [ $# -gt 0 ]; do + case "$1" in + --ca-url) + CA_URL="$2" + shift + shift + ;; + --fingerprint) + CA_FINGERPRINT="$2" + shift + shift + ;; + --provisioner-name) + CA_PROVISIONER_NAME="$2" + shift + shift + ;; + --provisioner-password-file) + CA_PROVISIONER_JWK_PASSWORD_FILE="$2" + shift + shift + ;; + --dns-names) + RA_DNS_NAMES="$2" + shift + shift + ;; + --listen-address) + RA_ADDRESS="$2" + shift + shift + ;; + *) + shift + ;; + esac +done + +# Install step +if ! hash step &> /dev/null; then + echo "Installing 'step' in /usr/bin..." + STEP_VERSION=$(curl -s https://api.github.com/repos/smallstep/cli/releases/latest | jq -r '.tag_name') + + curl -sLO https://github.com/smallstep/cli/releases/download/$STEP_VERSION/step_linux_${STEP_VERSION:1}_$arch.tar.gz + tar xvzf step_linux_${STEP_VERSION:1}_$arch.tar.gz + install -m 0755 -t /usr/bin step_${STEP_VERSION:1}/bin/step + + rm step_linux_${STEP_VERSION:1}_$arch.tar.gz + rm -rf step_${STEP_VERSION:1} +fi + +# Prompt for required parameters +if [ -z "$CA_URL" ]; then + CA_URL="" + while [[ $CA_URL = "" ]]; do + read -p "Issuing CA URL: " CA_URL < /dev/tty + done +fi + +if [ -z "$CA_FINGERPRINT" ]; then + CA_FINGERPRINT="" + while [[ $CA_FINGERPRINT = "" ]]; do + read -p "Issuing CA Fingerprint: " CA_FINGERPRINT < /dev/tty + done +fi + +echo "Bootstrapping with the CA..." +export STEPPATH=$(mktemp -d) +export STEP_CONSOLE=true + +step ca bootstrap --ca-url $CA_URL --fingerprint $CA_FINGERPRINT + +if [ -z "$CA_PROVISIONER_NAME" ]; then + declare -a provisioners + readarray -t provisioners < <(step ca provisioner list | jq -r '.[] | select(.type == "JWK") | .name') + provisioners+=("Create provisioner") + printf '%s\n' "${provisioners[@]}" + + printf "%b" "\nSelect a JWK provisioner:\n" >&2 + select provisioner in "${provisioners[@]}"; do + if [ "$provisioner" == "Create provisioner" ]; then + echo "Creating a JWK provisioner on the upstream CA..." + echo "" + read -p "Label your provisioner (e.g. example-ra): " CA_PROVISIONER_NAME < /dev/tty + step beta ca provisioner add $CA_PROVISIONER_NAME --type JWK --create + break + elif [ -n "$provisioner" ]; then + echo "Using existing provisioner $provisioner." + CA_PROVISIONER_NAME=$provisioner + break + else + echo "Invalid selection!" + fi + done +fi + +if [ -z "$RA_DNS_NAMES" ]; then + RA_DNS_NAMES="" + while [[ $RA_DNS_NAMES = "" ]]; do + echo "What DNS names or IP addresses will your RA use?" + read -p "(e.g. acme.example.com[,1.1.1.1,etc.]): " RA_DNS_NAMES < /dev/tty + done +fi + +if [ -z "$RA_ADDRESS" ]; then + RA_ADDRESS="" + while [[ $RA_ADDRESS = "" ]] ; do + echo "What address should your RA listen on?" + read -p "(e.g. :443 or 10.2.1.201:4430): " RA_ADDRESS < /dev/tty + done +fi + +if [ -z "$CA_PROVISIONER_JWK_PASSWORD_FILE" ]; then + read -s -p "Enter the CA Provisioner Password: " CA_PROVISIONER_JWK_PASSWORD < /dev/tty + printf "%b" "\n" +fi + +echo "Installing 'step-ca' in /usr/bin..." +CA_VERSION=$(curl -s https://api.github.com/repos/smallstep/certificates/releases/latest | jq -r '.tag_name') + +curl -sLO https://github.com/smallstep/certificates/releases/download/$CA_VERSION/step-ca_linux_${CA_VERSION:1}_$arch.tar.gz +tar -xf step-ca_linux_${CA_VERSION:1}_$arch.tar.gz +install -m 0755 -t /usr/bin step-ca_${CA_VERSION:1}/bin/step-ca +setcap CAP_NET_BIND_SERVICE=+eip $(which step-ca) +rm step-ca_linux_${CA_VERSION:1}_$arch.tar.gz +rm -rf step-ca_${CA_VERSION:1} + +echo "Creating 'step' user..." +export STEPPATH=/etc/step-ca + +useradd --system --home $(step path) --shell /bin/false step + +echo "Creating RA configuration..." +mkdir -p $(step path)/db +mkdir -p $(step path)/config + +cat < $(step path)/config/ca.json +{ + "address": "$RA_ADDRESS", + "dnsNames": ["$RA_DNS_NAMES"], + "db": { + "type": "badgerV2", + "dataSource": "/etc/step-ca/db" + }, + "logger": {"format": "text"}, + "authority": { + "type": "stepcas", + "certificateAuthority": "$CA_URL", + "certificateAuthorityFingerprint": "$CA_FINGERPRINT", + "certificateIssuer": { + "type" : "jwk", + "provisioner": "$CA_PROVISIONER_NAME" + }, + "provisioners": [{ + "type": "ACME", + "name": "acme" + }] + }, + "tls": { + "cipherSuites": [ + "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305", + "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256" + ], + "minVersion": 1.2, + "maxVersion": 1.3, + "renegotiation": false + } +} +EOF + +if ! [ -z "$CA_PROVISIONER_JWK_PASSWORD" ]; then + echo "Saving provisoiner password to $(step path)/password.txt..." + echo $CA_PROVISIONER_JWK_PASSWORD > $(step path)/password.txt +else + echo "Copying provisioner password file to $(step path)/password.txt..." + cp $CA_PROVISIONER_JWK_PASSWORD_FILE $(step path)/password.txt +fi +chmod 440 $(step path)/password.txt + +# Add a service to systemd for the RA. +echo "Creating systemd service step-ca.service..." +curl -sL https://raw.githubusercontent.com/smallstep/certificates/master/systemd/step-ca.service \ + -o /etc/systemd/system/step-ca.service + +echo "Creating RA mode override /etc/systemd/system/step-ca.service.d/local.conf..." +mkdir /etc/systemd/system/step-ca.service.d +cat < /etc/systemd/system/step-ca.service.d/local.conf +[Service] +; The empty ExecStart= clears the inherited ExecStart= value +ExecStart= +ExecStart=/usr/bin/step-ca config/ca.json --issuer-password-file password.txt +EOF + +echo "Starting step-ca.service..." +systemctl daemon-reload + +chown -R step:step $(step path) + +systemctl enable --now step-ca + +echo "Adding STEPPATH export to /root/.bash_profile..." +echo "export STEPPATH=$STEPPATH" >> /root/.bash_profile + +echo "Finished. Check the journal with journalctl -fu step-ca.service" + From 4f27f4b0020a0715be830e6f557fa04fa850b0cb Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Wed, 28 Jul 2021 13:56:05 -0700 Subject: [PATCH 030/195] Change default ciphersuites to newer names. --- authority/config/config.go | 3 ++- authority/config/tls_options.go | 19 ++++++++----------- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/authority/config/config.go b/authority/config/config.go index 4d7592ac..7c6de130 100644 --- a/authority/config/config.go +++ b/authority/config/config.go @@ -189,9 +189,10 @@ func (c *Config) Validate() error { switch { case c.Address == "": return errors.New("address cannot be empty") - case len(c.DNSNames) == 0: return errors.New("dnsNames cannot be empty") + case c.AuthorityConfig == nil: + return errors.New("authority cannot be nil") } // Options holds the RA/CAS configuration. diff --git a/authority/config/tls_options.go b/authority/config/tls_options.go index ed61cfc9..0db202e5 100644 --- a/authority/config/tls_options.go +++ b/authority/config/tls_options.go @@ -15,8 +15,9 @@ var ( // DefaultTLSRenegotiation default TLS connection renegotiation policy. DefaultTLSRenegotiation = false // Never regnegotiate. // DefaultTLSCipherSuites specifies default step ciphersuite(s). + // These are TLS 1.0 - 1.2 cipher suites. DefaultTLSCipherSuites = CipherSuites{ - "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305", + "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256", "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", } // ApprovedTLSCipherSuites smallstep approved ciphersuites. @@ -26,25 +27,21 @@ var ( "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", - "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305", + "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", - "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305", + "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256", } // DefaultTLSOptions represents the default TLS version as well as the cipher // suites used in the TLS certificates. DefaultTLSOptions = TLSOptions{ - CipherSuites: CipherSuites{ - "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305", - "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", - "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", - }, - MinVersion: 1.2, - MaxVersion: 1.2, - Renegotiation: false, + CipherSuites: DefaultTLSCipherSuites, + MinVersion: DefaultTLSMinVersion, + MaxVersion: DefaultTLSMaxVersion, + Renegotiation: DefaultTLSRenegotiation, } ) From ac363d7824c1ea4c71edbd26de6d7b53bdb5a822 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Wed, 28 Jul 2021 15:21:48 -0700 Subject: [PATCH 031/195] Add --password-file and --issuer-password-file flags to export. --- commands/export.go | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/commands/export.go b/commands/export.go index bb11fea7..0080df7d 100644 --- a/commands/export.go +++ b/commands/export.go @@ -4,6 +4,8 @@ import ( "bytes" "encoding/json" "fmt" + "io/ioutil" + "unicode" "github.com/pkg/errors" "github.com/smallstep/certificates/authority" @@ -23,6 +25,7 @@ func init() { Action: exportAction, Description: `**step-ca export** exports the current configuration of step-ca. +Note that neither the PKI password nor ## POSITIONAL ARGUMENTS @@ -34,6 +37,18 @@ Export the current configuration: ''' $ step-ca export $(step path)/config/ca.json '''`, + Flags: []cli.Flag{ + cli.StringFlag{ + Name: "password-file", + Usage: `path to the containing the password to decrypt the +intermediate private key.`, + }, + cli.StringFlag{ + Name: "issuer-password-file", + Usage: `path to the containing the password to decrypt the + certificate issuer private key used in the RA mode.`, + }, + }, }) } @@ -43,11 +58,33 @@ func exportAction(ctx *cli.Context) error { } configFile := ctx.Args().Get(0) + passwordFile := ctx.String("password-file") + issuerPasswordFile := ctx.String("issuer-password-file") config, err := config.LoadConfiguration(configFile) if err != nil { return err } + if err := config.Validate(); err != nil { + return err + } + + if passwordFile != "" { + b, err := ioutil.ReadFile(passwordFile) + if err != nil { + return errors.Wrapf(err, "error reading %s", passwordFile) + } + config.Password = string(bytes.TrimRightFunc(b, unicode.IsSpace)) + } + if issuerPasswordFile != "" { + b, err := ioutil.ReadFile(issuerPasswordFile) + if err != nil { + return errors.Wrapf(err, "error reading %s", issuerPasswordFile) + } + if config.AuthorityConfig.CertificateIssuer != nil { + config.AuthorityConfig.CertificateIssuer.Password = string(bytes.TrimRightFunc(b, unicode.IsSpace)) + } + } auth, err := authority.New(config) if err != nil { From e62d7988b836e660500718bf78e362054d159c37 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Wed, 28 Jul 2021 15:22:21 -0700 Subject: [PATCH 032/195] Do not store password on exports. --- authority/export.go | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/authority/export.go b/authority/export.go index 4c5059ea..b8679ac6 100644 --- a/authority/export.go +++ b/authority/export.go @@ -13,6 +13,11 @@ import ( "google.golang.org/protobuf/types/known/structpb" ) +// Export creates a linkedca configuration form the current ca.json and loaded +// authorities. +// +// Note that export will not export neither the pki password nor the certificate +// issuer password. func (a *Authority) Export() (c *config.Configuration, err error) { // Recover from panics defer func() { @@ -22,6 +27,8 @@ func (a *Authority) Export() (c *config.Configuration, err error) { }() files := make(map[string][]byte) + + // The exported configuration should not include the password in it. c = &config.Configuration{ Version: "1.0", Root: mustReadFilesOrUris(a.config.Root, files), @@ -40,8 +47,7 @@ func (a *Authority) Export() (c *config.Configuration, err error) { DisableIssuedAtCheck: a.config.AuthorityConfig.DisableIssuedAtCheck, Backdate: a.config.AuthorityConfig.Backdate.String(), }, - Password: mustPassword(a.config.Password), - Files: files, + Files: files, } // SSH @@ -109,12 +115,12 @@ func (a *Authority) Export() (c *config.Configuration, err error) { if !ok { return nil, errors.Errorf("unknown certificate issuer type %s", iss.Type) } + // The exporte certificate issuer should not include the password. c.Authority.CertificateIssuer = &config.CertificateIssuer{ Type: config.CertificateIssuer_Type(typ), Provisioner: iss.Provisioner, Certificate: mustReadFileOrUri(iss.Certificate, files), Key: mustReadFileOrUri(iss.Key, files), - Password: mustPassword(iss.Password), } } } From 2620c38aee77526692c8c3934d7a3e3acb8a5861 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Wed, 28 Jul 2021 18:05:57 -0700 Subject: [PATCH 033/195] Add is converting provisioners to linkedca. The ids are required to be able to link admins with provisioners. --- authority/provisioners.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/authority/provisioners.go b/authority/provisioners.go index 3e2d1276..ab069501 100644 --- a/authority/provisioners.go +++ b/authority/provisioners.go @@ -716,6 +716,7 @@ func ProvisionerToLinkedca(p provisioner.Interface) (*linkedca.Provisioner, erro return nil, errors.Wrap(err, "error marshaling key") } return &linkedca.Provisioner{ + Id: p.ID, Type: linkedca.Provisioner_JWK, Name: p.GetName(), Details: &linkedca.ProvisionerDetails{ @@ -736,6 +737,7 @@ func ProvisionerToLinkedca(p provisioner.Interface) (*linkedca.Provisioner, erro return nil, err } return &linkedca.Provisioner{ + Id: p.ID, Type: linkedca.Provisioner_OIDC, Name: p.GetName(), Details: &linkedca.ProvisionerDetails{ @@ -762,6 +764,7 @@ func ProvisionerToLinkedca(p provisioner.Interface) (*linkedca.Provisioner, erro return nil, err } return &linkedca.Provisioner{ + Id: p.ID, Type: linkedca.Provisioner_GCP, Name: p.GetName(), Details: &linkedca.ProvisionerDetails{ @@ -785,6 +788,7 @@ func ProvisionerToLinkedca(p provisioner.Interface) (*linkedca.Provisioner, erro return nil, err } return &linkedca.Provisioner{ + Id: p.ID, Type: linkedca.Provisioner_AWS, Name: p.GetName(), Details: &linkedca.ProvisionerDetails{ @@ -807,6 +811,7 @@ func ProvisionerToLinkedca(p provisioner.Interface) (*linkedca.Provisioner, erro return nil, err } return &linkedca.Provisioner{ + Id: p.ID, Type: linkedca.Provisioner_AZURE, Name: p.GetName(), Details: &linkedca.ProvisionerDetails{ @@ -830,6 +835,7 @@ func ProvisionerToLinkedca(p provisioner.Interface) (*linkedca.Provisioner, erro return nil, err } return &linkedca.Provisioner{ + Id: p.ID, Type: linkedca.Provisioner_ACME, Name: p.GetName(), Details: &linkedca.ProvisionerDetails{ @@ -849,6 +855,7 @@ func ProvisionerToLinkedca(p provisioner.Interface) (*linkedca.Provisioner, erro return nil, err } return &linkedca.Provisioner{ + Id: p.ID, Type: linkedca.Provisioner_X5C, Name: p.GetName(), Details: &linkedca.ProvisionerDetails{ @@ -868,6 +875,7 @@ func ProvisionerToLinkedca(p provisioner.Interface) (*linkedca.Provisioner, erro return nil, err } return &linkedca.Provisioner{ + Id: p.ID, Type: linkedca.Provisioner_K8SSA, Name: p.GetName(), Details: &linkedca.ProvisionerDetails{ @@ -883,6 +891,7 @@ func ProvisionerToLinkedca(p provisioner.Interface) (*linkedca.Provisioner, erro }, nil case *provisioner.SSHPOP: return &linkedca.Provisioner{ + Id: p.ID, Type: linkedca.Provisioner_SSHPOP, Name: p.GetName(), Details: &linkedca.ProvisionerDetails{ @@ -898,6 +907,7 @@ func ProvisionerToLinkedca(p provisioner.Interface) (*linkedca.Provisioner, erro return nil, err } return &linkedca.Provisioner{ + Id: p.ID, Type: linkedca.Provisioner_SCEP, Name: p.GetName(), Details: &linkedca.ProvisionerDetails{ From 5344f42f21f271f260fc159827cff5fcc2363aa7 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Mon, 2 Aug 2021 11:33:02 -0700 Subject: [PATCH 034/195] Allow to use the environment variable STEP_CA_TOKEN For helm charts we want to store the tokens in a secret and load it from an environment variable. --- commands/app.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/commands/app.go b/commands/app.go index 3b874ae8..481c4867 100644 --- a/commands/app.go +++ b/commands/app.go @@ -39,8 +39,9 @@ certificate issuer private key used in the RA mode.`, Usage: "address of a DNS resolver to be used instead of the default.", }, cli.StringFlag{ - Name: "token", - Usage: "token used to enable the linked ca.", + Name: "token", + Usage: "token used to enable the linked ca.", + EnvVar: "STEP_CA_TOKEN", }, }, } From 26122a2cbfa7530712de7713c04ab0477ce04991 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Mon, 2 Aug 2021 11:48:37 -0700 Subject: [PATCH 035/195] Enable admin automatically if a token is provided. --- authority/authority.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/authority/authority.go b/authority/authority.go index 80242e8b..ae41f129 100644 --- a/authority/authority.go +++ b/authority/authority.go @@ -440,7 +440,7 @@ func (a *Authority) init() error { // TODO: mimick the x509CAService GetCertificateAuthority here too? } - if a.config.AuthorityConfig.EnableAdmin { + if a.config.AuthorityConfig.EnableAdmin || a.linkedCAToken != "" { // Initialize step-ca Admin Database if it's not already initialized using // WithAdminDB. if a.adminDB == nil { From 91a369f61857748f96f28a712ac8563a8282ce38 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Mon, 2 Aug 2021 12:13:39 -0700 Subject: [PATCH 036/195] Automatically enable admin properly on linked cas. --- authority/authority.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/authority/authority.go b/authority/authority.go index ae41f129..28af693c 100644 --- a/authority/authority.go +++ b/authority/authority.go @@ -207,6 +207,11 @@ func (a *Authority) init() error { var err error + // Automatically enable admin for all linked cas. + if a.linkedCAToken != "" { + a.config.AuthorityConfig.EnableAdmin = true + } + // Initialize step-ca Database if it's not already initialized with WithDB. // If a.config.DB is nil then a simple, barebones in memory DB will be used. if a.db == nil { @@ -440,7 +445,7 @@ func (a *Authority) init() error { // TODO: mimick the x509CAService GetCertificateAuthority here too? } - if a.config.AuthorityConfig.EnableAdmin || a.linkedCAToken != "" { + if a.config.AuthorityConfig.EnableAdmin { // Initialize step-ca Admin Database if it's not already initialized using // WithAdminDB. if a.adminDB == nil { From b0e0f2b89d8d9c14f582b6d40ad0620c943b0902 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Mon, 2 Aug 2021 14:45:59 -0700 Subject: [PATCH 037/195] Use linkedca GetAdmin and GetProvisioner. --- authority/linkedca.go | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/authority/linkedca.go b/authority/linkedca.go index 75bc6e1a..e0678aca 100644 --- a/authority/linkedca.go +++ b/authority/linkedca.go @@ -15,7 +15,6 @@ import ( "time" "github.com/pkg/errors" - "github.com/smallstep/certificates/errs" "go.step.sm/crypto/jose" "go.step.sm/crypto/keyutil" "go.step.sm/crypto/tlsutil" @@ -141,18 +140,13 @@ func (c *linkedCaClient) CreateProvisioner(ctx context.Context, prov *linkedca.P } func (c *linkedCaClient) GetProvisioner(ctx context.Context, id string) (*linkedca.Provisioner, error) { - resp, err := c.client.GetConfiguration(ctx, &linkedca.ConfigurationRequest{ - AuthorityId: c.authorityID, + resp, err := c.client.GetProvisioner(ctx, &linkedca.GetProvisionerRequest{ + Id: id, }) if err != nil { return nil, errors.Wrap(err, "error getting provisioners") } - for _, p := range resp.Provisioners { - if p.Id == id { - return p, nil - } - } - return nil, errs.NotFound("provisioner not found") + return resp, nil } func (c *linkedCaClient) GetProvisioners(ctx context.Context) ([]*linkedca.Provisioner, error) { @@ -199,18 +193,13 @@ func (c *linkedCaClient) CreateAdmin(ctx context.Context, adm *linkedca.Admin) e } func (c *linkedCaClient) GetAdmin(ctx context.Context, id string) (*linkedca.Admin, error) { - resp, err := c.client.GetConfiguration(ctx, &linkedca.ConfigurationRequest{ - AuthorityId: c.authorityID, + resp, err := c.client.GetAdmin(ctx, &linkedca.GetAdminRequest{ + Id: id, }) if err != nil { return nil, errors.Wrap(err, "error getting admins") } - for _, a := range resp.Admins { - if a.Id == id { - return a, nil - } - } - return nil, errs.NotFound("admin not found") + return resp, nil } func (c *linkedCaClient) GetAdmins(ctx context.Context) ([]*linkedca.Admin, error) { From 384be6e2053e9826011faa4ae05f1d9cdbc518aa Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Mon, 2 Aug 2021 15:34:39 -0700 Subject: [PATCH 038/195] Do not show provisioners if they are not required. For deployment types like linked ca, the list of provisioners in the ca.json are not required, so we should tag the json as omitempty. --- authority/config/config.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/authority/config/config.go b/authority/config/config.go index 7c6de130..68886d77 100644 --- a/authority/config/config.go +++ b/authority/config/config.go @@ -85,7 +85,7 @@ type ASN1DN struct { type AuthConfig struct { *cas.Options AuthorityID string `json:"authorityId,omitempty"` - Provisioners provisioner.List `json:"provisioners"` + Provisioners provisioner.List `json:"provisioners,omitempty"` Admins []*linkedca.Admin `json:"-"` Template *ASN1DN `json:"template,omitempty"` Claims *provisioner.Claims `json:"claims,omitempty"` From 721459210ee273397770ec7976975bb36c88a0cf Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Mon, 2 Aug 2021 16:07:30 -0700 Subject: [PATCH 039/195] Make pki initialization more flexible. --- pki/pki.go | 307 +++++++++++++++++++++++++++++++++++++---------- pki/templates.go | 2 +- 2 files changed, 243 insertions(+), 66 deletions(-) diff --git a/pki/pki.go b/pki/pki.go index e4e7bad3..cfe9c49c 100644 --- a/pki/pki.go +++ b/pki/pki.go @@ -19,12 +19,16 @@ import ( "time" "github.com/pkg/errors" + "github.com/smallstep/certificates/authority" + "github.com/smallstep/certificates/authority/admin" + admindb "github.com/smallstep/certificates/authority/admin/db/nosql" authconfig "github.com/smallstep/certificates/authority/config" "github.com/smallstep/certificates/authority/provisioner" "github.com/smallstep/certificates/ca" "github.com/smallstep/certificates/cas" "github.com/smallstep/certificates/cas/apiv1" "github.com/smallstep/certificates/db" + "github.com/smallstep/nosql" "go.step.sm/cli-utils/config" "go.step.sm/cli-utils/errs" "go.step.sm/cli-utils/fileutil" @@ -32,9 +36,26 @@ import ( "go.step.sm/crypto/jose" "go.step.sm/crypto/keyutil" "go.step.sm/crypto/pemutil" + "go.step.sm/linkedca" "golang.org/x/crypto/ssh" ) +// DeploymentType defines witch type of deployment a user is initializing +type DeploymentType int + +const ( + // StandaloneDeployment is a deployment where all the components like keys, + // provisioners, admins, certificates and others are managed by the user. + StandaloneDeployment DeploymentType = iota + // LinkedDeployment is a deployment where the keys are managed by the user, + // but provisioners, admins and the record of certificates are managed in + // the cloud. + LinkedDeployment + // HostedDeployment is a deployment where all the components are managed in + // the cloud by smallstep.com/certificate-manager. + HostedDeployment +) + const ( // ConfigPath is the directory name under the step path where the configuration // files will be stored. @@ -134,9 +155,88 @@ func GetProvisionerKey(caURL, rootFile, kid string) (string, error) { return resp.Key, nil } +type options struct { + address string + caURL string + dnsNames []string + provisioner string + enableACME bool + enableSSH bool + enableAdmin bool + noDB bool + deploymentType DeploymentType +} + +// PKIOption is the type of a configuration option on the pki constructor. +type PKIOption func(o *options) + +// WithAddress sets the listen address of step-ca. +func WithAddress(s string) PKIOption { + return func(o *options) { + o.address = s + } +} + +// WithCaUrl sets the default ca-url of step-ca. +func WithCaUrl(s string) PKIOption { + return func(o *options) { + o.caURL = s + } +} + +// WithDNSNames sets the SANs of step-ca. +func WithDNSNames(s []string) PKIOption { + return func(o *options) { + o.dnsNames = s + } +} + +// WithProvisioner defines the name of the default provisioner. +func WithProvisioner(s string) PKIOption { + return func(o *options) { + o.provisioner = s + } +} + +// WithACME enables acme provisioner in step-ca. +func WithACME() PKIOption { + return func(o *options) { + o.enableACME = true + } +} + +// WithSSH enables ssh in step-ca. +func WithSSH() PKIOption { + return func(o *options) { + o.enableSSH = true + } +} + +// WithAdmin enables the admin api in step-ca. +func WithAdmin() PKIOption { + return func(o *options) { + o.enableAdmin = true + } +} + +// WithNoDB disables the db in step-ca. +func WithNoDB() PKIOption { + return func(o *options) { + o.noDB = true + } +} + +// WithDeploymentType defines the deployment type of step-ca. +func WithDeploymentType(dt DeploymentType) PKIOption { + return func(o *options) { + o.deploymentType = dt + } +} + // PKI represents the Public Key Infrastructure used by a certificate authority. type PKI struct { casOptions apiv1.Options + caService apiv1.CertificateAuthorityService caCreator apiv1.CertificateAuthorityCreator root, rootKey, rootFingerprint string intermediate, intermediateKey string @@ -145,20 +245,25 @@ type PKI struct { config, defaults string ottPublicKey *jose.JSONWebKey ottPrivateKey *jose.JSONWebEncryption - provisioner string - address string - dnsNames []string - caURL string - enableSSH bool + options *options } // New creates a new PKI configuration. -func New(opts apiv1.Options) (*PKI, error) { - caCreator, err := cas.NewCreator(context.Background(), opts) +func New(o apiv1.Options, opts ...PKIOption) (*PKI, error) { + caService, err := cas.New(context.Background(), o) if err != nil { return nil, err } + var caCreator apiv1.CertificateAuthorityCreator + if o.IsCreator { + creator, ok := caService.(apiv1.CertificateAuthorityCreator) + if !ok { + return nil, errors.Errorf("cas type '%s' does not implements CertificateAuthorityCreator", o.Type) + } + caCreator = creator + } + public := GetPublicPath() private := GetSecretsPath() config := GetConfigPath() @@ -180,12 +285,19 @@ func New(opts apiv1.Options) (*PKI, error) { } p := &PKI{ - casOptions: opts, - caCreator: caCreator, - provisioner: "step-cli", - address: "127.0.0.1:9000", - dnsNames: []string{"127.0.0.1"}, + casOptions: o, + caCreator: caCreator, + caService: caService, + options: &options{ + provisioner: "step-cli", + address: "127.0.0.1:9000", + dnsNames: []string{"127.0.0.1"}, + }, } + for _, fn := range opts { + fn(p.options) + } + if p.root, err = getPath(public, "root_ca.crt"); err != nil { return nil, err } @@ -233,23 +345,31 @@ func (p *PKI) GetRootFingerprint() string { } // SetProvisioner sets the provisioner name of the OTT keys. +// +// Deprecated: this method is deprecated in favor of WithProvisioner. func (p *PKI) SetProvisioner(s string) { - p.provisioner = s + p.options.provisioner = s } // SetAddress sets the listening address of the CA. +// +// Deprecated: this method is deprecated in favor of WithAddress. func (p *PKI) SetAddress(s string) { - p.address = s + p.options.address = s } // SetDNSNames sets the dns names of the CA. +// +// Deprecated: this method is deprecated in favor of WithDNSNames. func (p *PKI) SetDNSNames(s []string) { - p.dnsNames = s + p.options.dnsNames = s } // SetCAURL sets the ca-url to use in the defaults.json. +// +// Deprecated: this method is deprecated in favor of WithCaUrl. func (p *PKI) SetCAURL(s string) { - p.caURL = s + p.options.caURL = s } // GenerateKeyPairs generates the key pairs used by the certificate authority. @@ -379,7 +499,7 @@ func (p *PKI) CreateCertificateAuthorityResponse(cert *x509.Certificate, key cry // GetCertificateAuthority attempts to load the certificate authority from the // RA. func (p *PKI) GetCertificateAuthority() error { - srv, ok := p.caCreator.(apiv1.CertificateAuthorityGetter) + srv, ok := p.caService.(apiv1.CertificateAuthorityGetter) if !ok { return nil } @@ -427,7 +547,7 @@ func (p *PKI) GenerateSSHSigningKeys(password []byte) error { return err } } - p.enableSSH = true + p.options.enableSSH = true return nil } @@ -440,7 +560,8 @@ func (p *PKI) askFeedback() { ui.Println(" phone home. But your feedback is extremely valuable. Any information you") ui.Println(" can provide regarding how you’re using `step` helps. Please send us a") ui.Println(" sentence or two, good or bad: \033[1mfeedback@smallstep.com\033[0m or join") - ui.Println(" \033[1mhttps://github.com/smallstep/certificates/discussions\033[0m.") + ui.Println(" \033[1mhttps://github.com/smallstep/certificates/discussions\033[0m and our Discord") + ui.Println(" \033[1mhttps://bit.ly/step-discord\033[0m.") } // TellPKI outputs the locations of public and private keys generated @@ -465,7 +586,7 @@ func (p *PKI) tellPKI() { } else { ui.Printf(`{{ "%s" | red }} {{ "Root certificate:" | bold }} failed to retrieve it from RA`+"\n", ui.IconBad) } - if p.enableSSH { + if p.options.enableSSH { ui.PrintSelected("SSH user root certificate", p.sshUserPubKey) ui.PrintSelected("SSH user root private key", p.sshUserKey) ui.PrintSelected("SSH host root certificate", p.sshHostPubKey) @@ -485,6 +606,8 @@ type Option func(c *authconfig.Config) error // WithDefaultDB is a configuration modifier that adds a default DB stanza to // the authority config. +// +// Deprecated: this method is deprecated because this is the default behavior. func WithDefaultDB() Option { return func(c *authconfig.Config) error { c.DB = &db.Config{ @@ -497,6 +620,8 @@ func WithDefaultDB() Option { // WithoutDB is a configuration modifier that adds a default DB stanza to // the authority config. +// +// De[recated: this method is deprecated in favor or WithNoDB. func WithoutDB() Option { return func(c *authconfig.Config) error { c.DB = nil @@ -506,18 +631,6 @@ func WithoutDB() Option { // GenerateConfig returns the step certificates configuration. func (p *PKI) GenerateConfig(opt ...Option) (*authconfig.Config, error) { - key, err := p.ottPrivateKey.CompactSerialize() - if err != nil { - return nil, errors.Wrap(err, "error serializing private key") - } - - prov := &provisioner.JWK{ - Name: p.provisioner, - Type: "JWK", - Key: p.ottPublicKey, - EncryptedKey: key, - } - var authorityOptions *apiv1.Options if !p.casOptions.Is(apiv1.SoftCAS) { authorityOptions = &p.casOptions @@ -528,8 +641,8 @@ func (p *PKI) GenerateConfig(opt ...Option) (*authconfig.Config, error) { FederatedRoots: []string{}, IntermediateCert: p.intermediate, IntermediateKey: p.intermediateKey, - Address: p.address, - DNSNames: p.dnsNames, + Address: p.options.address, + DNSNames: p.options.dnsNames, Logger: []byte(`{"format": "text"}`), DB: &db.Config{ Type: "badger", @@ -538,44 +651,109 @@ func (p *PKI) GenerateConfig(opt ...Option) (*authconfig.Config, error) { AuthorityConfig: &authconfig.AuthConfig{ Options: authorityOptions, DisableIssuedAtCheck: false, - Provisioners: provisioner.List{prov}, - }, - TLS: &authconfig.TLSOptions{ - MinVersion: authconfig.DefaultTLSMinVersion, - MaxVersion: authconfig.DefaultTLSMaxVersion, - Renegotiation: authconfig.DefaultTLSRenegotiation, - CipherSuites: authconfig.DefaultTLSCipherSuites, + EnableAdmin: false, }, + TLS: &authconfig.DefaultTLSOptions, Templates: p.getTemplates(), } - if p.enableSSH { - enableSSHCA := true - config.SSH = &authconfig.SSHConfig{ - HostKey: p.sshHostKey, - UserKey: p.sshUserKey, + + // On standalone deployments add the provisioners to either the ca.json or + // the database. + var provisioners []provisioner.Interface + if p.options.deploymentType == StandaloneDeployment { + key, err := p.ottPrivateKey.CompactSerialize() + if err != nil { + return nil, errors.Wrap(err, "error serializing private key") } - // Enable SSH authorization for default JWK provisioner - prov.Claims = &provisioner.Claims{ - EnableSSHCA: &enableSSHCA, + + prov := &provisioner.JWK{ + Name: p.options.provisioner, + Type: "JWK", + Key: p.ottPublicKey, + EncryptedKey: key, } - // Add default SSHPOP provisioner - sshpop := &provisioner.SSHPOP{ - Type: "SSHPOP", - Name: "sshpop", - Claims: &provisioner.Claims{ + provisioners = append(provisioners, prov) + + // Add default ACME provisioner if enabled + if p.options.enableACME { + provisioners = append(provisioners, &provisioner.ACME{ + Type: "ACME", + Name: "acme", + }) + } + + if p.options.enableSSH { + enableSSHCA := true + config.SSH = &authconfig.SSHConfig{ + HostKey: p.sshHostKey, + UserKey: p.sshUserKey, + } + // Enable SSH authorization for default JWK provisioner + prov.Claims = &provisioner.Claims{ EnableSSHCA: &enableSSHCA, - }, + } + + // Add default SSHPOP provisioner + provisioners = append(provisioners, &provisioner.SSHPOP{ + Type: "SSHPOP", + Name: "sshpop", + Claims: &provisioner.Claims{ + EnableSSHCA: &enableSSHCA, + }, + }) } - config.AuthorityConfig.Provisioners = append(config.AuthorityConfig.Provisioners, sshpop) } // Apply configuration modifiers for _, o := range opt { - if err = o(config); err != nil { + if err := o(config); err != nil { return nil, err } } + // Set authority.enableAdmin to true + if p.options.enableAdmin { + config.AuthorityConfig.EnableAdmin = true + } + + if p.options.deploymentType == StandaloneDeployment { + if !config.AuthorityConfig.EnableAdmin { + config.AuthorityConfig.Provisioners = provisioners + } else { + db, err := db.New(config.DB) + if err != nil { + return nil, err + } + adminDB, err := admindb.New(db.(nosql.DB), admin.DefaultAuthorityID) + if err != nil { + return nil, err + } + // Add all the provisioners to the db. + var adminID string + for i, p := range provisioners { + prov, err := authority.ProvisionerToLinkedca(p) + if err != nil { + return nil, err + } + if err := adminDB.CreateProvisioner(context.Background(), prov); err != nil { + return nil, err + } + if i == 0 { + adminID = prov.Id + } + } + // Add the first provisioner as an admin. + if err := adminDB.CreateAdmin(context.Background(), &linkedca.Admin{ + AuthorityId: admin.DefaultAuthorityID, + Subject: "step", + Type: linkedca.Admin_SUPER_ADMIN, + ProvisionerId: adminID, + }); err != nil { + return nil, err + } + } + } + return config, nil } @@ -599,17 +777,16 @@ func (p *PKI) Save(opt ...Option) error { } // Generate the CA URL. - if p.caURL == "" { - p.caURL = p.dnsNames[0] - var port string - _, port, err = net.SplitHostPort(p.address) + if p.options.caURL == "" { + p.options.caURL = p.options.dnsNames[0] + _, port, err := net.SplitHostPort(p.options.address) if err != nil { - return errors.Wrapf(err, "error parsing %s", p.address) + return errors.Wrapf(err, "error parsing %s", p.options.address) } if port == "443" { - p.caURL = fmt.Sprintf("https://%s", p.caURL) + p.options.caURL = fmt.Sprintf("https://%s", p.options.caURL) } else { - p.caURL = fmt.Sprintf("https://%s:%s", p.caURL, port) + p.options.caURL = fmt.Sprintf("https://%s:%s", p.options.caURL, port) } } @@ -617,7 +794,7 @@ func (p *PKI) Save(opt ...Option) error { defaults := &caDefaults{ Root: p.root, CAConfig: p.config, - CAUrl: p.caURL, + CAUrl: p.options.caURL, Fingerprint: p.rootFingerprint, } b, err = json.MarshalIndent(defaults, "", "\t") diff --git a/pki/templates.go b/pki/templates.go index 4c5309bb..3506a96d 100644 --- a/pki/templates.go +++ b/pki/templates.go @@ -13,7 +13,7 @@ import ( // getTemplates returns all the templates enabled func (p *PKI) getTemplates() *templates.Templates { - if !p.enableSSH { + if !p.options.enableSSH { return nil } return &templates.Templates{ From de292fbed60731360f00dbd6d173f4a83903ded1 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Mon, 2 Aug 2021 16:08:54 -0700 Subject: [PATCH 040/195] Use branch version of linkedca. --- go.mod | 4 ++-- go.sum | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index 98e7dbdb..12933ece 100644 --- a/go.mod +++ b/go.mod @@ -28,7 +28,7 @@ require ( go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1 go.step.sm/cli-utils v0.4.1 go.step.sm/crypto v0.9.0 - go.step.sm/linkedca v0.3.0 + go.step.sm/linkedca v0.4.1-0.20210802195257-6104dc57167d golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 golang.org/x/net v0.0.0-20210716203947-853a461950ff golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c // indirect @@ -42,6 +42,6 @@ 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 replace go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1 => github.com/omorsi/pkcs7 v0.0.0-20210217142924-a7b80a2a8568 diff --git a/go.sum b/go.sum index 9310efc5..a0996433 100644 --- a/go.sum +++ b/go.sum @@ -528,8 +528,8 @@ go.step.sm/cli-utils v0.4.1 h1:QztRUhGYjOPM1I2Nmi7V6XejQyVtcESmo+sbegxvX7Q= go.step.sm/cli-utils v0.4.1/go.mod h1:hWYVOSlw8W9Pd+BwIbs/aftVVMRms3EG7Q2qLRwc0WA= go.step.sm/crypto v0.9.0 h1:q2AllTSnVj4NRtyEPkGW2ohArLmbGbe6ZAL/VIOKDzA= go.step.sm/crypto v0.9.0/go.mod h1:+CYG05Mek1YDqi5WK0ERc6cOpKly2i/a5aZmU1sfGj0= -go.step.sm/linkedca v0.3.0 h1:6jyghg/ErVTJ/J23DrbWhGyWbWX2b4aJkPQEGL4xZ40= -go.step.sm/linkedca v0.3.0/go.mod h1:5uTRjozEGSPAZal9xJqlaD38cvJcLe3o1VAFVjqcORo= +go.step.sm/linkedca v0.4.1-0.20210802195257-6104dc57167d h1:d5cE1Bgyqw4pW3M7cPD+DndyOgKf41WJIzO+Dnx3q+4= +go.step.sm/linkedca v0.4.1-0.20210802195257-6104dc57167d/go.mod h1:5uTRjozEGSPAZal9xJqlaD38cvJcLe3o1VAFVjqcORo= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= From de719eb6f0228b8ebef847f96c6b60c842080f3f Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Wed, 4 Aug 2021 16:16:35 -0700 Subject: [PATCH 041/195] Add an option to avoid password prompts on step cas When we are using `step ca init` to create a stepcas RA we don't have access to the password for verify the provisioner. --- cas/apiv1/options.go | 11 +++++++++-- cas/stepcas/stepcas.go | 11 +++++++---- cas/stepcas/stepcas_test.go | 13 +++++++++++++ 3 files changed, 29 insertions(+), 6 deletions(-) diff --git a/cas/apiv1/options.go b/cas/apiv1/options.go index 61cac9a2..badad7fc 100644 --- a/cas/apiv1/options.go +++ b/cas/apiv1/options.go @@ -38,10 +38,17 @@ type Options struct { CertificateChain []*x509.Certificate `json:"-"` Signer crypto.Signer `json:"-"` - // IsCreator is set to true when we're creating a certificate authority. Is - // used to skip some validations when initializing a CertificateAuthority. + // IsCreator is set to true when we're creating a certificate authority. It + // is used to skip some validations when initializing a + // CertificateAuthority. This option is used on SoftCAS and CloudCAS. IsCreator bool `json:"-"` + // IsCAGetter is set to true when we're just using the + // CertificateAuthorityGetter interface to retrieve the root certificate. It + // is used to skip some validations when initializing a + // CertificateAuthority. This option is used on StepCAS. + IsCAGetter bool `json:"-"` + // KeyManager is the KMS used to generate keys in SoftCAS. KeyManager kms.KeyManager `json:"-"` diff --git a/cas/stepcas/stepcas.go b/cas/stepcas/stepcas.go index 49a99963..a124b4ae 100644 --- a/cas/stepcas/stepcas.go +++ b/cas/stepcas/stepcas.go @@ -47,10 +47,13 @@ func New(ctx context.Context, opts apiv1.Options) (*StepCAS, error) { return nil, err } - // Create configured issuer - iss, err := newStepIssuer(caURL, client, opts.CertificateIssuer) - if err != nil { - return nil, err + var iss stepIssuer + // Create configured issuer unless we only want to use GetCertificateAuthority. + // This avoid the request for the password if not provided. + if !opts.IsCAGetter { + if iss, err = newStepIssuer(caURL, client, opts.CertificateIssuer); err != nil { + return nil, err + } } return &StepCAS{ diff --git a/cas/stepcas/stepcas_test.go b/cas/stepcas/stepcas_test.go index fb8259f5..f430a1dd 100644 --- a/cas/stepcas/stepcas_test.go +++ b/cas/stepcas/stepcas_test.go @@ -411,6 +411,19 @@ func TestNew(t *testing.T) { client: client, fingerprint: testRootFingerprint, }, false}, + {"ok ca getter", args{context.TODO(), apiv1.Options{ + IsCAGetter: true, + CertificateAuthority: caURL.String(), + CertificateAuthorityFingerprint: testRootFingerprint, + CertificateIssuer: &apiv1.CertificateIssuer{ + Type: "jwk", + Provisioner: "ra@doe.org", + }, + }}, &StepCAS{ + iss: nil, + client: client, + fingerprint: testRootFingerprint, + }, false}, {"fail authority", args{context.TODO(), apiv1.Options{ CertificateAuthority: "", CertificateAuthorityFingerprint: testRootFingerprint, From 798b90c35947d6cd72e2eb6c2cb0ef746e90f528 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Wed, 4 Aug 2021 20:15:04 -0700 Subject: [PATCH 042/195] Move linkedca configuration to the main package. --- authority/export.go | 70 +++++++++++++++++++++++++-------------------- go.mod | 2 +- go.sum | 4 +-- 3 files changed, 42 insertions(+), 34 deletions(-) diff --git a/authority/export.go b/authority/export.go index b8679ac6..97efac03 100644 --- a/authority/export.go +++ b/authority/export.go @@ -8,8 +8,9 @@ import ( "strings" "github.com/pkg/errors" - step "go.step.sm/cli-utils/config" - "go.step.sm/linkedca/config" + "github.com/smallstep/certificates/authority/provisioner" + "go.step.sm/cli-utils/config" + "go.step.sm/linkedca" "google.golang.org/protobuf/types/known/structpb" ) @@ -18,7 +19,7 @@ import ( // // Note that export will not export neither the pki password nor the certificate // issuer password. -func (a *Authority) Export() (c *config.Configuration, err error) { +func (a *Authority) Export() (c *linkedca.Configuration, err error) { // Recover from panics defer func() { if r := recover(); r != nil { @@ -29,7 +30,7 @@ func (a *Authority) Export() (c *config.Configuration, err error) { files := make(map[string][]byte) // The exported configuration should not include the password in it. - c = &config.Configuration{ + c = &linkedca.Configuration{ Version: "1.0", Root: mustReadFilesOrUris(a.config.Root, files), FederatedRoots: mustReadFilesOrUris(a.config.FederatedRoots, files), @@ -41,36 +42,36 @@ func (a *Authority) Export() (c *config.Configuration, err error) { Db: mustMarshalToStruct(a.config.DB), Logger: mustMarshalToStruct(a.config.Logger), Monitoring: mustMarshalToStruct(a.config.Monitoring), - Authority: &config.Authority{ + Authority: &linkedca.Authority{ Id: a.config.AuthorityConfig.AuthorityID, EnableAdmin: a.config.AuthorityConfig.EnableAdmin, DisableIssuedAtCheck: a.config.AuthorityConfig.DisableIssuedAtCheck, - Backdate: a.config.AuthorityConfig.Backdate.String(), + Backdate: mustDuration(a.config.AuthorityConfig.Backdate), }, Files: files, } // SSH if v := a.config.SSH; v != nil { - c.Ssh = &config.SSH{ + c.Ssh = &linkedca.SSH{ HostKey: mustReadFileOrUri(v.HostKey, files), UserKey: mustReadFileOrUri(v.UserKey, files), AddUserPrincipal: v.AddUserPrincipal, AddUserCommand: v.AddUserCommand, } for _, k := range v.Keys { - typ, ok := config.SSHPublicKey_Type_value[strings.ToUpper(k.Type)] + typ, ok := linkedca.SSHPublicKey_Type_value[strings.ToUpper(k.Type)] if !ok { return nil, errors.Errorf("unsupported ssh key type %s", k.Type) } - c.Ssh.Keys = append(c.Ssh.Keys, &config.SSHPublicKey{ - Type: config.SSHPublicKey_Type(typ), + c.Ssh.Keys = append(c.Ssh.Keys, &linkedca.SSHPublicKey{ + Type: linkedca.SSHPublicKey_Type(typ), Federated: k.Federated, Key: mustMarshalToStruct(k), }) } if b := v.Bastion; b != nil { - c.Ssh.Bastion = &config.Bastion{ + c.Ssh.Bastion = &linkedca.Bastion{ Hostname: b.Hostname, User: b.User, Port: b.Port, @@ -85,15 +86,15 @@ func (a *Authority) Export() (c *config.Configuration, err error) { var typ int32 var ok bool if v.Type == "" { - typ = int32(config.KMS_SOFTKMS) + typ = int32(linkedca.KMS_SOFTKMS) } else { - typ, ok = config.KMS_Type_value[strings.ToUpper(v.Type)] + typ, ok = linkedca.KMS_Type_value[strings.ToUpper(v.Type)] if !ok { return nil, errors.Errorf("unsupported kms type %s", v.Type) } } - c.Kms = &config.KMS{ - Type: config.KMS_Type(typ), + c.Kms = &linkedca.KMS{ + Type: linkedca.KMS_Type(typ), CredentialsFile: v.CredentialsFile, Uri: v.URI, Pin: v.Pin, @@ -111,13 +112,13 @@ func (a *Authority) Export() (c *config.Configuration, err error) { c.Authority.CertificateAuthorityFingerprint = v.CertificateAuthorityFingerprint c.Authority.CredentialsFile = v.CredentialsFile if iss := v.CertificateIssuer; iss != nil { - typ, ok := config.CertificateIssuer_Type_value[strings.ToUpper(iss.Type)] + typ, ok := linkedca.CertificateIssuer_Type_value[strings.ToUpper(iss.Type)] if !ok { return nil, errors.Errorf("unknown certificate issuer type %s", iss.Type) } // The exporte certificate issuer should not include the password. - c.Authority.CertificateIssuer = &config.CertificateIssuer{ - Type: config.CertificateIssuer_Type(typ), + c.Authority.CertificateIssuer = &linkedca.CertificateIssuer{ + Type: linkedca.CertificateIssuer_Type(typ), Provisioner: iss.Provisioner, Certificate: mustReadFileOrUri(iss.Certificate, files), Key: mustReadFileOrUri(iss.Key, files), @@ -150,7 +151,7 @@ func (a *Authority) Export() (c *config.Configuration, err error) { c.Authority.Claims = claimsToLinkedca(a.config.AuthorityConfig.Claims) // Distiguised names template if v := a.config.AuthorityConfig.Template; v != nil { - c.Authority.Template = &config.DistinguishedName{ + c.Authority.Template = &linkedca.DistinguishedName{ Country: v.Country, Organization: v.Organization, OrganizationalUnit: v.OrganizationalUnit, @@ -164,20 +165,20 @@ func (a *Authority) Export() (c *config.Configuration, err error) { // TLS if v := a.config.TLS; v != nil { - c.Tls = &config.TLS{ + c.Tls = &linkedca.TLS{ MinVersion: v.MinVersion.String(), MaxVersion: v.MaxVersion.String(), Renegotiation: v.Renegotiation, } for _, cs := range v.CipherSuites.Value() { - c.Tls.CipherSuites = append(c.Tls.CipherSuites, config.TLS_CiperSuite(cs)) + c.Tls.CipherSuites = append(c.Tls.CipherSuites, linkedca.TLS_CiperSuite(cs)) } } // Templates if v := a.config.Templates; v != nil { - c.Templates = &config.Templates{ - Ssh: &config.SSHTemplate{}, + c.Templates = &linkedca.ConfigTemplates{ + Ssh: &linkedca.SSHConfigTemplate{}, Data: mustMarshalToStruct(v.Data), } // Remove automatically loaded vars @@ -185,12 +186,12 @@ func (a *Authority) Export() (c *config.Configuration, err error) { delete(c.Templates.Data.Fields, "Step") } for _, t := range v.SSH.Host { - typ, ok := config.Template_Type_value[strings.ToUpper(string(t.Type))] + typ, ok := linkedca.ConfigTemplate_Type_value[strings.ToUpper(string(t.Type))] if !ok { return nil, errors.Errorf("unsupported template type %s", t.Type) } - c.Templates.Ssh.Hosts = append(c.Templates.Ssh.Hosts, &config.Template{ - Type: config.Template_Type(typ), + c.Templates.Ssh.Hosts = append(c.Templates.Ssh.Hosts, &linkedca.ConfigTemplate{ + Type: linkedca.ConfigTemplate_Type(typ), Name: t.Name, Template: mustReadFileOrUri(t.TemplatePath, files), Path: t.Path, @@ -200,12 +201,12 @@ func (a *Authority) Export() (c *config.Configuration, err error) { }) } for _, t := range v.SSH.User { - typ, ok := config.Template_Type_value[strings.ToUpper(string(t.Type))] + typ, ok := linkedca.ConfigTemplate_Type_value[strings.ToUpper(string(t.Type))] if !ok { return nil, errors.Errorf("unsupported template type %s", t.Type) } - c.Templates.Ssh.Users = append(c.Templates.Ssh.Users, &config.Template{ - Type: config.Template_Type(typ), + c.Templates.Ssh.Users = append(c.Templates.Ssh.Users, &linkedca.ConfigTemplate{ + Type: linkedca.ConfigTemplate_Type(typ), Name: t.Name, Template: mustReadFileOrUri(t.TemplatePath, files), Path: t.Path, @@ -226,6 +227,13 @@ func mustPassword(s string) []byte { return []byte(s) } +func mustDuration(d *provisioner.Duration) string { + if d == nil || d.Duration == 0 { + return "" + } + return d.String() +} + func mustMarshalToStruct(v interface{}) *structpb.Struct { b, err := json.Marshal(v) if err != nil { @@ -243,7 +251,7 @@ func mustReadFileOrUri(fn string, m map[string][]byte) string { return "" } - stepPath := filepath.ToSlash(step.StepPath()) + stepPath := filepath.ToSlash(config.StepPath()) if !strings.HasSuffix(stepPath, "/") { stepPath += "/" } @@ -255,7 +263,7 @@ func mustReadFileOrUri(fn string, m map[string][]byte) string { panic(err) } if ok { - b, err := ioutil.ReadFile(step.StepAbs(fn)) + b, err := ioutil.ReadFile(config.StepAbs(fn)) if err != nil { panic(errors.Wrapf(err, "error reading %s", fn)) } diff --git a/go.mod b/go.mod index 12933ece..1149ac33 100644 --- a/go.mod +++ b/go.mod @@ -28,7 +28,7 @@ require ( go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1 go.step.sm/cli-utils v0.4.1 go.step.sm/crypto v0.9.0 - go.step.sm/linkedca v0.4.1-0.20210802195257-6104dc57167d + go.step.sm/linkedca v0.4.1-0.20210805031331-a377303edb9d golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 golang.org/x/net v0.0.0-20210716203947-853a461950ff golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c // indirect diff --git a/go.sum b/go.sum index a0996433..555f5b64 100644 --- a/go.sum +++ b/go.sum @@ -528,8 +528,8 @@ go.step.sm/cli-utils v0.4.1 h1:QztRUhGYjOPM1I2Nmi7V6XejQyVtcESmo+sbegxvX7Q= go.step.sm/cli-utils v0.4.1/go.mod h1:hWYVOSlw8W9Pd+BwIbs/aftVVMRms3EG7Q2qLRwc0WA= go.step.sm/crypto v0.9.0 h1:q2AllTSnVj4NRtyEPkGW2ohArLmbGbe6ZAL/VIOKDzA= go.step.sm/crypto v0.9.0/go.mod h1:+CYG05Mek1YDqi5WK0ERc6cOpKly2i/a5aZmU1sfGj0= -go.step.sm/linkedca v0.4.1-0.20210802195257-6104dc57167d h1:d5cE1Bgyqw4pW3M7cPD+DndyOgKf41WJIzO+Dnx3q+4= -go.step.sm/linkedca v0.4.1-0.20210802195257-6104dc57167d/go.mod h1:5uTRjozEGSPAZal9xJqlaD38cvJcLe3o1VAFVjqcORo= +go.step.sm/linkedca v0.4.1-0.20210805031331-a377303edb9d h1:bMcTynjdYq1Xmoi0G3NPCfV/aP1/vVQ/p7W3oYhoVXU= +go.step.sm/linkedca v0.4.1-0.20210805031331-a377303edb9d/go.mod h1:5uTRjozEGSPAZal9xJqlaD38cvJcLe3o1VAFVjqcORo= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= From 50f7a0d0c017da03a60a41cbc72b6e2ddb252e41 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Wed, 4 Aug 2021 20:15:26 -0700 Subject: [PATCH 043/195] Work in progress implementation of PKI with helm support --- pki/helm.go | 150 ++++++++++++++++++++++ pki/pki.go | 357 ++++++++++++++++++++++++++++++++-------------------- 2 files changed, 369 insertions(+), 138 deletions(-) create mode 100644 pki/helm.go diff --git a/pki/helm.go b/pki/helm.go new file mode 100644 index 00000000..7e4f1b2d --- /dev/null +++ b/pki/helm.go @@ -0,0 +1,150 @@ +package pki + +import ( + "io" + "text/template" + + "github.com/Masterminds/sprig/v3" + "github.com/pkg/errors" + authconfig "github.com/smallstep/certificates/authority/config" + "github.com/smallstep/certificates/authority/provisioner" + "go.step.sm/linkedca" +) + +type helmVariables struct { + linkedca.Configuration + Defaults linkedca.Defaults + Password string + SSH struct { + Enabled bool + } + TLS authconfig.TLSOptions + Provisioners []provisioner.Interface +} + +func (p *PKI) WriteHelmTemplate(w io.Writer) error { + tmpl, err := template.New("helm").Funcs(sprig.TxtFuncMap()).Parse(helmTemplate) + if err != nil { + return errors.Wrap(err, "error writing helm template") + } + + // Delete ssh section if it is not enabled + if !p.options.enableSSH { + p.Ssh = nil + } + + if err := tmpl.Execute(w, helmVariables{ + Configuration: p.Configuration, + Defaults: p.Defaults, + Password: "asdf", + TLS: authconfig.DefaultTLSOptions, + Provisioners: []provisioner.Interface{ + &provisioner.JWK{ + Name: p.options.provisioner, + Type: "JWK", + Key: p.ottPublicKey, + EncryptedKey: "", + }, + }, + }); err != nil { + return errors.Wrap(err, "error executing helm template") + } + return nil +} + +const helmTemplate = `# Helm template +inject: + enabled: true + # Config contains the configuration files ca.json and defaults.json + config: + files: + ca.json: + root: {{ first .Root }} + federateRoots: [] + crt: {{ .Intermediate }} + key: {{ .IntermediateKey }} + {{- if .SSH.Enabled }} + ssh: + hostKey: {{ .Ssh.HostKey }} + userKey: {{ .Ssh.UserKey }} + {{- end }} + address: {{ .Address }} + dnsNames: + {{- range .DnsNames }} + - {{ . }} + {{- end }} + logger: + format: json + db: + type: badger + dataSource: /home/step/db + authority: + provisioners: + {{- range .Provisioners }} + - {{ . | toJson }} + {{- end }} + tls: + cipherSuites: + {{- range .TLS.CipherSuites }} + - {{ . }} + {{- end }} + minVersion: {{ .TLS.MinVersion }} + maxVersion: {{ .TLS.MaxVersion }} + renegotiation: {{ .TLS.Renegotiation }} + + defaults.json: + ca-url: {{ .Defaults.CaUrl }} + ca-config: {{ .Defaults.CaConfig }} + fingerprint: {{ .Defaults.Fingerprint }} + root: {{ .Defaults.Root }} + + # Certificates contains the root and intermediate certificate and + # optionally the SSH host and user public keys + certificates: + # intermediate_ca contains the text of the intermediate CA Certificate + intermediate_ca: | + {{- index .Files .Intermediate | toString | nindent 6 }} + + # root_ca contains the text of the root CA Certificate + root_ca: | + {{- first .Root | index .Files | toString | nindent 6 }} + + {{- if .Ssh }} + # ssh_host_ca contains the text of the public ssh key for the SSH root CA + ssh_host_ca: {{ index .Files .Ssh.HostPublicKey | toString }} + + # ssh_user_ca contains the text of the public ssh key for the SSH root CA + ssh_user_ca: {{ index .Files .Ssh.UserPublicKey | toString }} + {{- end }} + + # Secrets contains the root and intermediate keys and optionally the SSH + # private keys + secrets: + # ca_password contains the password used to encrypt x509.intermediate_ca_key, ssh.host_ca_key and ssh.user_ca_key + # This value must be base64 encoded. + ca_password: {{ .Password | b64enc }} + provisioner_password: {{ .Password | b64enc}} + + x509: + # intermediate_ca_key contains the contents of your encrypted intermediate CA key + intermediate_ca_key: | + {{- index .Files .IntermediateKey | toString | nindent 8 }} + + # root_ca_key contains the contents of your encrypted root CA key + # Note that this value can be omitted without impacting the functionality of step-certificates + # If supplied, this should be encrypted using a unique password that is not used for encrypting + # the intermediate_ca_key, ssh.host_ca_key or ssh.user_ca_key. + root_ca_key: | + {{- first .RootKey | index .Files | toString | nindent 8 }} + + {{- if .Ssh }} + ssh: + # ssh_host_ca_key contains the contents of your encrypted SSH Host CA key + host_ca_key: | + {{- index .Files .Ssh.HostKey | toString | nindent 8 }} + + # ssh_user_ca_key contains the contents of your encrypted SSH User CA key + user_ca_key: | + {{- index .Files .Ssh.UserKey | toString | nindent 8 }} + {{- end }} +` diff --git a/pki/pki.go b/pki/pki.go index cfe9c49c..72350cd6 100644 --- a/pki/pki.go +++ b/pki/pki.go @@ -156,96 +156,108 @@ func GetProvisionerKey(caURL, rootFile, kid string) (string, error) { } type options struct { - address string - caURL string - dnsNames []string + // address string + // caURL string + // dnsNames []string provisioner string enableACME bool enableSSH bool enableAdmin bool noDB bool + isHelm bool deploymentType DeploymentType } // PKIOption is the type of a configuration option on the pki constructor. -type PKIOption func(o *options) +type PKIOption func(p *PKI) // WithAddress sets the listen address of step-ca. func WithAddress(s string) PKIOption { - return func(o *options) { - o.address = s + return func(p *PKI) { + p.Address = s } } // WithCaUrl sets the default ca-url of step-ca. func WithCaUrl(s string) PKIOption { - return func(o *options) { - o.caURL = s + return func(p *PKI) { + p.Defaults.CaUrl = s } } // WithDNSNames sets the SANs of step-ca. func WithDNSNames(s []string) PKIOption { - return func(o *options) { - o.dnsNames = s + return func(p *PKI) { + p.DnsNames = s } } // WithProvisioner defines the name of the default provisioner. func WithProvisioner(s string) PKIOption { - return func(o *options) { - o.provisioner = s + return func(p *PKI) { + p.options.provisioner = s } } // WithACME enables acme provisioner in step-ca. func WithACME() PKIOption { - return func(o *options) { - o.enableACME = true + return func(p *PKI) { + p.options.enableACME = true } } // WithSSH enables ssh in step-ca. func WithSSH() PKIOption { - return func(o *options) { - o.enableSSH = true + return func(p *PKI) { + p.options.enableSSH = true } } // WithAdmin enables the admin api in step-ca. func WithAdmin() PKIOption { - return func(o *options) { - o.enableAdmin = true + return func(p *PKI) { + p.options.enableAdmin = true } } // WithNoDB disables the db in step-ca. func WithNoDB() PKIOption { - return func(o *options) { - o.noDB = true + return func(p *PKI) { + p.options.noDB = true + } +} + +// WithHelm configures the pki to create a helm values.yaml. +func WithHelm() PKIOption { + return func(p *PKI) { + p.options.isHelm = true } } // WithDeploymentType defines the deployment type of step-ca. func WithDeploymentType(dt DeploymentType) PKIOption { - return func(o *options) { - o.deploymentType = dt + return func(p *PKI) { + p.options.deploymentType = dt } } // PKI represents the Public Key Infrastructure used by a certificate authority. type PKI struct { - casOptions apiv1.Options - caService apiv1.CertificateAuthorityService - caCreator apiv1.CertificateAuthorityCreator - root, rootKey, rootFingerprint string - intermediate, intermediateKey string - sshHostPubKey, sshHostKey string - sshUserPubKey, sshUserKey string - config, defaults string - ottPublicKey *jose.JSONWebKey - ottPrivateKey *jose.JSONWebEncryption - options *options + linkedca.Configuration + Defaults linkedca.Defaults + casOptions apiv1.Options + caService apiv1.CertificateAuthorityService + caCreator apiv1.CertificateAuthorityCreator + // root, rootKey, rootFingerprint string + // intermediate, intermediateKey string + // sshHostPubKey, sshHostKey string + // sshUserPubKey, sshUserKey string + config string + defaults string + // rootFingerprint string + ottPublicKey *jose.JSONWebKey + ottPrivateKey *jose.JSONWebEncryption + options *options } // New creates a new PKI configuration. @@ -264,20 +276,6 @@ func New(o apiv1.Options, opts ...PKIOption) (*PKI, error) { caCreator = creator } - public := GetPublicPath() - private := GetSecretsPath() - config := GetConfigPath() - - // Create directories - dirs := []string{public, private, config, GetTemplatesPath()} - for _, name := range dirs { - if _, err := os.Stat(name); os.IsNotExist(err) { - if err = os.MkdirAll(name, 0700); err != nil { - return nil, errs.FileError(err, name) - } - } - } - // get absolute path for dir/name getPath := func(dir string, name string) (string, error) { s, err := filepath.Abs(filepath.Join(dir, name)) @@ -285,52 +283,96 @@ func New(o apiv1.Options, opts ...PKIOption) (*PKI, error) { } p := &PKI{ + Configuration: linkedca.Configuration{ + Address: "127.0.0.1:9000", + DnsNames: []string{"127.0.0.1"}, + Ssh: &linkedca.SSH{}, + Files: make(map[string][]byte), + }, casOptions: o, caCreator: caCreator, caService: caService, options: &options{ provisioner: "step-cli", - address: "127.0.0.1:9000", - dnsNames: []string{"127.0.0.1"}, }, } for _, fn := range opts { - fn(p.options) + fn(p) } - if p.root, err = getPath(public, "root_ca.crt"); err != nil { - return nil, err - } - if p.rootKey, err = getPath(private, "root_ca_key"); err != nil { - return nil, err - } - if p.intermediate, err = getPath(public, "intermediate_ca.crt"); err != nil { - return nil, err - } - if p.intermediateKey, err = getPath(private, "intermediate_ca_key"); err != nil { - return nil, err - } - if p.sshHostPubKey, err = getPath(public, "ssh_host_ca_key.pub"); err != nil { - return nil, err - } - if p.sshUserPubKey, err = getPath(public, "ssh_user_ca_key.pub"); err != nil { - return nil, err - } - if p.sshHostKey, err = getPath(private, "ssh_host_ca_key"); err != nil { - return nil, err - } - if p.sshUserKey, err = getPath(private, "ssh_user_ca_key"); err != nil { - return nil, err - } - if len(config) > 0 { - if p.config, err = getPath(config, "ca.json"); err != nil { - return nil, err - } - if p.defaults, err = getPath(config, "defaults.json"); err != nil { - return nil, err + // Use /home/step as the step path in helm configurations. + // Use the current step path when creating pki in files. + var public, private, config string + if p.options.isHelm { + public = "/home/step/certs" + private = "/home/step/secrets" + config = "/home/step/config" + } else { + public = GetPublicPath() + private = GetSecretsPath() + config = GetConfigPath() + // Create directories + dirs := []string{public, private, config, GetTemplatesPath()} + for _, name := range dirs { + if _, err := os.Stat(name); os.IsNotExist(err) { + if err = os.MkdirAll(name, 0700); err != nil { + return nil, errs.FileError(err, name) + } + } } } + if p.Defaults.CaUrl == "" { + p.Defaults.CaUrl = p.DnsNames[0] + _, port, err := net.SplitHostPort(p.Address) + if err != nil { + return nil, errors.Wrapf(err, "error parsing %s", p.Address) + } + if port == "443" { + p.Defaults.CaUrl = fmt.Sprintf("https://%s", p.Defaults.CaUrl) + } else { + p.Defaults.CaUrl = fmt.Sprintf("https://%s:%s", p.Defaults.CaUrl, port) + } + } + + root, err := getPath(public, "root_ca.crt") + if err != nil { + return nil, err + } + rootKey, err := getPath(private, "root_ca_key") + if err != nil { + return nil, err + } + p.Root = []string{root} + p.RootKey = []string{rootKey} + p.Defaults.Root = root + + if p.Intermediate, err = getPath(public, "intermediate_ca.crt"); err != nil { + return nil, err + } + if p.IntermediateKey, err = getPath(private, "intermediate_ca_key"); err != nil { + return nil, err + } + if p.Ssh.HostPublicKey, err = getPath(public, "ssh_host_ca_key.pub"); err != nil { + return nil, err + } + if p.Ssh.UserPublicKey, err = getPath(public, "ssh_user_ca_key.pub"); err != nil { + return nil, err + } + if p.Ssh.HostKey, err = getPath(private, "ssh_host_ca_key"); err != nil { + return nil, err + } + if p.Ssh.UserKey, err = getPath(private, "ssh_user_ca_key"); err != nil { + return nil, err + } + if p.defaults, err = getPath(config, "defaults.json"); err != nil { + return nil, err + } + if p.config, err = getPath(config, "ca.json"); err != nil { + return nil, err + } + p.Defaults.CaConfig = p.config + return p, nil } @@ -341,7 +383,7 @@ func (p *PKI) GetCAConfigPath() string { // GetRootFingerprint returns the root fingerprint. func (p *PKI) GetRootFingerprint() string { - return p.rootFingerprint + return p.Defaults.Fingerprint } // SetProvisioner sets the provisioner name of the OTT keys. @@ -355,21 +397,21 @@ func (p *PKI) SetProvisioner(s string) { // // Deprecated: this method is deprecated in favor of WithAddress. func (p *PKI) SetAddress(s string) { - p.options.address = s + p.Address = s } // SetDNSNames sets the dns names of the CA. // // Deprecated: this method is deprecated in favor of WithDNSNames. func (p *PKI) SetDNSNames(s []string) { - p.options.dnsNames = s + p.DnsNames = s } // SetCAURL sets the ca-url to use in the defaults.json. // // Deprecated: this method is deprecated in favor of WithCaUrl. func (p *PKI) SetCAURL(s string) { - p.options.caURL = s + p.Defaults.CaUrl = s } // GenerateKeyPairs generates the key pairs used by the certificate authority. @@ -408,11 +450,19 @@ func (p *PKI) GenerateRootCertificate(name, org, resource string, pass []byte) ( return nil, err } - // PrivateKey will only be set if we have access to it (SoftCAS). - if err := p.WriteRootCertificate(resp.Certificate, resp.PrivateKey, pass); err != nil { + sum := sha256.Sum256(resp.Certificate.Raw) + p.Defaults.Fingerprint = strings.ToLower(hex.EncodeToString(sum[:])) + p.Files[p.Root[0]] = encodeCertificate(resp.Certificate) + p.Files[p.RootKey[0]], err = encodePrivateKey(resp.PrivateKey, pass) + if err != nil { return nil, err } + // PrivateKey will only be set if we have access to it (SoftCAS). + // if err := p.WriteRootCertificate(resp.Certificate, resp.PrivateKey, pass); err != nil { + // return nil, err + // } + return resp, nil } @@ -442,12 +492,24 @@ func (p *PKI) GenerateIntermediateCertificate(name, org, resource string, parent } p.casOptions.CertificateAuthority = resp.Name - return p.WriteIntermediateCertificate(resp.Certificate, resp.PrivateKey, pass) + p.Files[p.Intermediate] = encodeCertificate(resp.Certificate) + p.Files[p.IntermediateKey], err = encodePrivateKey(resp.PrivateKey, pass) + if err != nil { + return err + } + + return nil + // return p.WriteIntermediateCertificate(resp.Certificate, resp.PrivateKey, pass) } // WriteRootCertificate writes to disk the given certificate and key. func (p *PKI) WriteRootCertificate(rootCrt *x509.Certificate, rootKey interface{}, pass []byte) error { - if err := fileutil.WriteFile(p.root, pem.EncodeToMemory(&pem.Block{ + fmt.Println(p.options.isHelm) + if p.options.isHelm { + return nil + } + + if err := fileutil.WriteFile(p.Root[0], pem.EncodeToMemory(&pem.Block{ Type: "CERTIFICATE", Bytes: rootCrt.Raw, }), 0600); err != nil { @@ -455,28 +517,32 @@ func (p *PKI) WriteRootCertificate(rootCrt *x509.Certificate, rootKey interface{ } if rootKey != nil { - _, err := pemutil.Serialize(rootKey, pemutil.WithPassword(pass), pemutil.ToFile(p.rootKey, 0600)) + _, err := pemutil.Serialize(rootKey, pemutil.WithPassword(pass), pemutil.ToFile(p.RootKey[0], 0600)) if err != nil { return err } } sum := sha256.Sum256(rootCrt.Raw) - p.rootFingerprint = strings.ToLower(hex.EncodeToString(sum[:])) + p.Defaults.Fingerprint = strings.ToLower(hex.EncodeToString(sum[:])) return nil } // WriteIntermediateCertificate writes to disk the given certificate and key. func (p *PKI) WriteIntermediateCertificate(crt *x509.Certificate, key interface{}, pass []byte) error { - if err := fileutil.WriteFile(p.intermediate, pem.EncodeToMemory(&pem.Block{ + if p.options.isHelm { + return nil + } + + if err := fileutil.WriteFile(p.Intermediate, pem.EncodeToMemory(&pem.Block{ Type: "CERTIFICATE", Bytes: crt.Raw, }), 0600); err != nil { return err } if key != nil { - _, err := pemutil.Serialize(key, pemutil.WithPassword(pass), pemutil.ToFile(p.intermediateKey, 0600)) + _, err := pemutil.Serialize(key, pemutil.WithPassword(pass), pemutil.ToFile(p.IntermediateKey, 0600)) if err != nil { return err } @@ -516,8 +582,8 @@ func (p *PKI) GetCertificateAuthority() error { } // Issuer is in the RA - p.intermediate = "" - p.intermediateKey = "" + p.Intermediate = "" + p.IntermediateKey = "" return nil } @@ -525,8 +591,8 @@ func (p *PKI) GetCertificateAuthority() error { // GenerateSSHSigningKeys generates and encrypts a private key used for signing // SSH user certificates and a private key used for signing host certificates. func (p *PKI) GenerateSSHSigningKeys(password []byte) error { - var pubNames = []string{p.sshHostPubKey, p.sshUserPubKey} - var privNames = []string{p.sshHostKey, p.sshUserKey} + var pubNames = []string{p.Ssh.HostPublicKey, p.Ssh.UserPublicKey} + var privNames = []string{p.Ssh.HostKey, p.Ssh.UserKey} for i := 0; i < 2; i++ { pub, priv, err := keyutil.GenerateDefaultKeyPair() if err != nil { @@ -539,13 +605,19 @@ func (p *PKI) GenerateSSHSigningKeys(password []byte) error { if err != nil { return errors.Wrapf(err, "error converting public key") } - _, err = pemutil.Serialize(priv, pemutil.WithFilename(privNames[i]), pemutil.WithPassword(password)) + p.Files[pubNames[i]] = ssh.MarshalAuthorizedKey(sshKey) + p.Files[privNames[i]], err = encodePrivateKey(priv, password) if err != nil { return err } - if err = fileutil.WriteFile(pubNames[i], ssh.MarshalAuthorizedKey(sshKey), 0600); err != nil { - return err - } + + // _, err = pemutil.Serialize(priv, pemutil.WithFilename(privNames[i]), pemutil.WithPassword(password)) + // if err != nil { + // return err + // } + // if err = fileutil.WriteFile(pubNames[i], ssh.MarshalAuthorizedKey(sshKey), 0600); err != nil { + // return err + // } } p.options.enableSSH = true return nil @@ -575,22 +647,22 @@ func (p *PKI) TellPKI() { func (p *PKI) tellPKI() { ui.Println() if p.casOptions.Is(apiv1.SoftCAS) { - ui.PrintSelected("Root certificate", p.root) - ui.PrintSelected("Root private key", p.rootKey) - ui.PrintSelected("Root fingerprint", p.rootFingerprint) - ui.PrintSelected("Intermediate certificate", p.intermediate) - ui.PrintSelected("Intermediate private key", p.intermediateKey) - } else if p.rootFingerprint != "" { - ui.PrintSelected("Root certificate", p.root) - ui.PrintSelected("Root fingerprint", p.rootFingerprint) + ui.PrintSelected("Root certificate", p.Root[0]) + ui.PrintSelected("Root private key", p.RootKey[0]) + ui.PrintSelected("Root fingerprint", p.Defaults.Fingerprint) + ui.PrintSelected("Intermediate certificate", p.Intermediate) + ui.PrintSelected("Intermediate private key", p.IntermediateKey) + } else if p.Defaults.Fingerprint != "" { + ui.PrintSelected("Root certificate", p.Root[0]) + ui.PrintSelected("Root fingerprint", p.Defaults.Fingerprint) } else { ui.Printf(`{{ "%s" | red }} {{ "Root certificate:" | bold }} failed to retrieve it from RA`+"\n", ui.IconBad) } if p.options.enableSSH { - ui.PrintSelected("SSH user root certificate", p.sshUserPubKey) - ui.PrintSelected("SSH user root private key", p.sshUserKey) - ui.PrintSelected("SSH host root certificate", p.sshHostPubKey) - ui.PrintSelected("SSH host root private key", p.sshHostKey) + ui.PrintSelected("SSH user public key", p.Ssh.UserPublicKey) + ui.PrintSelected("SSH user private key", p.Ssh.UserKey) + ui.PrintSelected("SSH host public key", p.Ssh.HostPublicKey) + ui.PrintSelected("SSH host private key", p.Ssh.HostKey) } } @@ -637,12 +709,12 @@ func (p *PKI) GenerateConfig(opt ...Option) (*authconfig.Config, error) { } config := &authconfig.Config{ - Root: []string{p.root}, - FederatedRoots: []string{}, - IntermediateCert: p.intermediate, - IntermediateKey: p.intermediateKey, - Address: p.options.address, - DNSNames: p.options.dnsNames, + Root: p.Root, + FederatedRoots: p.FederatedRoots, + IntermediateCert: p.Intermediate, + IntermediateKey: p.IntermediateKey, + Address: p.Address, + DNSNames: p.DnsNames, Logger: []byte(`{"format": "text"}`), DB: &db.Config{ Type: "badger", @@ -685,8 +757,8 @@ func (p *PKI) GenerateConfig(opt ...Option) (*authconfig.Config, error) { if p.options.enableSSH { enableSSHCA := true config.SSH = &authconfig.SSHConfig{ - HostKey: p.sshHostKey, - UserKey: p.sshUserKey, + HostKey: p.Ssh.HostKey, + UserKey: p.Ssh.UserKey, } // Enable SSH authorization for default JWK provisioner prov.Claims = &provisioner.Claims{ @@ -776,26 +848,12 @@ func (p *PKI) Save(opt ...Option) error { return errs.FileError(err, p.config) } - // Generate the CA URL. - if p.options.caURL == "" { - p.options.caURL = p.options.dnsNames[0] - _, port, err := net.SplitHostPort(p.options.address) - if err != nil { - return errors.Wrapf(err, "error parsing %s", p.options.address) - } - if port == "443" { - p.options.caURL = fmt.Sprintf("https://%s", p.options.caURL) - } else { - p.options.caURL = fmt.Sprintf("https://%s:%s", p.options.caURL, port) - } - } - // Generate and write defaults.json defaults := &caDefaults{ - Root: p.root, - CAConfig: p.config, - CAUrl: p.options.caURL, - Fingerprint: p.rootFingerprint, + Root: p.Defaults.Root, + CAConfig: p.Defaults.CaConfig, + CAUrl: p.Defaults.CaUrl, + Fingerprint: p.Defaults.Fingerprint, } b, err = json.MarshalIndent(defaults, "", "\t") if err != nil { @@ -830,3 +888,26 @@ func (p *PKI) Save(opt ...Option) error { return nil } + +func encodeCertificate(c *x509.Certificate) []byte { + return pem.EncodeToMemory(&pem.Block{ + Type: "CERTIFICATE", + Bytes: c.Raw, + }) +} + +func encodePublicKey(key crypto.PublicKey) ([]byte, error) { + block, err := pemutil.Serialize(key) + if err != nil { + return nil, err + } + return pem.EncodeToMemory(block), nil +} + +func encodePrivateKey(key crypto.PrivateKey, pass []byte) ([]byte, error) { + block, err := pemutil.Serialize(key, pemutil.WithPassword(pass)) + if err != nil { + return nil, err + } + return pem.EncodeToMemory(block), nil +} From ad4dbd6764ef807f952b7490a988a3c3f4376e19 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Thu, 5 Aug 2021 12:58:54 -0700 Subject: [PATCH 044/195] Write all files on save. --- pki/pki.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pki/pki.go b/pki/pki.go index 72350cd6..87e4842e 100644 --- a/pki/pki.go +++ b/pki/pki.go @@ -832,6 +832,13 @@ func (p *PKI) GenerateConfig(opt ...Option) (*authconfig.Config, error) { // Save stores the pki on a json file that will be used as the certificate // authority configuration. func (p *PKI) Save(opt ...Option) error { + // Write pre-generated files. + for fn, b := range p.Files { + if err := fileutil.WriteFile(fn, b, 0600); err != nil { + return err + } + } + p.tellPKI() // Generate and write ca.json From 79cf059447ff6b62b23a5bde019dd54a86235578 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Thu, 5 Aug 2021 15:57:13 -0700 Subject: [PATCH 045/195] Remove deprecated methods and write all pki files at once. --- pki/pki.go | 260 +++++++++++++++++++---------------------------------- 1 file changed, 90 insertions(+), 170 deletions(-) diff --git a/pki/pki.go b/pki/pki.go index 87e4842e..db168cf8 100644 --- a/pki/pki.go +++ b/pki/pki.go @@ -156,10 +156,8 @@ func GetProvisionerKey(caURL, rootFile, kid string) (string, error) { } type options struct { - // address string - // caURL string - // dnsNames []string provisioner string + pkiOnly bool enableACME bool enableSSH bool enableAdmin bool @@ -199,6 +197,13 @@ func WithProvisioner(s string) PKIOption { } } +// WithPKIOnly will only generate the PKI without the step-ca config files. +func WithPKIOnly() PKIOption { + return func(p *PKI) { + p.options.pkiOnly = true + } +} + // WithACME enables acme provisioner in step-ca. func WithACME() PKIOption { return func(p *PKI) { @@ -244,17 +249,12 @@ func WithDeploymentType(dt DeploymentType) PKIOption { // PKI represents the Public Key Infrastructure used by a certificate authority. type PKI struct { linkedca.Configuration - Defaults linkedca.Defaults - casOptions apiv1.Options - caService apiv1.CertificateAuthorityService - caCreator apiv1.CertificateAuthorityCreator - // root, rootKey, rootFingerprint string - // intermediate, intermediateKey string - // sshHostPubKey, sshHostKey string - // sshUserPubKey, sshUserKey string - config string - defaults string - // rootFingerprint string + Defaults linkedca.Defaults + casOptions apiv1.Options + caService apiv1.CertificateAuthorityService + caCreator apiv1.CertificateAuthorityCreator + config string + defaults string ottPublicKey *jose.JSONWebKey ottPrivateKey *jose.JSONWebEncryption options *options @@ -386,34 +386,6 @@ func (p *PKI) GetRootFingerprint() string { return p.Defaults.Fingerprint } -// SetProvisioner sets the provisioner name of the OTT keys. -// -// Deprecated: this method is deprecated in favor of WithProvisioner. -func (p *PKI) SetProvisioner(s string) { - p.options.provisioner = s -} - -// SetAddress sets the listening address of the CA. -// -// Deprecated: this method is deprecated in favor of WithAddress. -func (p *PKI) SetAddress(s string) { - p.Address = s -} - -// SetDNSNames sets the dns names of the CA. -// -// Deprecated: this method is deprecated in favor of WithDNSNames. -func (p *PKI) SetDNSNames(s []string) { - p.DnsNames = s -} - -// SetCAURL sets the ca-url to use in the defaults.json. -// -// Deprecated: this method is deprecated in favor of WithCaUrl. -func (p *PKI) SetCAURL(s string) { - p.Defaults.CaUrl = s -} - // GenerateKeyPairs generates the key pairs used by the certificate authority. func (p *PKI) GenerateKeyPairs(pass []byte) error { var err error @@ -450,22 +422,29 @@ func (p *PKI) GenerateRootCertificate(name, org, resource string, pass []byte) ( return nil, err } - sum := sha256.Sum256(resp.Certificate.Raw) - p.Defaults.Fingerprint = strings.ToLower(hex.EncodeToString(sum[:])) - p.Files[p.Root[0]] = encodeCertificate(resp.Certificate) - p.Files[p.RootKey[0]], err = encodePrivateKey(resp.PrivateKey, pass) - if err != nil { + // PrivateKey will only be set if we have access to it (SoftCAS). + if err := p.WriteRootCertificate(resp.Certificate, resp.PrivateKey, pass); err != nil { return nil, err } - // PrivateKey will only be set if we have access to it (SoftCAS). - // if err := p.WriteRootCertificate(resp.Certificate, resp.PrivateKey, pass); err != nil { - // return nil, err - // } - return resp, nil } +// WriteRootCertificate writes to the buffer the given certificate and key if given. +func (p *PKI) WriteRootCertificate(rootCrt *x509.Certificate, rootKey interface{}, pass []byte) error { + p.Files[p.Root[0]] = encodeCertificate(rootCrt) + if rootKey != nil { + var err error + p.Files[p.RootKey[0]], err = encodePrivateKey(rootKey, pass) + if err != nil { + return err + } + } + sum := sha256.Sum256(rootCrt.Raw) + p.Defaults.Fingerprint = strings.ToLower(hex.EncodeToString(sum[:])) + return nil +} + // GenerateIntermediateCertificate generates an intermediate certificate with // the given name and using the default key type. func (p *PKI) GenerateIntermediateCertificate(name, org, resource string, parent *apiv1.CreateCertificateAuthorityResponse, pass []byte) error { @@ -494,60 +473,7 @@ func (p *PKI) GenerateIntermediateCertificate(name, org, resource string, parent p.casOptions.CertificateAuthority = resp.Name p.Files[p.Intermediate] = encodeCertificate(resp.Certificate) p.Files[p.IntermediateKey], err = encodePrivateKey(resp.PrivateKey, pass) - if err != nil { - return err - } - - return nil - // return p.WriteIntermediateCertificate(resp.Certificate, resp.PrivateKey, pass) -} - -// WriteRootCertificate writes to disk the given certificate and key. -func (p *PKI) WriteRootCertificate(rootCrt *x509.Certificate, rootKey interface{}, pass []byte) error { - fmt.Println(p.options.isHelm) - if p.options.isHelm { - return nil - } - - if err := fileutil.WriteFile(p.Root[0], pem.EncodeToMemory(&pem.Block{ - Type: "CERTIFICATE", - Bytes: rootCrt.Raw, - }), 0600); err != nil { - return err - } - - if rootKey != nil { - _, err := pemutil.Serialize(rootKey, pemutil.WithPassword(pass), pemutil.ToFile(p.RootKey[0], 0600)) - if err != nil { - return err - } - } - - sum := sha256.Sum256(rootCrt.Raw) - p.Defaults.Fingerprint = strings.ToLower(hex.EncodeToString(sum[:])) - - return nil -} - -// WriteIntermediateCertificate writes to disk the given certificate and key. -func (p *PKI) WriteIntermediateCertificate(crt *x509.Certificate, key interface{}, pass []byte) error { - if p.options.isHelm { - return nil - } - - if err := fileutil.WriteFile(p.Intermediate, pem.EncodeToMemory(&pem.Block{ - Type: "CERTIFICATE", - Bytes: crt.Raw, - }), 0600); err != nil { - return err - } - if key != nil { - _, err := pemutil.Serialize(key, pemutil.WithPassword(pass), pemutil.ToFile(p.IntermediateKey, 0600)) - if err != nil { - return err - } - } - return nil + return err } // CreateCertificateAuthorityResponse returns a @@ -610,19 +536,21 @@ func (p *PKI) GenerateSSHSigningKeys(password []byte) error { if err != nil { return err } - - // _, err = pemutil.Serialize(priv, pemutil.WithFilename(privNames[i]), pemutil.WithPassword(password)) - // if err != nil { - // return err - // } - // if err = fileutil.WriteFile(pubNames[i], ssh.MarshalAuthorizedKey(sshKey), 0600); err != nil { - // return err - // } } p.options.enableSSH = true return nil } +// WriteFiles writes on disk the previously generated files. +func (p *PKI) WriteFiles() error { + for fn, b := range p.Files { + if err := fileutil.WriteFile(fn, b, 0600); err != nil { + return err + } + } + return nil +} + func (p *PKI) askFeedback() { ui.Println() ui.Printf("\033[1mFEEDBACK\033[0m %s %s\n", @@ -636,14 +564,6 @@ func (p *PKI) askFeedback() { ui.Println(" \033[1mhttps://bit.ly/step-discord\033[0m.") } -// TellPKI outputs the locations of public and private keys generated -// generated for a new PKI. Generally this will consist of a root certificate -// and key and an intermediate certificate and key. -func (p *PKI) TellPKI() { - p.tellPKI() - p.askFeedback() -} - func (p *PKI) tellPKI() { ui.Println() if p.casOptions.Is(apiv1.SoftCAS) { @@ -832,67 +752,67 @@ func (p *PKI) GenerateConfig(opt ...Option) (*authconfig.Config, error) { // Save stores the pki on a json file that will be used as the certificate // authority configuration. func (p *PKI) Save(opt ...Option) error { - // Write pre-generated files. - for fn, b := range p.Files { - if err := fileutil.WriteFile(fn, b, 0600); err != nil { - return err - } + // Write generated files + if err := p.WriteFiles(); err != nil { + return err } + // Display only the p.tellPKI() // Generate and write ca.json - config, err := p.GenerateConfig(opt...) - if err != nil { - return err - } + if !p.options.pkiOnly { + config, err := p.GenerateConfig(opt...) + if err != nil { + return err + } - b, err := json.MarshalIndent(config, "", "\t") - if err != nil { - return errors.Wrapf(err, "error marshaling %s", p.config) - } - if err = fileutil.WriteFile(p.config, b, 0644); err != nil { - return errs.FileError(err, p.config) - } + b, err := json.MarshalIndent(config, "", "\t") + if err != nil { + return errors.Wrapf(err, "error marshaling %s", p.config) + } + if err = fileutil.WriteFile(p.config, b, 0644); err != nil { + return errs.FileError(err, p.config) + } - // Generate and write defaults.json - defaults := &caDefaults{ - Root: p.Defaults.Root, - CAConfig: p.Defaults.CaConfig, - CAUrl: p.Defaults.CaUrl, - Fingerprint: p.Defaults.Fingerprint, - } - b, err = json.MarshalIndent(defaults, "", "\t") - if err != nil { - return errors.Wrapf(err, "error marshaling %s", p.defaults) - } - if err = fileutil.WriteFile(p.defaults, b, 0644); err != nil { - return errs.FileError(err, p.defaults) - } + // Generate and write defaults.json + defaults := &caDefaults{ + Root: p.Defaults.Root, + CAConfig: p.Defaults.CaConfig, + CAUrl: p.Defaults.CaUrl, + Fingerprint: p.Defaults.Fingerprint, + } + b, err = json.MarshalIndent(defaults, "", "\t") + if err != nil { + return errors.Wrapf(err, "error marshaling %s", p.defaults) + } + if err = fileutil.WriteFile(p.defaults, b, 0644); err != nil { + return errs.FileError(err, p.defaults) + } - // Generate and write templates - if err := generateTemplates(config.Templates); err != nil { - return err - } + // Generate and write templates + if err := generateTemplates(config.Templates); err != nil { + return err + } - if config.DB != nil { - ui.PrintSelected("Database folder", config.DB.DataSource) - } - if config.Templates != nil { - ui.PrintSelected("Templates folder", GetTemplatesPath()) - } + if config.DB != nil { + ui.PrintSelected("Database folder", config.DB.DataSource) + } + if config.Templates != nil { + ui.PrintSelected("Templates folder", GetTemplatesPath()) + } - ui.PrintSelected("Default configuration", p.defaults) - ui.PrintSelected("Certificate Authority configuration", p.config) - ui.Println() - if p.casOptions.Is(apiv1.SoftCAS) { - ui.Println("Your PKI is ready to go. To generate certificates for individual services see 'step help ca'.") - } else { - ui.Println("Your registration authority is ready to go. To generate certificates for individual services see 'step help ca'.") + ui.PrintSelected("Default configuration", p.defaults) + ui.PrintSelected("Certificate Authority configuration", p.config) + ui.Println() + if p.casOptions.Is(apiv1.SoftCAS) { + ui.Println("Your PKI is ready to go. To generate certificates for individual services see 'step help ca'.") + } else { + ui.Println("Your registration authority is ready to go. To generate certificates for individual services see 'step help ca'.") + } } p.askFeedback() - return nil } From f643af70951044a11b6e312459dced2b6bbc2bce Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Thu, 5 Aug 2021 15:57:48 -0700 Subject: [PATCH 046/195] Update onboarding flow with new pki package. --- commands/onboard.go | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/commands/onboard.go b/commands/onboard.go index 251a4b47..4b804560 100644 --- a/commands/onboard.go +++ b/commands/onboard.go @@ -163,17 +163,21 @@ func onboardAction(ctx *cli.Context) error { } func onboardPKI(config onboardingConfiguration) (*config.Config, string, error) { + var opts = []pki.PKIOption{ + pki.WithAddress(config.Address), + pki.WithDNSNames([]string{config.DNS}), + pki.WithProvisioner("admin"), + } + p, err := pki.New(apiv1.Options{ Type: apiv1.SoftCAS, IsCreator: true, - }) + }, opts...) if err != nil { return nil, "", err } - p.SetAddress(config.Address) - p.SetDNSNames([]string{config.DNS}) - + // Generate pki ui.Println("Generating root certificate...") root, err := p.GenerateRootCertificate(config.Name, config.Name, config.Name, config.password) if err != nil { @@ -186,8 +190,12 @@ func onboardPKI(config onboardingConfiguration) (*config.Config, string, error) return nil, "", err } + // Write files to disk + if err = p.WriteFiles(); err != nil { + return nil, "", err + } + // Generate provisioner - p.SetProvisioner("admin") ui.Println("Generating admin provisioner...") if err = p.GenerateKeyPairs(config.password); err != nil { return nil, "", err From 81004ce1f9319f934a6e4fa7e4843c4e7a1561ef Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Thu, 5 Aug 2021 17:36:18 -0700 Subject: [PATCH 047/195] Remove deprecated functions. --- pki/pki.go | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/pki/pki.go b/pki/pki.go index db168cf8..912865cf 100644 --- a/pki/pki.go +++ b/pki/pki.go @@ -596,31 +596,6 @@ type caDefaults struct { // Option is the type for modifiers over the auth config object. type Option func(c *authconfig.Config) error -// WithDefaultDB is a configuration modifier that adds a default DB stanza to -// the authority config. -// -// Deprecated: this method is deprecated because this is the default behavior. -func WithDefaultDB() Option { - return func(c *authconfig.Config) error { - c.DB = &db.Config{ - Type: "badger", - DataSource: GetDBPath(), - } - return nil - } -} - -// WithoutDB is a configuration modifier that adds a default DB stanza to -// the authority config. -// -// De[recated: this method is deprecated in favor or WithNoDB. -func WithoutDB() Option { - return func(c *authconfig.Config) error { - c.DB = nil - return nil - } -} - // GenerateConfig returns the step certificates configuration. func (p *PKI) GenerateConfig(opt ...Option) (*authconfig.Config, error) { var authorityOptions *apiv1.Options From 3f07eb597a731872465820a2c6a4381d08d89b68 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Thu, 5 Aug 2021 18:45:50 -0700 Subject: [PATCH 048/195] Implement revocation using linkedca. --- authority/linkedca.go | 46 +++++++++++++++++++++++++++++++++++++++++++ authority/tls.go | 25 +++++++++++++++++++++-- 2 files changed, 69 insertions(+), 2 deletions(-) diff --git a/authority/linkedca.go b/authority/linkedca.go index e0678aca..9c816e1e 100644 --- a/authority/linkedca.go +++ b/authority/linkedca.go @@ -15,6 +15,7 @@ import ( "time" "github.com/pkg/errors" + "github.com/smallstep/certificates/db" "go.step.sm/crypto/jose" "go.step.sm/crypto/keyutil" "go.step.sm/crypto/tlsutil" @@ -257,6 +258,34 @@ func (c *linkedCaClient) StoreSSHCertificate(crt *ssh.Certificate) error { return errors.Wrap(err, "error posting ssh certificate") } +func (c *linkedCaClient) Revoke(crt *x509.Certificate, rci *db.RevokedCertificateInfo) error { + ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) + defer cancel() + _, err := c.client.RevokeCertificate(ctx, &linkedca.RevokeCertificateRequest{ + Serial: rci.Serial, + PemCertificate: serializeCertificate(crt), + Reason: rci.Reason, + ReasonCode: linkedca.RevocationReasonCode(rci.ReasonCode), + Passive: true, + }) + + return errors.Wrap(err, "error revoking certificate") +} + +func (c *linkedCaClient) RevokeSSH(ssh *ssh.Certificate, rci *db.RevokedCertificateInfo) error { + ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) + defer cancel() + _, err := c.client.RevokeSSHCertificate(ctx, &linkedca.RevokeSSHCertificateRequest{ + Serial: rci.Serial, + Certificate: serializeSSHCertificate(ssh), + Reason: rci.Reason, + ReasonCode: linkedca.RevocationReasonCode(rci.ReasonCode), + Passive: true, + }) + + return errors.Wrap(err, "error revoking ssh certificate") +} + func (c *linkedCaClient) IsRevoked(serial string) (bool, error) { ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) defer cancel() @@ -281,6 +310,16 @@ func (c *linkedCaClient) IsSSHRevoked(serial string) (bool, error) { return resp.Status != linkedca.RevocationStatus_ACTIVE, nil } +func serializeCertificate(crt *x509.Certificate) string { + if crt == nil { + return "" + } + return string(pem.EncodeToMemory(&pem.Block{ + Type: "CERTIFICATE", + Bytes: crt.Raw, + })) +} + func serializeCertificateChain(fullchain ...*x509.Certificate) string { var chain string for _, crt := range fullchain { @@ -292,6 +331,13 @@ func serializeCertificateChain(fullchain ...*x509.Certificate) string { return chain } +func serializeSSHCertificate(crt *ssh.Certificate) string { + if crt == nil { + return "" + } + return string(ssh.MarshalAuthorizedKey(crt)) +} + func getAuthority(sans []string) (string, error) { for _, s := range sans { if strings.HasPrefix(s, "urn:smallstep:authority:") { diff --git a/authority/tls.go b/authority/tls.go index 32d6f3c6..90c70fc3 100644 --- a/authority/tls.go +++ b/authority/tls.go @@ -21,6 +21,7 @@ import ( "go.step.sm/crypto/keyutil" "go.step.sm/crypto/pemutil" "go.step.sm/crypto/x509util" + "golang.org/x/crypto/ssh" ) // GetTLSOptions returns the tls options configured. @@ -397,7 +398,7 @@ func (a *Authority) Revoke(ctx context.Context, revokeOpts *RevokeOptions) error } if provisioner.MethodFromContext(ctx) == provisioner.SSHRevokeMethod { - err = a.db.RevokeSSH(rci) + err = a.revokeSSH(nil, rci) } else { // Revoke an X.509 certificate using CAS. If the certificate is not // provided we will try to read it from the db. If the read fails we @@ -424,7 +425,7 @@ func (a *Authority) Revoke(ctx context.Context, revokeOpts *RevokeOptions) error } // Save as revoked in the Db. - err = a.db.Revoke(rci) + err = a.revoke(revokedCert, rci) } switch err { case nil: @@ -439,6 +440,26 @@ func (a *Authority) Revoke(ctx context.Context, revokeOpts *RevokeOptions) error } } +func (a *Authority) revoke(crt *x509.Certificate, rci *db.RevokedCertificateInfo) error { + if lca, ok := a.adminDB.(interface { + Revoke(*x509.Certificate, *db.RevokedCertificateInfo) error + }); ok { + println(true) + return lca.Revoke(crt, rci) + } + println(false) + return a.db.Revoke(rci) +} + +func (a *Authority) revokeSSH(crt *ssh.Certificate, rci *db.RevokedCertificateInfo) error { + if lca, ok := a.adminDB.(interface { + RevokeSSH(*ssh.Certificate, *db.RevokedCertificateInfo) error + }); ok { + return lca.RevokeSSH(crt, rci) + } + return a.db.Revoke(rci) +} + // GetTLSCertificate creates a new leaf certificate to be used by the CA HTTPS server. func (a *Authority) GetTLSCertificate() (*tls.Certificate, error) { fatal := func(err error) (*tls.Certificate, error) { From d72fa953acb1da02f4462c0f983ea4472801f3fa Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Thu, 5 Aug 2021 18:50:18 -0700 Subject: [PATCH 049/195] Remove debug statements. --- authority/tls.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/authority/tls.go b/authority/tls.go index 90c70fc3..bba0243a 100644 --- a/authority/tls.go +++ b/authority/tls.go @@ -444,10 +444,8 @@ func (a *Authority) revoke(crt *x509.Certificate, rci *db.RevokedCertificateInfo if lca, ok := a.adminDB.(interface { Revoke(*x509.Certificate, *db.RevokedCertificateInfo) error }); ok { - println(true) return lca.Revoke(crt, rci) } - println(false) return a.db.Revoke(rci) } From 16d3afb92aa1c1785c9f170161bfefd354b94b40 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Fri, 6 Aug 2021 12:37:20 -0700 Subject: [PATCH 050/195] Remove unused method. --- authority/export.go | 7 ------- 1 file changed, 7 deletions(-) diff --git a/authority/export.go b/authority/export.go index 97efac03..c7a4724b 100644 --- a/authority/export.go +++ b/authority/export.go @@ -220,13 +220,6 @@ func (a *Authority) Export() (c *linkedca.Configuration, err error) { return c, nil } -func mustPassword(s string) []byte { - if s == "" { - return nil - } - return []byte(s) -} - func mustDuration(d *provisioner.Duration) string { if d == nil || d.Duration == 0 { return "" From 9d51c2ccebf74e63d186fce8e40cd8191f50f6b0 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Fri, 6 Aug 2021 14:29:54 -0700 Subject: [PATCH 051/195] Fix linter errors in the name of export methods. --- authority/export.go | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/authority/export.go b/authority/export.go index c7a4724b..290c6e7b 100644 --- a/authority/export.go +++ b/authority/export.go @@ -32,10 +32,10 @@ func (a *Authority) Export() (c *linkedca.Configuration, err error) { // The exported configuration should not include the password in it. c = &linkedca.Configuration{ Version: "1.0", - Root: mustReadFilesOrUris(a.config.Root, files), - FederatedRoots: mustReadFilesOrUris(a.config.FederatedRoots, files), - Intermediate: mustReadFileOrUri(a.config.IntermediateCert, files), - IntermediateKey: mustReadFileOrUri(a.config.IntermediateKey, files), + Root: mustReadFilesOrURIs(a.config.Root, files), + FederatedRoots: mustReadFilesOrURIs(a.config.FederatedRoots, files), + Intermediate: mustReadFileOrURI(a.config.IntermediateCert, files), + IntermediateKey: mustReadFileOrURI(a.config.IntermediateKey, files), Address: a.config.Address, InsecureAddress: a.config.InsecureAddress, DnsNames: a.config.DNSNames, @@ -54,8 +54,8 @@ func (a *Authority) Export() (c *linkedca.Configuration, err error) { // SSH if v := a.config.SSH; v != nil { c.Ssh = &linkedca.SSH{ - HostKey: mustReadFileOrUri(v.HostKey, files), - UserKey: mustReadFileOrUri(v.UserKey, files), + HostKey: mustReadFileOrURI(v.HostKey, files), + UserKey: mustReadFileOrURI(v.UserKey, files), AddUserPrincipal: v.AddUserPrincipal, AddUserCommand: v.AddUserCommand, } @@ -120,8 +120,8 @@ func (a *Authority) Export() (c *linkedca.Configuration, err error) { c.Authority.CertificateIssuer = &linkedca.CertificateIssuer{ Type: linkedca.CertificateIssuer_Type(typ), Provisioner: iss.Provisioner, - Certificate: mustReadFileOrUri(iss.Certificate, files), - Key: mustReadFileOrUri(iss.Key, files), + Certificate: mustReadFileOrURI(iss.Certificate, files), + Key: mustReadFileOrURI(iss.Key, files), } } } @@ -193,7 +193,7 @@ func (a *Authority) Export() (c *linkedca.Configuration, err error) { c.Templates.Ssh.Hosts = append(c.Templates.Ssh.Hosts, &linkedca.ConfigTemplate{ Type: linkedca.ConfigTemplate_Type(typ), Name: t.Name, - Template: mustReadFileOrUri(t.TemplatePath, files), + Template: mustReadFileOrURI(t.TemplatePath, files), Path: t.Path, Comment: t.Comment, Requires: t.RequiredData, @@ -208,7 +208,7 @@ func (a *Authority) Export() (c *linkedca.Configuration, err error) { c.Templates.Ssh.Users = append(c.Templates.Ssh.Users, &linkedca.ConfigTemplate{ Type: linkedca.ConfigTemplate_Type(typ), Name: t.Name, - Template: mustReadFileOrUri(t.TemplatePath, files), + Template: mustReadFileOrURI(t.TemplatePath, files), Path: t.Path, Comment: t.Comment, Requires: t.RequiredData, @@ -239,7 +239,7 @@ func mustMarshalToStruct(v interface{}) *structpb.Struct { return r } -func mustReadFileOrUri(fn string, m map[string][]byte) string { +func mustReadFileOrURI(fn string, m map[string][]byte) string { if fn == "" { return "" } @@ -266,10 +266,10 @@ func mustReadFileOrUri(fn string, m map[string][]byte) string { return fn } -func mustReadFilesOrUris(fns []string, m map[string][]byte) []string { +func mustReadFilesOrURIs(fns []string, m map[string][]byte) []string { var result []string for _, fn := range fns { - result = append(result, mustReadFileOrUri(fn, m)) + result = append(result, mustReadFileOrURI(fn, m)) } return result } From 640f523150e8f5931f59d23ad4a3664142ec5141 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Fri, 6 Aug 2021 14:31:49 -0700 Subject: [PATCH 052/195] Remove unused function. --- pki/pki.go | 8 -------- 1 file changed, 8 deletions(-) diff --git a/pki/pki.go b/pki/pki.go index 912865cf..5474a707 100644 --- a/pki/pki.go +++ b/pki/pki.go @@ -798,14 +798,6 @@ func encodeCertificate(c *x509.Certificate) []byte { }) } -func encodePublicKey(key crypto.PublicKey) ([]byte, error) { - block, err := pemutil.Serialize(key) - if err != nil { - return nil, err - } - return pem.EncodeToMemory(block), nil -} - func encodePrivateKey(key crypto.PrivateKey, pass []byte) ([]byte, error) { block, err := pemutil.Serialize(key, pemutil.WithPassword(pass)) if err != nil { From 536536c92da8e9a8c40e96b4df3aa0d73a10e41f Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Fri, 6 Aug 2021 14:55:17 -0700 Subject: [PATCH 053/195] Wrap json errors. --- authority/provisioners.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/authority/provisioners.go b/authority/provisioners.go index ab069501..beb4f9ed 100644 --- a/authority/provisioners.go +++ b/authority/provisioners.go @@ -562,7 +562,7 @@ func ProvisionerToCertificates(p *linkedca.Provisioner) (provisioner.Interface, details := p.Details.GetData() if details == nil { - return nil, fmt.Errorf("provisioner does not have any details") + return nil, errors.New("provisioner does not have any details") } options := optionsToCertificates(p) @@ -571,7 +571,7 @@ func ProvisionerToCertificates(p *linkedca.Provisioner) (provisioner.Interface, case *linkedca.ProvisionerDetails_JWK: jwk := new(jose.JSONWebKey) if err := json.Unmarshal(d.JWK.PublicKey, &jwk); err != nil { - return nil, err + return nil, errors.Wrap(err, "error unmarshaling public key") } return &provisioner.JWK{ ID: p.Id, From 47a30f15248d0c864fef2c7112716a031a1305db Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Fri, 6 Aug 2021 14:58:03 -0700 Subject: [PATCH 054/195] Add JWK provisioner to generic config. Fix linter errors. --- commands/onboard.go | 2 +- pki/helm.go | 30 +++++++++++--------- pki/pki.go | 69 ++++++++++++++++++++++++++++++--------------- 3 files changed, 64 insertions(+), 37 deletions(-) diff --git a/commands/onboard.go b/commands/onboard.go index 4b804560..eb8285aa 100644 --- a/commands/onboard.go +++ b/commands/onboard.go @@ -163,7 +163,7 @@ func onboardAction(ctx *cli.Context) error { } func onboardPKI(config onboardingConfiguration) (*config.Config, string, error) { - var opts = []pki.PKIOption{ + var opts = []pki.Option{ pki.WithAddress(config.Address), pki.WithDNSNames([]string{config.DNS}), pki.WithProvisioner("admin"), diff --git a/pki/helm.go b/pki/helm.go index 7e4f1b2d..2a8ac513 100644 --- a/pki/helm.go +++ b/pki/helm.go @@ -6,14 +6,15 @@ import ( "github.com/Masterminds/sprig/v3" "github.com/pkg/errors" + "github.com/smallstep/certificates/authority" authconfig "github.com/smallstep/certificates/authority/config" "github.com/smallstep/certificates/authority/provisioner" "go.step.sm/linkedca" ) type helmVariables struct { - linkedca.Configuration - Defaults linkedca.Defaults + *linkedca.Configuration + Defaults *linkedca.Defaults Password string SSH struct { Enabled bool @@ -33,19 +34,22 @@ func (p *PKI) WriteHelmTemplate(w io.Writer) error { p.Ssh = nil } + // Convert provisioner to ca.json + provisioners := make([]provisioner.Interface, len(p.Authority.Provisioners)) + for i, p := range p.Authority.Provisioners { + pp, err := authority.ProvisionerToCertificates(p) + if err != nil { + return err + } + provisioners[i] = pp + } + if err := tmpl.Execute(w, helmVariables{ - Configuration: p.Configuration, - Defaults: p.Defaults, - Password: "asdf", + Configuration: &p.Configuration, + Defaults: &p.Defaults, + Password: "", TLS: authconfig.DefaultTLSOptions, - Provisioners: []provisioner.Interface{ - &provisioner.JWK{ - Name: p.options.provisioner, - Type: "JWK", - Key: p.ottPublicKey, - EncryptedKey: "", - }, - }, + Provisioners: provisioners, }); err != nil { return errors.Wrap(err, "error executing helm template") } diff --git a/pki/pki.go b/pki/pki.go index 5474a707..626e42d3 100644 --- a/pki/pki.go +++ b/pki/pki.go @@ -166,81 +166,81 @@ type options struct { deploymentType DeploymentType } -// PKIOption is the type of a configuration option on the pki constructor. -type PKIOption func(p *PKI) +// Option is the type of a configuration option on the pki constructor. +type Option func(p *PKI) // WithAddress sets the listen address of step-ca. -func WithAddress(s string) PKIOption { +func WithAddress(s string) Option { return func(p *PKI) { p.Address = s } } -// WithCaUrl sets the default ca-url of step-ca. -func WithCaUrl(s string) PKIOption { +// WithCaURL sets the default ca-url of step-ca. +func WithCaURL(s string) Option { return func(p *PKI) { p.Defaults.CaUrl = s } } // WithDNSNames sets the SANs of step-ca. -func WithDNSNames(s []string) PKIOption { +func WithDNSNames(s []string) Option { return func(p *PKI) { p.DnsNames = s } } // WithProvisioner defines the name of the default provisioner. -func WithProvisioner(s string) PKIOption { +func WithProvisioner(s string) Option { return func(p *PKI) { p.options.provisioner = s } } // WithPKIOnly will only generate the PKI without the step-ca config files. -func WithPKIOnly() PKIOption { +func WithPKIOnly() Option { return func(p *PKI) { p.options.pkiOnly = true } } // WithACME enables acme provisioner in step-ca. -func WithACME() PKIOption { +func WithACME() Option { return func(p *PKI) { p.options.enableACME = true } } // WithSSH enables ssh in step-ca. -func WithSSH() PKIOption { +func WithSSH() Option { return func(p *PKI) { p.options.enableSSH = true } } // WithAdmin enables the admin api in step-ca. -func WithAdmin() PKIOption { +func WithAdmin() Option { return func(p *PKI) { p.options.enableAdmin = true } } // WithNoDB disables the db in step-ca. -func WithNoDB() PKIOption { +func WithNoDB() Option { return func(p *PKI) { p.options.noDB = true } } // WithHelm configures the pki to create a helm values.yaml. -func WithHelm() PKIOption { +func WithHelm() Option { return func(p *PKI) { p.options.isHelm = true } } // WithDeploymentType defines the deployment type of step-ca. -func WithDeploymentType(dt DeploymentType) PKIOption { +func WithDeploymentType(dt DeploymentType) Option { return func(p *PKI) { p.options.deploymentType = dt } @@ -261,7 +261,7 @@ type PKI struct { } // New creates a new PKI configuration. -func New(o apiv1.Options, opts ...PKIOption) (*PKI, error) { +func New(o apiv1.Options, opts ...Option) (*PKI, error) { caService, err := cas.New(context.Background(), o) if err != nil { return nil, err @@ -284,10 +284,11 @@ func New(o apiv1.Options, opts ...PKIOption) (*PKI, error) { p := &PKI{ Configuration: linkedca.Configuration{ - Address: "127.0.0.1:9000", - DnsNames: []string{"127.0.0.1"}, - Ssh: &linkedca.SSH{}, - Files: make(map[string][]byte), + Address: "127.0.0.1:9000", + DnsNames: []string{"127.0.0.1"}, + Ssh: &linkedca.SSH{}, + Authority: &linkedca.Authority{}, + Files: make(map[string][]byte), }, casOptions: o, caCreator: caCreator, @@ -395,6 +396,28 @@ func (p *PKI) GenerateKeyPairs(pass []byte) error { return err } + // Add JWK provisioner to the configuration. + publicKey, err := json.Marshal(p.ottPublicKey) + if err != nil { + return errors.Wrap(err, "error marshaling public key") + } + encryptedKey, err := p.ottPrivateKey.CompactSerialize() + if err != nil { + return errors.Wrap(err, "error serializing private key") + } + p.Authority.Provisioners = append(p.Authority.Provisioners, &linkedca.Provisioner{ + Type: linkedca.Provisioner_JWK, + Name: p.options.provisioner, + Details: &linkedca.ProvisionerDetails{ + Data: &linkedca.ProvisionerDetails_JWK{ + JWK: &linkedca.JWKProvisioner{ + PublicKey: publicKey, + EncryptedPrivateKey: []byte(encryptedKey), + }, + }, + }, + }) + return nil } @@ -593,11 +616,11 @@ type caDefaults struct { Root string `json:"root"` } -// Option is the type for modifiers over the auth config object. -type Option func(c *authconfig.Config) error +// ConfigOption is the type for modifiers over the auth config object. +type ConfigOption func(c *authconfig.Config) error // GenerateConfig returns the step certificates configuration. -func (p *PKI) GenerateConfig(opt ...Option) (*authconfig.Config, error) { +func (p *PKI) GenerateConfig(opt ...ConfigOption) (*authconfig.Config, error) { var authorityOptions *apiv1.Options if !p.casOptions.Is(apiv1.SoftCAS) { authorityOptions = &p.casOptions @@ -726,7 +749,7 @@ func (p *PKI) GenerateConfig(opt ...Option) (*authconfig.Config, error) { // Save stores the pki on a json file that will be used as the certificate // authority configuration. -func (p *PKI) Save(opt ...Option) error { +func (p *PKI) Save(opt ...ConfigOption) error { // Write generated files if err := p.WriteFiles(); err != nil { return err From 56bb3eb6e1b5c03d5298922652c82c99bd50986b Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Tue, 10 Aug 2021 14:54:31 -0700 Subject: [PATCH 055/195] Add next steps for linked ca. --- pki/pki.go | 39 +++++++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/pki/pki.go b/pki/pki.go index 626e42d3..6ada040d 100644 --- a/pki/pki.go +++ b/pki/pki.go @@ -10,11 +10,9 @@ import ( "encoding/json" "encoding/pem" "fmt" - "html" "net" "os" "path/filepath" - "strconv" "strings" "time" @@ -576,15 +574,22 @@ func (p *PKI) WriteFiles() error { func (p *PKI) askFeedback() { ui.Println() - ui.Printf("\033[1mFEEDBACK\033[0m %s %s\n", - html.UnescapeString("&#"+strconv.Itoa(128525)+";"), - html.UnescapeString("&#"+strconv.Itoa(127867)+";")) - ui.Println(" The \033[1mstep\033[0m utility is not instrumented for usage statistics. It does not") - ui.Println(" phone home. But your feedback is extremely valuable. Any information you") - ui.Println(" can provide regarding how you’re using `step` helps. Please send us a") - ui.Println(" sentence or two, good or bad: \033[1mfeedback@smallstep.com\033[0m or join") - ui.Println(" \033[1mhttps://github.com/smallstep/certificates/discussions\033[0m and our Discord") - ui.Println(" \033[1mhttps://bit.ly/step-discord\033[0m.") + ui.Println("\033[1mFEEDBACK\033[0m 😍 🍻") + ui.Println(" The \033[1mstep\033[0m utility is not instrumented for usage statistics. It does not phone") + ui.Println(" home. But your feedback is extremely valuable. Any information you can provide") + ui.Println(" regarding how you’re using `step` helps. Please send us a sentence or two,") + ui.Println(" good or bad at \033[1mfeedback@smallstep.com\033[0m or join GitHub Discussions") + ui.Println(" \033[1mhttps://github.com/smallstep/certificates/discussions\033[0m and our Discord ") + ui.Println(" \033[1mhttps://bit.ly/step-discord\033[0m.") + + if p.options.deploymentType == LinkedDeployment { + ui.Println() + ui.Println("\033[1mNEXT STEPS\033[0m") + ui.Println(" 1. Log in or create a Certificate Manager account at \033[1mhttps://u.step.sm/linked\033[0m") + ui.Println(" 2. Add a new authority with \"linked\" type") + ui.Println(" 3. Follow instructions in browser to start `step-ca` using the `--token` flag") + ui.Println() + } } func (p *PKI) tellPKI() { @@ -802,11 +807,13 @@ func (p *PKI) Save(opt ...ConfigOption) error { ui.PrintSelected("Default configuration", p.defaults) ui.PrintSelected("Certificate Authority configuration", p.config) - ui.Println() - if p.casOptions.Is(apiv1.SoftCAS) { - ui.Println("Your PKI is ready to go. To generate certificates for individual services see 'step help ca'.") - } else { - ui.Println("Your registration authority is ready to go. To generate certificates for individual services see 'step help ca'.") + if p.options.deploymentType != LinkedDeployment { + ui.Println() + if p.casOptions.Is(apiv1.SoftCAS) { + ui.Println("Your PKI is ready to go. To generate certificates for individual services see 'step help ca'.") + } else { + ui.Println("Your registration authority is ready to go. To generate certificates for individual services see 'step help ca'.") + } } } From 072ba4227caaf1cf3489cc6cec85478791724681 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Tue, 10 Aug 2021 17:07:15 -0700 Subject: [PATCH 056/195] Add deployment type to config. This field is ignored except for the start of the ca. If the type is linked and the token is not passed, it will fail with an error. --- authority/config/config.go | 1 + commands/app.go | 14 ++++++++++++++ pki/pki.go | 22 +++++++++++++++++++++- 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/authority/config/config.go b/authority/config/config.go index 68886d77..2cf6bfac 100644 --- a/authority/config/config.go +++ b/authority/config/config.go @@ -85,6 +85,7 @@ type ASN1DN struct { type AuthConfig struct { *cas.Options AuthorityID string `json:"authorityId,omitempty"` + DeploymentType string `json:"deploymentType,omitempty"` Provisioners provisioner.List `json:"provisioners,omitempty"` Admins []*linkedca.Admin `json:"-"` Template *ASN1DN `json:"template,omitempty"` diff --git a/commands/app.go b/commands/app.go index 481c4867..faa25e31 100644 --- a/commands/app.go +++ b/commands/app.go @@ -8,11 +8,13 @@ import ( "net" "net/http" "os" + "strings" "unicode" "github.com/pkg/errors" "github.com/smallstep/certificates/authority/config" "github.com/smallstep/certificates/ca" + "github.com/smallstep/certificates/pki" "github.com/urfave/cli" "go.step.sm/cli-utils/errs" ) @@ -67,6 +69,18 @@ func appAction(ctx *cli.Context) error { fatal(err) } + if config.AuthorityConfig != nil { + if token == "" && strings.EqualFold(config.AuthorityConfig.DeploymentType, pki.LinkedDeployment.String()) { + return errors.New(`'step-ca' requires the '--token' flag for linked deploy type. + +To get a linked authority token: + 1. Log in or create a Certificate Manager account at ` + "\033[1mhttps://u.step.sm/linked\033[0m" + ` + 2. Add a new authority with "linked" type + 3. Follow instructions in browser to start 'step-ca' using the '--token' flag +`) + } + } + var password []byte if passFile != "" { if password, err = ioutil.ReadFile(passFile); err != nil { diff --git a/pki/pki.go b/pki/pki.go index 6ada040d..3f566bad 100644 --- a/pki/pki.go +++ b/pki/pki.go @@ -54,6 +54,20 @@ const ( HostedDeployment ) +// String returns the string version of the deployment type. +func (d DeploymentType) String() string { + switch d { + case StandaloneDeployment: + return "standalone" + case LinkedDeployment: + return "linked" + case HostedDeployment: + return "hosted" + default: + return "unknown" + } +} + const ( // ConfigPath is the directory name under the step path where the configuration // files will be stored. @@ -580,7 +594,7 @@ func (p *PKI) askFeedback() { ui.Println(" regarding how you’re using `step` helps. Please send us a sentence or two,") ui.Println(" good or bad at \033[1mfeedback@smallstep.com\033[0m or join GitHub Discussions") ui.Println(" \033[1mhttps://github.com/smallstep/certificates/discussions\033[0m and our Discord ") - ui.Println(" \033[1mhttps://bit.ly/step-discord\033[0m.") + ui.Println(" \033[1mhttps://u.step.sm/discord\033[0m.") if p.options.deploymentType == LinkedDeployment { ui.Println() @@ -652,6 +666,12 @@ func (p *PKI) GenerateConfig(opt ...ConfigOption) (*authconfig.Config, error) { Templates: p.getTemplates(), } + // Add linked as a deployment type to detect it on start and provide a + // message if the token is not given. + if p.options.deploymentType == LinkedDeployment { + config.AuthorityConfig.DeploymentType = LinkedDeployment.String() + } + // On standalone deployments add the provisioners to either the ca.json or // the database. var provisioners []provisioner.Interface From 28e882c9b30ff3e7b18670ed50da05e4e4d1e71c Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Tue, 10 Aug 2021 17:14:17 -0700 Subject: [PATCH 057/195] Add deployment type to export. --- authority/export.go | 1 + go.mod | 2 +- go.sum | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/authority/export.go b/authority/export.go index 290c6e7b..4eeb2813 100644 --- a/authority/export.go +++ b/authority/export.go @@ -47,6 +47,7 @@ func (a *Authority) Export() (c *linkedca.Configuration, err error) { EnableAdmin: a.config.AuthorityConfig.EnableAdmin, DisableIssuedAtCheck: a.config.AuthorityConfig.DisableIssuedAtCheck, Backdate: mustDuration(a.config.AuthorityConfig.Backdate), + DeploymentType: a.config.AuthorityConfig.DeploymentType, }, Files: files, } diff --git a/go.mod b/go.mod index 1149ac33..b26b1f29 100644 --- a/go.mod +++ b/go.mod @@ -28,7 +28,7 @@ require ( go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1 go.step.sm/cli-utils v0.4.1 go.step.sm/crypto v0.9.0 - go.step.sm/linkedca v0.4.1-0.20210805031331-a377303edb9d + go.step.sm/linkedca v0.4.1-0.20210811000902-b3e9cfa09de4 golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 golang.org/x/net v0.0.0-20210716203947-853a461950ff golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c // indirect diff --git a/go.sum b/go.sum index 555f5b64..28f22b04 100644 --- a/go.sum +++ b/go.sum @@ -528,8 +528,8 @@ go.step.sm/cli-utils v0.4.1 h1:QztRUhGYjOPM1I2Nmi7V6XejQyVtcESmo+sbegxvX7Q= go.step.sm/cli-utils v0.4.1/go.mod h1:hWYVOSlw8W9Pd+BwIbs/aftVVMRms3EG7Q2qLRwc0WA= go.step.sm/crypto v0.9.0 h1:q2AllTSnVj4NRtyEPkGW2ohArLmbGbe6ZAL/VIOKDzA= go.step.sm/crypto v0.9.0/go.mod h1:+CYG05Mek1YDqi5WK0ERc6cOpKly2i/a5aZmU1sfGj0= -go.step.sm/linkedca v0.4.1-0.20210805031331-a377303edb9d h1:bMcTynjdYq1Xmoi0G3NPCfV/aP1/vVQ/p7W3oYhoVXU= -go.step.sm/linkedca v0.4.1-0.20210805031331-a377303edb9d/go.mod h1:5uTRjozEGSPAZal9xJqlaD38cvJcLe3o1VAFVjqcORo= +go.step.sm/linkedca v0.4.1-0.20210811000902-b3e9cfa09de4 h1:9xNAR/hIsmw5K/B7oe27U3NoISS4KJux+c6Ij0YpwoY= +go.step.sm/linkedca v0.4.1-0.20210811000902-b3e9cfa09de4/go.mod h1:5uTRjozEGSPAZal9xJqlaD38cvJcLe3o1VAFVjqcORo= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= From 492ff4b6323cf3bd2765298fa5c0fdfafe28b08b Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Tue, 10 Aug 2021 17:30:33 -0700 Subject: [PATCH 058/195] Ask for the first provisioner password if none is provided. --- authority/authority.go | 9 ++++----- authority/provisioners.go | 9 +++++++++ 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/authority/authority.go b/authority/authority.go index 28af693c..1b060ef8 100644 --- a/authority/authority.go +++ b/authority/authority.go @@ -11,24 +11,23 @@ import ( "sync" "time" - "github.com/smallstep/certificates/cas" - "github.com/smallstep/certificates/scep" - "go.step.sm/linkedca" - "github.com/pkg/errors" "github.com/smallstep/certificates/authority/admin" adminDBNosql "github.com/smallstep/certificates/authority/admin/db/nosql" "github.com/smallstep/certificates/authority/administrator" "github.com/smallstep/certificates/authority/config" "github.com/smallstep/certificates/authority/provisioner" + "github.com/smallstep/certificates/cas" casapi "github.com/smallstep/certificates/cas/apiv1" "github.com/smallstep/certificates/db" "github.com/smallstep/certificates/kms" kmsapi "github.com/smallstep/certificates/kms/apiv1" "github.com/smallstep/certificates/kms/sshagentkms" + "github.com/smallstep/certificates/scep" "github.com/smallstep/certificates/templates" "github.com/smallstep/nosql" "go.step.sm/crypto/pemutil" + "go.step.sm/linkedca" "golang.org/x/crypto/ssh" ) @@ -474,7 +473,7 @@ func (a *Authority) init() error { if err != nil { return admin.WrapErrorISE(err, "error loading provisioners to initialize authority") } - if len(provs) == 0 { + if len(provs) == 0 && !strings.EqualFold(a.config.AuthorityConfig.DeploymentType, "linked") { // Create First Provisioner prov, err := CreateFirstProvisioner(context.Background(), a.adminDB, a.config.Password) if err != nil { diff --git a/authority/provisioners.go b/authority/provisioners.go index beb4f9ed..7e02126f 100644 --- a/authority/provisioners.go +++ b/authority/provisioners.go @@ -14,6 +14,7 @@ import ( "github.com/smallstep/certificates/authority/provisioner" "github.com/smallstep/certificates/errs" step "go.step.sm/cli-utils/config" + "go.step.sm/cli-utils/ui" "go.step.sm/crypto/jose" "go.step.sm/linkedca" "gopkg.in/square/go-jose.v2/jwt" @@ -238,6 +239,14 @@ func (a *Authority) RemoveProvisioner(ctx context.Context, id string) error { } func CreateFirstProvisioner(ctx context.Context, db admin.DB, password string) (*linkedca.Provisioner, error) { + if password == "" { + pass, err := ui.PromptPasswordGenerate("Please enter the password to encrypt your first provisioner, leave empty and we'll generate one") + if err != nil { + return nil, err + } + password = string(pass) + } + jwk, jwe, err := jose.GenerateDefaultKeyPair([]byte(password)) if err != nil { return nil, admin.WrapErrorISE(err, "error generating JWK key pair") From 66f6c73655da2a4cb89325fca577576fd8fc090a Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Wed, 11 Aug 2021 11:19:29 -0700 Subject: [PATCH 059/195] Update badger driver to use v2 by default. --- pki/pki.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pki/pki.go b/pki/pki.go index 3f566bad..333497db 100644 --- a/pki/pki.go +++ b/pki/pki.go @@ -654,7 +654,7 @@ func (p *PKI) GenerateConfig(opt ...ConfigOption) (*authconfig.Config, error) { DNSNames: p.DnsNames, Logger: []byte(`{"format": "text"}`), DB: &db.Config{ - Type: "badger", + Type: "badgerv2", DataSource: GetDBPath(), }, AuthorityConfig: &authconfig.AuthConfig{ From 9e5762fe063b663e9e852d3a4a15f9cae7adb4b9 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Wed, 11 Aug 2021 11:50:54 -0700 Subject: [PATCH 060/195] Allow the reuse of azure token if DisableTrustOnFirstUse is true Azure caches tokens for 24h and we cannot issue a new certificate for the same instance in that period of time. The meaning of this parameter is to allow the signing of multiple certificate in one instance. This is possible in GCP, because we get a new token, and is possible in AWS because we can generate a new one. On Azure there was no other way to do it unless you wait for 24h. Fixes #656 --- authority/authorize.go | 3 +++ authority/provisioner/azure.go | 5 +++-- authority/provisioner/azure_test.go | 2 +- authority/provisioner/provisioner.go | 12 ++++++++++++ authority/tls.go | 2 +- 5 files changed, 20 insertions(+), 4 deletions(-) diff --git a/authority/authorize.go b/authority/authorize.go index 8d1f878a..69ad2a90 100644 --- a/authority/authorize.go +++ b/authority/authorize.go @@ -173,6 +173,9 @@ func (a *Authority) AuthorizeAdminToken(r *http.Request, token string) (*linkedc } // UseToken stores the token to protect against reuse. +// +// This method currently ignores any error coming from the GetTokenID, but it +// should specifically ignore the error provisioner.ErrAllowTokenReuse. func (a *Authority) UseToken(token string, prov provisioner.Interface) error { if reuseKey, err := prov.GetTokenID(token); err == nil { if reuseKey == "" { diff --git a/authority/provisioner/azure.go b/authority/provisioner/azure.go index 230f246f..fee50658 100644 --- a/authority/provisioner/azure.go +++ b/authority/provisioner/azure.go @@ -131,9 +131,10 @@ func (p *Azure) GetTokenID(token string) (string, error) { return "", errors.Wrap(err, "error verifying claims") } - // If TOFU is disabled create return the token kid + // If TOFU is disabled then allow token re-use. Azure caches the token for + // 24h and without allowing the re-use we cannot use it twice. if p.DisableTrustOnFirstUse { - return claims.ID, nil + return "", ErrAllowTokenReuse } sum := sha256.Sum256([]byte(claims.XMSMirID)) diff --git a/authority/provisioner/azure_test.go b/authority/provisioner/azure_test.go index f21a5676..8033d345 100644 --- a/authority/provisioner/azure_test.go +++ b/authority/provisioner/azure_test.go @@ -72,7 +72,7 @@ func TestAzure_GetTokenID(t *testing.T) { wantErr bool }{ {"ok", p1, args{t1}, w1, false}, - {"ok no TOFU", p2, args{t2}, "the-jti", false}, + {"ok no TOFU", p2, args{t2}, "", true}, {"fail token", p1, args{"bad-token"}, "", true}, {"fail claims", p1, args{"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.ey.fooo"}, "", true}, } diff --git a/authority/provisioner/provisioner.go b/authority/provisioner/provisioner.go index 83cc6946..75fabed5 100644 --- a/authority/provisioner/provisioner.go +++ b/authority/provisioner/provisioner.go @@ -4,6 +4,7 @@ import ( "context" "crypto/x509" "encoding/json" + stderrors "errors" "net/url" "regexp" "strings" @@ -32,6 +33,17 @@ type Interface interface { AuthorizeSSHRekey(ctx context.Context, token string) (*ssh.Certificate, []SignOption, error) } +// ErrAllowTokenReuse is an error that is returned by provisioners that allows +// the reuse of tokens. +// +// This is for example returned by the Azure provisioner when +// DisableTrustOnFirstUse is set to true. For AWS and GCP DisableTrustOnFirst +// use means that we allow the re-use of a token coming from a specific +// instance, but in these providers we can always get a new token, but because +// Azure caches the token for up to 24h we should add a mechanism to allow the +// re-use. +var ErrAllowTokenReuse = stderrors.New("allow token reuse") + // Audiences stores all supported audiences by request type. type Audiences struct { Sign []string diff --git a/authority/tls.go b/authority/tls.go index 4c3420df..a3dd95d3 100644 --- a/authority/tls.go +++ b/authority/tls.go @@ -366,7 +366,7 @@ func (a *Authority) Revoke(ctx context.Context, revokeOpts *RevokeOptions) error } rci.ProvisionerID = p.GetID() rci.TokenID, err = p.GetTokenID(revokeOpts.OTT) - if err != nil { + if err != nil && !errors.Is(err, provisioner.ErrAllowTokenReuse) { return errs.Wrap(http.StatusInternalServerError, err, "authority.Revoke; could not get ID for token") } From d4ae267addc45ad7b4d9009b218f52f0933a2c89 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Wed, 11 Aug 2021 14:59:26 -0700 Subject: [PATCH 061/195] Fix ErrAllowTokenReuse comment. --- authority/provisioner/provisioner.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/authority/provisioner/provisioner.go b/authority/provisioner/provisioner.go index 75fabed5..652cb888 100644 --- a/authority/provisioner/provisioner.go +++ b/authority/provisioner/provisioner.go @@ -36,12 +36,12 @@ type Interface interface { // ErrAllowTokenReuse is an error that is returned by provisioners that allows // the reuse of tokens. // -// This is for example returned by the Azure provisioner when -// DisableTrustOnFirstUse is set to true. For AWS and GCP DisableTrustOnFirst -// use means that we allow the re-use of a token coming from a specific -// instance, but in these providers we can always get a new token, but because -// Azure caches the token for up to 24h we should add a mechanism to allow the -// re-use. +// This is, for example, returned by the Azure provisioner when +// DisableTrustOnFirstUse is set to true. Azure caches tokens for up to 24hr and +// has no mechanism for getting a different token - this can be an issue when +// rebooting a VM. In contrast, AWS and GCP have facilities for requesting a new +// token. Therefore, for the Azure provisioner we are enabling token reuse, with +// the understanding that we are not following security best practices var ErrAllowTokenReuse = stderrors.New("allow token reuse") // Audiences stores all supported audiences by request type. From 456ffd88060988dbb989496003fa1258eec4577d Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Wed, 11 Aug 2021 15:33:34 -0700 Subject: [PATCH 062/195] Use linkedca v0.5.0 --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index b26b1f29..dcc6721e 100644 --- a/go.mod +++ b/go.mod @@ -28,7 +28,7 @@ require ( go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1 go.step.sm/cli-utils v0.4.1 go.step.sm/crypto v0.9.0 - go.step.sm/linkedca v0.4.1-0.20210811000902-b3e9cfa09de4 + go.step.sm/linkedca v0.5.0 golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 golang.org/x/net v0.0.0-20210716203947-853a461950ff golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c // indirect diff --git a/go.sum b/go.sum index 28f22b04..f50932aa 100644 --- a/go.sum +++ b/go.sum @@ -528,8 +528,8 @@ go.step.sm/cli-utils v0.4.1 h1:QztRUhGYjOPM1I2Nmi7V6XejQyVtcESmo+sbegxvX7Q= go.step.sm/cli-utils v0.4.1/go.mod h1:hWYVOSlw8W9Pd+BwIbs/aftVVMRms3EG7Q2qLRwc0WA= go.step.sm/crypto v0.9.0 h1:q2AllTSnVj4NRtyEPkGW2ohArLmbGbe6ZAL/VIOKDzA= go.step.sm/crypto v0.9.0/go.mod h1:+CYG05Mek1YDqi5WK0ERc6cOpKly2i/a5aZmU1sfGj0= -go.step.sm/linkedca v0.4.1-0.20210811000902-b3e9cfa09de4 h1:9xNAR/hIsmw5K/B7oe27U3NoISS4KJux+c6Ij0YpwoY= -go.step.sm/linkedca v0.4.1-0.20210811000902-b3e9cfa09de4/go.mod h1:5uTRjozEGSPAZal9xJqlaD38cvJcLe3o1VAFVjqcORo= +go.step.sm/linkedca v0.5.0 h1:oZVRSpElM7lAL1XN2YkjdHwI/oIZ+1ULOnuqYPM6xjY= +go.step.sm/linkedca v0.5.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.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= From da2802504b9e1378da0afc8c0484b71dba0e9e4d Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Wed, 11 Aug 2021 15:33:45 -0700 Subject: [PATCH 063/195] Use Default min version if not specified. --- authority/config/config.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/authority/config/config.go b/authority/config/config.go index 2cf6bfac..75c32994 100644 --- a/authority/config/config.go +++ b/authority/config/config.go @@ -225,7 +225,7 @@ func (c *Config) Validate() error { c.TLS.MaxVersion = DefaultTLSOptions.MaxVersion } if c.TLS.MinVersion == 0 { - c.TLS.MinVersion = c.TLS.MaxVersion + c.TLS.MinVersion = DefaultTLSOptions.MinVersion } if c.TLS.MinVersion > c.TLS.MaxVersion { return errors.New("tls minVersion cannot exceed tls maxVersion") From e3ef4a7da973cdbb24eb1a044b009e98a63ae495 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Wed, 11 Aug 2021 15:42:22 -0700 Subject: [PATCH 064/195] Update test with default tls options. --- ca/testdata/ca.json | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/ca/testdata/ca.json b/ca/testdata/ca.json index 0a5149d9..d40325e8 100644 --- a/ca/testdata/ca.json +++ b/ca/testdata/ca.json @@ -9,12 +9,11 @@ "logger": {"format": "text"}, "tls": { "minVersion": 1.2, - "maxVersion": 1.2, + "maxVersion": 1.3, "renegotiation": false, "cipherSuites": [ - "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305", - "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", - "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384" + "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256", + "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256" ] }, "authority": { From b1f59586ab0335ee43cf495c078acb23edbdb7bf Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Fri, 13 Aug 2021 11:59:12 -0700 Subject: [PATCH 065/195] Update message to align with UI. --- commands/app.go | 2 +- pki/pki.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/commands/app.go b/commands/app.go index faa25e31..aa7b43d4 100644 --- a/commands/app.go +++ b/commands/app.go @@ -75,7 +75,7 @@ func appAction(ctx *cli.Context) error { To get a linked authority token: 1. Log in or create a Certificate Manager account at ` + "\033[1mhttps://u.step.sm/linked\033[0m" + ` - 2. Add a new authority with "linked" type + 2. Add a new authority and select "Link a step-ca instance" 3. Follow instructions in browser to start 'step-ca' using the '--token' flag `) } diff --git a/pki/pki.go b/pki/pki.go index 333497db..1d81d82a 100644 --- a/pki/pki.go +++ b/pki/pki.go @@ -600,7 +600,7 @@ func (p *PKI) askFeedback() { ui.Println() ui.Println("\033[1mNEXT STEPS\033[0m") ui.Println(" 1. Log in or create a Certificate Manager account at \033[1mhttps://u.step.sm/linked\033[0m") - ui.Println(" 2. Add a new authority with \"linked\" type") + ui.Println(" 2. Add a new authority and select \"Link a step-ca instance\"") ui.Println(" 3. Follow instructions in browser to start `step-ca` using the `--token` flag") ui.Println() } From a864f0134db9acbf64d5155f7ab3a0dbea58dd5a Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Mon, 16 Aug 2021 14:47:38 -0700 Subject: [PATCH 066/195] Fix key version when SHA512WithRSA is used. There was a typo creating RSA keys with SHA256 digests instead of SHA512 --- kms/cloudkms/cloudkms.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kms/cloudkms/cloudkms.go b/kms/cloudkms/cloudkms.go index cfbf8235..f4c656d3 100644 --- a/kms/cloudkms/cloudkms.go +++ b/kms/cloudkms/cloudkms.go @@ -46,8 +46,8 @@ var signatureAlgorithmMapping = map[apiv1.SignatureAlgorithm]interface{}{ 4096: kmspb.CryptoKeyVersion_RSA_SIGN_PKCS1_4096_SHA256, }, apiv1.SHA512WithRSA: map[int]kmspb.CryptoKeyVersion_CryptoKeyVersionAlgorithm{ - 0: kmspb.CryptoKeyVersion_RSA_SIGN_PKCS1_4096_SHA256, - 4096: kmspb.CryptoKeyVersion_RSA_SIGN_PKCS1_4096_SHA256, + 0: kmspb.CryptoKeyVersion_RSA_SIGN_PKCS1_4096_SHA512, + 4096: kmspb.CryptoKeyVersion_RSA_SIGN_PKCS1_4096_SHA512, }, apiv1.SHA256WithRSAPSS: map[int]kmspb.CryptoKeyVersion_CryptoKeyVersionAlgorithm{ 0: kmspb.CryptoKeyVersion_RSA_SIGN_PSS_3072_SHA256, From abd78e2d2acb5c84c4026300d88f1451c077697e Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Tue, 17 Aug 2021 13:25:55 -0700 Subject: [PATCH 067/195] Make kms uri compatible with Go 1.17. Go 1.17 introduces a change in the net/url package disallowing the use of semicolon (;) in URL queries. We used url.ParseQuery to decode the opaque string that is semicolon separated. This change replaces the semicolon with ampersands before decoding it. --- kms/uri/uri.go | 4 +++- kms/uri/uri_test.go | 25 +++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/kms/uri/uri.go b/kms/uri/uri.go index 94009c47..44271e74 100644 --- a/kms/uri/uri.go +++ b/kms/uri/uri.go @@ -59,7 +59,9 @@ func Parse(rawuri string) (*URI, error) { if u.Scheme == "" { return nil, errors.Errorf("error parsing %s: scheme is missing", rawuri) } - v, err := url.ParseQuery(u.Opaque) + // Starting with Go 1.17 url.ParseQuery returns an error using semicolon as + // separator. + v, err := url.ParseQuery(strings.ReplaceAll(u.Opaque, ";", "&")) if err != nil { return nil, errors.Wrapf(err, "error parsing %s", rawuri) } diff --git a/kms/uri/uri_test.go b/kms/uri/uri_test.go index aa420db4..c2e0a9fe 100644 --- a/kms/uri/uri_test.go +++ b/kms/uri/uri_test.go @@ -274,3 +274,28 @@ func TestURI_Pin(t *testing.T) { }) } } + +func TestURI_String(t *testing.T) { + mustParse := func(s string) *URI { + u, err := Parse(s) + if err != nil { + t.Fatal(err) + } + return u + } + tests := []struct { + name string + uri *URI + want string + }{ + {"ok new", New("yubikey", url.Values{"slot-id": []string{"9a"}, "foo": []string{"bar"}}), "yubikey:foo=bar;slot-id=9a"}, + {"ok parse", mustParse("yubikey:slot-id=9a;foo=bar?bar=zar"), "yubikey:slot-id=9a;foo=bar?bar=zar"}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := tt.uri.String(); got != tt.want { + t.Errorf("URI.String() = %v, want %v", got, tt.want) + } + }) + } +} From ae58a0ee4e5291a4d55c0a3ac6400030ba6dec51 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Tue, 17 Aug 2021 16:31:53 -0700 Subject: [PATCH 068/195] Make tests compatible with Go 1.17. With Go 1.17 tls.Dial will fail if the client and server configured protocols do not overlap. See https://golang.org/doc/go1.17#ALPN --- acme/challenge.go | 6 ++++++ acme/challenge_test.go | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/acme/challenge.go b/acme/challenge.go index 1d5f0ec9..559eeb13 100644 --- a/acme/challenge.go +++ b/acme/challenge.go @@ -129,6 +129,12 @@ func tlsalpn01Validate(ctx context.Context, ch *Challenge, db DB, jwk *jose.JSON conn, err := vo.TLSDial("tcp", hostPort, config) if err != nil { + // With Go 1.17+ tls.Dial fails if there's no overlap between configured + // client and server protocols. See https://golang.org/doc/go1.17#ALPN + if err.Error() == "remote error: tls: no application protocol" { + return storeError(ctx, db, ch, true, NewError(ErrorRejectedIdentifierType, + "cannot negotiate ALPN acme-tls/1 protocol for tls-alpn-01 challenge")) + } return storeError(ctx, db, ch, false, WrapError(ErrorConnectionType, err, "error doing TLS dial for %s", hostPort)) } diff --git a/acme/challenge_test.go b/acme/challenge_test.go index bb9a2507..97c5e4cd 100644 --- a/acme/challenge_test.go +++ b/acme/challenge_test.go @@ -1395,7 +1395,7 @@ func TestTLSALPN01Validate(t *testing.T) { assert.Equals(t, updch.Type, ch.Type) assert.Equals(t, updch.Value, ch.Value) - err := NewError(ErrorConnectionType, "error doing TLS dial for %v:443: tls: DialWithDialer timed out", ch.Value) + err := NewError(ErrorConnectionType, "error doing TLS dial for %v:443:", ch.Value) assert.HasPrefix(t, updch.Error.Err.Error(), err.Err.Error()) assert.Equals(t, updch.Error.Type, err.Type) From dc5205cc7276b8e803ffc8eb6f08cdb88b6d8cb6 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Tue, 17 Aug 2021 17:06:25 -0700 Subject: [PATCH 069/195] Extract the tls error code and fail accordingly. --- acme/challenge.go | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/acme/challenge.go b/acme/challenge.go index 559eeb13..70c52578 100644 --- a/acme/challenge.go +++ b/acme/challenge.go @@ -10,11 +10,13 @@ import ( "encoding/base64" "encoding/hex" "encoding/json" + "errors" "fmt" "io/ioutil" "net" "net/http" "net/url" + "reflect" "strings" "time" @@ -114,6 +116,17 @@ func http01Validate(ctx context.Context, ch *Challenge, db DB, jwk *jose.JSONWeb return nil } +func tlsAlert(err error) uint8 { + var opErr *net.OpError + if errors.As(err, &opErr) { + v := reflect.ValueOf(opErr.Err) + if v.Kind() == reflect.Uint8 { + return uint8(v.Uint()) + } + } + return 0 +} + func tlsalpn01Validate(ctx context.Context, ch *Challenge, db DB, jwk *jose.JSONWebKey, vo *ValidateChallengeOptions) error { config := &tls.Config{ NextProtos: []string{"acme-tls/1"}, @@ -130,8 +143,10 @@ func tlsalpn01Validate(ctx context.Context, ch *Challenge, db DB, jwk *jose.JSON conn, err := vo.TLSDial("tcp", hostPort, config) if err != nil { // With Go 1.17+ tls.Dial fails if there's no overlap between configured - // client and server protocols. See https://golang.org/doc/go1.17#ALPN - if err.Error() == "remote error: tls: no application protocol" { + // client and server protocols. When this happens the connection is + // closed with the error no_application_protocol(120) as required by + // RFC7301. See https://golang.org/doc/go1.17#ALPN + if tlsAlert(err) == 120 { return storeError(ctx, db, ch, true, NewError(ErrorRejectedIdentifierType, "cannot negotiate ALPN acme-tls/1 protocol for tls-alpn-01 challenge")) } From 8d523797718f61e96ecd521fbd8d840eb877ec27 Mon Sep 17 00:00:00 2001 From: Carl Tashian Date: Tue, 17 Aug 2021 17:17:28 -0700 Subject: [PATCH 070/195] New Dockerfile with entrypoint script for easy CA init --- docker/Dockerfile.step-ca | 3 +++ docker/entrypoint.sh | 52 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 docker/entrypoint.sh diff --git a/docker/Dockerfile.step-ca b/docker/Dockerfile.step-ca index 4a1908d6..9363b6ae 100644 --- a/docker/Dockerfile.step-ca +++ b/docker/Dockerfile.step-ca @@ -24,4 +24,7 @@ VOLUME ["/home/step"] STOPSIGNAL SIGTERM HEALTHCHECK CMD step ca health 2>/dev/null | grep "^ok" >/dev/null +COPY docker/entrypoint.sh /entrypoint.sh + +ENTRYPOINT ["/bin/bash", "/entrypoint.sh"] CMD exec /usr/local/bin/step-ca --password-file $PWDPATH $CONFIGPATH diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh new file mode 100644 index 00000000..f3e51705 --- /dev/null +++ b/docker/entrypoint.sh @@ -0,0 +1,52 @@ +#!/bin/bash +set -eo pipefail + +# Paraphrased from: +# https://github.com/influxdata/influxdata-docker/blob/0d341f18067c4652dfa8df7dcb24d69bf707363d/influxdb/2.0/entrypoint.sh +# (a repo with no LICENSE.md) + +export STEPPATH=$(step path) + +# List of env vars required for step ca init +declare -ra REQUIRED_INIT_VARS=(DOCKER_STEPCA_INIT_NAME DOCKER_STEPCA_INIT_DNS DOCKER_STEPCA_INIT_EMAIL DOCKER_STEPCA_INIT_PASSWORD) + +# optional: +# DOCKER_STEPCA_INIT_SSH (boolean default false) + +# Ensure all env vars required to run step ca init are set. +function init_if_possible () { + local missing_vars=0 + for var in "${REQUIRED_INIT_VARS[@]}"; do + if [ -z "${!var}" ]; then + missing_vars=1 + fi + done + if [ ${missing_vars} = 1 ]; then + >&2 echo "there is no ca.json config file; please run step ca init, or provide config parameters via DOCKER_STEPCA_INIT_ vars" + else + step_ca_init "${@}" + fi +} + +# Initialize a CA if not already initialized +function step_ca_init () { + echo "${DOCKER_STEPCA_INIT_PASSWORD}" > "${STEPPATH}/password" + local -a setup_args=( + --name "${DOCKER_STEPCA_INIT_NAME}" + --dns "${DOCKER_STEPCA_INIT_DNS}" + --provisioner "${DOCKER_STEPCA_INIT_EMAIL}" + --password-file "${STEPPATH}/password" + --address ":9000" + ) + if [ -n "${DOCKER_STEPCA_INIT_SSH}" ]; then + setup_args=("${setup_args[@]}" --ssh) + fi + step ca init "${setup_args[@]}" + mv $STEPPATH/password $PWDPATH +} + +if [ ! -f "${STEPPATH}/config/ca.json" ]; then + init_if_possible +fi + +exec "${@}" \ No newline at end of file From b88b2f9808bdc637fc41f688a5cd760fc2652e86 Mon Sep 17 00:00:00 2001 From: Carl Tashian Date: Wed, 18 Aug 2021 08:46:37 -0700 Subject: [PATCH 071/195] Just adding a comment to the step-ra install script --- scripts/install-step-ra.sh | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/scripts/install-step-ra.sh b/scripts/install-step-ra.sh index a24f6ea4..1920b17d 100644 --- a/scripts/install-step-ra.sh +++ b/scripts/install-step-ra.sh @@ -1,6 +1,18 @@ #!/bin/bash set -e +# TODO: +# - Parse params using argbash (argbash.io). Here's a template that I have tested but have not implemented yet: +# +# ARG_OPTIONAL_SINGLE([ca-url], , [the URL of the upstream (issuing) step-ca server]) +# ARG_OPTIONAL_SINGLE([fingerprint], , [the SHA256 fingerprint of the upstream peer step-ca server]) +# ARG_OPTIONAL_SINGLE([provisioner-name], , [the name of a JWK provisioner on the upstream CA that this RA will use]) +# ARG_OPTIONAL_SINGLE([provisioner-password-file], , [the name a file containing the upstream JWK provisioner password]) +# ARG_OPTIONAL_REPEATED([dns-name], , [DNS name of this RA that will appear on its TLS certificate; you may pass this flag multiple times]) +# ARG_OPTIONAL_SINGLE([listen-address], , [the address (and port #) this RA will listen on, eg. :443 or 127.0.0.1:4443]) +# ARG_HELP([This script will install and configure a Registration Authority that connects to an upstream CA running step-ca.]) +# ARGBASH_GO + echo "This script will install and start a step-ca server running in Registration Authority (RA) mode." echo "" echo "You will need an upstream CA (URL and fingerprint)" From 7ab26c830365bb717fc2e7a41f9bd21f9c86d5c4 Mon Sep 17 00:00:00 2001 From: Carl Tashian Date: Wed, 18 Aug 2021 11:09:26 -0700 Subject: [PATCH 072/195] Auto-generate password by default --- docker/entrypoint.sh | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh index f3e51705..583e2e97 100644 --- a/docker/entrypoint.sh +++ b/docker/entrypoint.sh @@ -8,10 +8,11 @@ set -eo pipefail export STEPPATH=$(step path) # List of env vars required for step ca init -declare -ra REQUIRED_INIT_VARS=(DOCKER_STEPCA_INIT_NAME DOCKER_STEPCA_INIT_DNS DOCKER_STEPCA_INIT_EMAIL DOCKER_STEPCA_INIT_PASSWORD) +declare -ra REQUIRED_INIT_VARS=(DOCKER_STEPCA_INIT_NAME DOCKER_STEPCA_INIT_DNS DOCKER_STEPCA_INIT_EMAIL) # optional: -# DOCKER_STEPCA_INIT_SSH (boolean default false) +# DOCKER_STEPCA_INIT_PASSWORD (initial CA password) +# DOCKER_STEPCA_INIT_SSH (boolean: given a non-empty value, create an SSH CA) # Ensure all env vars required to run step ca init are set. function init_if_possible () { @@ -28,9 +29,19 @@ function init_if_possible () { fi } +function generate_password () { + set +o pipefail + < /dev/urandom tr -dc A-Za-z0-9 | head -c40 + set -o pipefail +} + # Initialize a CA if not already initialized function step_ca_init () { - echo "${DOCKER_STEPCA_INIT_PASSWORD}" > "${STEPPATH}/password" + if [ -n "${DOCKER_STEPCA_INIT_PASSWORD}" ]; then + echo -n "${DOCKER_STEPCA_INIT_PASSWORD}" > "${STEPPATH}/password" + else + generate_password > "${STEPPATH}/password" + fi local -a setup_args=( --name "${DOCKER_STEPCA_INIT_NAME}" --dns "${DOCKER_STEPCA_INIT_DNS}" From bc63829111dbcb6ada9a776c71c84deaa5187754 Mon Sep 17 00:00:00 2001 From: Carl Tashian Date: Wed, 18 Aug 2021 11:11:05 -0700 Subject: [PATCH 073/195] Auto-generate password by default --- docker/entrypoint.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh index 583e2e97..a6d29768 100644 --- a/docker/entrypoint.sh +++ b/docker/entrypoint.sh @@ -37,11 +37,6 @@ function generate_password () { # Initialize a CA if not already initialized function step_ca_init () { - if [ -n "${DOCKER_STEPCA_INIT_PASSWORD}" ]; then - echo -n "${DOCKER_STEPCA_INIT_PASSWORD}" > "${STEPPATH}/password" - else - generate_password > "${STEPPATH}/password" - fi local -a setup_args=( --name "${DOCKER_STEPCA_INIT_NAME}" --dns "${DOCKER_STEPCA_INIT_DNS}" @@ -49,6 +44,11 @@ function step_ca_init () { --password-file "${STEPPATH}/password" --address ":9000" ) + if [ -n "${DOCKER_STEPCA_INIT_PASSWORD}" ]; then + echo -n "${DOCKER_STEPCA_INIT_PASSWORD}" > "${STEPPATH}/password" + else + generate_password > "${STEPPATH}/password" + fi if [ -n "${DOCKER_STEPCA_INIT_SSH}" ]; then setup_args=("${setup_args[@]}" --ssh) fi From f53f78974eda5022ae16a6a8b0775e8e1326ae0f Mon Sep 17 00:00:00 2001 From: max furman Date: Wed, 18 Aug 2021 11:38:31 -0700 Subject: [PATCH 074/195] Badger bump to fix issue with caddy build --- go.mod | 5 +- go.sum | 190 ++------------------------------------------------------- 2 files changed, 8 insertions(+), 187 deletions(-) diff --git a/go.mod b/go.mod index 58228557..f17b29bc 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,7 @@ require ( github.com/Masterminds/sprig/v3 v3.1.0 github.com/ThalesIgnite/crypto11 v1.2.4 github.com/aws/aws-sdk-go v1.30.29 + github.com/dgraph-io/ristretto v0.0.4-0.20200906165740-41ebdbffecfd // indirect github.com/go-chi/chi v4.0.2+incompatible github.com/go-kit/kit v0.10.0 // indirect github.com/go-piv/piv-go v1.7.0 @@ -22,7 +23,7 @@ require ( github.com/rs/xid v1.2.1 github.com/sirupsen/logrus v1.4.2 github.com/smallstep/assert v0.0.0-20200723003110-82e2b9b3b262 - github.com/smallstep/nosql v0.3.6 + github.com/smallstep/nosql v0.3.7 github.com/stretchr/testify v1.7.0 // indirect github.com/urfave/cli v1.22.4 go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1 @@ -38,7 +39,7 @@ require ( gopkg.in/square/go-jose.v2 v2.5.1 ) -// replace github.com/smallstep/nosql => ../nosql +//replace github.com/smallstep/nosql => ../nosql //replace go.step.sm/crypto => ../crypto diff --git a/go.sum b/go.sum index e2e71580..c0d45435 100644 --- a/go.sum +++ b/go.sum @@ -45,7 +45,6 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym github.com/DataDog/zstd v1.4.1/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= github.com/DataDog/zstd v1.4.5 h1:EndNeuB0l9syBZhut0wns3gV1hL8zX8LIu6ZiVHWLIQ= github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= -github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible h1:1G1pk05UrOh0NlF1oeaaix1x8XzrfjIDK47TY0Zehcw= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/Masterminds/goutils v1.1.0 h1:zukEsf/1JZwCMgHiK3GZftabmxiCw4apj3a28RPBiVg= github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= @@ -55,77 +54,56 @@ github.com/Masterminds/sprig/v3 v3.1.0 h1:j7GpgZ7PdFqNsmncycTHsLmVPf5/3wJtlgW9TN github.com/Masterminds/sprig/v3 v3.1.0/go.mod h1:ONGMf7UfYGAbMXCZmQLy8x3lCDIPrEZE/rU8pmrbihA= github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/Shopify/sarama v1.19.0 h1:9oksLxC6uxVPHPVYUmq6xhr1BOF/hHobWH2UzO67z1s= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= -github.com/Shopify/toxiproxy v2.1.4+incompatible h1:TKdv8HiTLgE5wdJuEML90aBgNWsokNbMijUGhmcoBJc= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= github.com/ThalesIgnite/crypto11 v1.2.4 h1:3MebRK/U0mA2SmSthXAIZAdUA9w8+ZuKem2O6HuR1f8= github.com/ThalesIgnite/crypto11 v1.2.4 h1:3MebRK/U0mA2SmSthXAIZAdUA9w8+ZuKem2O6HuR1f8= github.com/ThalesIgnite/crypto11 v1.2.4/go.mod h1:ILDKtnCKiQ7zRoNxcp36Y1ZR8LBPmR2E23+wTQe/MlE= github.com/ThalesIgnite/crypto11 v1.2.4/go.mod h1:ILDKtnCKiQ7zRoNxcp36Y1ZR8LBPmR2E23+wTQe/MlE= -github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE= github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= -github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5 h1:rFw4nCn9iMW+Vajsk51NtYIcwSTkXr+JGrMd36kTDJw= github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4 h1:Hs82Z41s6SdL1CELW+XaDYmOH4hkBN4/N9og/AsOv7E= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= -github.com/apache/thrift v0.13.0 h1:5hryIiq9gtn+MiLVn0wP37kb/uTeRZgN08WoCsAhIhI= github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= -github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e h1:QEF07wC0T1rKkctt1RINW/+RMTVmiwxETico2l3gxJA= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= -github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6 h1:G1bPvciwNyF7IUmKXNt9Ak3m6u9DE1rF+RmtIkBpVdA= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= -github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da h1:8GUt8eRujhVEGZFFEjBj46YV4rDjvGrNxb0KMWYkL2I= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= -github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310 h1:BUAU3CGlLvorLI26FmByPp2eC2qla6E1Tw+scpcg/to= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a h1:pv34s756C4pEXnjgPfGYgdhg/ZdajGhyOvzx8k+23nw= github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= -github.com/aws/aws-lambda-go v1.13.3 h1:SuCy7H3NLyp+1Mrfp+m80jcbi9KYWAs9/BXwppwRDzY= github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.30.29 h1:NXNqBS9hjOCpDL8SyCyl38gZX3LLLunKOJc5E7vJ8P0= github.com/aws/aws-sdk-go v1.30.29/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= -github.com/aws/aws-sdk-go-v2 v0.18.0 h1:qZ+woO4SamnH/eEbjM2IDLhRNwIwND/RQyVlBLp3Jqg= github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= -github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4= github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= -github.com/casbin/casbin/v2 v2.1.2 h1:bTwon/ECRx9dwBy2ewRVr5OiqjeXSGiTUY74sDPQi/g= github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= -github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= -github.com/census-instrumentation/opencensus-proto v0.2.1 h1:glEXhBS5PSLLv4IXzLA5yPRVX4bilULVyxxbrfOtDAk= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= @@ -133,44 +111,35 @@ github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5O github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 h1:q763qf9huN11kDQavWsoZXJNW3xEE4JJyHa5Q25/sd8= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec h1:EdRZT3IeKQmfCSrgo8SZ8V3MEnskuJP0wCYNpe+aiXo= github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= -github.com/client9/misspell v0.3.4 h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403 h1:cqQfy1jclcSy/FwLjemeg3SR1yaINm74aQyupQ0Bl8M= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa h1:OaNxuTZr7kxeODyLWsRMC+OD03aFUH+mW6r2d+MWa5Y= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= -github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd h1:qMd81Ts1T2OTKmB4acZcyKaMtRnY5Y44NuXGX2GFJ1w= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= -github.com/coreos/etcd v3.3.10+incompatible h1:jFneRYjIvLMLhDLCzuTuU4rSJUjRplcJQ7pD7MnhC04= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7 h1:u9SHYsPQNyt5tgDm3YN7+9dYrpK96E5wFilTFWIDZOM= github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf h1:CAKfRE2YtTUIjjh1bkBtyYFaUT/WmOqsJjgtihT0vMI= github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/creack/pty v1.1.7 h1:6pwm8kMQKCmgUg0ZHTm5+/YvRK0s3THD/28+T6/kk4A= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgraph-io/badger v1.6.2 h1:mNw0qs90GVgGGWylh0umH5iag1j6n/PeJtNvL6KY/x8= github.com/dgraph-io/badger v1.6.2/go.mod h1:JW2yswe3V058sS0kZ2h/AXeDSqFjxnZcRrVH//y2UQE= -github.com/dgraph-io/badger/v2 v2.0.1-rc1.0.20201003150343-5d1bab4fc658 h1:/WBjuutuivOA02gpDtrvrWKw01ugkyt3QnimB7enbtI= -github.com/dgraph-io/badger/v2 v2.0.1-rc1.0.20201003150343-5d1bab4fc658/go.mod h1:2uGEvGm+JSDLd5UAaKIFSbXDcYyeH0fWJP4N2HMMYMI= +github.com/dgraph-io/badger/v2 v2.2007.3 h1:Sl9tQWz92WCbVSe8pj04Tkqlm2boW+KAxd+XSs58SQI= +github.com/dgraph-io/badger/v2 v2.2007.3/go.mod h1:26P/7fbL4kUZVEVKLAKXkBXKOydDmM2p1e+NhhnBCAE= github.com/dgraph-io/ristretto v0.0.2/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E= +github.com/dgraph-io/ristretto v0.0.3-0.20200630154024-f66de99634de/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E= github.com/dgraph-io/ristretto v0.0.4-0.20200906165740-41ebdbffecfd h1:KoJOtZf+6wpQaDTuOWGuo61GxcPBIfhwRxRTaTWGCTc= github.com/dgraph-io/ristretto v0.0.4-0.20200906165740-41ebdbffecfd/go.mod h1:YylP9MpCYGVZQrly/j/diqcdUetCRRePeBB0c2VGXsA= -github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y= @@ -178,13 +147,9 @@ github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUn github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/eapache/go-resiliency v1.1.0 h1:1NtRmCAqadE2FN4ZcN6g90TP3uk8cg9rn9eNK2197aU= github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= -github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21 h1:YEetp8/yCZMuEPMUDHG0CW/brkkEp8mzqk2+ODEitlw= github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= -github.com/eapache/queue v1.1.0 h1:YOEu7KNc61ntiQlcEeUIoDTJ2o8mQznoNvUhiigpIqc= github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= -github.com/edsrzf/mmap-go v1.0.0 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw= github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -192,32 +157,23 @@ github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.m github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d h1:QyzYnTnPE15SQyUeqU6qLbWxMkwyAyu+vGksa0b7j00= github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/protoc-gen-validate v0.1.0 h1:EQciDnbrYxy13PgWoY8AqoxGiPrpgBZ1R8UNe3ddc+A= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db h1:gb2Z18BhTPJPpLQWj4T+rfKHYCHxRHCtRxhKKjRidVw= github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= -github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8 h1:a9ENSRDFBUPkJ5lCgVZh26+ZbGyoVJG7yb5SSzF5H54= github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= -github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-chi/chi v4.0.2+incompatible h1:maB6vn6FqCxrpz4FqWdh4+lwpyZIQS7YEAUcHlgXVRs= github.com/go-chi/chi v4.0.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-kit/kit v0.4.0 h1:KeVK+Emj3c3S4eRztFuzbFYb2BAgf2jmwDwyXEri7Lo= github.com/go-kit/kit v0.4.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.10.0 h1:dXFJfIHVvUcpSgDOV+Ne6t7jXri8Tfv2uOLHUZ2XNuo= github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= -github.com/go-logfmt/logfmt v0.3.0 h1:8HUsc87TaSWLKwrnumgC8/YconD2fJQsRJAsWaPg2ic= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0 h1:TrB8swr/68K7m9CcGut2g3UOihhbcbiMAYiuTXdEih4= @@ -227,17 +183,13 @@ github.com/go-piv/piv-go v1.7.0/go.mod h1:ON2WvQncm7dIkCQ7kYJs+nc3V4jHGfrrJnSF8H github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= -github.com/go-stack/stack v1.6.0 h1:MmJCxYVKTJ0SplGKqFVX3SBnmaUhODHZrrFF6jMbpZk= github.com/go-stack/stack v1.6.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/gogo/googleapis v1.1.0 h1:kFkMAZBNAn4j7K0GiZr8cRYzejq68VbheufiV3YuyFI= github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -267,7 +219,6 @@ github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvq github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.5.0 h1:LUVKkCeviFUMKqHa4tXIIij/lbhnMbP7Fn5wKdKkRh4= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= @@ -289,13 +240,10 @@ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 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 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= 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/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= @@ -320,101 +268,66 @@ github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+ 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/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= 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 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/mux v1.4.0/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw= github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c h1:Lh2aW+HnU2Nbe1gqD9SOJLJxW1jBMmQOktN2acDyJk8= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= -github.com/groob/finalizer v0.0.0-20170707115354-4c2ed49aabda h1:5ikpG9mYCMFiZX0nkxoV6aU2IpCHPdws3gCNgdZeEV0= github.com/groob/finalizer v0.0.0-20170707115354-4c2ed49aabda/go.mod h1:MyndkAZd5rUMdNogn35MWXBX1UiBigrU8eTj8DoAC2c= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4 h1:z53tR0945TRRQO/fLEVPI6SMv7ZflF0TEaTAoU7tOzg= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway v1.9.5 h1:UImYN5qQ8tuGpGE16ZmjvcTtTw24zw1QAp/SlnNrZhI= github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/hashicorp/consul/api v1.3.0 h1:HXNYlRkkM/t+Y/Yhxtwcy02dlYwIaoxzvxPnS+cqy78= github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= -github.com/hashicorp/consul/sdk v0.3.0 h1:UOxjlb4xVNF93jak1mzzoBatyFju9nrkxpVwIp/QqxQ= github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= -github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-cleanhttp v0.5.1 h1:dH3aiDG9Jvb5r5+bYHsikaOUIpcM0xvgMXVoDkXMzJM= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-immutable-radix v1.0.0 h1:AKDB1HM5PWEA7i4nhcpwOrO2byshxBjXVn/J/3+z5/0= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-msgpack v0.5.3 h1:zKjpN5BK/P5lMYrLmBHdBULWbJ0XpYR+7NGzqkZzoD4= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= -github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= -github.com/hashicorp/go-rootcerts v1.0.0 h1:Rqb66Oo1X/eSV1x66xbDccZjhJigjg0+e82kpwzSwCI= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= -github.com/hashicorp/go-sockaddr v1.0.0 h1:GeH6tui99pF4NJgfnhp+L6+FfobzVW3Ah46sLo0ICXs= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= -github.com/hashicorp/go-syslog v1.0.0 h1:KaodqZuhUoZereWVIYmpUgZysurB1kBLX2j0MwMrUAE= github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-version v1.2.0 h1:3vNe/fWF5CBgRIguda1meWhsZHy3m8gCJ5wx+dIzX/E= github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/go.net v0.0.1 h1:sNCoNyDEvN1xa+X0baata4RdcpKwcMS6DH+xwfqPgjw= github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/hashicorp/logutils v1.0.0 h1:dLEQVugN8vlakKOUE3ihGLTZJRB4j+M2cdTm/ORI65Y= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= -github.com/hashicorp/mdns v1.0.0 h1:WhIgCr5a7AaVH6jPUwjtRuuE7/RDufnUvzIr48smyxs= github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= -github.com/hashicorp/memberlist v0.1.3 h1:EmmoJme1matNzb+hMpDuR/0sbJSUisxyqBGG676r31M= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= -github.com/hashicorp/serf v0.8.2 h1:YZ7UKsJv+hKjqGVUUbtE3HNj79Eln2oQ75tniF6iPt0= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= -github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huandu/xstrings v1.3.1 h1:4jgBlKK6tLKFvO8u5pmYjG91cqytmDCDvGh7ECVFfFs= github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= -github.com/hudl/fargo v1.3.0 h1:0U6+BtN6LhaYuTnIJq4Wyq5cpn6O2kWrxAtcqBmYY6w= github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.8 h1:CGgOkSJeqMRmt0D9XLWExdT4m4F1vd3FV3VPt+0VxkQ= github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d h1:/WZQPMZNsjZ7IlCpsLGdQBINg5bxKQ1K1sh6awxLtkA= github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.3.0 h1:OS12ieG61fsCg5+qLJ+SsW9NicxNkg3b25OyT2yCeUc= github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik= -github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.8 h1:QiWkFLKq0T7mpzwOTu6BzNDbfTE8OLrYhVKYMLF46Ok= github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a h1:FaWFmfWdAUKbSCtOU2QjDaorUexogfaMgbipgYATUMU= github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a/go.mod h1:UJSiEoRfvx3hP73CvoARgeLjaIOjybY9vj8PUPPFGeU= -github.com/julienschmidt/httprouter v1.2.0 h1:TDTW5Yz1mjftljbcKqRcrYhd4XeOoI98t+9HbQbYf7g= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/kisielk/errcheck v1.1.0 h1:ZqfnKyx9KGpRcW04j5nnPDgRgoXUeLh2YFBeFzphcA0= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= -github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515 h1:T+h1c/A9Gawja4Y9mFVWj2vyii2bbUNDw3kt9VxK2EY= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs= @@ -422,16 +335,12 @@ github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfn github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743 h1:143Bb8f8DuGWck/xpNUOckBVYfFbBTnLevfRZ1aVVqo= github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= -github.com/lightstep/lightstep-tracer-go v0.18.1 h1:vi1F1IQ8N7hNWytK9DpJsUfQhGuNSc19z330K6vl4zk= github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= github.com/lunixbochs/vtclean v0.0.0-20180621232353-2d01aacdc34a/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= github.com/lunixbochs/vtclean v1.0.0 h1:xu2sLAri4lGiovBDQKxl5mrXyESr3gUr5m5SM5+LVb8= github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= -github.com/lyft/protoc-gen-validate v0.0.13 h1:KNt/RhmQTOLr7Aj8PsJ7mTronaFyx80mRTT9qF261dA= github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= -github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/manifoldco/promptui v0.8.0 h1:R95mMF+McvXZQ7j1g8ucVZE1gLP3Sv6j9vlF9kyRqQo= github.com/manifoldco/promptui v0.8.0/go.mod h1:n4zTdgP0vr0S3w7/O/g98U+e0gwLScEXGwov2nIKuGQ= @@ -446,132 +355,89 @@ github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOA github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.13 h1:qdl+GuBjcsKKDco5BsxPJlId98mSWNKqYA+Co0SC1yA= github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-runewidth v0.0.2 h1:UnlwIPBGaTZfPQ6T1IGzPI0EkYAQmT9fAEJ/poFC63o= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/micromdm/scep/v2 v2.0.0 h1:cRzcY0S5QX+0+J+7YC4P2uZSnfMup8S8zJu/bLFgOkA= github.com/micromdm/scep/v2 v2.0.0/go.mod h1:ouaDs5tcjOjdHD/h8BGaQsWE87MUnQ/wMTMgfMMIpPc= -github.com/miekg/dns v1.0.14 h1:9jZdLNd/P4+SfEJ0TNyxYpsK8N4GtfylBLqtbYN1sbA= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/pkcs11 v1.0.3-0.20190429190417-a667d056470f h1:eVB9ELsoq5ouItQBr5Tj334bhPJG/MX+m7rTchmzVUQ= github.com/miekg/pkcs11 v1.0.3-0.20190429190417-a667d056470f/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= -github.com/mitchellh/cli v1.0.0 h1:iGBIsUe3+HZ/AD/Vd7DErOt5sU9fa8Uj7A2s1aggv1Y= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ= github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdIPrefOvVG1VZ96U0= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= -github.com/mitchellh/gox v0.4.0 h1:lfGJxY7ToLJQjHHwi0EX6uYBdK78egf954SQl13PQJc= github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= -github.com/mitchellh/iochan v1.0.0 h1:C+X3KsSTLFVBr/tK1eYN/vs4rJcvsiLU338UhYPJWeY= github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY= github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223 h1:F9x/1yl3T2AeKLr2AMdilSD8+f9bvMnNN8VS5iDtovc= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= -github.com/nats-io/jwt v0.3.2 h1:+RB5hMpXUUA2dfxuhBTEkMOrYmM+gKIZYS1KjSostMI= github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= -github.com/nats-io/nats-server/v2 v2.1.2 h1:i2Ly0B+1+rzNZHHWtD4ZwKi+OU5l+uQo1iDHZ2PmiIc= github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= -github.com/nats-io/nats.go v1.9.1 h1:ik3HbLhZ0YABLto7iX80pZLPw/6dx3T+++MZJwLnMrQ= github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= -github.com/nats-io/nkeys v0.1.3 h1:6JrEfig+HzTH85yxzhSVbjHRJv9cn0p6n3IngIcM5/k= github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= -github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/newrelic/go-agent v2.15.0+incompatible h1:IB0Fy+dClpBq9aEoIrLyQXzU34JyI1xVTanPLB/+jvU= github.com/newrelic/go-agent v2.15.0+incompatible/go.mod h1:a8Fv1b/fYhFSReoTU6HDkTYIMZeSVNffmoS726Y0LzQ= -github.com/oklog/oklog v0.3.2 h1:wVfs8F+in6nTBMkA7CbRw+zZMIB7nNM825cM1wuzoTk= github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= -github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= -github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5 h1:58+kh9C6jJVXYjt8IE48G2eWl6BjwU5Gj0gqY84fy78= github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/omorsi/pkcs7 v0.0.0-20210217142924-a7b80a2a8568 h1:+MPqEswjYiS0S1FCTg8MIhMBMzxiVQ94rooFwvPPiWk= github.com/omorsi/pkcs7 v0.0.0-20210217142924-a7b80a2a8568/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 h1:lDH9UUVJtmYCjyT0CI4q8xvlXPxeZ0gYCVvWbmPlp88= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= -github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492 h1:lM6RxxfUMrYL/f8bWEUqdXrANWtrL7Nndbm9iFN0DlU= github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= -github.com/opentracing/basictracer-go v1.0.0 h1:YyUAhaEfjoWXclZVJ9sGoNct7j4TVk7lZWlQw5UXuoo= github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5 h1:ZCnq+JUrvXcDVhX/xRolRBZifmabN1HcS1wrPSvxhrU= github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= -github.com/openzipkin/zipkin-go v0.2.2 h1:nY8Hti+WKaP0cRsSeQ026wU03QsM762XBeCXBb9NAWI= github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= -github.com/pact-foundation/pact-go v1.0.4 h1:OYkFijGHoZAYbOIb1LWXrwKQbMMRUv1oQ89blD2Mh2Q= github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= -github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c h1:Lgl0gzECD8GnQ5QCWA8o6BtfL6mDH5rQgM4/fX3avOs= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= -github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/performancecopilot/speed v3.0.0+incompatible h1:2WnRzIquHa5QxaJKShDkLM+sc0JPuwhXzK8OYOyt3Vg= github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= -github.com/pierrec/lz4 v2.0.5+incompatible h1:2xWsjqPFWcplujydGg4WmhC/6fZqK42wMM8aXeqhl0I= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/profile v1.2.1 h1:F++O52m40owAmADcojzM+9gyjmMOY/T4oYJkgFDH8RE= github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/posener/complete v1.1.1 h1:ccV59UEOTzVDnDUEFdT95ZzHVZ+5+158q8+SJb2QV5w= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.3.0 h1:miYCvYqFXtl/J9FIy8eNpBfYthAEFg+Ys0XyUVEcDsc= github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.1.0 h1:ElTg5tNp4DqfV7UQjDqv2+RJlNzsDtvNAWccbItceIE= github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.7.0 h1:L+1lyG48J1zAQXA3RBX/nG/B3gjlHq0zTt2tlbJLyCY= github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.8 h1:+fpWZdT24pJBiqJdAwYBjPSk+5YmQzYNPYzQsdzLkt8= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= -github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a h1:9ZKAASQSHhDYGoxY8uLVpewe1GDZ2vu2Tr/vTdVAkFQ= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af h1:gu+uRPtBe88sKxUCEXRoeCvVG90TJmwhiqRpvdhQFng= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= -github.com/rogpeppe/go-internal v1.3.0 h1:RR9dF3JtopPvtkroDZuVD7qquD0bnHlKSqaQhgwt8yk= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rs/xid v1.2.1 h1:mhH9Nq+C1fY2l1XIpgxIiUOfNpRBYH1kKcr+qfKgjRc= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= @@ -579,13 +445,10 @@ github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNue github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f h1:UFr9zpz4xgTnIE5yIMtWAMngCdZ9p/+q6lTbgelo80M= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/samfoo/ansi v0.0.0-20160124022901-b6bd2ded7189 h1:CmSpbxmewNQbzqztaY0bke1qzHhyNyC29wYgh17Gxfo= github.com/samfoo/ansi v0.0.0-20160124022901-b6bd2ded7189/go.mod h1:UUwuHEJ9zkkPDxspIHOa59PUeSkGFljESGzbxntLmIg= -github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da h1:p3Vo3i64TCLY7gIfzeQaUJ+kppEO5WQG3cL8iE8tGHU= github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= -github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= @@ -595,15 +458,11 @@ github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6Mwd github.com/smallstep/assert v0.0.0-20180720014142-de77670473b5/go.mod h1:TC9A4+RjIOS+HyTH7wG17/gSqVv95uDw2J64dQZx7RE= github.com/smallstep/assert v0.0.0-20200723003110-82e2b9b3b262 h1:unQFBIznI+VYD1/1fApl1A+9VcBk+9dcqGfnePY87LY= github.com/smallstep/assert v0.0.0-20200723003110-82e2b9b3b262/go.mod h1:MyOHs9Po2fbM1LHej6sBUT8ozbxmMOFG+E+rx/GSGuc= -github.com/smallstep/nosql v0.3.6 h1:cq6a3NwjFJxkVlWU1T4qGskcfEXr0fO1WqQrraDO1Po= -github.com/smallstep/nosql v0.3.6/go.mod h1:h1zC/Z54uNHc8euquLED4qJNCrMHd3nytA141ZZh4qQ= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= +github.com/smallstep/nosql v0.3.7 h1:P5C1cCj89a/MbD+4k8k585fzoaZNISmRA06v3q6u5lU= +github.com/smallstep/nosql v0.3.7/go.mod h1:mC+MOhUY1uV5S5vGmAwp1FSPfDB7iImiYn5nJCjzAdA= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= -github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/soheilhy/cmux v0.1.4 h1:0HKaf1o97UwFjHH9o5XsHUOF+tqmdA7KEzXLpiyaw0E= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= -github.com/sony/gobreaker v0.4.1 h1:oMnRNZXX5j85zso6xCPRNPtmAycat+WcoKbklScLDgQ= github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= @@ -613,17 +472,13 @@ github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkU github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng= github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= -github.com/spf13/cobra v0.0.5 h1:f0B+LkLX6DtmRH1isoNA9VTtNUK9K8xYd28JNNfOv/s= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= -github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271 h1:WhxRHzgeVGETMlmVfqhRn8RIeeNoPr2Czh33I4Zdccw= github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= -github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a h1:AhmOdSHeswKHBjhsLs/7+1voOxT+LLrSk/Nxvk35fug= github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -636,18 +491,14 @@ github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5Cc github.com/stretchr/testify v1.7.0/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 h1:ndzgwNDnKIqyCvHTXaCqh9KlOWKvBry6nuXMJmonVsE= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8 h1:3SVOIvH7Ae1KRYyQWRjXWJEA9sS/c/pjvH++55Gr648= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli v1.22.4 h1:u7tSpNPPswAFymm8IehJhy4uJMlUuU/GmqSkvJ1InXA= github.com/urfave/cli v1.22.4/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= -github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77 h1:ESFSdwYZvkeru3RtdrYueztKhOBCSAAzS4Gf+k0tEow= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -657,7 +508,6 @@ github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1 go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.5 h1:XAzx9gjCb0Rxj7EoqcClPD1d5ZBxZJk0jbuoPHenBt0= go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= -go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738 h1:VcrIfasaLFkyjk6KNlXQSzO+B0fZcnECiDrKJsfxka0= go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= @@ -669,31 +519,18 @@ go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= -go.step.sm/cli-utils v0.2.0 h1:hpVu9+6dpv/7/Bd8nGJFc3V+gQ+TciSJRTu9TavDUQ4= -go.step.sm/cli-utils v0.2.0/go.mod h1:+t4qCp5NO+080DdGkJxEh3xL5S4TcYC2JTPLMM72b6Y= -go.step.sm/cli-utils v0.4.0 h1:dni6gR/6/LOqfbzm/yUdgz5O12tkxX17SxA9+pRMidI= -go.step.sm/cli-utils v0.4.0/go.mod h1:1zFgatDqEJ1Y4MNStdWa0b1NPc1fvSHbDJC+wZ6iQlE= go.step.sm/cli-utils v0.4.1 h1:QztRUhGYjOPM1I2Nmi7V6XejQyVtcESmo+sbegxvX7Q= go.step.sm/cli-utils v0.4.1/go.mod h1:hWYVOSlw8W9Pd+BwIbs/aftVVMRms3EG7Q2qLRwc0WA= -go.step.sm/crypto v0.6.1/go.mod h1:AKS4yMZVZD4EGjpSkY4eibuMenrvKCscb+BpWMet8c0= -go.step.sm/crypto v0.8.3 h1:TO/OPlaUrYXhs8srGEFNyL6OWVQvRmEPCUONNnQUuEM= -go.step.sm/crypto v0.8.3/go.mod h1:+CYG05Mek1YDqi5WK0ERc6cOpKly2i/a5aZmU1sfGj0= go.step.sm/crypto v0.9.0 h1:q2AllTSnVj4NRtyEPkGW2ohArLmbGbe6ZAL/VIOKDzA= go.step.sm/crypto v0.9.0/go.mod h1:+CYG05Mek1YDqi5WK0ERc6cOpKly2i/a5aZmU1sfGj0= -go.step.sm/linkedca v0.0.0-20210610014030-59b16916c7e7 h1:hAfzUm80XWGtFnxyVgeT/gc/3XnlVNnHD5HrLbk4Fc0= -go.step.sm/linkedca v0.0.0-20210610014030-59b16916c7e7/go.mod h1:5uTRjozEGSPAZal9xJqlaD38cvJcLe3o1VAFVjqcORo= go.step.sm/linkedca v0.0.0-20210611183751-27424aae8d25 h1:ncJqviWswJT19IdnfOYQGKG1zL7IDy4lAJz1PuM3fgw= go.step.sm/linkedca v0.0.0-20210611183751-27424aae8d25/go.mod h1:5uTRjozEGSPAZal9xJqlaD38cvJcLe3o1VAFVjqcORo= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.5.0 h1:OI5t8sDa1Or+q8AeE+yKeB/SDYioSHAgcVljj9JIETY= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/multierr v1.3.0 h1:sFPn2GLc3poCkfrpIXGhBD2X0CMIo4Q/zSULXrj/+uc= go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= -go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.13.0 h1:nR6NoDBgAf67s68NhaXbsojM+2gxp3S1hWkHDl27pVU= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -788,8 +625,6 @@ golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLd golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420 h1:a8jGStKg0XqKDlKqjLrXn0ioF5MH36pT7Z0BRTqLhbk= golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210525063256-abc453219eb5 h1:wjuX4b5yYQnEQHzd+CBcrcC6OVR2J1CN6mUy0oSxIPo= -golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 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= @@ -872,9 +707,6 @@ 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 h1:hZR0X1kPW+nwyJ9xRxqZk1vx5RUObAPBdKVvXPDUH/E= golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210616094352-59db8d763f22 h1:RqytpXGR1iVNX7psjB3ff8y7sNFinVFvkx1c8SjBkio= -golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1024,8 +856,6 @@ google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaE google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c h1:wtujag7C+4D6KMoulW9YauvK2lgdvCMS260jsqqBXr0= google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d h1:KzwjikDymrEmYYbdyfievTwjEeGlu+OM6oiKBkF3Jfg= -google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= 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= @@ -1067,27 +897,19 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/cheggaaa/pb.v1 v1.0.25 h1:Ev7yu1/f6+d+b3pi5vPdRPc6nNtP1umSfcWiEfRqv6I= gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= -gopkg.in/errgo.v2 v2.1.0 h1:0vLT13EuvQ0hNvakwLuFZ/jYrLp5F3kcWHXdRggjCE8= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/gcfg.v1 v1.2.3 h1:m8OOJ4ccYHnx2f4gQwpno8nAX5OGOh7RLaaz0pj3Ogs= gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= -gopkg.in/resty.v1 v1.12.0 h1:CuXP0Pjfw9rOuY6EP+UvtNvt5DSqHpIxILZKT/quCZI= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/square/go-jose.v2 v2.5.1 h1:7odma5RETjNHWJnR32wx8t+Io4djHE1PqxCFx3iiZ2w= gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -1107,7 +929,5 @@ honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9 rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= -sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= -sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0 h1:ucqkfpjg9WzSUubAO62csmucvxl4/JeW3F4I4909XkM= sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= From 4e8e4c638ecc6ee2437a43a5fc7e3b5b3821deb4 Mon Sep 17 00:00:00 2001 From: Carl Tashian Date: Wed, 18 Aug 2021 12:50:14 -0700 Subject: [PATCH 075/195] Add newline to password file for readabiliy --- docker/entrypoint.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh index a6d29768..eb764bd4 100644 --- a/docker/entrypoint.sh +++ b/docker/entrypoint.sh @@ -32,6 +32,7 @@ function init_if_possible () { function generate_password () { set +o pipefail < /dev/urandom tr -dc A-Za-z0-9 | head -c40 + echo set -o pipefail } @@ -45,7 +46,7 @@ function step_ca_init () { --address ":9000" ) if [ -n "${DOCKER_STEPCA_INIT_PASSWORD}" ]; then - echo -n "${DOCKER_STEPCA_INIT_PASSWORD}" > "${STEPPATH}/password" + echo "${DOCKER_STEPCA_INIT_PASSWORD}" > "${STEPPATH}/password" else generate_password > "${STEPPATH}/password" fi From f738cb43c34e79c6254738aeb18a3579fb35c000 Mon Sep 17 00:00:00 2001 From: Carl Tashian Date: Wed, 18 Aug 2021 13:37:58 -0700 Subject: [PATCH 076/195] Make the default provisioner name optional; change DNS names variable name --- docker/entrypoint.sh | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh index eb764bd4..1f48c028 100644 --- a/docker/entrypoint.sh +++ b/docker/entrypoint.sh @@ -8,11 +8,7 @@ set -eo pipefail export STEPPATH=$(step path) # List of env vars required for step ca init -declare -ra REQUIRED_INIT_VARS=(DOCKER_STEPCA_INIT_NAME DOCKER_STEPCA_INIT_DNS DOCKER_STEPCA_INIT_EMAIL) - -# optional: -# DOCKER_STEPCA_INIT_PASSWORD (initial CA password) -# DOCKER_STEPCA_INIT_SSH (boolean: given a non-empty value, create an SSH CA) +declare -ra REQUIRED_INIT_VARS=(DOCKER_STEPCA_INIT_NAME DOCKER_STEPCA_INIT_DNS_NAMES) # Ensure all env vars required to run step ca init are set. function init_if_possible () { @@ -40,8 +36,8 @@ function generate_password () { function step_ca_init () { local -a setup_args=( --name "${DOCKER_STEPCA_INIT_NAME}" - --dns "${DOCKER_STEPCA_INIT_DNS}" - --provisioner "${DOCKER_STEPCA_INIT_EMAIL}" + --dns "${DOCKER_STEPCA_INIT_DNS_NAMES}" + --provisioner "${DOCKER_STEPCA_INIT_PROVISIONER_NAME:-admin}" --password-file "${STEPPATH}/password" --address ":9000" ) @@ -61,4 +57,4 @@ if [ ! -f "${STEPPATH}/config/ca.json" ]; then init_if_possible fi -exec "${@}" \ No newline at end of file +exec "${@}" From 31d3bf1cfc6785d0504682a2195e9e2ccc1bc70a Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Wed, 18 Aug 2021 18:50:31 -0700 Subject: [PATCH 077/195] Update discord link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 79e567ab..eb441c7b 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ You can use it to: Whatever your use case, `step-ca` is easy to use and hard to misuse, thanks to [safe, sane defaults](https://smallstep.com/docs/step-ca/certificate-authority-server-production#sane-cryptographic-defaults). -**Questions? Find us in [Discussions](https://github.com/smallstep/certificates/discussions) or [Join our Discord](https://bit.ly/stepdiscord).** +**Questions? Find us in [Discussions](https://github.com/smallstep/certificates/discussions) or [Join our Discord](https://bit.ly/step-discord).** [Website](https://smallstep.com/certificates) | [Documentation](https://smallstep.com/docs) | From a3028bbc0e60967c994e6b5000c96c778b60cc24 Mon Sep 17 00:00:00 2001 From: max furman Date: Wed, 18 Aug 2021 23:44:24 -0700 Subject: [PATCH 078/195] Add test for updateAddOrderIDs --- acme/db/nosql/order.go | 4 +--- acme/db/nosql/order_test.go | 29 +++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/acme/db/nosql/order.go b/acme/db/nosql/order.go index ba3934af..0c6bf795 100644 --- a/acme/db/nosql/order.go +++ b/acme/db/nosql/order.go @@ -124,10 +124,8 @@ func (db *DB) updateAddOrderIDs(ctx context.Context, accID string, addOids ...st ordersByAccountMux.Lock() defer ordersByAccountMux.Unlock() + var oldOids []string b, err := db.db.Get(ordersByAccountIDTable, []byte(accID)) - var ( - oldOids []string - ) if err != nil { if !nosql.IsErrNotFound(err) { return nil, errors.Wrapf(err, "error loading orderIDs for account %s", accID) diff --git a/acme/db/nosql/order_test.go b/acme/db/nosql/order_test.go index 7248700f..8882fd82 100644 --- a/acme/db/nosql/order_test.go +++ b/acme/db/nosql/order_test.go @@ -12,6 +12,7 @@ import ( "github.com/smallstep/certificates/acme" "github.com/smallstep/certificates/db" "github.com/smallstep/nosql" + "github.com/smallstep/nosql/database" nosqldb "github.com/smallstep/nosql/database" ) @@ -710,6 +711,34 @@ func TestDB_updateAddOrderIDs(t *testing.T) { err: errors.Errorf("error saving orderIDs index for account %s", accID), } }, + "ok/no-old": func(t *testing.T) test { + return test{ + db: &db.MockNoSQLDB{ + MGet: func(bucket, key []byte) ([]byte, error) { + switch string(bucket) { + case string(ordersByAccountIDTable): + return nil, database.ErrNotFound + default: + assert.FatalError(t, errors.Errorf("unexpected bucket %s", string(bucket))) + return nil, errors.New("force") + } + }, + MCmpAndSwap: func(bucket, key, old, nu []byte) ([]byte, bool, error) { + switch string(bucket) { + case string(ordersByAccountIDTable): + assert.Equals(t, key, []byte(accID)) + assert.Equals(t, old, nil) + assert.Equals(t, nu, nil) + return nil, true, nil + default: + assert.FatalError(t, errors.Errorf("unexpected bucket %s", string(bucket))) + return nil, false, errors.New("force") + } + }, + }, + res: []string{}, + } + }, "ok/all-old-not-pending": func(t *testing.T) test { oldOids := []string{"foo", "bar"} bOldOids, err := json.Marshal(oldOids) From 568fce201a964f338add0af86e74da472605d2eb Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Mon, 23 Aug 2021 15:15:36 -0700 Subject: [PATCH 079/195] Enforce identity cert to match ssh cert on renewals. --- api/sshRekey.go | 7 ++++++- api/sshRenew.go | 24 ++++++++++++++++++++---- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/api/sshRekey.go b/api/sshRekey.go index 285422f9..3d8e7c47 100644 --- a/api/sshRekey.go +++ b/api/sshRekey.go @@ -2,6 +2,7 @@ package api import ( "net/http" + "time" "github.com/pkg/errors" "github.com/smallstep/certificates/authority/provisioner" @@ -72,7 +73,11 @@ func (h *caHandler) SSHRekey(w http.ResponseWriter, r *http.Request) { return } - identity, err := h.renewIdentityCertificate(r) + // Match identity cert with the SSH cert + notBefore := time.Unix(int64(oldCert.ValidAfter), 0) + notAfter := time.Unix(int64(oldCert.ValidBefore), 0) + + identity, err := h.renewIdentityCertificate(r, notBefore, notAfter) if err != nil { WriteError(w, errs.ForbiddenErr(err)) return diff --git a/api/sshRenew.go b/api/sshRenew.go index 048c83a3..4a36673a 100644 --- a/api/sshRenew.go +++ b/api/sshRenew.go @@ -2,6 +2,7 @@ package api import ( "net/http" + "time" "github.com/pkg/errors" "github.com/smallstep/certificates/authority/provisioner" @@ -62,7 +63,11 @@ func (h *caHandler) SSHRenew(w http.ResponseWriter, r *http.Request) { return } - identity, err := h.renewIdentityCertificate(r) + // Match identity cert with the SSH cert + notBefore := time.Unix(int64(oldCert.ValidAfter), 0) + notAfter := time.Unix(int64(oldCert.ValidBefore), 0) + + identity, err := h.renewIdentityCertificate(r, notBefore, notAfter) if err != nil { WriteError(w, errs.ForbiddenErr(err)) return @@ -74,13 +79,24 @@ func (h *caHandler) SSHRenew(w http.ResponseWriter, r *http.Request) { }, http.StatusCreated) } -// renewIdentityCertificate request the client TLS certificate if present. -func (h *caHandler) renewIdentityCertificate(r *http.Request) ([]Certificate, error) { +// renewIdentityCertificate request the client TLS certificate if present. If notBefore and notAfter are passed the +func (h *caHandler) renewIdentityCertificate(r *http.Request, notBefore, notAfter time.Time) ([]Certificate, error) { if r.TLS == nil || len(r.TLS.PeerCertificates) == 0 { return nil, nil } - certChain, err := h.Authority.Renew(r.TLS.PeerCertificates[0]) + cert := r.TLS.PeerCertificates[0] + + // Enforce the cert to match another certificate, for example an ssh + // certificate. + if !notBefore.IsZero() { + cert.NotBefore = notBefore + } + if !notAfter.IsZero() { + cert.NotAfter = notAfter + } + + certChain, err := h.Authority.Renew(cert) if err != nil { return nil, err } From 61b8bfda1a32999a7d081f3fca2808e05471eddc Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Mon, 23 Aug 2021 15:18:54 -0700 Subject: [PATCH 080/195] Fix comment typos. --- authority/export.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/authority/export.go b/authority/export.go index 4eeb2813..8a5a257f 100644 --- a/authority/export.go +++ b/authority/export.go @@ -117,7 +117,7 @@ func (a *Authority) Export() (c *linkedca.Configuration, err error) { if !ok { return nil, errors.Errorf("unknown certificate issuer type %s", iss.Type) } - // The exporte certificate issuer should not include the password. + // The exported certificate issuer should not include the password. c.Authority.CertificateIssuer = &linkedca.CertificateIssuer{ Type: linkedca.CertificateIssuer_Type(typ), Provisioner: iss.Provisioner, @@ -150,7 +150,7 @@ func (a *Authority) Export() (c *linkedca.Configuration, err error) { } // global claims c.Authority.Claims = claimsToLinkedca(a.config.AuthorityConfig.Claims) - // Distiguised names template + // Distinguished names template if v := a.config.AuthorityConfig.Template; v != nil { c.Authority.Template = &linkedca.DistinguishedName{ Country: v.Country, From e12f6fcc84cbb90df8858e89e45421f43201f3ae Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Mon, 23 Aug 2021 15:24:13 -0700 Subject: [PATCH 081/195] Complete phrase in step-ca export help. --- commands/export.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/commands/export.go b/commands/export.go index 0080df7d..4a18a0dd 100644 --- a/commands/export.go +++ b/commands/export.go @@ -25,7 +25,9 @@ func init() { Action: exportAction, Description: `**step-ca export** exports the current configuration of step-ca. -Note that neither the PKI password nor +Note that neither the PKI password nor the certificate issuer password will be +included in the export file. + ## POSITIONAL ARGUMENTS From 3d141896e2b1ebce4ea6867e0985edb9f758593a Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Mon, 23 Aug 2021 15:26:32 -0700 Subject: [PATCH 082/195] Remove extra space. --- commands/export.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/commands/export.go b/commands/export.go index 4a18a0dd..be6d88e5 100644 --- a/commands/export.go +++ b/commands/export.go @@ -48,7 +48,7 @@ intermediate private key.`, cli.StringFlag{ Name: "issuer-password-file", Usage: `path to the containing the password to decrypt the - certificate issuer private key used in the RA mode.`, +certificate issuer private key used in the RA mode.`, }, }, }) From ff25f4974f7a9d0df3859ce11205e4f3972c3a80 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Mon, 23 Aug 2021 15:29:18 -0700 Subject: [PATCH 083/195] Fix comment. --- pki/pki.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pki/pki.go b/pki/pki.go index 1d81d82a..7ba56ad3 100644 --- a/pki/pki.go +++ b/pki/pki.go @@ -780,7 +780,7 @@ func (p *PKI) Save(opt ...ConfigOption) error { return err } - // Display only the + // Display the files written p.tellPKI() // Generate and write ca.json From 516b74f43a3e4bb670825adff9d53053465f1759 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Mon, 23 Aug 2021 15:33:16 -0700 Subject: [PATCH 084/195] Add comment about unused code. --- pki/pki.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pki/pki.go b/pki/pki.go index 7ba56ad3..1b6c83e7 100644 --- a/pki/pki.go +++ b/pki/pki.go @@ -735,6 +735,13 @@ func (p *PKI) GenerateConfig(opt ...ConfigOption) (*authconfig.Config, error) { if !config.AuthorityConfig.EnableAdmin { config.AuthorityConfig.Provisioners = provisioners } else { + // At this moment this code path is never used because `step ca + // init` will always set enableAdmin to false for a standalone + // deployment. Once we move `step beta` commands out of the beta we + // should probably default to this route. + // + // Note that we might want to be able to define the database as a + // flag in `step ca init` so we can write to the proper place. db, err := db.New(config.DB) if err != nil { return nil, err From 21b2057ecdb28050403c921e629013fb5f9b75b5 Mon Sep 17 00:00:00 2001 From: Alan Christopher Thomas Date: Wed, 25 Aug 2021 09:54:22 -0700 Subject: [PATCH 085/195] Add Certificate Manager notice for the pragmatic folks --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index eb441c7b..64458929 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,13 @@ You can use it to: Whatever your use case, `step-ca` is easy to use and hard to misuse, thanks to [safe, sane defaults](https://smallstep.com/docs/step-ca/certificate-authority-server-production#sane-cryptographic-defaults). +--- + +**Don't want to run your own CA?** +To get up and running quickly, or as an alternative to running your own `step-ca` server, consider creating a [free hosted smallstep Certificate Manager authority](https://info.smallstep.com/certificate-manager-early-access-mvp/). + +--- + **Questions? Find us in [Discussions](https://github.com/smallstep/certificates/discussions) or [Join our Discord](https://bit.ly/step-discord).** [Website](https://smallstep.com/certificates) | From cc9bc9c84bc32f7c08c8b1e2b23fe5cdfc526b50 Mon Sep 17 00:00:00 2001 From: max furman Date: Wed, 25 Aug 2021 10:24:18 -0700 Subject: [PATCH 086/195] Bump Badger --- go.mod | 1 + go.sum | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index f17b29bc..2067bb20 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,7 @@ require ( github.com/Masterminds/sprig/v3 v3.1.0 github.com/ThalesIgnite/crypto11 v1.2.4 github.com/aws/aws-sdk-go v1.30.29 + github.com/dgraph-io/badger/v2 v2.2007.4 // indirect github.com/dgraph-io/ristretto v0.0.4-0.20200906165740-41ebdbffecfd // indirect github.com/go-chi/chi v4.0.2+incompatible github.com/go-kit/kit v0.10.0 // indirect diff --git a/go.sum b/go.sum index c0d45435..f73da328 100644 --- a/go.sum +++ b/go.sum @@ -43,7 +43,6 @@ github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96/go.mod h1:bOv github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/DataDog/zstd v1.4.1/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= -github.com/DataDog/zstd v1.4.5 h1:EndNeuB0l9syBZhut0wns3gV1hL8zX8LIu6ZiVHWLIQ= github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/Masterminds/goutils v1.1.0 h1:zukEsf/1JZwCMgHiK3GZftabmxiCw4apj3a28RPBiVg= @@ -134,8 +133,9 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgraph-io/badger v1.6.2 h1:mNw0qs90GVgGGWylh0umH5iag1j6n/PeJtNvL6KY/x8= github.com/dgraph-io/badger v1.6.2/go.mod h1:JW2yswe3V058sS0kZ2h/AXeDSqFjxnZcRrVH//y2UQE= -github.com/dgraph-io/badger/v2 v2.2007.3 h1:Sl9tQWz92WCbVSe8pj04Tkqlm2boW+KAxd+XSs58SQI= github.com/dgraph-io/badger/v2 v2.2007.3/go.mod h1:26P/7fbL4kUZVEVKLAKXkBXKOydDmM2p1e+NhhnBCAE= +github.com/dgraph-io/badger/v2 v2.2007.4 h1:TRWBQg8UrlUhaFdco01nO2uXwzKS7zd+HVdwV/GHc4o= +github.com/dgraph-io/badger/v2 v2.2007.4/go.mod h1:vSw/ax2qojzbN6eXHIx6KPKtCSHJN/Uz0X0VPruTIhk= github.com/dgraph-io/ristretto v0.0.2/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E= github.com/dgraph-io/ristretto v0.0.3-0.20200630154024-f66de99634de/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E= github.com/dgraph-io/ristretto v0.0.4-0.20200906165740-41ebdbffecfd h1:KoJOtZf+6wpQaDTuOWGuo61GxcPBIfhwRxRTaTWGCTc= @@ -325,6 +325,8 @@ github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a/go.mod h1:UJSiEoRfvx github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.12.3 h1:G5AfA94pHPysR56qqrkO2pxEexdDzrpFJ6yt/VqWxVU= +github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= From 2317bf183b9fdc78f7d61bd554224eec693a2eca Mon Sep 17 00:00:00 2001 From: max furman Date: Wed, 25 Aug 2021 10:32:12 -0700 Subject: [PATCH 087/195] Nosql and badger bump --- go.mod | 3 +-- go.sum | 9 ++------- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index 2067bb20..9340565c 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,6 @@ require ( github.com/Masterminds/sprig/v3 v3.1.0 github.com/ThalesIgnite/crypto11 v1.2.4 github.com/aws/aws-sdk-go v1.30.29 - github.com/dgraph-io/badger/v2 v2.2007.4 // indirect github.com/dgraph-io/ristretto v0.0.4-0.20200906165740-41ebdbffecfd // indirect github.com/go-chi/chi v4.0.2+incompatible github.com/go-kit/kit v0.10.0 // indirect @@ -24,7 +23,7 @@ require ( github.com/rs/xid v1.2.1 github.com/sirupsen/logrus v1.4.2 github.com/smallstep/assert v0.0.0-20200723003110-82e2b9b3b262 - github.com/smallstep/nosql v0.3.7 + github.com/smallstep/nosql v0.3.8 github.com/stretchr/testify v1.7.0 // indirect github.com/urfave/cli v1.22.4 go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1 diff --git a/go.sum b/go.sum index f73da328..c82c70c8 100644 --- a/go.sum +++ b/go.sum @@ -42,8 +42,6 @@ github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96 h1:cTp8I5+VIo github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/DataDog/zstd v1.4.1/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= -github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/Masterminds/goutils v1.1.0 h1:zukEsf/1JZwCMgHiK3GZftabmxiCw4apj3a28RPBiVg= github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= @@ -133,7 +131,6 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgraph-io/badger v1.6.2 h1:mNw0qs90GVgGGWylh0umH5iag1j6n/PeJtNvL6KY/x8= github.com/dgraph-io/badger v1.6.2/go.mod h1:JW2yswe3V058sS0kZ2h/AXeDSqFjxnZcRrVH//y2UQE= -github.com/dgraph-io/badger/v2 v2.2007.3/go.mod h1:26P/7fbL4kUZVEVKLAKXkBXKOydDmM2p1e+NhhnBCAE= github.com/dgraph-io/badger/v2 v2.2007.4 h1:TRWBQg8UrlUhaFdco01nO2uXwzKS7zd+HVdwV/GHc4o= github.com/dgraph-io/badger/v2 v2.2007.4/go.mod h1:vSw/ax2qojzbN6eXHIx6KPKtCSHJN/Uz0X0VPruTIhk= github.com/dgraph-io/ristretto v0.0.2/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E= @@ -224,8 +221,6 @@ github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.2/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.3 h1:fHPg5GQYlCeLIPB9BZqMVR5nR9A+IM5zcgeTdjMYmLA= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= @@ -460,8 +455,8 @@ github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6Mwd github.com/smallstep/assert v0.0.0-20180720014142-de77670473b5/go.mod h1:TC9A4+RjIOS+HyTH7wG17/gSqVv95uDw2J64dQZx7RE= github.com/smallstep/assert v0.0.0-20200723003110-82e2b9b3b262 h1:unQFBIznI+VYD1/1fApl1A+9VcBk+9dcqGfnePY87LY= github.com/smallstep/assert v0.0.0-20200723003110-82e2b9b3b262/go.mod h1:MyOHs9Po2fbM1LHej6sBUT8ozbxmMOFG+E+rx/GSGuc= -github.com/smallstep/nosql v0.3.7 h1:P5C1cCj89a/MbD+4k8k585fzoaZNISmRA06v3q6u5lU= -github.com/smallstep/nosql v0.3.7/go.mod h1:mC+MOhUY1uV5S5vGmAwp1FSPfDB7iImiYn5nJCjzAdA= +github.com/smallstep/nosql v0.3.8 h1:1/EWUbbEdz9ai0g9Fd09VekVjtxp+5+gIHpV2PdwW3o= +github.com/smallstep/nosql v0.3.8/go.mod h1:X2qkYpNcW3yjLUvhEHfgGfClpKbFPapewvx7zo4TOFs= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= From 2c5080aae0352984e7bf57112a5ed9f9cd3b2a3e Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Wed, 25 Aug 2021 15:57:47 -0700 Subject: [PATCH 088/195] go mod tidy --- go.sum | 3 --- 1 file changed, 3 deletions(-) diff --git a/go.sum b/go.sum index 60e9ab6b..cb6766a6 100644 --- a/go.sum +++ b/go.sum @@ -42,9 +42,6 @@ github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96 h1:cTp8I5+VIo github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/DataDog/zstd v1.4.1/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= -github.com/DataDog/zstd v1.4.5 h1:EndNeuB0l9syBZhut0wns3gV1hL8zX8LIu6ZiVHWLIQ= -github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/Masterminds/goutils v1.1.0 h1:zukEsf/1JZwCMgHiK3GZftabmxiCw4apj3a28RPBiVg= github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= From 833d28cb6a59bb935f781e2811c840b348eaf19b Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Wed, 25 Aug 2021 16:15:12 -0700 Subject: [PATCH 089/195] Clone the certificate in case we need to look at it later. --- api/sshRenew.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/api/sshRenew.go b/api/sshRenew.go index 4a36673a..cb6ec5fd 100644 --- a/api/sshRenew.go +++ b/api/sshRenew.go @@ -1,6 +1,7 @@ package api import ( + "crypto/x509" "net/http" "time" @@ -85,7 +86,11 @@ func (h *caHandler) renewIdentityCertificate(r *http.Request, notBefore, notAfte return nil, nil } - cert := r.TLS.PeerCertificates[0] + // Clone the certificate as we can modify it. + cert, err := x509.ParseCertificate(r.TLS.PeerCertificates[0].Raw) + if err != nil { + return nil, errors.Wrap(err, "error parsing client certificate") + } // Enforce the cert to match another certificate, for example an ssh // certificate. From 8cb62b6d67019af7981c5c840f68fa7b5711d1f6 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Thu, 26 Aug 2021 10:20:16 -0700 Subject: [PATCH 090/195] Fix ssh in helm chart values. --- pki/helm.go | 11 +++++------ pki/pki.go | 14 ++++++++++++-- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/pki/helm.go b/pki/helm.go index 2a8ac513..570fb04d 100644 --- a/pki/helm.go +++ b/pki/helm.go @@ -14,11 +14,9 @@ import ( type helmVariables struct { *linkedca.Configuration - Defaults *linkedca.Defaults - Password string - SSH struct { - Enabled bool - } + Defaults *linkedca.Defaults + Password string + EnableSSH bool TLS authconfig.TLSOptions Provisioners []provisioner.Interface } @@ -48,6 +46,7 @@ func (p *PKI) WriteHelmTemplate(w io.Writer) error { Configuration: &p.Configuration, Defaults: &p.Defaults, Password: "", + EnableSSH: p.options.enableSSH, TLS: authconfig.DefaultTLSOptions, Provisioners: provisioners, }); err != nil { @@ -67,7 +66,7 @@ inject: federateRoots: [] crt: {{ .Intermediate }} key: {{ .IntermediateKey }} - {{- if .SSH.Enabled }} + {{- if .EnableSSH }} ssh: hostKey: {{ .Ssh.HostKey }} userKey: {{ .Ssh.UserKey }} diff --git a/pki/pki.go b/pki/pki.go index 1b6c83e7..fd625199 100644 --- a/pki/pki.go +++ b/pki/pki.go @@ -408,6 +408,15 @@ func (p *PKI) GenerateKeyPairs(pass []byte) error { return err } + var claims *linkedca.Claims + if p.options.enableSSH { + claims = &linkedca.Claims{ + Ssh: &linkedca.SSHClaims{ + Enabled: true, + }, + } + } + // Add JWK provisioner to the configuration. publicKey, err := json.Marshal(p.ottPublicKey) if err != nil { @@ -418,8 +427,9 @@ func (p *PKI) GenerateKeyPairs(pass []byte) error { return errors.Wrap(err, "error serializing private key") } p.Authority.Provisioners = append(p.Authority.Provisioners, &linkedca.Provisioner{ - Type: linkedca.Provisioner_JWK, - Name: p.options.provisioner, + Type: linkedca.Provisioner_JWK, + Name: p.options.provisioner, + Claims: claims, Details: &linkedca.ProvisionerDetails{ Data: &linkedca.ProvisionerDetails_JWK{ JWK: &linkedca.JWKProvisioner{ From 352acf8faa718d52b6ba2e44a246ecea9e140ae8 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Thu, 26 Aug 2021 11:29:13 -0700 Subject: [PATCH 091/195] Upgrade golang.org/x/crypto --- go.mod | 6 ++---- go.sum | 16 ++++++++-------- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/go.mod b/go.mod index f6228a9b..89cae8e2 100644 --- a/go.mod +++ b/go.mod @@ -24,15 +24,13 @@ require ( github.com/sirupsen/logrus v1.4.2 github.com/smallstep/assert v0.0.0-20200723003110-82e2b9b3b262 github.com/smallstep/nosql v0.3.8 - github.com/stretchr/testify v1.7.0 // indirect github.com/urfave/cli v1.22.4 go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1 go.step.sm/cli-utils v0.4.1 go.step.sm/crypto v0.9.0 go.step.sm/linkedca v0.5.0 - golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 - golang.org/x/net v0.0.0-20210716203947-853a461950ff - golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c // indirect + golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 + golang.org/x/net v0.0.0-20210825183410-e898025ed96a google.golang.org/api v0.47.0 google.golang.org/genproto v0.0.0-20210719143636-1d5a45f8e492 google.golang.org/grpc v1.39.0 diff --git a/go.sum b/go.sum index cb6766a6..d06e3ad7 100644 --- a/go.sum +++ b/go.sum @@ -488,9 +488,8 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 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 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= 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/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= @@ -546,8 +545,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 h1:pLI5jrR7OSLijeIDcmRxNmw2api+jEfxLoykJVice/E= -golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ= +golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -627,8 +626,8 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210716203947-853a461950ff h1:j2EK/QoxYNBsXI4R7fQkkRUk8y6wnOBI+6hgPdP/6Ds= -golang.org/x/net v0.0.0-20210716203947-853a461950ff/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210825183410-e898025ed96a h1:bRuuGXV8wwSdGTB+CtJf+FjgO1APK1CoO39T4BN/XBw= +golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 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= @@ -710,8 +709,9 @@ golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 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-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= From 40e77f6e9a480299496c03abe8a5fe7429608239 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Thu, 26 Aug 2021 17:55:42 -0700 Subject: [PATCH 092/195] Initialize required variables on GetIdentityToken Fixes smallstep/cli#465 --- authority/provisioner/aws.go | 5 +++++ authority/provisioner/aws_test.go | 7 +++++++ 2 files changed, 12 insertions(+) diff --git a/authority/provisioner/aws.go b/authority/provisioner/aws.go index c1c77ce5..cdd06f00 100644 --- a/authority/provisioner/aws.go +++ b/authority/provisioner/aws.go @@ -515,6 +515,11 @@ func (p *AWS) readURL(url string) ([]byte, error) { var resp *http.Response var err error + // Initialize IMDS versions when this is called from the cli. + if len(p.IMDSVersions) == 0 { + p.IMDSVersions = []string{"v2", "v1"} + } + for _, v := range p.IMDSVersions { switch v { case "v1": diff --git a/authority/provisioner/aws_test.go b/authority/provisioner/aws_test.go index dadf1f17..aff0aecb 100644 --- a/authority/provisioner/aws_test.go +++ b/authority/provisioner/aws_test.go @@ -141,6 +141,12 @@ func TestAWS_GetIdentityToken(t *testing.T) { p7.config.signatureURL = p1.config.signatureURL p7.config.tokenURL = p1.config.tokenURL + p8, err := generateAWS() + assert.FatalError(t, err) + p8.IMDSVersions = nil + p8.Accounts = p1.Accounts + p8.config = p1.config + caURL := "https://ca.smallstep.com" u, err := url.Parse(caURL) assert.FatalError(t, err) @@ -156,6 +162,7 @@ func TestAWS_GetIdentityToken(t *testing.T) { wantErr bool }{ {"ok", p1, args{"foo.local", caURL}, false}, + {"ok no imds", p8, args{"foo.local", caURL}, false}, {"fail ca url", p1, args{"foo.local", "://ca.smallstep.com"}, true}, {"fail identityURL", p2, args{"foo.local", caURL}, true}, {"fail signatureURL", p3, args{"foo.local", caURL}, true}, From 9e7a3cd897dfe4518b4afd861cf4f3a42d11bf7d Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Thu, 26 Aug 2021 18:12:37 -0700 Subject: [PATCH 093/195] Update go.step.sm/crypto --- go.mod | 2 +- go.sum | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index 89cae8e2..d786a523 100644 --- a/go.mod +++ b/go.mod @@ -27,7 +27,7 @@ require ( github.com/urfave/cli v1.22.4 go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1 go.step.sm/cli-utils v0.4.1 - go.step.sm/crypto v0.9.0 + go.step.sm/crypto v0.9.2 go.step.sm/linkedca v0.5.0 golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 golang.org/x/net v0.0.0-20210825183410-e898025ed96a diff --git a/go.sum b/go.sum index d06e3ad7..cc687ddd 100644 --- a/go.sum +++ b/go.sum @@ -523,8 +523,9 @@ go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.step.sm/cli-utils v0.4.1 h1:QztRUhGYjOPM1I2Nmi7V6XejQyVtcESmo+sbegxvX7Q= go.step.sm/cli-utils v0.4.1/go.mod h1:hWYVOSlw8W9Pd+BwIbs/aftVVMRms3EG7Q2qLRwc0WA= -go.step.sm/crypto v0.9.0 h1:q2AllTSnVj4NRtyEPkGW2ohArLmbGbe6ZAL/VIOKDzA= go.step.sm/crypto v0.9.0/go.mod h1:+CYG05Mek1YDqi5WK0ERc6cOpKly2i/a5aZmU1sfGj0= +go.step.sm/crypto v0.9.2 h1:UvQHE4brjAOdgcK2ob6zupL1iRzDd8+QiEvPOeQrm4E= +go.step.sm/crypto v0.9.2/go.mod h1:F5OJyPDWntNa1SbuWPxuHJc9bLzu84NzYrrdzDuBugk= go.step.sm/linkedca v0.5.0 h1:oZVRSpElM7lAL1XN2YkjdHwI/oIZ+1ULOnuqYPM6xjY= go.step.sm/linkedca v0.5.0/go.mod h1:5uTRjozEGSPAZal9xJqlaD38cvJcLe3o1VAFVjqcORo= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= From 6ec8a1f114695cb045127fd0a9724a561debe833 Mon Sep 17 00:00:00 2001 From: max furman Date: Mon, 30 Aug 2021 12:57:39 -0700 Subject: [PATCH 094/195] Bump golangci-lint to latest --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 235517b2..3435f132 100644 --- a/Makefile +++ b/Makefile @@ -29,7 +29,7 @@ ci: testcgo build bootstra%: # Using a released version of golangci-lint to take into account custom replacements in their go.mod - $Q curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(shell go env GOPATH)/bin v1.39.0 + $Q curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(shell go env GOPATH)/bin v1.42.0 .PHONY: bootstra% From 097a918da7397665d7b64a50c9fe234313065659 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Mon, 30 Aug 2021 16:36:18 -0700 Subject: [PATCH 095/195] Fix tests when we create re-use a token with a new authority. --- authority/authority_test.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/authority/authority_test.go b/authority/authority_test.go index 7604ec6b..1e18a24f 100644 --- a/authority/authority_test.go +++ b/authority/authority_test.go @@ -11,6 +11,7 @@ import ( "net" "reflect" "testing" + "time" "github.com/pkg/errors" "github.com/smallstep/assert" @@ -82,6 +83,10 @@ func testAuthority(t *testing.T, opts ...Option) *Authority { } a, err := New(c, opts...) assert.FatalError(t, err) + // Avoid errors when test tokens are created before the test authority. This + // happens in some tests where we re-create the same authority to test + // special cases without re-creating the token. + a.startTime = a.startTime.Add(-1 * time.Minute) return a } From f919535475f7821249fad7ec61ca6fd8c0be6dae Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Mon, 30 Aug 2021 16:37:29 -0700 Subject: [PATCH 096/195] Add an extra way to distinguish Azure and Azure OIDC tokens. We used to distinguish these tokens using the azp claim, but this claim does not appear on new azure oidc tokens, at least on some configurations. This change will try to load by audience (client id) if the token contains an email, required for OIDC. --- authority/provisioner/collection.go | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/authority/provisioner/collection.go b/authority/provisioner/collection.go index 3ba98a23..caf46ca9 100644 --- a/authority/provisioner/collection.go +++ b/authority/provisioner/collection.go @@ -37,8 +37,9 @@ func (p provisionerSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] } // provisioner. type loadByTokenPayload struct { jose.Claims - AuthorizedParty string `json:"azp"` // OIDC client id - TenantID string `json:"tid"` // Microsoft Azure tenant id + Email string `json:"email"` // OIDC email + AuthorizedParty string `json:"azp"` // OIDC client id + TenantID string `json:"tid"` // Microsoft Azure tenant id } // Collection is a memory map of provisioners. @@ -129,12 +130,20 @@ func (c *Collection) LoadByToken(token *jose.JSONWebToken, claims *jose.Claims) return p, ok } } - // Try with tid (Azure) + // Try with tid (Azure, Azure OIDC) if payload.TenantID != "" { + // Try to load an OIDC provisioner first. + if payload.Email != "" { + if p, ok := c.LoadByTokenID(payload.Audience[0]); ok { + return p, ok + } + } + // Try to load an Azure provisioner. if p, ok := c.LoadByTokenID(payload.TenantID); ok { return p, ok } } + // Fallback to aud return c.LoadByTokenID(payload.Audience[0]) } From d6203eb2512de64f9394e08b9b65797c0249a069 Mon Sep 17 00:00:00 2001 From: max furman Date: Mon, 30 Aug 2021 16:52:40 -0700 Subject: [PATCH 097/195] [action] use cosign to sign over goreleaser artifacts --- .github/workflows/release.yml | 12 +++++++++++- .goreleaser.yml | 5 +++++ cosign.pub | 4 ++++ 3 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 cosign.pub diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 819a470e..a15f893d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -100,14 +100,24 @@ jobs: uses: actions/setup-go@v2 with: go-version: 1.16 + - + name: Install cosign + uses: sigstore/cosign-installer@main + with: + cosign-release: 'v1.1.0' + - + name: Write cosign key to disk + id: write_key + run: echo "${{ secrets.COSIGN_KEY }}" > "/tmp/cosign.key" - name: Run GoReleaser - uses: goreleaser/goreleaser-action@56f5b77f7fa4a8fe068bf22b732ec036cc9bc13f # v2.4.1 + uses: goreleaser/goreleaser-action@5a54d7e660bda43b405e8463261b3d25631ffe86 # v2.7.0 with: version: latest args: release --rm-dist env: GITHUB_TOKEN: ${{ secrets.PAT }} + COSIGN_PWD: ${{ secrets.COSIGN_PWD }} release_deb: name: Build & Upload Debian Package To Github diff --git a/.goreleaser.yml b/.goreleaser.yml index 7a7e20d3..1acf405a 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -111,6 +111,11 @@ source: name_template: '{{ .ProjectName }}_{{ .Version }}' checksum: name_template: 'checksums.txt' +signs: +- cmd: cosign + stdin: '{{ .Env.COSIGN_PWD }}' + args: ["sign-blob", "-key=/tmp/cosign.key", "-output=${signature}", "${artifact}"] + artifacts: all snapshot: name_template: "{{ .Tag }}-next" release: diff --git a/cosign.pub b/cosign.pub new file mode 100644 index 00000000..9a0b42be --- /dev/null +++ b/cosign.pub @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEs+6THbAiXx4bja5ARQFNZmPwZjlD +GRvt5H+9ZFDhrcFPR1E7eB2rt1B/DhobANdHGKjvEBZEf0v4X/7S+SHrIw== +-----END PUBLIC KEY----- From 96762226cd8e327ad35fa53adea6843ec2359adc Mon Sep 17 00:00:00 2001 From: max furman Date: Mon, 30 Aug 2021 20:54:46 -0700 Subject: [PATCH 098/195] changelog update for 0.17.2 --- CHANGELOG.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2a2b3e25..bd9ba01e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,10 +4,16 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). -## [Unreleased - 0.0.1] - DATE +## [Unreleased - 0.17.3] - DATE ### Added ### Changed ### Deprecated ### Removed ### Fixed ### Security + +## [0.17.2] - 08.30.2021 +### Added +- Additional way to distinguish Azure IID and Azure OIDC tokens. +### Security +- Sign over all goreleaser github artifacts using cosign From 12153c96aeae54928f4f340bd217f57d051c8468 Mon Sep 17 00:00:00 2001 From: Kevin Chen <49530888+devadvocado@users.noreply.github.com> Date: Tue, 31 Aug 2021 10:18:13 -0700 Subject: [PATCH 099/195] update changelog --- CHANGELOG.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index bd9ba01e..5909638f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,3 +17,19 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Additional way to distinguish Azure IID and Azure OIDC tokens. ### Security - Sign over all goreleaser github artifacts using cosign + +## [0.17.1] - 2021-08-26 + +## [0.17.0] - 2021-08-25 +### Added +- Add support for Linked CAs using protocol buffers and gRPC +- `step-ca init` adds support for + - configuring a StepCAS RA + - configuring a Linked CA + - congifuring a `step-ca` using Helm +### Changed +- Update badger driver to use v2 by default +- Update TLS cipher suites to include 1.3 +### Security +- Fix key version when SHA512WithRSA is used. There was a typo creating RSA keys with SHA256 digests instead of SHA512. + From e73612da079f11f85c4f3ba2d274e0aafef652fc Mon Sep 17 00:00:00 2001 From: max furman Date: Wed, 1 Sep 2021 12:43:59 -0700 Subject: [PATCH 100/195] [action] sign and push sigs for multi-arch docker containers w/ cosign --- .github/workflows/release.yml | 19 ++++++++++++++++--- make/docker.mk | 2 ++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a15f893d..87a3228b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -158,13 +158,25 @@ jobs: runs-on: ubuntu-20.04 needs: test steps: - - name: Checkout + - + name: Checkout uses: actions/checkout@v2 - - name: Setup Go + - + name: Setup Go uses: actions/setup-go@v2 with: go-version: '1.16' - - name: Build + - + name: Install cosign + uses: sigstore/cosign-installer@main + with: + cosign-release: 'v1.1.0' + - + name: Write cosign key to disk + id: write_key + run: echo "${{ secrets.COSIGN_KEY }}" > "/tmp/cosign.key" + - + name: Build id: build run: | PATH=$PATH:/usr/local/go/bin:/home/admin/go/bin @@ -172,3 +184,4 @@ jobs: env: DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }} DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }} + COSIGN_PWD: ${{ secrets.COSIGN_PWD }} diff --git a/make/docker.mk b/make/docker.mk index 8ed25219..edb82423 100644 --- a/make/docker.mk +++ b/make/docker.mk @@ -54,6 +54,8 @@ define DOCKER_BUILDX # $(1) -- Image Tag # $(2) -- Push (empty is no push | --push will push to dockerhub) docker buildx build . --progress plain -t $(DOCKER_IMAGE_NAME):$(1) -f docker/Dockerfile.step-ca --platform="$(DOCKER_PLATFORMS)" $(2) + echo -n "$(COSIGN_PWD)" | cosign sign -key /tmp/cosign.key -r $(DOCKER_IMAGE_NAME):$(1) + endef # For non-master builds don't build the docker containers. From 19726aa61f39ea7809dee6360fca98e6d45c08d0 Mon Sep 17 00:00:00 2001 From: max furman Date: Wed, 1 Sep 2021 13:21:59 -0700 Subject: [PATCH 101/195] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5909638f..272e2716 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Removed ### Fixed ### Security +- Use cosign to sign and upload signatures for multi-arch Docker container. ## [0.17.2] - 08.30.2021 ### Added From e4739171b4cf66dba0dc80bed67025758f9a6266 Mon Sep 17 00:00:00 2001 From: max furman Date: Tue, 7 Sep 2021 11:28:16 -0700 Subject: [PATCH 102/195] [action] Build deb during goreleaser action, add to checksum and ... - add go 1.17 to test matrix - build with go 1.17 --- .github/workflows/release.yml | 25 +++++++++++++++++++------ .github/workflows/test.yml | 2 +- .goreleaser.yml | 12 ++++++++++++ 3 files changed, 32 insertions(+), 7 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 87a3228b..08dd88ce 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' ] + go: [ '1.15', '1.16', '1.17' ] outputs: is_prerelease: ${{ steps.is_prerelease.outputs.IS_PRERELEASE }} steps: @@ -99,10 +99,23 @@ jobs: name: Set up Go uses: actions/setup-go@v2 with: - go-version: 1.16 + go-version: 1.17 + - + name: APT Install + id: aptInstall + run: sudo apt-get -y install build-essential debhelper fakeroot + - + name: Build Debian package + id: make_debian + run: | + PATH=$PATH:/usr/local/go/bin:/home/admin/go/bin + make debian + # need to restore the git state otherwise goreleaser fails due to dirty state + git restore debian/changelog + git clean -fd - name: Install cosign - uses: sigstore/cosign-installer@main + uses: sigstore/cosign-installer@v1.1.0 with: cosign-release: 'v1.1.0' - @@ -133,7 +146,7 @@ jobs: name: Set up Go uses: actions/setup-go@v2 with: - go-version: '1.16' + go-version: '1.17' - name: APT Install id: aptInstall @@ -165,10 +178,10 @@ jobs: name: Setup Go uses: actions/setup-go@v2 with: - go-version: '1.16' + go-version: '1.17' - name: Install cosign - uses: sigstore/cosign-installer@main + uses: sigstore/cosign-installer@v1.1.0 with: cosign-release: 'v1.1.0' - diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 9c73cfbd..96655664 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.15', '1.16' ] + go: [ '1.15', '1.16', '1.17' ] steps: - name: Checkout diff --git a/.goreleaser.yml b/.goreleaser.yml index 1acf405a..8dbbac29 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -1,10 +1,12 @@ # This is an example .goreleaser.yml file with some sane defaults. # Make sure to check the documentation at http://goreleaser.com project_name: step-ca + before: hooks: # You may remove this if you don't use go modules. - go mod download + builds: - id: step-ca @@ -93,6 +95,7 @@ builds: binary: bin/step-awskms-init ldflags: - -w -X main.Version={{.Version}} -X main.BuildTime={{.Date}} + archives: - # Can be used to change the archive formats for specific GOOSs. @@ -106,18 +109,25 @@ archives: files: - README.md - LICENSE + source: enabled: true name_template: '{{ .ProjectName }}_{{ .Version }}' + checksum: name_template: 'checksums.txt' + extra_files: + - glob: ./.releases/* + signs: - cmd: cosign stdin: '{{ .Env.COSIGN_PWD }}' args: ["sign-blob", "-key=/tmp/cosign.key", "-output=${signature}", "${artifact}"] artifacts: all + snapshot: name_template: "{{ .Tag }}-next" + release: # Repo in which the release will be created. # Default is extracted from the origin remote URL or empty if its private hosted. @@ -154,6 +164,8 @@ release: # The filename on the release will be the last part of the path (base). If # another file with the same name exists, the latest one found will be used. # Defaults to empty. + extra_files: + - glob: ./.releases/* #extra_files: # - glob: ./path/to/file.txt # - glob: ./glob/**/to/**/file/**/* From 8bec473f8ebfea7935db239d9ec18b3ed319f34b Mon Sep 17 00:00:00 2001 From: max furman Date: Tue, 7 Sep 2021 11:30:35 -0700 Subject: [PATCH 103/195] fix gofmt linting errors --- kms/pkcs11/pkcs11_no_cgo.go | 1 + kms/yubikey/yubikey_no_cgo.go | 1 + 2 files changed, 2 insertions(+) diff --git a/kms/pkcs11/pkcs11_no_cgo.go b/kms/pkcs11/pkcs11_no_cgo.go index 87c9a36b..6fa51dff 100644 --- a/kms/pkcs11/pkcs11_no_cgo.go +++ b/kms/pkcs11/pkcs11_no_cgo.go @@ -1,3 +1,4 @@ +//go:build !cgo // +build !cgo package pkcs11 diff --git a/kms/yubikey/yubikey_no_cgo.go b/kms/yubikey/yubikey_no_cgo.go index 6ed7c630..24a76174 100644 --- a/kms/yubikey/yubikey_no_cgo.go +++ b/kms/yubikey/yubikey_no_cgo.go @@ -1,3 +1,4 @@ +//go:build !cgo // +build !cgo package yubikey From 8ba9013f5d21c2a38a0011451fefc3bc5bc353aa Mon Sep 17 00:00:00 2001 From: max furman Date: Tue, 7 Sep 2021 11:35:51 -0700 Subject: [PATCH 104/195] gofmt linting errors --- kms/pkcs11/benchmark_test.go | 1 + kms/pkcs11/opensc_test.go | 1 + kms/pkcs11/other_test.go | 1 + kms/pkcs11/pkcs11.go | 1 + kms/pkcs11/pkcs11_test.go | 1 + kms/pkcs11/setup_test.go | 1 + kms/pkcs11/softhsm2_test.go | 1 + kms/pkcs11/yubihsm2_test.go | 1 + kms/yubikey/yubikey.go | 1 + 9 files changed, 9 insertions(+) diff --git a/kms/pkcs11/benchmark_test.go b/kms/pkcs11/benchmark_test.go index 30e21117..c567872f 100644 --- a/kms/pkcs11/benchmark_test.go +++ b/kms/pkcs11/benchmark_test.go @@ -1,3 +1,4 @@ +//go:build cgo // +build cgo package pkcs11 diff --git a/kms/pkcs11/opensc_test.go b/kms/pkcs11/opensc_test.go index f3b61932..b365e614 100644 --- a/kms/pkcs11/opensc_test.go +++ b/kms/pkcs11/opensc_test.go @@ -1,3 +1,4 @@ +//go:build opensc // +build opensc package pkcs11 diff --git a/kms/pkcs11/other_test.go b/kms/pkcs11/other_test.go index 835587f7..680d3860 100644 --- a/kms/pkcs11/other_test.go +++ b/kms/pkcs11/other_test.go @@ -1,3 +1,4 @@ +//go:build cgo && !softhsm2 && !yubihsm2 && !opensc // +build cgo,!softhsm2,!yubihsm2,!opensc package pkcs11 diff --git a/kms/pkcs11/pkcs11.go b/kms/pkcs11/pkcs11.go index 47c298a5..07d40c05 100644 --- a/kms/pkcs11/pkcs11.go +++ b/kms/pkcs11/pkcs11.go @@ -1,3 +1,4 @@ +//go:build cgo // +build cgo package pkcs11 diff --git a/kms/pkcs11/pkcs11_test.go b/kms/pkcs11/pkcs11_test.go index 77277366..6df9b92a 100644 --- a/kms/pkcs11/pkcs11_test.go +++ b/kms/pkcs11/pkcs11_test.go @@ -1,3 +1,4 @@ +//go:build cgo // +build cgo package pkcs11 diff --git a/kms/pkcs11/setup_test.go b/kms/pkcs11/setup_test.go index c9ff9311..52dc5207 100644 --- a/kms/pkcs11/setup_test.go +++ b/kms/pkcs11/setup_test.go @@ -1,3 +1,4 @@ +//go:build cgo // +build cgo package pkcs11 diff --git a/kms/pkcs11/softhsm2_test.go b/kms/pkcs11/softhsm2_test.go index 37aa667d..ed2ff208 100644 --- a/kms/pkcs11/softhsm2_test.go +++ b/kms/pkcs11/softhsm2_test.go @@ -1,3 +1,4 @@ +//go:build cgo && softhsm2 // +build cgo,softhsm2 package pkcs11 diff --git a/kms/pkcs11/yubihsm2_test.go b/kms/pkcs11/yubihsm2_test.go index 6d02a420..281aff54 100644 --- a/kms/pkcs11/yubihsm2_test.go +++ b/kms/pkcs11/yubihsm2_test.go @@ -1,3 +1,4 @@ +//go:build cgo && yubihsm2 // +build cgo,yubihsm2 package pkcs11 diff --git a/kms/yubikey/yubikey.go b/kms/yubikey/yubikey.go index 2dde244a..b1d5f7e3 100644 --- a/kms/yubikey/yubikey.go +++ b/kms/yubikey/yubikey.go @@ -1,3 +1,4 @@ +//go:build cgo // +build cgo package yubikey From 23d3232d7589f015f762bced6c10e70aca9cdbdc Mon Sep 17 00:00:00 2001 From: max furman Date: Tue, 7 Sep 2021 11:39:49 -0700 Subject: [PATCH 105/195] Changelog updates --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 272e2716..a99bbd1a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,12 +6,15 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased - 0.17.3] - DATE ### Added +- go 1.17 to github action test matrix ### Changed +- Using go 1.17 for binaries ### Deprecated ### Removed ### Fixed ### Security - Use cosign to sign and upload signatures for multi-arch Docker container. +- Add debian checksum ## [0.17.2] - 08.30.2021 ### Added From 9df5cc40b6b86e952c1e285767b495d22db8385c Mon Sep 17 00:00:00 2001 From: max furman Date: Tue, 7 Sep 2021 12:16:40 -0700 Subject: [PATCH 106/195] [action] remove duplicate debian step --- .github/workflows/release.yml | 34 ---------------------------------- 1 file changed, 34 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 08dd88ce..e2e0176c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -132,40 +132,6 @@ jobs: GITHUB_TOKEN: ${{ secrets.PAT }} COSIGN_PWD: ${{ secrets.COSIGN_PWD }} - release_deb: - name: Build & Upload Debian Package To Github - runs-on: ubuntu-20.04 - needs: create_release - steps: - - - name: Checkout - uses: actions/checkout@v2 - with: - fetch-depth: 0 - - - name: Set up Go - uses: actions/setup-go@v2 - with: - go-version: '1.17' - - - name: APT Install - id: aptInstall - run: sudo apt-get -y install build-essential debhelper fakeroot - - - name: Build Debian package - id: build - run: | - PATH=$PATH:/usr/local/go/bin:/home/admin/go/bin - make debian - - - name: Upload Debian Package - id: upload_deb - run: | - tag_name="${GITHUB_REF##*/}" - hub release edit $(find ./.releases -type f -printf "-a %p ") -m "" "$tag_name" - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - build_upload_docker: name: Build & Upload Docker Images runs-on: ubuntu-20.04 From 9641354675a2cc14ea00233d5d29d017c95ac768 Mon Sep 17 00:00:00 2001 From: max furman Date: Tue, 7 Sep 2021 12:37:45 -0700 Subject: [PATCH 107/195] [action] tmate debugger --- .github/workflows/release.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e2e0176c..449bb072 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -122,6 +122,9 @@ jobs: name: Write cosign key to disk id: write_key run: echo "${{ secrets.COSIGN_KEY }}" > "/tmp/cosign.key" + - + name: Setup tmate session + uses: mxschmitt/action-tmate@v3 - name: Run GoReleaser uses: goreleaser/goreleaser-action@5a54d7e660bda43b405e8463261b3d25631ffe86 # v2.7.0 From 9ed84d71f605c10d29bf1bc099155ebbbace097c Mon Sep 17 00:00:00 2001 From: max furman Date: Tue, 7 Sep 2021 13:07:25 -0700 Subject: [PATCH 108/195] [action] Add .releases to .gitignore --- .github/workflows/release.yml | 3 --- .gitignore | 4 ++-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 449bb072..e2e0176c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -122,9 +122,6 @@ jobs: name: Write cosign key to disk id: write_key run: echo "${{ secrets.COSIGN_KEY }}" > "/tmp/cosign.key" - - - name: Setup tmate session - uses: mxschmitt/action-tmate@v3 - name: Run GoReleaser uses: goreleaser/goreleaser-action@5a54d7e660bda43b405e8463261b3d25631ffe86 # v2.7.0 diff --git a/.gitignore b/.gitignore index 7cba0d08..d87786b0 100644 --- a/.gitignore +++ b/.gitignore @@ -14,8 +14,8 @@ # Others *.swp -.travis-releases +.releases coverage.txt -vendor output +vendor .idea From 913bd0f24ad984f9571b83fba0815b93707149ec Mon Sep 17 00:00:00 2001 From: Filippo Tessarotto Date: Wed, 8 Sep 2021 06:45:32 +0200 Subject: [PATCH 109/195] CHANGELOG: use ISO-8601 dates --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a99bbd1a..e15dca6e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,7 +16,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Use cosign to sign and upload signatures for multi-arch Docker container. - Add debian checksum -## [0.17.2] - 08.30.2021 +## [0.17.2] - 2021-08-30 ### Added - Additional way to distinguish Azure IID and Azure OIDC tokens. ### Security From 7a94b0c1570e9b0ad60bb8eadfb3d80e75b5b3e7 Mon Sep 17 00:00:00 2001 From: Fearghal O Floinn Date: Wed, 8 Sep 2021 12:24:49 +0100 Subject: [PATCH 110/195] Converts group and subgroup to lowercase for comparison. Fixes #679 --- authority/provisioner/sign_ssh_options.go | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/authority/provisioner/sign_ssh_options.go b/authority/provisioner/sign_ssh_options.go index a872513e..4a0cf526 100644 --- a/authority/provisioner/sign_ssh_options.go +++ b/authority/provisioner/sign_ssh_options.go @@ -5,6 +5,7 @@ import ( "encoding/binary" "encoding/json" "math/big" + "strings" "time" "github.com/pkg/errors" @@ -453,12 +454,20 @@ func containsAllMembers(group, subgroup []string) bool { if lsg > lg || (lg > 0 && lsg == 0) { return false } + groupLower := []string{} + subgroupLower := []string{} + for _, s := range group { + groupLower = append(groupLower, strings.ToLower(s)) + } + for _, s := range subgroup { + subgroupLower = append(subgroupLower, strings.ToLower(s)) + } visit := make(map[string]struct{}, lg) for i := 0; i < lg; i++ { - visit[group[i]] = struct{}{} + visit[groupLower[i]] = struct{}{} } for i := 0; i < lsg; i++ { - if _, ok := visit[subgroup[i]]; !ok { + if _, ok := visit[subgroupLower[i]]; !ok { return false } } From 141c51917156f648cfe79e937ca9a7eb0724cd65 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Wed, 8 Sep 2021 16:00:33 -0700 Subject: [PATCH 111/195] Simplify check of principals in a case insensitive way Fixes #679 --- authority/provisioner/sign_ssh_options.go | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/authority/provisioner/sign_ssh_options.go b/authority/provisioner/sign_ssh_options.go index 4a0cf526..158470d1 100644 --- a/authority/provisioner/sign_ssh_options.go +++ b/authority/provisioner/sign_ssh_options.go @@ -454,20 +454,12 @@ func containsAllMembers(group, subgroup []string) bool { if lsg > lg || (lg > 0 && lsg == 0) { return false } - groupLower := []string{} - subgroupLower := []string{} - for _, s := range group { - groupLower = append(groupLower, strings.ToLower(s)) - } - for _, s := range subgroup { - subgroupLower = append(subgroupLower, strings.ToLower(s)) - } visit := make(map[string]struct{}, lg) for i := 0; i < lg; i++ { - visit[groupLower[i]] = struct{}{} + visit[strings.ToLower(group[i])] = struct{}{} } for i := 0; i < lsg; i++ { - if _, ok := visit[subgroupLower[i]]; !ok { + if _, ok := visit[strings.ToLower(subgroup[i])]; !ok { return false } } From 6d644880bd2012744e517b9fb0f354f45ae58c5a Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Wed, 8 Sep 2021 15:33:34 -0700 Subject: [PATCH 112/195] Allow to kms signers to define the SignatureAlgorithm CloudKMS keys signs data using an specific signature algorithm, in RSA keys, this can be PKCS#1 RSA or RSA-PSS, if the later is used, x509.CreateCertificate will fail unless the template SignatureCertificate is properly set. On contrast, AWSKMS RSA keys, are just RSA keys, and can sign with PKCS#1 or RSA-PSS schemes, so right now the way to enforce one or the other is to used templates. --- cas/apiv1/services.go | 7 ++++ cas/softcas/softcas.go | 21 ++++++++-- cas/softcas/softcas_test.go | 49 +++++++++++++++++++++++ kms/cloudkms/cloudkms.go | 14 +++++++ kms/cloudkms/signer.go | 11 +++++- kms/cloudkms/signer_test.go | 77 +++++++++++++++++++++++++++++++++++++ 6 files changed, 174 insertions(+), 5 deletions(-) diff --git a/cas/apiv1/services.go b/cas/apiv1/services.go index d4dd3c8c..cf9a5470 100644 --- a/cas/apiv1/services.go +++ b/cas/apiv1/services.go @@ -1,6 +1,7 @@ package apiv1 import ( + "crypto/x509" "net/http" "strings" ) @@ -26,6 +27,12 @@ type CertificateAuthorityCreator interface { CreateCertificateAuthority(req *CreateCertificateAuthorityRequest) (*CreateCertificateAuthorityResponse, error) } +// SignatureAlgorithmGetter is an optional implementation in a crypto.Signer +// that returns the SignatureAlgorithm to use. +type SignatureAlgorithmGetter interface { + SignatureAlgorithm() x509.SignatureAlgorithm +} + // Type represents the CAS type used. type Type string diff --git a/cas/softcas/softcas.go b/cas/softcas/softcas.go index 21760490..f3b2d051 100644 --- a/cas/softcas/softcas.go +++ b/cas/softcas/softcas.go @@ -68,7 +68,7 @@ func (c *SoftCAS) CreateCertificate(req *apiv1.CreateCertificateRequest) (*apiv1 } req.Template.Issuer = c.CertificateChain[0].Subject - cert, err := x509util.CreateCertificate(req.Template, c.CertificateChain[0], req.Template.PublicKey, c.Signer) + cert, err := createCertificate(req.Template, c.CertificateChain[0], req.Template.PublicKey, c.Signer) if err != nil { return nil, err } @@ -93,7 +93,7 @@ func (c *SoftCAS) RenewCertificate(req *apiv1.RenewCertificateRequest) (*apiv1.R req.Template.NotAfter = t.Add(req.Lifetime) req.Template.Issuer = c.CertificateChain[0].Subject - cert, err := x509util.CreateCertificate(req.Template, c.CertificateChain[0], req.Template.PublicKey, c.Signer) + cert, err := createCertificate(req.Template, c.CertificateChain[0], req.Template.PublicKey, c.Signer) if err != nil { return nil, err } @@ -150,12 +150,12 @@ func (c *SoftCAS) CreateCertificateAuthority(req *apiv1.CreateCertificateAuthori var cert *x509.Certificate switch req.Type { case apiv1.RootCA: - cert, err = x509util.CreateCertificate(req.Template, req.Template, signer.Public(), signer) + cert, err = createCertificate(req.Template, req.Template, signer.Public(), signer) if err != nil { return nil, err } case apiv1.IntermediateCA: - cert, err = x509util.CreateCertificate(req.Template, req.Parent.Certificate, signer.Public(), req.Parent.Signer) + cert, err = createCertificate(req.Template, req.Parent.Certificate, signer.Public(), req.Parent.Signer) if err != nil { return nil, err } @@ -210,3 +210,16 @@ func (c *SoftCAS) createSigner(req *kmsapi.CreateSignerRequest) (crypto.Signer, } return c.KeyManager.CreateSigner(req) } + +// createCertificate sets the SignatureAlgorithm of the template if necessary +// and calls x509util.CreateCertificate. +func createCertificate(template, parent *x509.Certificate, pub crypto.PublicKey, signer crypto.Signer) (*x509.Certificate, error) { + // Signers can specify the signature algorithm. This is specially important + // when x509.CreateCertificates attempts to validate a RSAPSS signature. + if template.SignatureAlgorithm == 0 { + if sa, ok := signer.(apiv1.SignatureAlgorithmGetter); ok { + template.SignatureAlgorithm = sa.SignatureAlgorithm() + } + } + return x509util.CreateCertificate(template, parent, pub, signer) +} diff --git a/cas/softcas/softcas_test.go b/cas/softcas/softcas_test.go index 092a0337..c8e1a8e9 100644 --- a/cas/softcas/softcas_test.go +++ b/cas/softcas/softcas_test.go @@ -75,6 +75,15 @@ var ( testSignedIntermediateTemplate = mustSign(testIntermediateTemplate, testSignedRootTemplate, testNow, testNow.Add(24*time.Hour)) ) +type signatureAlgorithmSigner struct { + crypto.Signer + algorithm x509.SignatureAlgorithm +} + +func (s *signatureAlgorithmSigner) SignatureAlgorithm() x509.SignatureAlgorithm { + return s.algorithm +} + type mockKeyManager struct { signer crypto.Signer errGetPublicKey error @@ -247,6 +256,13 @@ func TestSoftCAS_CreateCertificate(t *testing.T) { tmplNoSerial := *testTemplate tmplNoSerial.SerialNumber = nil + saTemplate := *testSignedTemplate + saTemplate.SignatureAlgorithm = 0 + saSigner := &signatureAlgorithmSigner{ + Signer: testSigner, + algorithm: x509.PureEd25519, + } + type fields struct { Issuer *x509.Certificate Signer crypto.Signer @@ -267,6 +283,12 @@ func TestSoftCAS_CreateCertificate(t *testing.T) { Certificate: testSignedTemplate, CertificateChain: []*x509.Certificate{testIssuer}, }, false}, + {"ok signature algorithm", fields{testIssuer, saSigner}, args{&apiv1.CreateCertificateRequest{ + Template: &saTemplate, Lifetime: 24 * time.Hour, + }}, &apiv1.CreateCertificateResponse{ + Certificate: testSignedTemplate, + CertificateChain: []*x509.Certificate{testIssuer}, + }, false}, {"ok with notBefore", fields{testIssuer, testSigner}, args{&apiv1.CreateCertificateRequest{ Template: &tmplNotBefore, Lifetime: 24 * time.Hour, }}, &apiv1.CreateCertificateResponse{ @@ -316,6 +338,11 @@ func TestSoftCAS_RenewCertificate(t *testing.T) { tmplNoSerial := *testTemplate tmplNoSerial.SerialNumber = nil + saSigner := &signatureAlgorithmSigner{ + Signer: testSigner, + algorithm: x509.PureEd25519, + } + type fields struct { Issuer *x509.Certificate Signer crypto.Signer @@ -336,6 +363,12 @@ func TestSoftCAS_RenewCertificate(t *testing.T) { Certificate: testSignedTemplate, CertificateChain: []*x509.Certificate{testIssuer}, }, false}, + {"ok signature algorithm", fields{testIssuer, saSigner}, args{&apiv1.RenewCertificateRequest{ + Template: testTemplate, Lifetime: 24 * time.Hour, + }}, &apiv1.RenewCertificateResponse{ + Certificate: testSignedTemplate, + CertificateChain: []*x509.Certificate{testIssuer}, + }, false}, {"fail template", fields{testIssuer, testSigner}, args{&apiv1.RenewCertificateRequest{Lifetime: 24 * time.Hour}}, nil, true}, {"fail lifetime", fields{testIssuer, testSigner}, args{&apiv1.RenewCertificateRequest{Template: testTemplate}}, nil, true}, {"fail CreateCertificate", fields{testIssuer, testSigner}, args{&apiv1.RenewCertificateRequest{ @@ -425,6 +458,11 @@ func Test_now(t *testing.T) { func TestSoftCAS_CreateCertificateAuthority(t *testing.T) { mockNow(t) + saSigner := &signatureAlgorithmSigner{ + Signer: testSigner, + algorithm: x509.PureEd25519, + } + type fields struct { Issuer *x509.Certificate Signer crypto.Signer @@ -467,6 +505,17 @@ func TestSoftCAS_CreateCertificateAuthority(t *testing.T) { PrivateKey: testSigner, Signer: testSigner, }, false}, + {"ok signature algorithm", fields{nil, nil, &mockKeyManager{signer: saSigner}}, args{&apiv1.CreateCertificateAuthorityRequest{ + Type: apiv1.RootCA, + Template: testRootTemplate, + Lifetime: 24 * time.Hour, + }}, &apiv1.CreateCertificateAuthorityResponse{ + Name: "Test Root CA", + Certificate: testSignedRootTemplate, + PublicKey: testSignedRootTemplate.PublicKey, + PrivateKey: saSigner, + Signer: saSigner, + }, false}, {"fail template", fields{nil, nil, &mockKeyManager{}}, args{&apiv1.CreateCertificateAuthorityRequest{ Type: apiv1.RootCA, Lifetime: 24 * time.Hour, diff --git a/kms/cloudkms/cloudkms.go b/kms/cloudkms/cloudkms.go index f4c656d3..65d06048 100644 --- a/kms/cloudkms/cloudkms.go +++ b/kms/cloudkms/cloudkms.go @@ -3,6 +3,7 @@ package cloudkms import ( "context" "crypto" + "crypto/x509" "log" "strings" "time" @@ -63,6 +64,19 @@ var signatureAlgorithmMapping = map[apiv1.SignatureAlgorithm]interface{}{ apiv1.ECDSAWithSHA384: kmspb.CryptoKeyVersion_EC_SIGN_P384_SHA384, } +var cryptoKeyVersionMapping = map[kmspb.CryptoKeyVersion_CryptoKeyVersionAlgorithm]x509.SignatureAlgorithm{ + kmspb.CryptoKeyVersion_EC_SIGN_P256_SHA256: x509.ECDSAWithSHA256, + kmspb.CryptoKeyVersion_EC_SIGN_P384_SHA384: x509.ECDSAWithSHA384, + kmspb.CryptoKeyVersion_RSA_SIGN_PKCS1_2048_SHA256: x509.SHA256WithRSA, + kmspb.CryptoKeyVersion_RSA_SIGN_PKCS1_3072_SHA256: x509.SHA256WithRSA, + kmspb.CryptoKeyVersion_RSA_SIGN_PKCS1_4096_SHA256: x509.SHA256WithRSA, + kmspb.CryptoKeyVersion_RSA_SIGN_PKCS1_4096_SHA512: x509.SHA512WithRSA, + kmspb.CryptoKeyVersion_RSA_SIGN_PSS_2048_SHA256: x509.SHA256WithRSAPSS, + kmspb.CryptoKeyVersion_RSA_SIGN_PSS_3072_SHA256: x509.SHA256WithRSAPSS, + kmspb.CryptoKeyVersion_RSA_SIGN_PSS_4096_SHA256: x509.SHA256WithRSAPSS, + kmspb.CryptoKeyVersion_RSA_SIGN_PSS_4096_SHA512: x509.SHA512WithRSAPSS, +} + // KeyManagementClient defines the methods on KeyManagementClient that this // package will use. This interface will be used for unit testing. type KeyManagementClient interface { diff --git a/kms/cloudkms/signer.go b/kms/cloudkms/signer.go index 686aca25..5a5443cf 100644 --- a/kms/cloudkms/signer.go +++ b/kms/cloudkms/signer.go @@ -2,6 +2,7 @@ package cloudkms import ( "crypto" + "crypto/x509" "io" "github.com/pkg/errors" @@ -13,6 +14,7 @@ import ( type Signer struct { client KeyManagementClient signingKey string + algorithm x509.SignatureAlgorithm publicKey crypto.PublicKey } @@ -40,7 +42,7 @@ func (s *Signer) preloadKey(signingKey string) error { if err != nil { return errors.Wrap(err, "cloudKMS GetPublicKey failed") } - + s.algorithm = cryptoKeyVersionMapping[response.Algorithm] s.publicKey, err = pemutil.ParseKey([]byte(response.Pem)) return err } @@ -84,3 +86,10 @@ func (s *Signer) Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts) ([] return response.Signature, nil } + +// SignatureAlgorithm returns the algorithm that must be specified in a +// certificate to sign. This is specially important to distinguish RSA and +// RSAPSS schemas. +func (s *Signer) SignatureAlgorithm() x509.SignatureAlgorithm { + return s.algorithm +} diff --git a/kms/cloudkms/signer_test.go b/kms/cloudkms/signer_test.go index fa730fe3..a8f964f1 100644 --- a/kms/cloudkms/signer_test.go +++ b/kms/cloudkms/signer_test.go @@ -4,6 +4,7 @@ import ( "context" "crypto" "crypto/rand" + "crypto/x509" "fmt" "io" "io/ioutil" @@ -156,3 +157,79 @@ func Test_signer_Sign(t *testing.T) { }) } } + +func TestSigner_SignatureAlgorithm(t *testing.T) { + pemBytes, err := ioutil.ReadFile("testdata/pub.pem") + if err != nil { + t.Fatal(err) + } + + client := &MockClient{ + getPublicKey: func(_ context.Context, req *kmspb.GetPublicKeyRequest, _ ...gax.CallOption) (*kmspb.PublicKey, error) { + var algorithm kmspb.CryptoKeyVersion_CryptoKeyVersionAlgorithm + switch req.Name { + case "ECDSA-SHA256": + algorithm = kmspb.CryptoKeyVersion_EC_SIGN_P256_SHA256 + case "ECDSA-SHA384": + algorithm = kmspb.CryptoKeyVersion_EC_SIGN_P384_SHA384 + case "SHA256-RSA-2048": + algorithm = kmspb.CryptoKeyVersion_RSA_SIGN_PKCS1_2048_SHA256 + case "SHA256-RSA-3072": + algorithm = kmspb.CryptoKeyVersion_RSA_SIGN_PKCS1_3072_SHA256 + case "SHA256-RSA-4096": + algorithm = kmspb.CryptoKeyVersion_RSA_SIGN_PKCS1_4096_SHA256 + case "SHA512-RSA-4096": + algorithm = kmspb.CryptoKeyVersion_RSA_SIGN_PKCS1_4096_SHA512 + case "SHA256-RSAPSS-2048": + algorithm = kmspb.CryptoKeyVersion_RSA_SIGN_PSS_2048_SHA256 + case "SHA256-RSAPSS-3072": + algorithm = kmspb.CryptoKeyVersion_RSA_SIGN_PSS_3072_SHA256 + case "SHA256-RSAPSS-4096": + algorithm = kmspb.CryptoKeyVersion_RSA_SIGN_PSS_4096_SHA256 + case "SHA512-RSAPSS-4096": + algorithm = kmspb.CryptoKeyVersion_RSA_SIGN_PSS_4096_SHA512 + } + return &kmspb.PublicKey{ + Pem: string(pemBytes), + Algorithm: algorithm, + }, nil + }, + } + + if err != nil { + t.Fatal(err) + } + + type fields struct { + client KeyManagementClient + signingKey string + } + tests := []struct { + name string + fields fields + want x509.SignatureAlgorithm + }{ + {"ECDSA-SHA256", fields{client, "ECDSA-SHA256"}, x509.ECDSAWithSHA256}, + {"ECDSA-SHA384", fields{client, "ECDSA-SHA384"}, x509.ECDSAWithSHA384}, + {"SHA256-RSA-2048", fields{client, "SHA256-RSA-2048"}, x509.SHA256WithRSA}, + {"SHA256-RSA-3072", fields{client, "SHA256-RSA-3072"}, x509.SHA256WithRSA}, + {"SHA256-RSA-4096", fields{client, "SHA256-RSA-4096"}, x509.SHA256WithRSA}, + {"SHA512-RSA-4096", fields{client, "SHA512-RSA-4096"}, x509.SHA512WithRSA}, + {"SHA256-RSAPSS-2048", fields{client, "SHA256-RSAPSS-2048"}, x509.SHA256WithRSAPSS}, + {"SHA256-RSAPSS-3072", fields{client, "SHA256-RSAPSS-3072"}, x509.SHA256WithRSAPSS}, + {"SHA256-RSAPSS-4096", fields{client, "SHA256-RSAPSS-4096"}, x509.SHA256WithRSAPSS}, + {"SHA512-RSAPSS-4096", fields{client, "SHA512-RSAPSS-4096"}, x509.SHA512WithRSAPSS}, + {"unknown", fields{client, "UNKNOWN"}, x509.UnknownSignatureAlgorithm}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + signer, err := NewSigner(tt.fields.client, tt.fields.signingKey) + if err != nil { + t.Errorf("NewSigner() error = %v", err) + } + if got := signer.SignatureAlgorithm(); !reflect.DeepEqual(got, tt.want) { + t.Errorf("Signer.SignatureAlgorithm() = %v, want %v", got, tt.want) + } + }) + } +} From 6e0d515a55854f419f596b2a6f979bfa7b3a2615 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Wed, 8 Sep 2021 17:46:55 -0700 Subject: [PATCH 113/195] Add entry to changelog. --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e15dca6e..c963b44f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased - 0.17.3] - DATE ### Added - go 1.17 to github action test matrix +- Support for CloudKMS RSA-PSS signers without using templates. ### Changed - Using go 1.17 for binaries ### Deprecated From e4e799ca8548771d0c3463d4d7dff12d039ccb1f Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Thu, 9 Sep 2021 12:45:29 -0700 Subject: [PATCH 114/195] Fix typos in comment. --- cas/softcas/softcas.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cas/softcas/softcas.go b/cas/softcas/softcas.go index f3b2d051..23dac91b 100644 --- a/cas/softcas/softcas.go +++ b/cas/softcas/softcas.go @@ -214,8 +214,8 @@ func (c *SoftCAS) createSigner(req *kmsapi.CreateSignerRequest) (crypto.Signer, // createCertificate sets the SignatureAlgorithm of the template if necessary // and calls x509util.CreateCertificate. func createCertificate(template, parent *x509.Certificate, pub crypto.PublicKey, signer crypto.Signer) (*x509.Certificate, error) { - // Signers can specify the signature algorithm. This is specially important - // when x509.CreateCertificates attempts to validate a RSAPSS signature. + // Signers can specify the signature algorithm. This is especially important + // when x509.CreateCertificate attempts to validate a RSAPSS signature. if template.SignatureAlgorithm == 0 { if sa, ok := signer.(apiv1.SignatureAlgorithmGetter); ok { template.SignatureAlgorithm = sa.SignatureAlgorithm() From 8a99f7e4586f838afb669d3065924208541304b4 Mon Sep 17 00:00:00 2001 From: max furman Date: Thu, 9 Sep 2021 16:35:09 -0700 Subject: [PATCH 115/195] [action] add header and footer to github release page --- .goreleaser.yml | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/.goreleaser.yml b/.goreleaser.yml index 8dbbac29..1bef6ce5 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -156,6 +156,35 @@ release: # Default is `{{.Tag}}` #name_template: "{{.ProjectName}}-v{{.Version}} {{.Env.USER}}" + # Header template for the release body. + # Defaults to empty. + header: | + Welcome to this new release! + + ## Signatures and Checksums + + `step-ca` uses [sigstore/cosign](https://github.com/sigstore/cosign) for signing and verifying release artifacts. + Here is an example of how to use `cosign` to verify a release artifact: + + ``` + cosign verify-blob \ + -key https://raw.githubusercontent.com/smallstep/cli/master/cosign.pub \ + -signature ~/Downloads/step-ca_darwin_0.17.2_amd64.tar.gz.sig + ~/Downloads/step-ca_darwin_0.17.2_amd64.tar.gz + ``` + + We use the `checksums.txt` file to store checksums for every artifact in the release. + + # Footer template for the release body. + # Defaults to empty. + footer: | + ## Thanks! + + Those were the changes on {{ .Tag }}! + + Come join us on [Discord](https://discord.gg/X2RKGwEbV9) to ask questions, chat about PKI, + or get a sneak peak at the freshest PKI memes. + # You can disable this pipe in order to not upload any artifacts. # Defaults to false. #disable: true From 2cce795d8f98ede22ddca836d91bf35ddc5228b8 Mon Sep 17 00:00:00 2001 From: max furman Date: Thu, 9 Sep 2021 16:53:47 -0700 Subject: [PATCH 116/195] [action] reference correct pub key in cosign example release header --- .goreleaser.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.goreleaser.yml b/.goreleaser.yml index 1bef6ce5..78c892f0 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -168,7 +168,7 @@ release: ``` cosign verify-blob \ - -key https://raw.githubusercontent.com/smallstep/cli/master/cosign.pub \ + -key https://raw.githubusercontent.com/smallstep/certificates/master/cosign.pub \ -signature ~/Downloads/step-ca_darwin_0.17.2_amd64.tar.gz.sig ~/Downloads/step-ca_darwin_0.17.2_amd64.tar.gz ``` From 494da3d668b3fc79dc6972e9a37c34650ba24eb6 Mon Sep 17 00:00:00 2001 From: max furman Date: Sat, 11 Sep 2021 13:05:17 -0700 Subject: [PATCH 117/195] [action] goreleaser header packages --- .github/workflows/release.yml | 15 +++++++++++++++ .goreleaser.yml | 34 ++++++++++++++++++++++++++-------- Makefile | 2 +- 3 files changed, 42 insertions(+), 9 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e2e0176c..6da2aa27 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -62,8 +62,15 @@ jobs: needs: test runs-on: ubuntu-20.04 outputs: + debversion: ${{ steps.extract-tag.outputs.DEB_VERSION }} is_prerelease: ${{ steps.is_prerelease.outputs.IS_PRERELEASE }} steps: + - + name: Extract Tag Names + id: extract-tag + run: | + DEB_VERSION=$(echo ${GITHUB_REF#refs/tags/v} | sed 's/-/./') + echo "::set-output name=DEB_VERSION::${DEB_VERSION}" - name: Is Pre-release id: is_prerelease @@ -122,6 +129,12 @@ jobs: name: Write cosign key to disk id: write_key run: echo "${{ secrets.COSIGN_KEY }}" > "/tmp/cosign.key" + - + name: Get Release Date + id: release_date + run: | + RELEASE_DATE=$(date +"%y-%m-%d") + echo "::set-output name=RELEASE_DATE::${RELEASE_DATE}" - name: Run GoReleaser uses: goreleaser/goreleaser-action@5a54d7e660bda43b405e8463261b3d25631ffe86 # v2.7.0 @@ -131,6 +144,8 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.PAT }} COSIGN_PWD: ${{ secrets.COSIGN_PWD }} + DEB_VERSION: ${{ needs.create_release.outputs.debversion }} + RELEASE_DATE: ${{ steps.release_date.outputs.RELEASE_DATE }} build_upload_docker: name: Build & Upload Docker Images diff --git a/.goreleaser.yml b/.goreleaser.yml index 78c892f0..b61bde61 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -154,26 +154,45 @@ release: # You can change the name of the release. # Default is `{{.Tag}}` - #name_template: "{{.ProjectName}}-v{{.Version}} {{.Env.USER}}" + name_template: "Step CA {{ .Tag }} ({{ .Env.RELEASE_DATE }})" # Header template for the release body. # Defaults to empty. header: | - Welcome to this new release! + ## Official Release Artifacts + + #### Linux + + - 📦 [step-ca_linux_{{ .Version }}_amd64.tar.gz](https://dl.step.sm/cli/{{ .Tag }}/step-ca_linux_{{ .Version }}_amd64.tar.gz) + - 📦 [step-ca_{{ .Env.DEB_VERSION }}_amd64.deb](https://dl.step.sm/cli/{{ .Tag }}/step-ca_{{ .Env.DEB_VERSION }}_amd64.deb) + + #### OSX Darwin + + - 📦 [step-ca_darwin_{{ .Version }}_amd64.tar.gz](https://dl.step.sm/cli/{{ .Tag }}/step-ca_darwin_{{ .Version }}_amd64.tar.gz) + - 📦 [step-ca_darwin_{{ .Version }}_arm64.tar.gz](https://dl.step.sm/cli/{{ .Tag }}/step-ca_darwin_{{ .Version }}_arm64.tar.gz) + + #### Windows + + - 📦 [step-ca_windows_{{ .Version }}_arm64.zip](https://dl.step.sm/cli/{{ .Tag }}/step-ca_windows_{{ .Version }}_amd64.zip) + + For more builds across platforms and architectures see the `Assets` section below. + + Don't see the artifact you need? Open an issue [here](https://github.com/smallstep/certificates/issues/new/choose). ## Signatures and Checksums `step-ca` uses [sigstore/cosign](https://github.com/sigstore/cosign) for signing and verifying release artifacts. - Here is an example of how to use `cosign` to verify a release artifact: + + Below is an example using `cosign` to verify a release artifact: ``` cosign verify-blob \ -key https://raw.githubusercontent.com/smallstep/certificates/master/cosign.pub \ - -signature ~/Downloads/step-ca_darwin_0.17.2_amd64.tar.gz.sig - ~/Downloads/step-ca_darwin_0.17.2_amd64.tar.gz + -signature ~/Downloads/step-ca_darwin_{{ .Version }_amd64.tar.gz.sig + ~/Downloads/step-ca_darwin_{{ .Version }_amd64.tar.gz ``` - We use the `checksums.txt` file to store checksums for every artifact in the release. + The `checksums.txt` file (in the `Assets` section below) contains a checksum for every artifact in the release. # Footer template for the release body. # Defaults to empty. @@ -182,8 +201,7 @@ release: Those were the changes on {{ .Tag }}! - Come join us on [Discord](https://discord.gg/X2RKGwEbV9) to ask questions, chat about PKI, - or get a sneak peak at the freshest PKI memes. + Come join us on [Discord](https://discord.gg/X2RKGwEbV9) to ask questions, chat about PKI, or get a sneak peak at the freshest PKI memes. # You can disable this pipe in order to not upload any artifacts. # Defaults to false. diff --git a/Makefile b/Makefile index 3435f132..108efa1d 100644 --- a/Makefile +++ b/Makefile @@ -68,7 +68,7 @@ PUSHTYPE := branch endif VERSION := $(shell echo $(VERSION) | sed 's/^v//') -DEB_VERSION := $(shell echo $(VERSION) | sed 's/-/~/g') +DEB_VERSION := $(shell echo $(VERSION) | sed 's/-/./g') ifdef V $(info TRAVIS_TAG is $(TRAVIS_TAG)) From fcf322023a7f3e7a55d241d245a7cafa539fdfb9 Mon Sep 17 00:00:00 2001 From: max furman Date: Sat, 11 Sep 2021 14:42:02 -0700 Subject: [PATCH 118/195] [action] goreleaser github release footer fix missing close braces --- .goreleaser.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.goreleaser.yml b/.goreleaser.yml index b61bde61..5d4e4ab0 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -188,8 +188,8 @@ release: ``` cosign verify-blob \ -key https://raw.githubusercontent.com/smallstep/certificates/master/cosign.pub \ - -signature ~/Downloads/step-ca_darwin_{{ .Version }_amd64.tar.gz.sig - ~/Downloads/step-ca_darwin_{{ .Version }_amd64.tar.gz + -signature ~/Downloads/step-ca_darwin_{{ .Version }}_amd64.tar.gz.sig + ~/Downloads/step-ca_darwin_{{ .Version }}_amd64.tar.gz ``` The `checksums.txt` file (in the `Assets` section below) contains a checksum for every artifact in the release. From 6d644ddb2a8cad1691384613890bf45066ca3114 Mon Sep 17 00:00:00 2001 From: max furman Date: Sun, 12 Sep 2021 21:32:22 -0700 Subject: [PATCH 119/195] [action] goreleaser pkg link cli -> certificates --- .goreleaser.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.goreleaser.yml b/.goreleaser.yml index 5d4e4ab0..05f98941 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -163,17 +163,17 @@ release: #### Linux - - 📦 [step-ca_linux_{{ .Version }}_amd64.tar.gz](https://dl.step.sm/cli/{{ .Tag }}/step-ca_linux_{{ .Version }}_amd64.tar.gz) - - 📦 [step-ca_{{ .Env.DEB_VERSION }}_amd64.deb](https://dl.step.sm/cli/{{ .Tag }}/step-ca_{{ .Env.DEB_VERSION }}_amd64.deb) + - 📦 [step-ca_linux_{{ .Version }}_amd64.tar.gz](https://dl.step.sm/certificates/{{ .Tag }}/step-ca_linux_{{ .Version }}_amd64.tar.gz) + - 📦 [step-ca_{{ .Env.DEB_VERSION }}_amd64.deb](https://dl.step.sm/certificates/{{ .Tag }}/step-ca_{{ .Env.DEB_VERSION }}_amd64.deb) #### OSX Darwin - - 📦 [step-ca_darwin_{{ .Version }}_amd64.tar.gz](https://dl.step.sm/cli/{{ .Tag }}/step-ca_darwin_{{ .Version }}_amd64.tar.gz) - - 📦 [step-ca_darwin_{{ .Version }}_arm64.tar.gz](https://dl.step.sm/cli/{{ .Tag }}/step-ca_darwin_{{ .Version }}_arm64.tar.gz) + - 📦 [step-ca_darwin_{{ .Version }}_amd64.tar.gz](https://dl.step.sm/certificates/{{ .Tag }}/step-ca_darwin_{{ .Version }}_amd64.tar.gz) + - 📦 [step-ca_darwin_{{ .Version }}_arm64.tar.gz](https://dl.step.sm/certificates/{{ .Tag }}/step-ca_darwin_{{ .Version }}_arm64.tar.gz) #### Windows - - 📦 [step-ca_windows_{{ .Version }}_arm64.zip](https://dl.step.sm/cli/{{ .Tag }}/step-ca_windows_{{ .Version }}_amd64.zip) + - 📦 [step-ca_windows_{{ .Version }}_arm64.zip](https://dl.step.sm/certificates/{{ .Tag }}/step-ca_windows_{{ .Version }}_amd64.zip) For more builds across platforms and architectures see the `Assets` section below. From e3acea97043365b7146d21eadf5c4380c07efad4 Mon Sep 17 00:00:00 2001 From: Carl Tashian Date: Wed, 15 Sep 2021 10:30:04 -0700 Subject: [PATCH 120/195] Add release page link to install docs --- .goreleaser.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.goreleaser.yml b/.goreleaser.yml index 05f98941..9e95e928 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -175,7 +175,8 @@ release: - 📦 [step-ca_windows_{{ .Version }}_arm64.zip](https://dl.step.sm/certificates/{{ .Tag }}/step-ca_windows_{{ .Version }}_amd64.zip) - For more builds across platforms and architectures see the `Assets` section below. + For more builds across platforms and architectures, see the `Assets` section below. + And for packaged versions (Docker, k8s, Homebrew), see our [installation docs](https://smallstep.com/docs/step-ca/installation). Don't see the artifact you need? Open an issue [here](https://github.com/smallstep/certificates/issues/new/choose). From 611859eec45ac9b77f797eed49826926addb9371 Mon Sep 17 00:00:00 2001 From: Herman Slatman Date: Thu, 16 Sep 2021 08:24:28 +0200 Subject: [PATCH 121/195] Update go.mozilla.org/pkcs7 This includes the fix as described in https://github.com/mozilla-services/pkcs7/pull/59, which was the reason a fork of the library was used. --- go.mod | 3 +-- go.sum | 3 +++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index d786a523..7fe587b6 100644 --- a/go.mod +++ b/go.mod @@ -25,7 +25,7 @@ require ( github.com/smallstep/assert v0.0.0-20200723003110-82e2b9b3b262 github.com/smallstep/nosql v0.3.8 github.com/urfave/cli v1.22.4 - go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1 + go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352 go.step.sm/cli-utils v0.4.1 go.step.sm/crypto v0.9.2 go.step.sm/linkedca v0.5.0 @@ -43,4 +43,3 @@ require ( // replace go.step.sm/cli-utils => ../cli-utils // replace go.step.sm/linkedca => ../linkedca -replace go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1 => github.com/omorsi/pkcs7 v0.0.0-20210217142924-a7b80a2a8568 diff --git a/go.sum b/go.sum index cc687ddd..47875803 100644 --- a/go.sum +++ b/go.sum @@ -510,6 +510,9 @@ go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.5 h1:XAzx9gjCb0Rxj7EoqcClPD1d5ZBxZJk0jbuoPHenBt0= go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= +go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk= +go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352 h1:CCriYyAfq1Br1aIYettdHZTy8mBTIPo7We18TuO/bak= +go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk= go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= From 73d0a11a2075517de9ea14dd7ed7322dcf7c8b80 Mon Sep 17 00:00:00 2001 From: Herman Slatman Date: Thu, 16 Sep 2021 08:29:25 +0200 Subject: [PATCH 122/195] Update github.com/micromdm/scep/v2 --- go.mod | 3 +-- go.sum | 3 +++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index 7fe587b6..524c98e7 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect github.com/mattn/go-colorable v0.1.8 // indirect github.com/mattn/go-isatty v0.0.13 // indirect - github.com/micromdm/scep/v2 v2.0.0 + github.com/micromdm/scep/v2 v2.1.0 github.com/newrelic/go-agent v2.15.0+incompatible github.com/pkg/errors v0.9.1 github.com/rs/xid v1.2.1 @@ -42,4 +42,3 @@ require ( // replace go.step.sm/crypto => ../crypto // replace go.step.sm/cli-utils => ../cli-utils // replace go.step.sm/linkedca => ../linkedca - diff --git a/go.sum b/go.sum index 47875803..8bd0b7ad 100644 --- a/go.sum +++ b/go.sum @@ -360,6 +360,8 @@ github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzp github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/micromdm/scep/v2 v2.0.0 h1:cRzcY0S5QX+0+J+7YC4P2uZSnfMup8S8zJu/bLFgOkA= github.com/micromdm/scep/v2 v2.0.0/go.mod h1:ouaDs5tcjOjdHD/h8BGaQsWE87MUnQ/wMTMgfMMIpPc= +github.com/micromdm/scep/v2 v2.1.0 h1:2fS9Rla7qRR266hvUoEauBJ7J6FhgssEiq2OkSKXmaU= +github.com/micromdm/scep/v2 v2.1.0/go.mod h1:BkF7TkPPhmgJAMtHfP+sFTKXmgzNJgLQlvvGoOExBcc= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/pkcs11 v1.0.3-0.20190429190417-a667d056470f h1:eVB9ELsoq5ouItQBr5Tj334bhPJG/MX+m7rTchmzVUQ= github.com/miekg/pkcs11 v1.0.3-0.20190429190417-a667d056470f/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= @@ -511,6 +513,7 @@ go.etcd.io/bbolt v1.3.5 h1:XAzx9gjCb0Rxj7EoqcClPD1d5ZBxZJk0jbuoPHenBt0= go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk= +go.mozilla.org/pkcs7 v0.0.0-20210730143726-725912489c62/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk= go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352 h1:CCriYyAfq1Br1aIYettdHZTy8mBTIPo7We18TuO/bak= go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk= go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= From 8df9f629b173182eb9c73768c87b377cb4f56d53 Mon Sep 17 00:00:00 2001 From: max furman Date: Thu, 16 Sep 2021 00:14:06 -0700 Subject: [PATCH 123/195] go mod tidy --- go.sum | 5 ----- 1 file changed, 5 deletions(-) diff --git a/go.sum b/go.sum index 8bd0b7ad..f216c1d3 100644 --- a/go.sum +++ b/go.sum @@ -358,8 +358,6 @@ github.com/mattn/go-isatty v0.0.13 h1:qdl+GuBjcsKKDco5BsxPJlId98mSWNKqYA+Co0SC1y github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/micromdm/scep/v2 v2.0.0 h1:cRzcY0S5QX+0+J+7YC4P2uZSnfMup8S8zJu/bLFgOkA= -github.com/micromdm/scep/v2 v2.0.0/go.mod h1:ouaDs5tcjOjdHD/h8BGaQsWE87MUnQ/wMTMgfMMIpPc= github.com/micromdm/scep/v2 v2.1.0 h1:2fS9Rla7qRR266hvUoEauBJ7J6FhgssEiq2OkSKXmaU= github.com/micromdm/scep/v2 v2.1.0/go.mod h1:BkF7TkPPhmgJAMtHfP+sFTKXmgzNJgLQlvvGoOExBcc= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= @@ -394,8 +392,6 @@ github.com/newrelic/go-agent v2.15.0+incompatible/go.mod h1:a8Fv1b/fYhFSReoTU6HD github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= -github.com/omorsi/pkcs7 v0.0.0-20210217142924-a7b80a2a8568 h1:+MPqEswjYiS0S1FCTg8MIhMBMzxiVQ94rooFwvPPiWk= -github.com/omorsi/pkcs7 v0.0.0-20210217142924-a7b80a2a8568/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= @@ -512,7 +508,6 @@ go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.5 h1:XAzx9gjCb0Rxj7EoqcClPD1d5ZBxZJk0jbuoPHenBt0= go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= -go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk= go.mozilla.org/pkcs7 v0.0.0-20210730143726-725912489c62/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk= go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352 h1:CCriYyAfq1Br1aIYettdHZTy8mBTIPo7We18TuO/bak= go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk= From 6729c79253a1721ef84a1180bf19215c6498c91b Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Thu, 16 Sep 2021 11:55:41 -0700 Subject: [PATCH 124/195] Add support for setting individual password for ssh and tls keys This change add the following flags: * --ssh-host-password-file * --ssh-user-password-file Fixes #693 --- authority/authority.go | 36 +++++++++++++++++++++++++------ authority/options.go | 36 +++++++++++++++++++++++++++++++ ca/ca.go | 49 +++++++++++++++++++++++++++--------------- commands/app.go | 32 +++++++++++++++++++++++++++ 4 files changed, 130 insertions(+), 23 deletions(-) diff --git a/authority/authority.go b/authority/authority.go index 1b060ef8..16968d9d 100644 --- a/authority/authority.go +++ b/authority/authority.go @@ -43,6 +43,8 @@ type Authority struct { linkedCAToken string // X509 CA + password []byte + issuerPassword []byte x509CAService cas.CertificateAuthorityService rootX509Certs []*x509.Certificate rootX509CertPool *x509.CertPool @@ -53,6 +55,8 @@ type Authority struct { scepService *scep.Service // SSH CA + sshHostPassword []byte + sshUserPassword []byte sshCAUserCertSignKey ssh.Signer sshCAHostCertSignKey ssh.Signer sshCAUserCerts []ssh.PublicKey @@ -206,6 +210,21 @@ func (a *Authority) init() error { var err error + // Set password if they are not set. + var configPassword []byte + if a.config.Password != "" { + configPassword = []byte(a.config.Password) + } + if configPassword != nil && a.password == nil { + a.password = configPassword + } + if a.sshHostPassword == nil { + a.sshHostPassword = a.password + } + if a.sshUserPassword == nil { + a.sshUserPassword = a.password + } + // Automatically enable admin for all linked cas. if a.linkedCAToken != "" { a.config.AuthorityConfig.EnableAdmin = true @@ -238,6 +257,11 @@ func (a *Authority) init() error { options = *a.config.AuthorityConfig.Options } + // Set the issuer password if passed in the flags. + if options.CertificateIssuer != nil && a.issuerPassword != nil { + options.CertificateIssuer.Password = string(a.issuerPassword) + } + // Read intermediate and create X509 signer for default CAS. if options.Is(casapi.SoftCAS) { options.CertificateChain, err = pemutil.ReadCertificateBundle(a.config.IntermediateCert) @@ -246,7 +270,7 @@ func (a *Authority) init() error { } options.Signer, err = a.keyManager.CreateSigner(&kmsapi.CreateSignerRequest{ SigningKey: a.config.IntermediateKey, - Password: []byte(a.config.Password), + Password: []byte(a.password), }) if err != nil { return err @@ -315,7 +339,7 @@ func (a *Authority) init() error { if a.config.SSH.HostKey != "" { signer, err := a.keyManager.CreateSigner(&kmsapi.CreateSignerRequest{ SigningKey: a.config.SSH.HostKey, - Password: []byte(a.config.Password), + Password: []byte(a.sshHostPassword), }) if err != nil { return err @@ -341,7 +365,7 @@ func (a *Authority) init() error { if a.config.SSH.UserKey != "" { signer, err := a.keyManager.CreateSigner(&kmsapi.CreateSignerRequest{ SigningKey: a.config.SSH.UserKey, - Password: []byte(a.config.Password), + Password: []byte(a.sshUserPassword), }) if err != nil { return err @@ -420,7 +444,7 @@ func (a *Authority) init() error { } options.Signer, err = a.keyManager.CreateSigner(&kmsapi.CreateSignerRequest{ SigningKey: a.config.IntermediateKey, - Password: []byte(a.config.Password), + Password: []byte(a.password), }) if err != nil { return err @@ -429,7 +453,7 @@ func (a *Authority) init() error { if km, ok := a.keyManager.(kmsapi.Decrypter); ok { options.Decrypter, err = km.CreateDecrypter(&kmsapi.CreateDecrypterRequest{ DecryptionKey: a.config.IntermediateKey, - Password: []byte(a.config.Password), + Password: []byte(a.password), }) if err != nil { return err @@ -475,7 +499,7 @@ func (a *Authority) init() error { } if len(provs) == 0 && !strings.EqualFold(a.config.AuthorityConfig.DeploymentType, "linked") { // Create First Provisioner - prov, err := CreateFirstProvisioner(context.Background(), a.adminDB, a.config.Password) + prov, err := CreateFirstProvisioner(context.Background(), a.adminDB, string(a.password)) if err != nil { return admin.WrapErrorISE(err, "error creating first provisioner") } diff --git a/authority/options.go b/authority/options.go index 6baeb2bc..5c8a6e66 100644 --- a/authority/options.go +++ b/authority/options.go @@ -38,6 +38,42 @@ func WithConfigFile(filename string) Option { } } +// WithPassword set the password to decrypt the intermediate key as well as the +// ssh host and user keys if they are not overridden by other options. +func WithPassword(password []byte) Option { + return func(a *Authority) (err error) { + a.password = password + return + } +} + +// WithSSHHostPassword set the password to decrypt the key used to sign SSH host +// certificates. +func WithSSHHostPassword(password []byte) Option { + return func(a *Authority) (err error) { + a.sshHostPassword = password + return + } +} + +// WithSSHUserPassword set the password to decrypt the key used to sign SSH user +// certificates. +func WithSSHUserPassword(password []byte) Option { + return func(a *Authority) (err error) { + a.sshUserPassword = password + return + } +} + +// WithIssuerPassword set the password to decrypt the certificate issuer private +// key used in RA mode. +func WithIssuerPassword(password []byte) Option { + return func(a *Authority) (err error) { + a.issuerPassword = password + return + } +} + // WithDatabase sets an already initialized authority database to a new // authority. This option is intended to be use on graceful reloads. func WithDatabase(db db.AuthDB) Option { diff --git a/ca/ca.go b/ca/ca.go index 51d15bec..00a5970a 100644 --- a/ca/ca.go +++ b/ca/ca.go @@ -29,11 +29,13 @@ import ( ) type options struct { - configFile string - linkedCAToken string - password []byte - issuerPassword []byte - database db.AuthDB + configFile string + linkedCAToken string + password []byte + issuerPassword []byte + sshHostPassword []byte + sshUserPassword []byte + database db.AuthDB } func (o *options) apply(opts []Option) { @@ -61,6 +63,22 @@ func WithPassword(password []byte) Option { } } +// WithSSHHostPassword sets the given password to decrypt the key used to sign +// ssh host certificates. +func WithSSHHostPassword(password []byte) Option { + return func(o *options) { + o.sshHostPassword = password + } +} + +// WithSSHUserPassword sets the given password to decrypt the key used to sign +// ssh user certificates. +func WithSSHUserPassword(password []byte) Option { + return func(o *options) { + o.sshUserPassword = password + } +} + // WithIssuerPassword sets the given password as the configured certificate // issuer password in the CA options. func WithIssuerPassword(password []byte) Option { @@ -106,19 +124,14 @@ func New(config *config.Config, opts ...Option) (*CA, error) { // Init initializes the CA with the given configuration. func (ca *CA) Init(config *config.Config) (*CA, error) { - // Intermediate Password. - if len(ca.opts.password) > 0 { - ca.config.Password = string(ca.opts.password) + // Set password, it's ok to set nil password, the ca will prompt for them if + // they are required. + opts := []authority.Option{ + authority.WithPassword(ca.opts.password), + authority.WithSSHHostPassword(ca.opts.sshHostPassword), + authority.WithSSHUserPassword(ca.opts.sshUserPassword), + authority.WithIssuerPassword(ca.opts.issuerPassword), } - - // Certificate issuer password for RA mode. - if len(ca.opts.issuerPassword) > 0 { - if ca.config.AuthorityConfig != nil && ca.config.AuthorityConfig.CertificateIssuer != nil { - ca.config.AuthorityConfig.CertificateIssuer.Password = string(ca.opts.issuerPassword) - } - } - - var opts []authority.Option if ca.opts.linkedCAToken != "" { opts = append(opts, authority.WithLinkedCAToken(ca.opts.linkedCAToken)) } @@ -337,6 +350,8 @@ func (ca *CA) Reload() error { newCA, err := New(config, WithPassword(ca.opts.password), + WithSSHHostPassword(ca.opts.sshHostPassword), + WithSSHUserPassword(ca.opts.sshUserPassword), WithIssuerPassword(ca.opts.issuerPassword), WithLinkedCAToken(ca.opts.linkedCAToken), WithConfigFile(ca.opts.configFile), diff --git a/commands/app.go b/commands/app.go index aa7b43d4..20e71506 100644 --- a/commands/app.go +++ b/commands/app.go @@ -30,6 +30,18 @@ var AppCommand = cli.Command{ Name: "password-file", Usage: `path to the containing the password to decrypt the intermediate private key.`, + }, + cli.StringFlag{ + Name: "ssh-host-password-file", + Usage: `path to the containing the password to decrypt the +private key used to sign SSH host certificates. If the flag is not passed it +will default to --password-file.`, + }, + cli.StringFlag{ + Name: "ssh-user-password-file", + Usage: `path to the containing the password to decrypt the +private key used to sign SSH user certificates. If the flag is not passed it +will default to --password-file.`, }, cli.StringFlag{ Name: "issuer-password-file", @@ -51,6 +63,8 @@ certificate issuer private key used in the RA mode.`, // AppAction is the action used when the top command runs. func appAction(ctx *cli.Context) error { passFile := ctx.String("password-file") + sshHostPassFile := ctx.String("ssh-host-password-file") + sshUserPassFile := ctx.String("ssh-user-password-file") issuerPassFile := ctx.String("issuer-password-file") resolver := ctx.String("resolver") token := ctx.String("token") @@ -89,6 +103,22 @@ To get a linked authority token: password = bytes.TrimRightFunc(password, unicode.IsSpace) } + var sshHostPassword []byte + if sshHostPassFile != "" { + if sshHostPassword, err = ioutil.ReadFile(sshHostPassFile); err != nil { + fatal(errors.Wrapf(err, "error reading %s", sshHostPassFile)) + } + sshHostPassword = bytes.TrimRightFunc(sshHostPassword, unicode.IsSpace) + } + + var sshUserPassword []byte + if sshUserPassFile != "" { + if sshUserPassword, err = ioutil.ReadFile(sshUserPassFile); err != nil { + fatal(errors.Wrapf(err, "error reading %s", sshUserPassFile)) + } + sshUserPassword = bytes.TrimRightFunc(sshUserPassword, unicode.IsSpace) + } + var issuerPassword []byte if issuerPassFile != "" { if issuerPassword, err = ioutil.ReadFile(issuerPassFile); err != nil { @@ -108,6 +138,8 @@ To get a linked authority token: srv, err := ca.New(config, ca.WithConfigFile(configFile), ca.WithPassword(password), + ca.WithSSHHostPassword(sshHostPassword), + ca.WithSSHUserPassword(sshUserPassword), ca.WithIssuerPassword(issuerPassword), ca.WithLinkedCAToken(token)) if err != nil { From cfe08ad6fe85e1477708ac81eeb4a42a2f005fd7 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Thu, 16 Sep 2021 12:05:23 -0700 Subject: [PATCH 125/195] Add flags to usage. --- cmd/step-ca/main.go | 4 +++- commands/app.go | 5 +++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/cmd/step-ca/main.go b/cmd/step-ca/main.go index 4396e028..aaf37df2 100644 --- a/cmd/step-ca/main.go +++ b/cmd/step-ca/main.go @@ -107,7 +107,9 @@ func main() { app.HelpName = "step-ca" app.Version = config.Version() app.Usage = "an online certificate authority for secure automated certificate management" - app.UsageText = `**step-ca** [**--password-file**=] [**--issuer-password-file**=] [**--resolver**=] [**--help**] [**--version**]` + app.UsageText = `**step-ca** [**--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 (Step CA) using the given configuration. See the README.md for more detailed configuration documentation. diff --git a/commands/app.go b/commands/app.go index 20e71506..3aaee0f5 100644 --- a/commands/app.go +++ b/commands/app.go @@ -23,8 +23,9 @@ import ( var AppCommand = cli.Command{ Name: "start", Action: appAction, - UsageText: `**step-ca** -[**--password-file**=] [**--issuer-password-file**=] [**--resolver**=]`, + UsageText: `**step-ca** [**--password-file**=] +[**--ssh-host-password-file**=] [**--ssh-user-password-file**=] +[**--issuer-password-file**=] [**--resolver**=]`, Flags: []cli.Flag{ cli.StringFlag{ Name: "password-file", From 4fde7b52501034ac0314c317d109d44884fe2267 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Fri, 17 Sep 2021 12:49:16 -0700 Subject: [PATCH 126/195] Use badgerv2 the default in helm too. Use also port 443 for the ca-url, as we usually access through the service, this can be overridden by --with-ca-url flag in the cli. --- pki/helm.go | 2 +- pki/pki.go | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/pki/helm.go b/pki/helm.go index 570fb04d..817c1bf4 100644 --- a/pki/helm.go +++ b/pki/helm.go @@ -79,7 +79,7 @@ inject: logger: format: json db: - type: badger + type: badgerv2 dataSource: /home/step/db authority: provisioners: diff --git a/pki/pki.go b/pki/pki.go index fd625199..12e71e47 100644 --- a/pki/pki.go +++ b/pki/pki.go @@ -341,7 +341,9 @@ func New(o apiv1.Options, opts ...Option) (*PKI, error) { if err != nil { return nil, errors.Wrapf(err, "error parsing %s", p.Address) } - if port == "443" { + // On k8s we usually access through a service, and this is configured on + // port 443 by default. + if port == "443" || p.options.isHelm { p.Defaults.CaUrl = fmt.Sprintf("https://%s", p.Defaults.CaUrl) } else { p.Defaults.CaUrl = fmt.Sprintf("https://%s:%s", p.Defaults.CaUrl, port) From 04784be03e61dd126abd465211cebb8a59c76587 Mon Sep 17 00:00:00 2001 From: Carl Tashian Date: Tue, 21 Sep 2021 17:23:29 -0700 Subject: [PATCH 127/195] Update cert-renewer@.service Wrap command line env variables in braces so they are treated as a single argument (rather than split on whitespace) --- systemd/cert-renewer@.service | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/systemd/cert-renewer@.service b/systemd/cert-renewer@.service index 5b56f5fc..a9962c2e 100644 --- a/systemd/cert-renewer@.service +++ b/systemd/cert-renewer@.service @@ -15,10 +15,10 @@ Environment=STEPPATH=/etc/step-ca \ ; ExecCondition checks if the certificate is ready for renewal, ; based on the exit status of the command. ; (In systemd 242 or below, you can use ExecStartPre= here.) -ExecCondition=/usr/bin/step certificate needs-renewal $CERT_LOCATION +ExecCondition=/usr/bin/step certificate needs-renewal ${CERT_LOCATION} ; ExecStart renews the certificate, if ExecStartPre was successful. -ExecStart=/usr/bin/step ca renew --force $CERT_LOCATION $KEY_LOCATION +ExecStart=/usr/bin/step ca renew --force ${CERT_LOCATION} ${KEY_LOCATION} ; Try to reload or restart the systemd service that relies on this cert-renewer ; If the relying service doesn't exist, forge ahead. From 2d5bfd34857eaebd682a91016a4106b03bb332cc Mon Sep 17 00:00:00 2001 From: max furman Date: Wed, 22 Sep 2021 11:56:52 -0700 Subject: [PATCH 128/195] fix comment --- authority/admin/db.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/authority/admin/db.go b/authority/admin/db.go index 15fe6686..8a6339d9 100644 --- a/authority/admin/db.go +++ b/authority/admin/db.go @@ -54,7 +54,7 @@ func UnmarshalProvisionerDetails(typ linkedca.Provisioner_Type, data []byte) (*l return &linkedca.ProvisionerDetails{Data: v.Data}, nil } -// DB is the DB interface expected by the step-ca ACME API. +// DB is the DB interface expected by the step-ca Admin API. type DB interface { CreateProvisioner(ctx context.Context, prov *linkedca.Provisioner) error GetProvisioner(ctx context.Context, id string) (*linkedca.Provisioner, error) From ad82d8a250be6c86990be361fa377f4e72f54df7 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Wed, 22 Sep 2021 15:15:19 -0700 Subject: [PATCH 129/195] Upgrade go.step.sm/crypto as long with go-jose.v2 There was a typo in the OKP template causing bad fingerprints for Ed25519 keys. See https://github.com/square/go-jose/commit/a10ff54e00bc6e833bf549e04ae976f0fe8ea2fd Fixes #705 --- CHANGELOG.md | 1 + go.mod | 12 ++++++------ go.sum | 54 ++++++++++++++++++++++++++++++++++------------------ 3 files changed, 42 insertions(+), 25 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c963b44f..bb4dc430 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Deprecated ### Removed ### Fixed +- Upgrade go-jose.v2 to fix a bug in the JWK fingerprint of Ed25519 keys. ### Security - Use cosign to sign and upload signatures for multi-arch Docker container. - Add debian checksum diff --git a/go.mod b/go.mod index 524c98e7..04af53fc 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.14 require ( cloud.google.com/go v0.83.0 - github.com/Masterminds/sprig/v3 v3.1.0 + github.com/Masterminds/sprig/v3 v3.2.2 github.com/ThalesIgnite/crypto11 v1.2.4 github.com/aws/aws-sdk-go v1.30.29 github.com/dgraph-io/ristretto v0.0.4-0.20200906165740-41ebdbffecfd // indirect @@ -12,7 +12,7 @@ require ( github.com/go-kit/kit v0.10.0 // indirect github.com/go-piv/piv-go v1.7.0 github.com/golang/mock v1.5.0 - github.com/google/uuid v1.1.2 + github.com/google/uuid v1.3.0 github.com/googleapis/gax-go/v2 v2.0.5 github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect github.com/mattn/go-colorable v0.1.8 // indirect @@ -27,15 +27,15 @@ require ( github.com/urfave/cli v1.22.4 go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352 go.step.sm/cli-utils v0.4.1 - go.step.sm/crypto v0.9.2 + go.step.sm/crypto v0.11.0 go.step.sm/linkedca v0.5.0 - golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 - golang.org/x/net v0.0.0-20210825183410-e898025ed96a + golang.org/x/crypto v0.0.0-20210915214749-c084706c2272 + golang.org/x/net v0.0.0-20210913180222-943fd674d43e google.golang.org/api v0.47.0 google.golang.org/genproto v0.0.0-20210719143636-1d5a45f8e492 google.golang.org/grpc v1.39.0 google.golang.org/protobuf v1.27.1 - gopkg.in/square/go-jose.v2 v2.5.1 + gopkg.in/square/go-jose.v2 v2.6.0 ) // replace github.com/smallstep/nosql => ../nosql diff --git a/go.sum b/go.sum index f216c1d3..a6ff0f08 100644 --- a/go.sum +++ b/go.sum @@ -43,12 +43,15 @@ github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96/go.mod h1:bOv github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= -github.com/Masterminds/goutils v1.1.0 h1:zukEsf/1JZwCMgHiK3GZftabmxiCw4apj3a28RPBiVg= github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= -github.com/Masterminds/semver/v3 v3.1.0 h1:Y2lUDsFKVRSYGojLJ1yLxSXdMmMYTYls0rCvoqmMUQk= +github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= +github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= github.com/Masterminds/semver/v3 v3.1.0/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= -github.com/Masterminds/sprig/v3 v3.1.0 h1:j7GpgZ7PdFqNsmncycTHsLmVPf5/3wJtlgW9TNDYD9Y= +github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc= +github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= github.com/Masterminds/sprig/v3 v3.1.0/go.mod h1:ONGMf7UfYGAbMXCZmQLy8x3lCDIPrEZE/rU8pmrbihA= +github.com/Masterminds/sprig/v3 v3.2.2 h1:17jRggJu518dr3QaafizSXOjKYp94wKfABxUmyxvxX8= +github.com/Masterminds/sprig/v3 v3.2.2/go.mod h1:UoaO7Yp8KlPnJIYWTFkMaqPUYKTfGFPhxNuwnnxkKlk= github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= @@ -261,8 +264,9 @@ github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLe 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= -github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +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= @@ -300,13 +304,16 @@ github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0m github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/huandu/xstrings v1.3.1 h1:4jgBlKK6tLKFvO8u5pmYjG91cqytmDCDvGh7ECVFfFs= github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= +github.com/huandu/xstrings v1.3.2 h1:L18LIDzqlW6xN2rEkpdV8+oL/IXWJ1APd+vsdYy4Wdw= +github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/imdario/mergo v0.3.8 h1:CGgOkSJeqMRmt0D9XLWExdT4m4F1vd3FV3VPt+0VxkQ= github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= +github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= @@ -364,8 +371,9 @@ github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3N github.com/miekg/pkcs11 v1.0.3-0.20190429190417-a667d056470f h1:eVB9ELsoq5ouItQBr5Tj334bhPJG/MX+m7rTchmzVUQ= github.com/miekg/pkcs11 v1.0.3-0.20190429190417-a667d056470f/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= -github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ= github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= +github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= +github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= @@ -373,8 +381,9 @@ github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS4 github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY= github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= +github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= @@ -450,6 +459,8 @@ github.com/samfoo/ansi v0.0.0-20160124022901-b6bd2ded7189 h1:CmSpbxmewNQbzqztaY0 github.com/samfoo/ansi v0.0.0-20160124022901-b6bd2ded7189/go.mod h1:UUwuHEJ9zkkPDxspIHOa59PUeSkGFljESGzbxntLmIg= github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= +github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= @@ -469,8 +480,9 @@ github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0b github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng= github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cast v1.4.1 h1:s0hze+J0196ZfEMTs80N7UlFt0BDuQ7Q+JDnHiMWKdA= +github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= @@ -525,8 +537,8 @@ go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqe go.step.sm/cli-utils v0.4.1 h1:QztRUhGYjOPM1I2Nmi7V6XejQyVtcESmo+sbegxvX7Q= go.step.sm/cli-utils v0.4.1/go.mod h1:hWYVOSlw8W9Pd+BwIbs/aftVVMRms3EG7Q2qLRwc0WA= go.step.sm/crypto v0.9.0/go.mod h1:+CYG05Mek1YDqi5WK0ERc6cOpKly2i/a5aZmU1sfGj0= -go.step.sm/crypto v0.9.2 h1:UvQHE4brjAOdgcK2ob6zupL1iRzDd8+QiEvPOeQrm4E= -go.step.sm/crypto v0.9.2/go.mod h1:F5OJyPDWntNa1SbuWPxuHJc9bLzu84NzYrrdzDuBugk= +go.step.sm/crypto v0.11.0 h1:VDpeVgEmqme/FK2w5QINxkOQ1FWOm/Wi2TwQXiacKr8= +go.step.sm/crypto v0.11.0/go.mod h1:5YzQ85BujYBu6NH18jw7nFjwuRnDch35nLzH0ES5sKg= go.step.sm/linkedca v0.5.0 h1:oZVRSpElM7lAL1XN2YkjdHwI/oIZ+1ULOnuqYPM6xjY= go.step.sm/linkedca v0.5.0/go.mod h1:5uTRjozEGSPAZal9xJqlaD38cvJcLe3o1VAFVjqcORo= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= @@ -547,8 +559,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ= -golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20210915214749-c084706c2272 h1:3erb+vDS8lU1sxfDHF4/hhWyaXnhIaO+7RgL4fDZORA= +golang.org/x/crypto v0.0.0-20210915214749-c084706c2272/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -628,8 +640,8 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210825183410-e898025ed96a h1:bRuuGXV8wwSdGTB+CtJf+FjgO1APK1CoO39T4BN/XBw= -golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210913180222-943fd674d43e h1:+b/22bPvDYt4NPDcy4xAGCmON713ONAWFeY3Z7I3tR8= +golang.org/x/net v0.0.0-20210913180222-943fd674d43e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 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= @@ -711,8 +723,9 @@ golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 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-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210915083310-ed5796bab164 h1:7ZDGnxgHAMw7thfC5bEos0RDAccZKxioiWBhfIe+tvw= +golang.org/x/sys v0.0.0-20210915083310-ed5796bab164/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -722,8 +735,9 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -920,16 +934,18 @@ gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= -gopkg.in/square/go-jose.v2 v2.5.1 h1:7odma5RETjNHWJnR32wx8t+Io4djHE1PqxCFx3iiZ2w= gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI= +gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.7 h1:VUgggvou5XRW9mHwD/yXxIYSMtY0zoKQf/v226p2nyo= gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= From 2ae6b42cfe05989bff5acac4608ac11f458b2ae1 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Wed, 22 Sep 2021 16:39:23 -0700 Subject: [PATCH 130/195] Add missing feature to the changelog. --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index bb4dc430..9aba9913 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Added - go 1.17 to github action test matrix - Support for CloudKMS RSA-PSS signers without using templates. +- Add flags to support different passwords for the intermediate and SSH keys. ### Changed - Using go 1.17 for binaries ### Deprecated From 7f00cc7aad7856df69c16a874487d0c6e5ad78b1 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Wed, 22 Sep 2021 17:41:12 -0700 Subject: [PATCH 131/195] Clarify changelog feature. --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9aba9913..a6e67397 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Added - go 1.17 to github action test matrix - Support for CloudKMS RSA-PSS signers without using templates. -- Add flags to support different passwords for the intermediate and SSH keys. +- Add flags to support individual passwords for the intermediate and SSH keys. ### Changed - Using go 1.17 for binaries ### Deprecated From a50654b46895d9aefdf26ebeac105dcef4f41c24 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Thu, 23 Sep 2021 15:49:28 -0700 Subject: [PATCH 132/195] Check for admins in both emails and groups. --- authority/provisioner/oidc.go | 71 ++++++++++++++---------------- authority/provisioner/oidc_test.go | 36 +++++++++++++++ 2 files changed, 68 insertions(+), 39 deletions(-) diff --git a/authority/provisioner/oidc.go b/authority/provisioner/oidc.go index b6bca872..3786f54b 100644 --- a/authority/provisioner/oidc.go +++ b/authority/provisioner/oidc.go @@ -49,6 +49,29 @@ type openIDPayload struct { Groups []string `json:"groups"` } +func (o *openIDPayload) IsAdmin(admins []string) bool { + if o.Email != "" { + email := sanitizeEmail(o.Email) + for _, e := range admins { + if email == sanitizeEmail(e) { + return true + } + } + } + + // The groups and emails can be in the same array for now, but consider + // making a specialized option later. + for _, name := range o.Groups { + for _, admin := range admins { + if name == admin { + return true + } + } + } + + return false +} + // OIDC represents an OAuth 2.0 OpenID Connect provider. // // ClientSecret is mandatory, but it can be an empty string. @@ -73,35 +96,6 @@ type OIDC struct { getIdentityFunc GetIdentityFunc } -// IsAdmin returns true if the given email is in the Admins allowlist, false -// otherwise. -func (o *OIDC) IsAdmin(email string) bool { - if email != "" { - email = sanitizeEmail(email) - for _, e := range o.Admins { - if email == sanitizeEmail(e) { - return true - } - } - } - return false -} - -// IsAdminGroup returns true if the one group in the given list is in the Admins -// allowlist, false otherwise. -func (o *OIDC) IsAdminGroup(groups []string) bool { - for _, g := range groups { - // The groups and emails can be in the same array for now, but consider - // making a specialized option later. - for _, gadmin := range o.Admins { - if g == gadmin { - return true - } - } - } - return false -} - func sanitizeEmail(email string) string { if i := strings.LastIndex(email, "@"); i >= 0 { email = email[:i] + strings.ToLower(email[i:]) @@ -234,7 +228,7 @@ func (o *OIDC) ValidatePayload(p openIDPayload) error { } // Validate domains (case-insensitive) - if p.Email != "" && len(o.Domains) > 0 && !o.IsAdmin(p.Email) { + if p.Email != "" && len(o.Domains) > 0 && !p.IsAdmin(o.Admins) { email := sanitizeEmail(p.Email) var found bool for _, d := range o.Domains { @@ -313,9 +307,10 @@ func (o *OIDC) AuthorizeRevoke(ctx context.Context, token string) error { } // Only admins can revoke certificates. - if o.IsAdmin(claims.Email) { + if claims.IsAdmin(o.Admins) { return nil } + return errs.Unauthorized("oidc.AuthorizeRevoke; cannot revoke with non-admin oidc token") } @@ -351,7 +346,7 @@ func (o *OIDC) AuthorizeSign(ctx context.Context, token string) ([]SignOption, e // Use the default template unless no-templates are configured and email is // an admin, in that case we will use the CR template. defaultTemplate := x509util.DefaultLeafTemplate - if !o.Options.GetX509Options().HasTemplate() && o.IsAdmin(claims.Email) { + if !o.Options.GetX509Options().HasTemplate() && claims.IsAdmin(o.Admins) { defaultTemplate = x509util.DefaultAdminLeafTemplate } @@ -420,10 +415,7 @@ func (o *OIDC) AuthorizeSSHSign(ctx context.Context, token string) ([]SignOption // Use the default template unless no-templates are configured and email is // an admin, in that case we will use the parameters in the request. - isAdmin := o.IsAdmin(claims.Email) - if !isAdmin && len(claims.Groups) > 0 { - isAdmin = o.IsAdminGroup(claims.Groups) - } + isAdmin := claims.IsAdmin(o.Admins) defaultTemplate := sshutil.DefaultTemplate if isAdmin && !o.Options.GetSSHOptions().HasTemplate() { defaultTemplate = sshutil.DefaultAdminTemplate @@ -471,10 +463,11 @@ func (o *OIDC) AuthorizeSSHRevoke(ctx context.Context, token string) error { } // Only admins can revoke certificates. - if !o.IsAdmin(claims.Email) { - return errs.Unauthorized("oidc.AuthorizeSSHRevoke; cannot revoke with non-admin oidc token") + if claims.IsAdmin(o.Admins) { + return nil } - return nil + + return errs.Unauthorized("oidc.AuthorizeSSHRevoke; cannot revoke with non-admin oidc token") } func getAndDecode(uri string, v interface{}) error { diff --git a/authority/provisioner/oidc_test.go b/authority/provisioner/oidc_test.go index 48f879a8..532bd2e0 100644 --- a/authority/provisioner/oidc_test.go +++ b/authority/provisioner/oidc_test.go @@ -698,3 +698,39 @@ func Test_sanitizeEmail(t *testing.T) { }) } } + +func Test_openIDPayload_IsAdmin(t *testing.T) { + type fields struct { + Email string + Groups []string + } + type args struct { + admins []string + } + tests := []struct { + name string + fields fields + args args + want bool + }{ + {"ok email", fields{"admin@smallstep.com", nil}, args{[]string{"admin@smallstep.com"}}, true}, + {"ok email multiple", fields{"admin@smallstep.com", []string{"admin", "eng"}}, args{[]string{"eng@smallstep.com", "admin@smallstep.com"}}, true}, + {"ok email sanitized", fields{"admin@Smallstep.com", nil}, args{[]string{"admin@smallStep.com"}}, true}, + {"ok group", fields{"", []string{"admin"}}, args{[]string{"admin"}}, true}, + {"ok group multiple", fields{"admin@smallstep.com", []string{"engineering", "admin"}}, args{[]string{"admin"}}, true}, + {"fail missing", fields{"eng@smallstep.com", []string{"admin"}}, args{[]string{"admin@smallstep.com"}}, false}, + {"fail email letter case", fields{"Admin@smallstep.com", []string{}}, args{[]string{"admin@smallstep.com"}}, false}, + {"fail group letter case", fields{"", []string{"Admin"}}, args{[]string{"admin"}}, false}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + o := &openIDPayload{ + Email: tt.fields.Email, + Groups: tt.fields.Groups, + } + if got := o.IsAdmin(tt.args.admins); got != tt.want { + t.Errorf("openIDPayload.IsAdmin() = %v, want %v", got, tt.want) + } + }) + } +} From 9eb757797ec4e514a80199d666dd66e9e1f29ff2 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Fri, 24 Sep 2021 13:50:10 -0700 Subject: [PATCH 133/195] Add line to changelog. --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a6e67397..0ec765d3 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. - go 1.17 to github action test matrix - Support for CloudKMS RSA-PSS signers without using templates. - Add flags to support individual passwords for the intermediate and SSH keys. +- Support for group admins in OIDC provisioners for X509 certificates. ### Changed - Using go 1.17 for binaries ### Deprecated From 963eaf8882cee1b3d881df7f969b220a8b6b4a83 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Fri, 24 Sep 2021 13:50:47 -0700 Subject: [PATCH 134/195] Fix line in changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ec765d3..60b36b9b 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. - go 1.17 to github action test matrix - Support for CloudKMS RSA-PSS signers without using templates. - Add flags to support individual passwords for the intermediate and SSH keys. -- Support for group admins in OIDC provisioners for X509 certificates. +- Global support for group admins in the OIDC provisioner. ### Changed - Using go 1.17 for binaries ### Deprecated From ba17869deb19111c4374a6a0c49dc36cff42a7f5 Mon Sep 17 00:00:00 2001 From: max furman Date: Fri, 24 Sep 2021 14:24:28 -0700 Subject: [PATCH 135/195] changelog update for 0.17.3 --- CHANGELOG.md | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 60b36b9b..b0d4bda1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,15 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). -## [Unreleased - 0.17.3] - DATE +## [Unreleased - 0.17.4] - DATE +### Added +### Changed +### Deprecated +### Removed +### Fixed +### Security + +## [0.17.3] - 2021-09-24 ### Added - go 1.17 to github action test matrix - Support for CloudKMS RSA-PSS signers without using templates. @@ -12,8 +20,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Global support for group admins in the OIDC provisioner. ### Changed - Using go 1.17 for binaries -### Deprecated -### Removed ### Fixed - Upgrade go-jose.v2 to fix a bug in the JWK fingerprint of Ed25519 keys. ### Security From 6aaa7853b28f6e225cecae93e82e6d73a3f9a085 Mon Sep 17 00:00:00 2001 From: max furman Date: Mon, 27 Sep 2021 16:24:01 -0700 Subject: [PATCH 136/195] [action] update release URLs in header --- .goreleaser.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.goreleaser.yml b/.goreleaser.yml index 9e95e928..97b9c24c 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -163,17 +163,17 @@ release: #### Linux - - 📦 [step-ca_linux_{{ .Version }}_amd64.tar.gz](https://dl.step.sm/certificates/{{ .Tag }}/step-ca_linux_{{ .Version }}_amd64.tar.gz) - - 📦 [step-ca_{{ .Env.DEB_VERSION }}_amd64.deb](https://dl.step.sm/certificates/{{ .Tag }}/step-ca_{{ .Env.DEB_VERSION }}_amd64.deb) + - 📦 [step-ca_linux_{{ .Version }}_amd64.tar.gz](https://dl.step.sm/gh-release/certificates/gh-release-header/{{ .Tag }}/step-ca_linux_{{ .Version }}_amd64.tar.gz) + - 📦 [step-ca_{{ .Env.DEB_VERSION }}_amd64.deb](https://dl.step.sm/gh-release/certificates/gh-release-header/{{ .Tag }}/step-ca_{{ .Env.DEB_VERSION }}_amd64.deb) #### OSX Darwin - - 📦 [step-ca_darwin_{{ .Version }}_amd64.tar.gz](https://dl.step.sm/certificates/{{ .Tag }}/step-ca_darwin_{{ .Version }}_amd64.tar.gz) - - 📦 [step-ca_darwin_{{ .Version }}_arm64.tar.gz](https://dl.step.sm/certificates/{{ .Tag }}/step-ca_darwin_{{ .Version }}_arm64.tar.gz) + - 📦 [step-ca_darwin_{{ .Version }}_amd64.tar.gz](https://dl.step.sm/gh-release/certificates/gh-release-header/{{ .Tag }}/step-ca_darwin_{{ .Version }}_amd64.tar.gz) + - 📦 [step-ca_darwin_{{ .Version }}_arm64.tar.gz](https://dl.step.sm/gh-release/certificates/gh-release-header/{{ .Tag }}/step-ca_darwin_{{ .Version }}_arm64.tar.gz) #### Windows - - 📦 [step-ca_windows_{{ .Version }}_arm64.zip](https://dl.step.sm/certificates/{{ .Tag }}/step-ca_windows_{{ .Version }}_amd64.zip) + - 📦 [step-ca_windows_{{ .Version }}_arm64.zip](https://dl.step.sm/gh-release/certificates/gh-release-header/{{ .Tag }}/step-ca_windows_{{ .Version }}_amd64.zip) For more builds across platforms and architectures, see the `Assets` section below. And for packaged versions (Docker, k8s, Homebrew), see our [installation docs](https://smallstep.com/docs/step-ca/installation). From aedd7fcc050e164b773589c1ceb51e3a8629d154 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Tue, 28 Sep 2021 15:07:09 -0700 Subject: [PATCH 137/195] Be able to start a SSH host or SSH user only CA In previous versions if the host or user CA is not configured, the start of step-ca was crashing. This allows to configure a user or host only ssh ca. --- authority/authority.go | 25 +++++++++++----------- authority/ssh_test.go | 48 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 13 deletions(-) diff --git a/authority/authority.go b/authority/authority.go index 16968d9d..e26ce591 100644 --- a/authority/authority.go +++ b/authority/authority.go @@ -361,6 +361,8 @@ func (a *Authority) init() error { // Append public key to list of host certs a.sshCAHostCerts = append(a.sshCAHostCerts, a.sshCAHostCertSignKey.PublicKey()) a.sshCAHostFederatedCerts = append(a.sshCAHostFederatedCerts, a.sshCAHostCertSignKey.PublicKey()) + // Configure template variables. + tmplVars.SSH.HostKey = a.sshCAHostCertSignKey.PublicKey() } if a.config.SSH.UserKey != "" { signer, err := a.keyManager.CreateSigner(&kmsapi.CreateSignerRequest{ @@ -387,35 +389,32 @@ func (a *Authority) init() error { // Append public key to list of user certs a.sshCAUserCerts = append(a.sshCAUserCerts, a.sshCAUserCertSignKey.PublicKey()) a.sshCAUserFederatedCerts = append(a.sshCAUserFederatedCerts, a.sshCAUserCertSignKey.PublicKey()) + // Configure template variables. + tmplVars.SSH.UserKey = a.sshCAUserCertSignKey.PublicKey() } - // Append other public keys + // Append other public keys and add them to the template variables. for _, key := range a.config.SSH.Keys { + publicKey := key.PublicKey() switch key.Type { case provisioner.SSHHostCert: if key.Federated { - a.sshCAHostFederatedCerts = append(a.sshCAHostFederatedCerts, key.PublicKey()) + a.sshCAHostFederatedCerts = append(a.sshCAHostFederatedCerts, publicKey) + tmplVars.SSH.HostFederatedKeys = append(tmplVars.SSH.HostFederatedKeys, publicKey) } else { - a.sshCAHostCerts = append(a.sshCAHostCerts, key.PublicKey()) + a.sshCAHostCerts = append(a.sshCAHostCerts, publicKey) } case provisioner.SSHUserCert: if key.Federated { - a.sshCAUserFederatedCerts = append(a.sshCAUserFederatedCerts, key.PublicKey()) + a.sshCAUserFederatedCerts = append(a.sshCAUserFederatedCerts, publicKey) + tmplVars.SSH.UserFederatedKeys = append(tmplVars.SSH.UserFederatedKeys, publicKey) } else { - a.sshCAUserCerts = append(a.sshCAUserCerts, key.PublicKey()) + a.sshCAUserCerts = append(a.sshCAUserCerts, publicKey) } default: return errors.Errorf("unsupported type %s", key.Type) } } - - // Configure template variables. - tmplVars.SSH.HostKey = a.sshCAHostCertSignKey.PublicKey() - tmplVars.SSH.UserKey = a.sshCAUserCertSignKey.PublicKey() - // On the templates we skip the first one because there's a distinction - // between the main key and federated keys. - tmplVars.SSH.HostFederatedKeys = append(tmplVars.SSH.HostFederatedKeys, a.sshCAHostFederatedCerts[1:]...) - tmplVars.SSH.UserFederatedKeys = append(tmplVars.SSH.UserFederatedKeys, a.sshCAUserFederatedCerts[1:]...) } // Check if a KMS with decryption capability is required and available diff --git a/authority/ssh_test.go b/authority/ssh_test.go index e468ecf0..41df8576 100644 --- a/authority/ssh_test.go +++ b/authority/ssh_test.go @@ -87,6 +87,52 @@ func (m sshTestOptionsModifier) Modify(cert *ssh.Certificate, opts provisioner.S return fmt.Errorf(string(m)) } +func TestAuthority_initHostOnly(t *testing.T) { + auth := testAuthority(t, func(a *Authority) error { + a.config.SSH.UserKey = "" + return nil + }) + + // Check keys + keys, err := auth.GetSSHRoots(context.Background()) + assert.NoError(t, err) + assert.Len(t, 1, keys.HostKeys) + assert.Len(t, 0, keys.UserKeys) + + // Check templates, user templates should work fine. + _, err = auth.GetSSHConfig(context.Background(), "user", nil) + assert.NoError(t, err) + + _, err = auth.GetSSHConfig(context.Background(), "host", map[string]string{ + "Certificate": "ssh_host_ecdsa_key-cert.pub", + "Key": "ssh_host_ecdsa_key", + }) + assert.Error(t, err) +} + +func TestAuthority_initUserOnly(t *testing.T) { + auth := testAuthority(t, func(a *Authority) error { + a.config.SSH.HostKey = "" + return nil + }) + + // Check keys + keys, err := auth.GetSSHRoots(context.Background()) + assert.NoError(t, err) + assert.Len(t, 0, keys.HostKeys) + assert.Len(t, 1, keys.UserKeys) + + // Check templates, host templates should work fine. + _, err = auth.GetSSHConfig(context.Background(), "host", map[string]string{ + "Certificate": "ssh_host_ecdsa_key-cert.pub", + "Key": "ssh_host_ecdsa_key", + }) + assert.NoError(t, err) + + _, err = auth.GetSSHConfig(context.Background(), "user", nil) + assert.Error(t, err) +} + func TestAuthority_SignSSH(t *testing.T) { key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) assert.FatalError(t, err) @@ -153,6 +199,8 @@ func TestAuthority_SignSSH(t *testing.T) { }{ {"ok-user", fields{signer, signer}, args{pub, provisioner.SignSSHOptions{}, []provisioner.SignOption{userTemplate, userOptions}}, want{CertType: ssh.UserCert}, false}, {"ok-host", fields{signer, signer}, args{pub, provisioner.SignSSHOptions{}, []provisioner.SignOption{hostTemplate, hostOptions}}, want{CertType: ssh.HostCert}, false}, + {"ok-user-only", fields{signer, nil}, args{pub, provisioner.SignSSHOptions{}, []provisioner.SignOption{userTemplate, userOptions}}, want{CertType: ssh.UserCert}, false}, + {"ok-host-only", fields{nil, signer}, args{pub, provisioner.SignSSHOptions{}, []provisioner.SignOption{hostTemplate, hostOptions}}, want{CertType: ssh.HostCert}, false}, {"ok-opts-type-user", fields{signer, signer}, args{pub, provisioner.SignSSHOptions{CertType: "user"}, []provisioner.SignOption{userTemplate}}, want{CertType: ssh.UserCert}, false}, {"ok-opts-type-host", fields{signer, signer}, args{pub, provisioner.SignSSHOptions{CertType: "host"}, []provisioner.SignOption{hostTemplate}}, want{CertType: ssh.HostCert}, false}, {"ok-opts-principals", fields{signer, signer}, args{pub, provisioner.SignSSHOptions{CertType: "user", Principals: []string{"user"}}, []provisioner.SignOption{userTemplateWithUser}}, want{CertType: ssh.UserCert, Principals: []string{"user"}}, false}, From 42e263584893c89e18f6fc4c0ff0bd4448647203 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Tue, 28 Sep 2021 15:59:48 -0700 Subject: [PATCH 138/195] Add entry in changelog. --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 60b36b9b..cce6f095 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Support for CloudKMS RSA-PSS signers without using templates. - Add flags to support individual passwords for the intermediate and SSH keys. - Global support for group admins in the OIDC provisioner. +- Support host-only or user-only SSH CA. ### Changed - Using go 1.17 for binaries ### Deprecated From afe1980d139a8f0a2b6212c69fae8fa4d94666c4 Mon Sep 17 00:00:00 2001 From: max furman Date: Tue, 28 Sep 2021 16:15:23 -0700 Subject: [PATCH 139/195] changelog update for 0.17.4 --- CHANGELOG.md | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ba6998a8..a902ee2f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). -## [Unreleased - 0.17.4] - DATE +## [Unreleased - 0.17.5] - DATE ### Added ### Changed ### Deprecated @@ -12,13 +12,21 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Fixed ### Security +## [0.17.4] - 2021-09-28 +### Added +### Changed +### Deprecated +### Removed +### Fixed +- Support host-only or user-only SSH CA. +### Security + ## [0.17.3] - 2021-09-24 ### Added - go 1.17 to github action test matrix - Support for CloudKMS RSA-PSS signers without using templates. - Add flags to support individual passwords for the intermediate and SSH keys. - Global support for group admins in the OIDC provisioner. -- Support host-only or user-only SSH CA. ### Changed - Using go 1.17 for binaries ### Fixed From 9fb6df3abb4178e5b95b02daaee1e223c9425a37 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Tue, 28 Sep 2021 18:50:45 -0700 Subject: [PATCH 140/195] Fix ssh template variables when CA is injected using options. --- authority/authority.go | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/authority/authority.go b/authority/authority.go index e26ce591..3f97ceab 100644 --- a/authority/authority.go +++ b/authority/authority.go @@ -361,8 +361,6 @@ func (a *Authority) init() error { // Append public key to list of host certs a.sshCAHostCerts = append(a.sshCAHostCerts, a.sshCAHostCertSignKey.PublicKey()) a.sshCAHostFederatedCerts = append(a.sshCAHostFederatedCerts, a.sshCAHostCertSignKey.PublicKey()) - // Configure template variables. - tmplVars.SSH.HostKey = a.sshCAHostCertSignKey.PublicKey() } if a.config.SSH.UserKey != "" { signer, err := a.keyManager.CreateSigner(&kmsapi.CreateSignerRequest{ @@ -389,8 +387,6 @@ func (a *Authority) init() error { // Append public key to list of user certs a.sshCAUserCerts = append(a.sshCAUserCerts, a.sshCAUserCertSignKey.PublicKey()) a.sshCAUserFederatedCerts = append(a.sshCAUserFederatedCerts, a.sshCAUserCertSignKey.PublicKey()) - // Configure template variables. - tmplVars.SSH.UserKey = a.sshCAUserCertSignKey.PublicKey() } // Append other public keys and add them to the template variables. @@ -400,14 +396,12 @@ func (a *Authority) init() error { case provisioner.SSHHostCert: if key.Federated { a.sshCAHostFederatedCerts = append(a.sshCAHostFederatedCerts, publicKey) - tmplVars.SSH.HostFederatedKeys = append(tmplVars.SSH.HostFederatedKeys, publicKey) } else { a.sshCAHostCerts = append(a.sshCAHostCerts, publicKey) } case provisioner.SSHUserCert: if key.Federated { a.sshCAUserFederatedCerts = append(a.sshCAUserFederatedCerts, publicKey) - tmplVars.SSH.UserFederatedKeys = append(tmplVars.SSH.UserFederatedKeys, publicKey) } else { a.sshCAUserCerts = append(a.sshCAUserCerts, publicKey) } @@ -417,6 +411,25 @@ func (a *Authority) init() error { } } + // Configure template variables. On the template variables HostFederatedKeys + // and UserFederatedKeys we will skip the actual CA that will be available + // in HostKey and UserKey. + // + // We cannot do it in the previous blocks because this configuration can be + // injected using options. + if a.sshCAHostCertSignKey != nil { + tmplVars.SSH.HostKey = a.sshCAHostCertSignKey.PublicKey() + tmplVars.SSH.HostFederatedKeys = append(tmplVars.SSH.HostFederatedKeys, a.sshCAHostFederatedCerts[1:]...) + } else { + tmplVars.SSH.HostFederatedKeys = append(tmplVars.SSH.HostFederatedKeys, a.sshCAHostFederatedCerts...) + } + if a.sshCAUserCertSignKey != nil { + tmplVars.SSH.UserKey = a.sshCAUserCertSignKey.PublicKey() + tmplVars.SSH.UserFederatedKeys = append(tmplVars.SSH.UserFederatedKeys, a.sshCAUserFederatedCerts[1:]...) + } else { + tmplVars.SSH.UserFederatedKeys = append(tmplVars.SSH.UserFederatedKeys, a.sshCAUserFederatedCerts...) + } + // Check if a KMS with decryption capability is required and available if a.requiresDecrypter() { if _, ok := a.keyManager.(kmsapi.Decrypter); !ok { From 392a18465f319cc963509e97d423e0885521d110 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Tue, 5 Oct 2021 17:06:17 -0700 Subject: [PATCH 141/195] Add initial implementation of Azure Key Vault KMS. Fixes #462 --- go.mod | 7 +- go.sum | 33 ++++++ kms/azurekms/key_vault.go | 242 ++++++++++++++++++++++++++++++++++++++ kms/azurekms/signer.go | 151 ++++++++++++++++++++++++ kms/azurekms/utils.go | 57 +++++++++ 5 files changed, 489 insertions(+), 1 deletion(-) create mode 100644 kms/azurekms/key_vault.go create mode 100644 kms/azurekms/signer.go create mode 100644 kms/azurekms/utils.go diff --git a/go.mod b/go.mod index 04af53fc..ddf51740 100644 --- a/go.mod +++ b/go.mod @@ -1,9 +1,14 @@ module github.com/smallstep/certificates -go 1.14 +go 1.15 require ( cloud.google.com/go v0.83.0 + github.com/Azure/azure-sdk-for-go v58.0.0+incompatible + github.com/Azure/go-autorest/autorest/azure/auth v0.5.8 + github.com/Azure/go-autorest/autorest/date v0.3.0 + github.com/Azure/go-autorest/autorest/to v0.4.0 // indirect + github.com/Azure/go-autorest/autorest/validation v0.3.1 // indirect github.com/Masterminds/sprig/v3 v3.2.2 github.com/ThalesIgnite/crypto11 v1.2.4 github.com/aws/aws-sdk-go v1.30.29 diff --git a/go.sum b/go.sum index a6ff0f08..5de2ab46 100644 --- a/go.sum +++ b/go.sum @@ -40,6 +40,31 @@ cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9 dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96 h1:cTp8I5+VIoKjsnZuH8vjyaysT/ses3EvZeaV/1UkF2M= github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= +github.com/Azure/azure-sdk-for-go v58.0.0+incompatible h1:Cw16jiP4dI+CK761aq44ol4RV5dUiIIXky1+EKpoiVM= +github.com/Azure/azure-sdk-for-go v58.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= +github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +github.com/Azure/go-autorest/autorest v0.11.17 h1:2zCdHwNgRH+St1J+ZMf66xI8aLr/5KMy+wWLH97zwYM= +github.com/Azure/go-autorest/autorest v0.11.17/go.mod h1:eipySxLmqSyC5s5k1CLupqet0PSENBEDP93LQ9a8QYw= +github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A= +github.com/Azure/go-autorest/autorest/adal v0.9.11 h1:L4/pmq7poLdsy41Bj1FayKvBhayuWRYkx9HU5i4Ybl0= +github.com/Azure/go-autorest/autorest/adal v0.9.11/go.mod h1:nBKAnTomx8gDtl+3ZCJv2v0KACFHWTB2drffI1B68Pk= +github.com/Azure/go-autorest/autorest/azure/auth v0.5.8 h1:TzPg6B6fTZ0G1zBf3T54aI7p3cAT6u//TOXGPmFMOXg= +github.com/Azure/go-autorest/autorest/azure/auth v0.5.8/go.mod h1:kxyKZTSfKh8OVFWPAgOgQ/frrJgeYQJPyR5fLFmXko4= +github.com/Azure/go-autorest/autorest/azure/cli v0.4.2 h1:dMOmEJfkLKW/7JsokJqkyoYSgmR08hi9KrhjZb+JALY= +github.com/Azure/go-autorest/autorest/azure/cli v0.4.2/go.mod h1:7qkJkT+j6b+hIpzMOwPChJhTqS8VbsqqgULzMNRugoM= +github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw= +github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= +github.com/Azure/go-autorest/autorest/mocks v0.4.1 h1:K0laFcLE6VLTOwNgSxaGbUcLPuGXlNkbVvq4cW4nIHk= +github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= +github.com/Azure/go-autorest/autorest/to v0.4.0 h1:oXVqrxakqqV1UZdSazDOPOLvOIz+XA683u8EctwboHk= +github.com/Azure/go-autorest/autorest/to v0.4.0/go.mod h1:fE8iZBn7LQR7zH/9XU2NcPR4o9jEImooCeWJcYV/zLE= +github.com/Azure/go-autorest/autorest/validation v0.3.1 h1:AgyqjAd94fwNAoTjl/WQXg4VvFeRFpO+UhNyRXqF1ac= +github.com/Azure/go-autorest/autorest/validation v0.3.1/go.mod h1:yhLgjC0Wda5DYXl6JAsWyUe4KVNffhoDhG0zVzUMo3E= +github.com/Azure/go-autorest/logger v0.2.0 h1:e4RVHVZKC5p6UANLJHkM4OfR1UKZPj8Wt8Pcx+3oqrE= +github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= +github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo= +github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= @@ -146,6 +171,9 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZm github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y= github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8= +github.com/dimchansky/utfbom v1.1.1 h1:vV6w1AhK4VMnhBno/TPVCoK9U/LP0PkLCS9tbxHdi/U= +github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= @@ -163,6 +191,8 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.m github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/form3tech-oss/jwt-go v3.2.2+incompatible h1:TcekIExNqud5crz4xD2pavyTgWiPvpYe4Xau31I0PRk= +github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= @@ -375,6 +405,7 @@ github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFW github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= @@ -559,6 +590,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/crypto v0.0.0-20210915214749-c084706c2272 h1:3erb+vDS8lU1sxfDHF4/hhWyaXnhIaO+7RgL4fDZORA= golang.org/x/crypto v0.0.0-20210915214749-c084706c2272/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= diff --git a/kms/azurekms/key_vault.go b/kms/azurekms/key_vault.go new file mode 100644 index 00000000..1b133c2e --- /dev/null +++ b/kms/azurekms/key_vault.go @@ -0,0 +1,242 @@ +package azurekms + +import ( + "context" + "crypto" + "net/url" + "time" + + "github.com/Azure/azure-sdk-for-go/services/keyvault/v7.1/keyvault" + "github.com/Azure/go-autorest/autorest/azure/auth" + "github.com/Azure/go-autorest/autorest/date" + "github.com/pkg/errors" + "github.com/smallstep/certificates/kms/apiv1" + "github.com/smallstep/certificates/kms/uri" +) + +func init() { + apiv1.Register(apiv1.CloudKMS, func(ctx context.Context, opts apiv1.Options) (apiv1.KeyManager, error) { + return New(ctx, opts) + }) +} + +// Scheme is the scheme used for Azure Key Vault uris. +const Scheme = "azurekms" + +var ( + valueTrue = true + value2048 int32 = 2048 + value3072 int32 = 3072 + value4096 int32 = 4096 +) + +var now = func() time.Time { + return time.Now().UTC() +} + +type keyType struct { + Kty keyvault.JSONWebKeyType + Curve keyvault.JSONWebKeyCurveName + KeySize int +} + +func (k keyType) KeyType(pl apiv1.ProtectionLevel) keyvault.JSONWebKeyType { + switch k.Kty { + case keyvault.EC: + if pl == apiv1.HSM { + return keyvault.ECHSM + } + return k.Kty + case keyvault.RSA: + if pl == apiv1.HSM { + return keyvault.RSAHSM + } + return k.Kty + default: + return "" + } +} + +var signatureAlgorithmMapping = map[apiv1.SignatureAlgorithm]keyType{ + apiv1.UnspecifiedSignAlgorithm: { + Kty: keyvault.EC, + Curve: keyvault.P256, + }, + apiv1.SHA256WithRSA: { + Kty: keyvault.RSA, + }, + apiv1.SHA384WithRSA: { + Kty: keyvault.RSA, + }, + apiv1.SHA512WithRSA: { + Kty: keyvault.RSA, + }, + apiv1.SHA256WithRSAPSS: { + Kty: keyvault.RSA, + }, + apiv1.SHA384WithRSAPSS: { + Kty: keyvault.RSA, + }, + apiv1.SHA512WithRSAPSS: { + Kty: keyvault.RSA, + }, + apiv1.ECDSAWithSHA256: { + Kty: keyvault.EC, + Curve: keyvault.P256, + }, + apiv1.ECDSAWithSHA384: { + Kty: keyvault.EC, + Curve: keyvault.P384, + }, + apiv1.ECDSAWithSHA512: { + Kty: keyvault.EC, + Curve: keyvault.P521, + }, +} + +// vaultResource is that the client will use as audience. +const vaultResource = "https://vault.azure.net" + +// KeyVaultClient is the interface implemented by keyvault.BaseClient. It it +// will be used for testing purposes. +type KeyVaultClient interface { + GetKey(ctx context.Context, vaultBaseURL string, keyName string, keyVersion string) (keyvault.KeyBundle, error) + CreateKey(ctx context.Context, vaultBaseURL string, keyName string, parameters keyvault.KeyCreateParameters) (keyvault.KeyBundle, error) + Sign(ctx context.Context, vaultBaseURL string, keyName string, keyVersion string, parameters keyvault.KeySignParameters) (keyvault.KeyOperationResult, error) +} + +// KeyVault implements a KMS using Azure Key Vault. +// +// TODO(mariano): The implementation is using /services/keyvault/v7.1/keyvault +// package, at some point Azure might create a keyvault client with all the +// functionality in /sdk/keyvault, we should migrate to that once available. +type KeyVault struct { + baseClient KeyVaultClient +} + +// New initializes a new KMS implemented using Azure Key Vault. +func New(ctx context.Context, opts apiv1.Options) (*KeyVault, error) { + // Attempt to authorize with the following methods: + // 1. Environment variables. + // - Client credentials + // - Client certificate + // - Username and password + // - MSI + // 2. Using Azure CLI 2.0 on local development. + authorizer, err := auth.NewAuthorizerFromEnvironmentWithResource(vaultResource) + if err != nil { + authorizer, err = auth.NewAuthorizerFromCLIWithResource(vaultResource) + if err != nil { + return nil, errors.Wrap(err, "error getting authorizer for key vault") + } + } + + baseClient := keyvault.New() + baseClient.Authorizer = authorizer + + return &KeyVault{ + baseClient: &baseClient, + }, nil +} + +// GetPublicKey loads a public key from Azure Key Vault by its resource name. +func (k *KeyVault) GetPublicKey(req *apiv1.GetPublicKeyRequest) (crypto.PublicKey, error) { + switch { + case req.Name == "": + return nil, errors.New("getPublicKeyRequest 'name' cannot be empty") + } + + vault, name, version, err := parseKeyName(req.Name) + if err != nil { + return nil, err + } + + ctx, cancel := defaultContext() + defer cancel() + + resp, err := k.baseClient.GetKey(ctx, vaultBaseURL(vault), name, version) + if err != nil { + return nil, errors.Wrap(err, "keyVault GetKey failed") + } + + return convertKey(resp.Key) +} + +// CreateKey creates a asymmetric key in Azure Key Vault. +func (k *KeyVault) CreateKey(req *apiv1.CreateKeyRequest) (*apiv1.CreateKeyResponse, error) { + vault, name, _, err := parseKeyName(req.Name) + if err != nil { + return nil, err + } + + kt, ok := signatureAlgorithmMapping[req.SignatureAlgorithm] + if !ok { + return nil, errors.Errorf("keyVault does not support signature algorithm '%s'", req.SignatureAlgorithm) + } + var keySize *int32 + if kt.Kty == keyvault.RSA || kt.Kty == keyvault.RSAHSM { + switch req.Bits { + case 2048: + keySize = &value2048 + case 0, 3072: + keySize = &value3072 + case 4096: + keySize = &value4096 + default: + return nil, errors.Errorf("keyVault does not support key size %d", req.Bits) + } + } + + created := date.UnixTime(now()) + + ctx, cancel := defaultContext() + defer cancel() + + resp, err := k.baseClient.CreateKey(ctx, vaultBaseURL(vault), name, keyvault.KeyCreateParameters{ + Kty: kt.KeyType(req.ProtectionLevel), + KeySize: keySize, + Curve: kt.Curve, + KeyOps: &[]keyvault.JSONWebKeyOperation{ + keyvault.Sign, keyvault.Verify, + }, + KeyAttributes: &keyvault.KeyAttributes{ + Enabled: &valueTrue, + Created: &created, + NotBefore: &created, + }, + }) + if err != nil { + return nil, errors.Wrap(err, "keyVault CreateKey failed") + } + + keyURI := uri.New("azurekms", url.Values{ + "vault": []string{vault}, + "id": []string{name}, + }).String() + + publicKey, err := convertKey(resp.Key) + if err != nil { + return nil, err + } + + return &apiv1.CreateKeyResponse{ + Name: keyURI, + PublicKey: publicKey, + CreateSignerRequest: apiv1.CreateSignerRequest{ + SigningKey: keyURI, + }, + }, nil +} + +// CreateSigner returns a crypto.Signer from a previously created asymmetric key. +func (k *KeyVault) CreateSigner(req *apiv1.CreateSignerRequest) (crypto.Signer, error) { + if req.SigningKey == "" { + return nil, errors.New("createSignerRequest 'signingKey' cannot be empty") + } + return NewSigner(k.baseClient, req.SigningKey) +} + +// Close closes the client connection to the Azure Key Vault. This is a noop. +func (k *KeyVault) Close() error { + return nil +} diff --git a/kms/azurekms/signer.go b/kms/azurekms/signer.go new file mode 100644 index 00000000..217c6258 --- /dev/null +++ b/kms/azurekms/signer.go @@ -0,0 +1,151 @@ +package azurekms + +import ( + "crypto" + "crypto/ecdsa" + "crypto/rsa" + "encoding/base64" + "io" + "math/big" + + "github.com/Azure/azure-sdk-for-go/services/keyvault/v7.1/keyvault" + "github.com/pkg/errors" + "golang.org/x/crypto/cryptobyte" + "golang.org/x/crypto/cryptobyte/asn1" +) + +// Signer implements a crypto.Signer using the AWS KMS. +type Signer struct { + client KeyVaultClient + vaultBaseURL string + name string + version string + publicKey crypto.PublicKey +} + +// NewSigner creates a new signer using a key in the AWS KMS. +func NewSigner(client KeyVaultClient, signingKey string) (*Signer, error) { + vault, name, version, err := parseKeyName(signingKey) + if err != nil { + return nil, err + } + + // Make sure that the key exists. + signer := &Signer{ + client: client, + vaultBaseURL: vaultBaseURL(vault), + name: name, + version: version, + } + if err := signer.preloadKey(); err != nil { + return nil, err + } + + return signer, nil +} + +func (s *Signer) preloadKey() error { + ctx, cancel := defaultContext() + defer cancel() + + resp, err := s.client.GetKey(ctx, s.vaultBaseURL, s.name, s.version) + if err != nil { + return errors.Wrap(err, "keyVault GetKey failed") + } + + s.publicKey, err = convertKey(resp.Key) + return err +} + +// Public returns the public key of this signer or an error. +func (s *Signer) Public() crypto.PublicKey { + return s.publicKey +} + +// Sign signs digest with the private key stored in the AWS KMS. +func (s *Signer) Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts) ([]byte, error) { + alg, err := getSigningAlgorithm(s.Public(), opts) + if err != nil { + return nil, err + } + + ctx, cancel := defaultContext() + defer cancel() + + b64 := base64.RawURLEncoding.EncodeToString(digest) + + resp, err := s.client.Sign(ctx, s.vaultBaseURL, s.name, s.version, keyvault.KeySignParameters{ + Algorithm: alg, + Value: &b64, + }) + if err != nil { + return nil, errors.Wrap(err, "keyVault Sign failed") + } + + sig, err := base64.RawURLEncoding.DecodeString(*resp.Result) + if err != nil { + return nil, errors.Wrap(err, "error decoding keyVault Sign result") + } + + var octetSize int + switch alg { + case keyvault.ES256: + octetSize = 32 // 256-bit, concat(R,S) = 64 bytes + case keyvault.ES384: + octetSize = 48 // 384-bit, concat(R,S) = 96 bytes + case keyvault.ES512: + octetSize = 66 // 528-bit, concat(R,S) = 132 bytes + default: + return sig, nil + } + + // Convert to ans1 + if len(sig) != octetSize*2 { + return nil, errors.Errorf("keyVault Sign failed: unexpected signature length") + } + var b cryptobyte.Builder + b.AddASN1(asn1.SEQUENCE, func(b *cryptobyte.Builder) { + b.AddASN1BigInt(new(big.Int).SetBytes(sig[:octetSize])) // R + b.AddASN1BigInt(new(big.Int).SetBytes(sig[octetSize:])) // S + }) + return b.Bytes() +} + +func getSigningAlgorithm(key crypto.PublicKey, opts crypto.SignerOpts) (keyvault.JSONWebKeySignatureAlgorithm, error) { + switch key.(type) { + case *rsa.PublicKey: + _, isPSS := opts.(*rsa.PSSOptions) + switch h := opts.HashFunc(); h { + case crypto.SHA256: + if isPSS { + return keyvault.PS256, nil + } + return keyvault.RS256, nil + case crypto.SHA384: + if isPSS { + return keyvault.PS384, nil + } + return keyvault.RS384, nil + case crypto.SHA512: + if isPSS { + return keyvault.PS512, nil + } + return keyvault.RS512, nil + default: + return "", errors.Errorf("unsupported hash function %v", h) + } + case *ecdsa.PublicKey: + switch h := opts.HashFunc(); h { + case crypto.SHA256: + return keyvault.ES256, nil + case crypto.SHA384: + return keyvault.ES384, nil + case crypto.SHA512: + return keyvault.ES512, nil + default: + return "", errors.Errorf("unsupported hash function %v", h) + } + default: + return "", errors.Errorf("unsupported key type %T", key) + } +} diff --git a/kms/azurekms/utils.go b/kms/azurekms/utils.go new file mode 100644 index 00000000..2d99f6d3 --- /dev/null +++ b/kms/azurekms/utils.go @@ -0,0 +1,57 @@ +package azurekms + +import ( + "context" + "crypto" + "encoding/json" + "time" + + "github.com/Azure/azure-sdk-for-go/services/keyvault/v7.1/keyvault" + "github.com/pkg/errors" + "github.com/smallstep/certificates/kms/uri" + "go.step.sm/crypto/jose" +) + +// defaultContext returns the default context used in requests to azure. +func defaultContext() (context.Context, context.CancelFunc) { + return context.WithTimeout(context.Background(), 15*time.Second) +} + +// parseKeyName returns the key vault, name and version for urls like +// azurekms:vault=key-vault;id=key-name?version=key-version. If version is not +// passed the latest version will be used. +func parseKeyName(rawURI string) (vault, name, version string, err error) { + var u *uri.URI + + u, err = uri.ParseWithScheme("azurekms", rawURI) + if err != nil { + return + } + + if vault = u.Get("vault"); vault == "" { + err = errors.Errorf("key uri %s is not valid: vault is missing", rawURI) + return + } + if name = u.Get("id"); name == "" { + err = errors.Errorf("key uri %s is not valid: id is missing", rawURI) + return + } + version = u.Get("version") + return +} + +func vaultBaseURL(vault string) string { + return "https://" + vault + ".vault.azure.net/" +} + +func convertKey(key *keyvault.JSONWebKey) (crypto.PublicKey, error) { + b, err := json.Marshal(key) + if err != nil { + return nil, errors.Wrap(err, "error marshalling key") + } + var jwk jose.JSONWebKey + if err := jwk.UnmarshalJSON(b); err != nil { + return nil, errors.Wrap(err, "error unmarshalling key") + } + return jwk.Key, nil +} From d02cb1c8691f8b18929caa0bd679e381e24974a3 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Tue, 5 Oct 2021 17:09:40 -0700 Subject: [PATCH 142/195] Enable azurekms. --- cmd/step-ca/main.go | 1 + 1 file changed, 1 insertion(+) diff --git a/cmd/step-ca/main.go b/cmd/step-ca/main.go index aaf37df2..cc2fffc9 100644 --- a/cmd/step-ca/main.go +++ b/cmd/step-ca/main.go @@ -26,6 +26,7 @@ import ( // Enabled kms interfaces. _ "github.com/smallstep/certificates/kms/awskms" + _ "github.com/smallstep/certificates/kms/azurekms" _ "github.com/smallstep/certificates/kms/cloudkms" _ "github.com/smallstep/certificates/kms/softkms" _ "github.com/smallstep/certificates/kms/sshagentkms" From 97d08a1b61ec56e5aed80ad65985bc0defabdde8 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Tue, 5 Oct 2021 17:11:23 -0700 Subject: [PATCH 143/195] Fix typos. --- kms/azurekms/utils.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kms/azurekms/utils.go b/kms/azurekms/utils.go index 2d99f6d3..46263726 100644 --- a/kms/azurekms/utils.go +++ b/kms/azurekms/utils.go @@ -47,11 +47,11 @@ func vaultBaseURL(vault string) string { func convertKey(key *keyvault.JSONWebKey) (crypto.PublicKey, error) { b, err := json.Marshal(key) if err != nil { - return nil, errors.Wrap(err, "error marshalling key") + return nil, errors.Wrap(err, "error marshaling key") } var jwk jose.JSONWebKey if err := jwk.UnmarshalJSON(b); err != nil { - return nil, errors.Wrap(err, "error unmarshalling key") + return nil, errors.Wrap(err, "error unmarshaling key") } return jwk.Key, nil } From 63891003259ca1b3a85f7419187671e305f25d11 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Tue, 5 Oct 2021 20:35:52 -0700 Subject: [PATCH 144/195] Add unit tests for azurekms. --- go.mod | 2 +- go.sum | 3 +- .../internal/mock/key_vault_client.go | 80 +++ kms/azurekms/key_vault.go | 17 +- kms/azurekms/key_vault_test.go | 482 ++++++++++++++++++ kms/azurekms/signer.go | 15 +- kms/azurekms/signer_test.go | 329 ++++++++++++ 7 files changed, 920 insertions(+), 8 deletions(-) create mode 100644 kms/azurekms/internal/mock/key_vault_client.go create mode 100644 kms/azurekms/key_vault_test.go create mode 100644 kms/azurekms/signer_test.go diff --git a/go.mod b/go.mod index ddf51740..43590e4a 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,7 @@ require ( github.com/go-chi/chi v4.0.2+incompatible github.com/go-kit/kit v0.10.0 // indirect github.com/go-piv/piv-go v1.7.0 - github.com/golang/mock v1.5.0 + github.com/golang/mock v1.6.0 github.com/google/uuid v1.3.0 github.com/googleapis/gax-go/v2 v2.0.5 github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect diff --git a/go.sum b/go.sum index 5de2ab46..cf33febd 100644 --- a/go.sum +++ b/go.sum @@ -236,8 +236,9 @@ github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/mock v1.5.0 h1:jlYHihg//f7RRwuPfptm04yp4s7O6Kw8EZiVYIGcH0g= github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= +github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= diff --git a/kms/azurekms/internal/mock/key_vault_client.go b/kms/azurekms/internal/mock/key_vault_client.go new file mode 100644 index 00000000..42bd55fd --- /dev/null +++ b/kms/azurekms/internal/mock/key_vault_client.go @@ -0,0 +1,80 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: github.com/smallstep/certificates/kms/azurekms (interfaces: KeyVaultClient) + +// Package mock is a generated GoMock package. +package mock + +import ( + context "context" + keyvault "github.com/Azure/azure-sdk-for-go/services/keyvault/v7.1/keyvault" + gomock "github.com/golang/mock/gomock" + reflect "reflect" +) + +// KeyVaultClient is a mock of KeyVaultClient interface +type KeyVaultClient struct { + ctrl *gomock.Controller + recorder *KeyVaultClientMockRecorder +} + +// KeyVaultClientMockRecorder is the mock recorder for KeyVaultClient +type KeyVaultClientMockRecorder struct { + mock *KeyVaultClient +} + +// NewKeyVaultClient creates a new mock instance +func NewKeyVaultClient(ctrl *gomock.Controller) *KeyVaultClient { + mock := &KeyVaultClient{ctrl: ctrl} + mock.recorder = &KeyVaultClientMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use +func (m *KeyVaultClient) EXPECT() *KeyVaultClientMockRecorder { + return m.recorder +} + +// CreateKey mocks base method +func (m *KeyVaultClient) CreateKey(arg0 context.Context, arg1, arg2 string, arg3 keyvault.KeyCreateParameters) (keyvault.KeyBundle, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CreateKey", arg0, arg1, arg2, arg3) + ret0, _ := ret[0].(keyvault.KeyBundle) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// CreateKey indicates an expected call of CreateKey +func (mr *KeyVaultClientMockRecorder) CreateKey(arg0, arg1, arg2, arg3 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateKey", reflect.TypeOf((*KeyVaultClient)(nil).CreateKey), arg0, arg1, arg2, arg3) +} + +// GetKey mocks base method +func (m *KeyVaultClient) GetKey(arg0 context.Context, arg1, arg2, arg3 string) (keyvault.KeyBundle, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetKey", arg0, arg1, arg2, arg3) + ret0, _ := ret[0].(keyvault.KeyBundle) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetKey indicates an expected call of GetKey +func (mr *KeyVaultClientMockRecorder) GetKey(arg0, arg1, arg2, arg3 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetKey", reflect.TypeOf((*KeyVaultClient)(nil).GetKey), arg0, arg1, arg2, arg3) +} + +// Sign mocks base method +func (m *KeyVaultClient) Sign(arg0 context.Context, arg1, arg2, arg3 string, arg4 keyvault.KeySignParameters) (keyvault.KeyOperationResult, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Sign", arg0, arg1, arg2, arg3, arg4) + ret0, _ := ret[0].(keyvault.KeyOperationResult) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Sign indicates an expected call of Sign +func (mr *KeyVaultClientMockRecorder) Sign(arg0, arg1, arg2, arg3, arg4 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Sign", reflect.TypeOf((*KeyVaultClient)(nil).Sign), arg0, arg1, arg2, arg3, arg4) +} diff --git a/kms/azurekms/key_vault.go b/kms/azurekms/key_vault.go index 1b133c2e..dde368da 100644 --- a/kms/azurekms/key_vault.go +++ b/kms/azurekms/key_vault.go @@ -114,8 +114,7 @@ type KeyVault struct { baseClient KeyVaultClient } -// New initializes a new KMS implemented using Azure Key Vault. -func New(ctx context.Context, opts apiv1.Options) (*KeyVault, error) { +var createClient = func(ctx context.Context, opts apiv1.Options) (KeyVaultClient, error) { // Attempt to authorize with the following methods: // 1. Environment variables. // - Client credentials @@ -133,9 +132,17 @@ func New(ctx context.Context, opts apiv1.Options) (*KeyVault, error) { baseClient := keyvault.New() baseClient.Authorizer = authorizer + return &baseClient, nil +} +// New initializes a new KMS implemented using Azure Key Vault. +func New(ctx context.Context, opts apiv1.Options) (*KeyVault, error) { + baseClient, err := createClient(ctx, opts) + if err != nil { + return nil, err + } return &KeyVault{ - baseClient: &baseClient, + baseClient: baseClient, }, nil } @@ -164,6 +171,10 @@ func (k *KeyVault) GetPublicKey(req *apiv1.GetPublicKeyRequest) (crypto.PublicKe // CreateKey creates a asymmetric key in Azure Key Vault. func (k *KeyVault) CreateKey(req *apiv1.CreateKeyRequest) (*apiv1.CreateKeyResponse, error) { + if req.Name == "" { + return nil, errors.New("createKeyRequest 'name' cannot be empty") + } + vault, name, _, err := parseKeyName(req.Name) if err != nil { return nil, err diff --git a/kms/azurekms/key_vault_test.go b/kms/azurekms/key_vault_test.go new file mode 100644 index 00000000..b5b3597d --- /dev/null +++ b/kms/azurekms/key_vault_test.go @@ -0,0 +1,482 @@ +//go:generate mockgen -package mock -mock_names=KeyVaultClient=KeyVaultClient -destination internal/mock/key_vault_client.go github.com/smallstep/certificates/kms/azurekms KeyVaultClient +package azurekms + +import ( + "context" + "crypto" + "encoding/json" + "fmt" + "reflect" + "testing" + "time" + + "github.com/Azure/azure-sdk-for-go/services/keyvault/v7.1/keyvault" + "github.com/Azure/go-autorest/autorest/date" + "github.com/golang/mock/gomock" + "github.com/smallstep/certificates/kms/apiv1" + "github.com/smallstep/certificates/kms/azurekms/internal/mock" + "go.step.sm/crypto/keyutil" + "gopkg.in/square/go-jose.v2" +) + +var errTest = fmt.Errorf("test error") + +func mockNow(t *testing.T) time.Time { + old := now + t0 := time.Unix(1234567890, 123).UTC() + now = func() time.Time { + return t0 + } + t.Cleanup(func() { + now = old + }) + return t0 +} + +func mockClient(t *testing.T) *mock.KeyVaultClient { + t.Helper() + ctrl := gomock.NewController(t) + t.Cleanup(func() { + ctrl.Finish() + }) + return mock.NewKeyVaultClient(ctrl) +} + +func mockCreateClient(t *testing.T, ctrl *gomock.Controller) { + t.Helper() + old := createClient + + createClient = func(ctx context.Context, opts apiv1.Options) (KeyVaultClient, error) { + return mock.NewKeyVaultClient(ctrl), nil + } + + t.Cleanup(func() { + createClient = old + }) +} + +func createJWK(t *testing.T, pub crypto.PublicKey) *keyvault.JSONWebKey { + t.Helper() + b, err := json.Marshal(&jose.JSONWebKey{ + Key: pub, + }) + if err != nil { + t.Fatal(err) + } + key := new(keyvault.JSONWebKey) + if err := json.Unmarshal(b, key); err != nil { + t.Fatal(err) + } + return key +} + +func TestNew(t *testing.T) { + ctrl := gomock.NewController(t) + mockCreateClient(t, ctrl) + + type args struct { + ctx context.Context + opts apiv1.Options + } + tests := []struct { + name string + args args + want *KeyVault + wantErr bool + }{ + {"ok", args{context.Background(), apiv1.Options{}}, &KeyVault{ + baseClient: mock.NewKeyVaultClient(ctrl), + }, false}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := New(tt.args.ctx, tt.args.opts) + if (err != nil) != tt.wantErr { + t.Errorf("New() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("New() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestKeyVault_GetPublicKey(t *testing.T) { + key, err := keyutil.GenerateDefaultSigner() + if err != nil { + t.Fatal(err) + } + pub := key.Public() + jwk := createJWK(t, pub) + + client := mockClient(t) + client.EXPECT().GetKey(gomock.Any(), "https://my-vault.vault.azure.net/", "my-key", "").Return(keyvault.KeyBundle{ + Key: jwk, + }, nil) + client.EXPECT().GetKey(gomock.Any(), "https://my-vault.vault.azure.net/", "my-key", "my-version").Return(keyvault.KeyBundle{ + Key: jwk, + }, nil) + client.EXPECT().GetKey(gomock.Any(), "https://my-vault.vault.azure.net/", "not-found", "my-version").Return(keyvault.KeyBundle{}, errTest) + + type fields struct { + baseClient KeyVaultClient + } + type args struct { + req *apiv1.GetPublicKeyRequest + } + tests := []struct { + name string + fields fields + args args + want crypto.PublicKey + wantErr bool + }{ + {"ok", fields{client}, args{&apiv1.GetPublicKeyRequest{ + Name: "azurekms:vault=my-vault;id=my-key", + }}, pub, false}, + {"ok with version", fields{client}, args{&apiv1.GetPublicKeyRequest{ + Name: "azurekms:vault=my-vault;id=my-key?version=my-version", + }}, pub, false}, + {"fail GetKey", fields{client}, args{&apiv1.GetPublicKeyRequest{ + Name: "azurekms:vault=my-vault;id=not-found?version=my-version", + }}, nil, true}, + {"fail vault", fields{client}, args{&apiv1.GetPublicKeyRequest{ + Name: "azurekms:vault=;id=not-found?version=my-version", + }}, nil, true}, + {"fail id", fields{client}, args{&apiv1.GetPublicKeyRequest{ + Name: "azurekms:vault=;id=?version=my-version", + }}, nil, true}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + k := &KeyVault{ + baseClient: tt.fields.baseClient, + } + got, err := k.GetPublicKey(tt.args.req) + if (err != nil) != tt.wantErr { + t.Errorf("KeyVault.GetPublicKey() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("KeyVault.GetPublicKey() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestKeyVault_CreateKey(t *testing.T) { + ecKey, err := keyutil.GenerateDefaultSigner() + if err != nil { + t.Fatal(err) + } + rsaKey, err := keyutil.GenerateSigner("RSA", "", 2048) + if err != nil { + t.Fatal(err) + } + ecPub := ecKey.Public() + rsaPub := rsaKey.Public() + ecJWK := createJWK(t, ecPub) + rsaJWK := createJWK(t, rsaPub) + + t0 := date.UnixTime(mockNow(t)) + client := mockClient(t) + + expects := []struct { + Name string + Kty keyvault.JSONWebKeyType + KeySize *int32 + Curve keyvault.JSONWebKeyCurveName + Key *keyvault.JSONWebKey + }{ + {"P-256", keyvault.EC, nil, keyvault.P256, ecJWK}, + {"P-256 HSM", keyvault.ECHSM, nil, keyvault.P256, ecJWK}, + {"P-256 Default", keyvault.EC, nil, keyvault.P256, ecJWK}, + {"P-384", keyvault.EC, nil, keyvault.P384, ecJWK}, + {"P-521", keyvault.EC, nil, keyvault.P521, ecJWK}, + {"RSA 0", keyvault.RSA, &value3072, "", rsaJWK}, + {"RSA 0 HSM", keyvault.RSAHSM, &value3072, "", rsaJWK}, + {"RSA 2048", keyvault.RSA, &value2048, "", rsaJWK}, + {"RSA 3072", keyvault.RSA, &value3072, "", rsaJWK}, + {"RSA 4096", keyvault.RSA, &value4096, "", rsaJWK}, + } + + for _, e := range expects { + client.EXPECT().CreateKey(gomock.Any(), "https://my-vault.vault.azure.net/", "my-key", keyvault.KeyCreateParameters{ + Kty: e.Kty, + KeySize: e.KeySize, + Curve: e.Curve, + KeyOps: &[]keyvault.JSONWebKeyOperation{ + keyvault.Sign, keyvault.Verify, + }, + KeyAttributes: &keyvault.KeyAttributes{ + Enabled: &valueTrue, + Created: &t0, + NotBefore: &t0, + }, + }).Return(keyvault.KeyBundle{ + Key: e.Key, + }, nil) + } + client.EXPECT().CreateKey(gomock.Any(), "https://my-vault.vault.azure.net/", "not-found", gomock.Any()).Return(keyvault.KeyBundle{}, errTest) + client.EXPECT().CreateKey(gomock.Any(), "https://my-vault.vault.azure.net/", "not-found", gomock.Any()).Return(keyvault.KeyBundle{ + Key: nil, + }, nil) + + type fields struct { + baseClient KeyVaultClient + } + type args struct { + req *apiv1.CreateKeyRequest + } + tests := []struct { + name string + fields fields + args args + want *apiv1.CreateKeyResponse + wantErr bool + }{ + {"ok P-256", fields{client}, args{&apiv1.CreateKeyRequest{ + Name: "azurekms:vault=my-vault;id=my-key", + SignatureAlgorithm: apiv1.ECDSAWithSHA256, + ProtectionLevel: apiv1.Software, + }}, &apiv1.CreateKeyResponse{ + Name: "azurekms:id=my-key;vault=my-vault", + PublicKey: ecPub, + CreateSignerRequest: apiv1.CreateSignerRequest{ + SigningKey: "azurekms:id=my-key;vault=my-vault", + }, + }, false}, + {"ok P-256 HSM", fields{client}, args{&apiv1.CreateKeyRequest{ + Name: "azurekms:vault=my-vault;id=my-key", + SignatureAlgorithm: apiv1.ECDSAWithSHA256, + ProtectionLevel: apiv1.HSM, + }}, &apiv1.CreateKeyResponse{ + Name: "azurekms:id=my-key;vault=my-vault", + PublicKey: ecPub, + CreateSignerRequest: apiv1.CreateSignerRequest{ + SigningKey: "azurekms:id=my-key;vault=my-vault", + }, + }, false}, + {"ok P-256 Default", fields{client}, args{&apiv1.CreateKeyRequest{ + Name: "azurekms:vault=my-vault;id=my-key", + }}, &apiv1.CreateKeyResponse{ + Name: "azurekms:id=my-key;vault=my-vault", + PublicKey: ecPub, + CreateSignerRequest: apiv1.CreateSignerRequest{ + SigningKey: "azurekms:id=my-key;vault=my-vault", + }, + }, false}, + {"ok P-384", fields{client}, args{&apiv1.CreateKeyRequest{ + Name: "azurekms:vault=my-vault;id=my-key", + SignatureAlgorithm: apiv1.ECDSAWithSHA384, + }}, &apiv1.CreateKeyResponse{ + Name: "azurekms:id=my-key;vault=my-vault", + PublicKey: ecPub, + CreateSignerRequest: apiv1.CreateSignerRequest{ + SigningKey: "azurekms:id=my-key;vault=my-vault", + }, + }, false}, + {"ok P-521", fields{client}, args{&apiv1.CreateKeyRequest{ + Name: "azurekms:vault=my-vault;id=my-key", + SignatureAlgorithm: apiv1.ECDSAWithSHA512, + }}, &apiv1.CreateKeyResponse{ + Name: "azurekms:id=my-key;vault=my-vault", + PublicKey: ecPub, + CreateSignerRequest: apiv1.CreateSignerRequest{ + SigningKey: "azurekms:id=my-key;vault=my-vault", + }, + }, false}, + {"ok RSA 0", fields{client}, args{&apiv1.CreateKeyRequest{ + Name: "azurekms:vault=my-vault;id=my-key", + Bits: 0, + SignatureAlgorithm: apiv1.SHA256WithRSA, + ProtectionLevel: apiv1.Software, + }}, &apiv1.CreateKeyResponse{ + Name: "azurekms:id=my-key;vault=my-vault", + PublicKey: rsaPub, + CreateSignerRequest: apiv1.CreateSignerRequest{ + SigningKey: "azurekms:id=my-key;vault=my-vault", + }, + }, false}, + {"ok RSA 0 HSM", fields{client}, args{&apiv1.CreateKeyRequest{ + Name: "azurekms:vault=my-vault;id=my-key", + Bits: 0, + SignatureAlgorithm: apiv1.SHA256WithRSAPSS, + ProtectionLevel: apiv1.HSM, + }}, &apiv1.CreateKeyResponse{ + Name: "azurekms:id=my-key;vault=my-vault", + PublicKey: rsaPub, + CreateSignerRequest: apiv1.CreateSignerRequest{ + SigningKey: "azurekms:id=my-key;vault=my-vault", + }, + }, false}, + {"ok RSA 2048", fields{client}, args{&apiv1.CreateKeyRequest{ + Name: "azurekms:vault=my-vault;id=my-key", + Bits: 2048, + SignatureAlgorithm: apiv1.SHA384WithRSA, + }}, &apiv1.CreateKeyResponse{ + Name: "azurekms:id=my-key;vault=my-vault", + PublicKey: rsaPub, + CreateSignerRequest: apiv1.CreateSignerRequest{ + SigningKey: "azurekms:id=my-key;vault=my-vault", + }, + }, false}, + {"ok RSA 3072", fields{client}, args{&apiv1.CreateKeyRequest{ + Name: "azurekms:vault=my-vault;id=my-key", + Bits: 3072, + SignatureAlgorithm: apiv1.SHA512WithRSA, + }}, &apiv1.CreateKeyResponse{ + Name: "azurekms:id=my-key;vault=my-vault", + PublicKey: rsaPub, + CreateSignerRequest: apiv1.CreateSignerRequest{ + SigningKey: "azurekms:id=my-key;vault=my-vault", + }, + }, false}, + {"ok RSA 4096", fields{client}, args{&apiv1.CreateKeyRequest{ + Name: "azurekms:vault=my-vault;id=my-key", + Bits: 4096, + SignatureAlgorithm: apiv1.SHA512WithRSAPSS, + }}, &apiv1.CreateKeyResponse{ + Name: "azurekms:id=my-key;vault=my-vault", + PublicKey: rsaPub, + CreateSignerRequest: apiv1.CreateSignerRequest{ + SigningKey: "azurekms:id=my-key;vault=my-vault", + }, + }, false}, + {"fail createKey", fields{client}, args{&apiv1.CreateKeyRequest{ + Name: "azurekms:vault=my-vault;id=not-found", + SignatureAlgorithm: apiv1.ECDSAWithSHA256, + }}, nil, true}, + {"fail convertKey", fields{client}, args{&apiv1.CreateKeyRequest{ + Name: "azurekms:vault=my-vault;id=not-found", + SignatureAlgorithm: apiv1.ECDSAWithSHA256, + }}, nil, true}, + {"fail name", fields{client}, args{&apiv1.CreateKeyRequest{ + Name: "", + }}, nil, true}, + {"fail vault", fields{client}, args{&apiv1.CreateKeyRequest{ + Name: "azurekms:vault=;id=not-found?version=my-version", + }}, nil, true}, + {"fail id", fields{client}, args{&apiv1.CreateKeyRequest{ + Name: "azurekms:vault=my-vault;id=?version=my-version", + }}, nil, true}, + {"fail SignatureAlgorithm", fields{client}, args{&apiv1.CreateKeyRequest{ + Name: "azurekms:vault=my-vault;id=not-found", + SignatureAlgorithm: apiv1.PureEd25519, + }}, nil, true}, + {"fail bit size", fields{client}, args{&apiv1.CreateKeyRequest{ + Name: "azurekms:vault=my-vault;id=not-found", + SignatureAlgorithm: apiv1.SHA384WithRSAPSS, + Bits: 1024, + }}, nil, true}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + k := &KeyVault{ + baseClient: tt.fields.baseClient, + } + got, err := k.CreateKey(tt.args.req) + if (err != nil) != tt.wantErr { + t.Errorf("KeyVault.CreateKey() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("KeyVault.CreateKey() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestKeyVault_CreateSigner(t *testing.T) { + key, err := keyutil.GenerateDefaultSigner() + if err != nil { + t.Fatal(err) + } + pub := key.Public() + jwk := createJWK(t, pub) + + client := mockClient(t) + client.EXPECT().GetKey(gomock.Any(), "https://my-vault.vault.azure.net/", "my-key", "").Return(keyvault.KeyBundle{ + Key: jwk, + }, nil) + client.EXPECT().GetKey(gomock.Any(), "https://my-vault.vault.azure.net/", "my-key", "my-version").Return(keyvault.KeyBundle{ + Key: jwk, + }, nil) + client.EXPECT().GetKey(gomock.Any(), "https://my-vault.vault.azure.net/", "not-found", "my-version").Return(keyvault.KeyBundle{}, errTest) + + type fields struct { + baseClient KeyVaultClient + } + type args struct { + req *apiv1.CreateSignerRequest + } + tests := []struct { + name string + fields fields + args args + want crypto.Signer + wantErr bool + }{ + {"ok", fields{client}, args{&apiv1.CreateSignerRequest{ + SigningKey: "azurekms:vault=my-vault;id=my-key", + }}, &Signer{ + client: client, + vaultBaseURL: "https://my-vault.vault.azure.net/", + name: "my-key", + version: "", + publicKey: pub, + }, false}, + {"ok with version", fields{client}, args{&apiv1.CreateSignerRequest{ + SigningKey: "azurekms:vault=my-vault;id=my-key;version=my-version", + }}, &Signer{ + client: client, + vaultBaseURL: "https://my-vault.vault.azure.net/", + name: "my-key", + version: "my-version", + publicKey: pub, + }, false}, + {"fail GetKey", fields{client}, args{&apiv1.CreateSignerRequest{ + SigningKey: "azurekms:vault=my-vault;id=not-found;version=my-version", + }}, nil, true}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + k := &KeyVault{ + baseClient: tt.fields.baseClient, + } + got, err := k.CreateSigner(tt.args.req) + if (err != nil) != tt.wantErr { + t.Errorf("KeyVault.CreateSigner() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("KeyVault.CreateSigner() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestKeyVault_Close(t *testing.T) { + client := mockClient(t) + type fields struct { + baseClient KeyVaultClient + } + tests := []struct { + name string + fields fields + wantErr bool + }{ + {"ok", fields{client}, false}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + k := &KeyVault{ + baseClient: tt.fields.baseClient, + } + if err := k.Close(); (err != nil) != tt.wantErr { + t.Errorf("KeyVault.Close() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/kms/azurekms/signer.go b/kms/azurekms/signer.go index 217c6258..cb844bdf 100644 --- a/kms/azurekms/signer.go +++ b/kms/azurekms/signer.go @@ -24,7 +24,7 @@ type Signer struct { } // NewSigner creates a new signer using a key in the AWS KMS. -func NewSigner(client KeyVaultClient, signingKey string) (*Signer, error) { +func NewSigner(client KeyVaultClient, signingKey string) (crypto.Signer, error) { vault, name, version, err := parseKeyName(signingKey) if err != nil { return nil, err @@ -114,8 +114,17 @@ func (s *Signer) Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts) ([] func getSigningAlgorithm(key crypto.PublicKey, opts crypto.SignerOpts) (keyvault.JSONWebKeySignatureAlgorithm, error) { switch key.(type) { case *rsa.PublicKey: - _, isPSS := opts.(*rsa.PSSOptions) - switch h := opts.HashFunc(); h { + hashFunc := opts.HashFunc() + pss, isPSS := opts.(*rsa.PSSOptions) + // Random salt lengths are not supported + if isPSS && + pss.SaltLength != rsa.PSSSaltLengthAuto && + pss.SaltLength != rsa.PSSSaltLengthEqualsHash && + pss.SaltLength != hashFunc.Size() { + return "", errors.Errorf("unsupported RSA-PSS salt length %d", pss.SaltLength) + } + + switch h := hashFunc; h { case crypto.SHA256: if isPSS { return keyvault.PS256, nil diff --git a/kms/azurekms/signer_test.go b/kms/azurekms/signer_test.go new file mode 100644 index 00000000..798d69f9 --- /dev/null +++ b/kms/azurekms/signer_test.go @@ -0,0 +1,329 @@ +package azurekms + +import ( + "crypto" + "crypto/ecdsa" + "crypto/rand" + "crypto/rsa" + "encoding/base64" + "io" + "reflect" + "testing" + + "github.com/Azure/azure-sdk-for-go/services/keyvault/v7.1/keyvault" + "github.com/golang/mock/gomock" + "go.step.sm/crypto/keyutil" + "golang.org/x/crypto/cryptobyte" + "golang.org/x/crypto/cryptobyte/asn1" +) + +func TestNewSigner(t *testing.T) { + key, err := keyutil.GenerateDefaultSigner() + if err != nil { + t.Fatal(err) + } + pub := key.Public() + jwk := createJWK(t, pub) + + client := mockClient(t) + client.EXPECT().GetKey(gomock.Any(), "https://my-vault.vault.azure.net/", "my-key", "").Return(keyvault.KeyBundle{ + Key: jwk, + }, nil) + client.EXPECT().GetKey(gomock.Any(), "https://my-vault.vault.azure.net/", "my-key", "my-version").Return(keyvault.KeyBundle{ + Key: jwk, + }, nil) + client.EXPECT().GetKey(gomock.Any(), "https://my-vault.vault.azure.net/", "not-found", "my-version").Return(keyvault.KeyBundle{}, errTest) + + type args struct { + client KeyVaultClient + signingKey string + } + tests := []struct { + name string + args args + want crypto.Signer + wantErr bool + }{ + {"ok", args{client, "azurekms:vault=my-vault;id=my-key"}, &Signer{ + client: client, + vaultBaseURL: "https://my-vault.vault.azure.net/", + name: "my-key", + version: "", + publicKey: pub, + }, false}, + {"ok with version", args{client, "azurekms:id=my-key;vault=my-vault?version=my-version"}, &Signer{ + client: client, + vaultBaseURL: "https://my-vault.vault.azure.net/", + name: "my-key", + version: "my-version", + publicKey: pub, + }, false}, + {"fail GetKey", args{client, "azurekms:id=not-found;vault=my-vault?version=my-version"}, nil, true}, + {"fail vault", args{client, "azurekms:id=not-found;vault="}, nil, true}, + {"fail id", args{client, "azurekms:id=;vault=my-vault?version=my-version"}, nil, true}, + {"fail scheme", args{client, "kms:id=not-found;vault=my-vault?version=my-version"}, nil, true}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := NewSigner(tt.args.client, tt.args.signingKey) + if (err != nil) != tt.wantErr { + t.Errorf("NewSigner() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("NewSigner() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestSigner_Public(t *testing.T) { + key, err := keyutil.GenerateDefaultSigner() + if err != nil { + t.Fatal(err) + } + pub := key.Public() + + type fields struct { + publicKey crypto.PublicKey + } + tests := []struct { + name string + fields fields + want crypto.PublicKey + }{ + {"ok", fields{pub}, pub}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + s := &Signer{ + publicKey: tt.fields.publicKey, + } + if got := s.Public(); !reflect.DeepEqual(got, tt.want) { + t.Errorf("Signer.Public() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestSigner_Sign(t *testing.T) { + sign := func(kty, crv string, bits int, opts crypto.SignerOpts) (crypto.PublicKey, []byte, string, []byte) { + key, err := keyutil.GenerateSigner(kty, crv, bits) + if err != nil { + t.Fatal(err) + } + h := opts.HashFunc().New() + h.Write([]byte("random-data")) + sum := h.Sum(nil) + + var sig, resultSig []byte + if priv, ok := key.(*ecdsa.PrivateKey); ok { + r, s, err := ecdsa.Sign(rand.Reader, priv, sum) + if err != nil { + t.Fatal(err) + } + curveBits := priv.Params().BitSize + keyBytes := curveBits / 8 + if curveBits%8 > 0 { + keyBytes++ + } + rBytes := r.Bytes() + rBytesPadded := make([]byte, keyBytes) + copy(rBytesPadded[keyBytes-len(rBytes):], rBytes) + + sBytes := s.Bytes() + sBytesPadded := make([]byte, keyBytes) + copy(sBytesPadded[keyBytes-len(sBytes):], sBytes) + resultSig = append(rBytesPadded, sBytesPadded...) + + var b cryptobyte.Builder + b.AddASN1(asn1.SEQUENCE, func(b *cryptobyte.Builder) { + b.AddASN1BigInt(r) + b.AddASN1BigInt(s) + }) + sig, err = b.Bytes() + if err != nil { + t.Fatal(err) + } + } else { + sig, err = key.Sign(rand.Reader, sum, opts) + if err != nil { + t.Fatal(err) + } + resultSig = sig + } + + return key.Public(), h.Sum(nil), base64.RawURLEncoding.EncodeToString(resultSig), sig + } + + p256, p256Digest, p256ResultSig, p256Sig := sign("EC", "P-256", 0, crypto.SHA256) + p384, p384Digest, p386ResultSig, p384Sig := sign("EC", "P-384", 0, crypto.SHA384) + p521, p521Digest, p521ResultSig, p521Sig := sign("EC", "P-521", 0, crypto.SHA512) + rsaSHA256, rsaSHA256Digest, rsaSHA256ResultSig, rsaSHA256Sig := sign("RSA", "", 2048, crypto.SHA256) + rsaSHA384, rsaSHA384Digest, rsaSHA384ResultSig, rsaSHA384Sig := sign("RSA", "", 2048, crypto.SHA384) + rsaSHA512, rsaSHA512Digest, rsaSHA512ResultSig, rsaSHA512Sig := sign("RSA", "", 2048, crypto.SHA512) + rsaPSSSHA256, rsaPSSSHA256Digest, rsaPSSSHA256ResultSig, rsaPSSSHA256Sig := sign("RSA", "", 2048, &rsa.PSSOptions{ + SaltLength: rsa.PSSSaltLengthAuto, + Hash: crypto.SHA256, + }) + rsaPSSSHA384, rsaPSSSHA384Digest, rsaPSSSHA384ResultSig, rsaPSSSHA384Sig := sign("RSA", "", 2048, &rsa.PSSOptions{ + SaltLength: rsa.PSSSaltLengthAuto, + Hash: crypto.SHA512, + }) + rsaPSSSHA512, rsaPSSSHA512Digest, rsaPSSSHA512ResultSig, rsaPSSSHA512Sig := sign("RSA", "", 2048, &rsa.PSSOptions{ + SaltLength: rsa.PSSSaltLengthAuto, + Hash: crypto.SHA512, + }) + + ed25519Key, err := keyutil.GenerateSigner("OKP", "Ed25519", 0) + if err != nil { + t.Fatal(err) + } + + client := mockClient(t) + expects := []struct { + name string + keyVersion string + alg keyvault.JSONWebKeySignatureAlgorithm + digest []byte + result keyvault.KeyOperationResult + err error + }{ + {"P-256", "", keyvault.ES256, p256Digest, keyvault.KeyOperationResult{ + Result: &p256ResultSig, + }, nil}, + {"P-384", "my-version", keyvault.ES384, p384Digest, keyvault.KeyOperationResult{ + Result: &p386ResultSig, + }, nil}, + {"P-521", "my-version", keyvault.ES512, p521Digest, keyvault.KeyOperationResult{ + Result: &p521ResultSig, + }, nil}, + {"RSA SHA256", "", keyvault.RS256, rsaSHA256Digest, keyvault.KeyOperationResult{ + Result: &rsaSHA256ResultSig, + }, nil}, + {"RSA SHA384", "", keyvault.RS384, rsaSHA384Digest, keyvault.KeyOperationResult{ + Result: &rsaSHA384ResultSig, + }, nil}, + {"RSA SHA512", "", keyvault.RS512, rsaSHA512Digest, keyvault.KeyOperationResult{ + Result: &rsaSHA512ResultSig, + }, nil}, + {"RSA-PSS SHA256", "", keyvault.PS256, rsaPSSSHA256Digest, keyvault.KeyOperationResult{ + Result: &rsaPSSSHA256ResultSig, + }, nil}, + {"RSA-PSS SHA384", "", keyvault.PS384, rsaPSSSHA384Digest, keyvault.KeyOperationResult{ + Result: &rsaPSSSHA384ResultSig, + }, nil}, + {"RSA-PSS SHA512", "", keyvault.PS512, rsaPSSSHA512Digest, keyvault.KeyOperationResult{ + Result: &rsaPSSSHA512ResultSig, + }, nil}, + // Errors + {"fail Sign", "", keyvault.RS256, rsaSHA256Digest, keyvault.KeyOperationResult{}, errTest}, + {"fail sign length", "", keyvault.ES256, p256Digest, keyvault.KeyOperationResult{ + Result: &rsaSHA256ResultSig, + }, nil}, + } + for _, e := range expects { + value := base64.RawURLEncoding.EncodeToString(e.digest) + client.EXPECT().Sign(gomock.Any(), "https://my-vault.vault.azure.net/", "my-key", e.keyVersion, keyvault.KeySignParameters{ + Algorithm: e.alg, + Value: &value, + }).Return(e.result, e.err) + } + + type fields struct { + client KeyVaultClient + vaultBaseURL string + name string + version string + publicKey crypto.PublicKey + } + type args struct { + rand io.Reader + digest []byte + opts crypto.SignerOpts + } + tests := []struct { + name string + fields fields + args args + want []byte + wantErr bool + }{ + {"ok P-256", fields{client, "https://my-vault.vault.azure.net/", "my-key", "", p256}, args{ + rand.Reader, p256Digest[:], crypto.SHA256, + }, p256Sig, false}, + {"ok P-384", fields{client, "https://my-vault.vault.azure.net/", "my-key", "my-version", p384}, args{ + rand.Reader, p384Digest[:], crypto.SHA384, + }, p384Sig, false}, + {"ok P-521", fields{client, "https://my-vault.vault.azure.net/", "my-key", "my-version", p521}, args{ + rand.Reader, p521Digest[:], crypto.SHA512, + }, p521Sig, false}, + {"ok RSA SHA256", fields{client, "https://my-vault.vault.azure.net/", "my-key", "", rsaSHA256}, args{ + rand.Reader, rsaSHA256Digest[:], crypto.SHA256, + }, rsaSHA256Sig, false}, + {"ok RSA SHA384", fields{client, "https://my-vault.vault.azure.net/", "my-key", "", rsaSHA384}, args{ + rand.Reader, rsaSHA384Digest[:], crypto.SHA384, + }, rsaSHA384Sig, false}, + {"ok RSA SHA512", fields{client, "https://my-vault.vault.azure.net/", "my-key", "", rsaSHA512}, args{ + rand.Reader, rsaSHA512Digest[:], crypto.SHA512, + }, rsaSHA512Sig, false}, + {"ok RSA-PSS SHA256", fields{client, "https://my-vault.vault.azure.net/", "my-key", "", rsaPSSSHA256}, args{ + rand.Reader, rsaPSSSHA256Digest[:], &rsa.PSSOptions{ + SaltLength: rsa.PSSSaltLengthAuto, + Hash: crypto.SHA256, + }, + }, rsaPSSSHA256Sig, false}, + {"ok RSA-PSS SHA384", fields{client, "https://my-vault.vault.azure.net/", "my-key", "", rsaPSSSHA384}, args{ + rand.Reader, rsaPSSSHA384Digest[:], &rsa.PSSOptions{ + SaltLength: rsa.PSSSaltLengthEqualsHash, + Hash: crypto.SHA384, + }, + }, rsaPSSSHA384Sig, false}, + {"ok RSA-PSS SHA512", fields{client, "https://my-vault.vault.azure.net/", "my-key", "", rsaPSSSHA512}, args{ + rand.Reader, rsaPSSSHA512Digest[:], &rsa.PSSOptions{ + SaltLength: 64, + Hash: crypto.SHA512, + }, + }, rsaPSSSHA512Sig, false}, + {"fail Sign", fields{client, "https://my-vault.vault.azure.net/", "my-key", "", rsaSHA256}, args{ + rand.Reader, rsaSHA256Digest[:], crypto.SHA256, + }, nil, true}, + {"fail sign length", fields{client, "https://my-vault.vault.azure.net/", "my-key", "", p256}, args{ + rand.Reader, p256Digest[:], crypto.SHA256, + }, nil, true}, + {"fail RSA-PSS salt length", fields{client, "https://my-vault.vault.azure.net/", "my-key", "", rsaPSSSHA256}, args{ + rand.Reader, rsaPSSSHA256Digest[:], &rsa.PSSOptions{ + SaltLength: 64, + Hash: crypto.SHA256, + }, + }, nil, true}, + {"fail RSA Hash", fields{client, "https://my-vault.vault.azure.net/", "my-key", "", rsaSHA256}, args{ + rand.Reader, rsaSHA256Digest[:], crypto.SHA1, + }, nil, true}, + {"fail ECDSA Hash", fields{client, "https://my-vault.vault.azure.net/", "my-key", "", p256}, args{ + rand.Reader, p256Digest[:], crypto.MD5, + }, nil, true}, + {"fail Ed25519", fields{client, "https://my-vault.vault.azure.net/", "my-key", "", ed25519Key}, args{ + rand.Reader, []byte("message"), crypto.Hash(0), + }, nil, true}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + s := &Signer{ + client: tt.fields.client, + vaultBaseURL: tt.fields.vaultBaseURL, + name: tt.fields.name, + version: tt.fields.version, + publicKey: tt.fields.publicKey, + } + got, err := s.Sign(tt.args.rand, tt.args.digest, tt.args.opts) + if (err != nil) != tt.wantErr { + t.Errorf("Signer.Sign() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("Signer.Sign() = %v, want %v", got, tt.want) + } + }) + } +} From 56c3559e52f9135c43e22756e66ba46eb3b9290b Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Tue, 5 Oct 2021 20:41:55 -0700 Subject: [PATCH 145/195] Add some extra coverage. --- kms/azurekms/key_vault_test.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/kms/azurekms/key_vault_test.go b/kms/azurekms/key_vault_test.go index b5b3597d..92048246 100644 --- a/kms/azurekms/key_vault_test.go +++ b/kms/azurekms/key_vault_test.go @@ -70,6 +70,13 @@ func createJWK(t *testing.T, pub crypto.PublicKey) *keyvault.JSONWebKey { return key } +func Test_now(t *testing.T) { + t0 := now() + if loc := t0.Location(); loc != time.UTC { + t.Errorf("now() Location = %v, want %v", loc, time.UTC) + } +} + func TestNew(t *testing.T) { ctrl := gomock.NewController(t) mockCreateClient(t, ctrl) @@ -439,6 +446,9 @@ func TestKeyVault_CreateSigner(t *testing.T) { {"fail GetKey", fields{client}, args{&apiv1.CreateSignerRequest{ SigningKey: "azurekms:vault=my-vault;id=not-found;version=my-version", }}, nil, true}, + {"fail SigningKey", fields{client}, args{&apiv1.CreateSignerRequest{ + SigningKey: "", + }}, nil, true}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { From 656099c4f0c3f937894dd9222c0dc7cec44badac Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Wed, 6 Oct 2021 18:38:32 -0700 Subject: [PATCH 146/195] Add type for azurekms. --- kms/apiv1/options.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/kms/apiv1/options.go b/kms/apiv1/options.go index 7cc7f748..37c1fd4c 100644 --- a/kms/apiv1/options.go +++ b/kms/apiv1/options.go @@ -73,6 +73,8 @@ const ( YubiKey Type = "yubikey" // SSHAgentKMS is a KMS implementation using ssh-agent to access keys. SSHAgentKMS Type = "sshagentkms" + // AzureKMS is a KMS implementation using Azure Key Vault. + AzureKMS Type = "azurekms" ) // Options are the KMS options. They represent the kms object in the ca.json. @@ -118,8 +120,9 @@ func (o *Options) Validate() error { switch Type(strings.ToLower(o.Type)) { case DefaultKMS, SoftKMS: // Go crypto based kms. - case CloudKMS, AmazonKMS, SSHAgentKMS: // Cloud based kms. + case CloudKMS, AmazonKMS, AzureKMS: // Cloud based kms. case YubiKey, PKCS11: // Hardware based kms. + case SSHAgentKMS: // Others default: return errors.Errorf("unsupported kms type %s", o.Type) } From d2581489a38d18765611ef38bf0634bc949139e0 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Wed, 6 Oct 2021 18:39:12 -0700 Subject: [PATCH 147/195] Redefine uris and set proper type. URIs will now have the form: - azurekms:name=my-key;vault=my-vault - azurekms:name=my-key;vault=my-vault?version=my-version --- kms/azurekms/key_vault.go | 25 ++++++---- kms/azurekms/key_vault_test.go | 88 +++++++++++++++++----------------- kms/azurekms/signer_test.go | 12 ++--- kms/azurekms/utils.go | 42 ++++++++++++---- kms/azurekms/utils_test.go | 83 ++++++++++++++++++++++++++++++++ 5 files changed, 184 insertions(+), 66 deletions(-) create mode 100644 kms/azurekms/utils_test.go diff --git a/kms/azurekms/key_vault.go b/kms/azurekms/key_vault.go index dde368da..f7b00ec7 100644 --- a/kms/azurekms/key_vault.go +++ b/kms/azurekms/key_vault.go @@ -3,7 +3,7 @@ package azurekms import ( "context" "crypto" - "net/url" + "regexp" "time" "github.com/Azure/azure-sdk-for-go/services/keyvault/v7.1/keyvault" @@ -11,11 +11,10 @@ import ( "github.com/Azure/go-autorest/autorest/date" "github.com/pkg/errors" "github.com/smallstep/certificates/kms/apiv1" - "github.com/smallstep/certificates/kms/uri" ) func init() { - apiv1.Register(apiv1.CloudKMS, func(ctx context.Context, opts apiv1.Options) (apiv1.KeyManager, error) { + apiv1.Register(apiv1.AzureKMS, func(ctx context.Context, opts apiv1.Options) (apiv1.KeyManager, error) { return New(ctx, opts) }) } @@ -23,6 +22,10 @@ func init() { // Scheme is the scheme used for Azure Key Vault uris. const Scheme = "azurekms" +// keyIDRegexp is the regular experssion that Key Vault uses for on the kid. We +// can extract the vault, name and version of the key. +var keyIDRegexp = regexp.MustCompile("^https://([0-9a-zA-Z-]+).vault.azure.net/keys/([0-9a-zA-Z-]+)/([0-9a-zA-Z-]+)$") + var ( valueTrue = true value2048 int32 = 2048 @@ -107,6 +110,16 @@ type KeyVaultClient interface { // KeyVault implements a KMS using Azure Key Vault. // +// The URI format used in Azure Key Vault is the following: +// +// - azurekms:name=key-name;vault=vault-name +// - azurekms:name=key-name;vault=vault-name?version=key-version +// +// The scheme is "azurekms"; "name" is the key name; "vault" is the key vault +// name where the key is located; "version" is an optional parameter that +// defines the version of they key, if version is not given, the latest one will +// be used. +// // TODO(mariano): The implementation is using /services/keyvault/v7.1/keyvault // package, at some point Azure might create a keyvault client with all the // functionality in /sdk/keyvault, we should migrate to that once available. @@ -220,16 +233,12 @@ func (k *KeyVault) CreateKey(req *apiv1.CreateKeyRequest) (*apiv1.CreateKeyRespo return nil, errors.Wrap(err, "keyVault CreateKey failed") } - keyURI := uri.New("azurekms", url.Values{ - "vault": []string{vault}, - "id": []string{name}, - }).String() - publicKey, err := convertKey(resp.Key) if err != nil { return nil, err } + keyURI := getKeyName(vault, name, resp) return &apiv1.CreateKeyResponse{ Name: keyURI, PublicKey: publicKey, diff --git a/kms/azurekms/key_vault_test.go b/kms/azurekms/key_vault_test.go index 92048246..1f09b2d5 100644 --- a/kms/azurekms/key_vault_test.go +++ b/kms/azurekms/key_vault_test.go @@ -140,19 +140,19 @@ func TestKeyVault_GetPublicKey(t *testing.T) { wantErr bool }{ {"ok", fields{client}, args{&apiv1.GetPublicKeyRequest{ - Name: "azurekms:vault=my-vault;id=my-key", + Name: "azurekms:vault=my-vault;name=my-key", }}, pub, false}, {"ok with version", fields{client}, args{&apiv1.GetPublicKeyRequest{ - Name: "azurekms:vault=my-vault;id=my-key?version=my-version", + Name: "azurekms:vault=my-vault;name=my-key?version=my-version", }}, pub, false}, {"fail GetKey", fields{client}, args{&apiv1.GetPublicKeyRequest{ - Name: "azurekms:vault=my-vault;id=not-found?version=my-version", + Name: "azurekms:vault=my-vault;name=not-found?version=my-version", }}, nil, true}, {"fail vault", fields{client}, args{&apiv1.GetPublicKeyRequest{ - Name: "azurekms:vault=;id=not-found?version=my-version", + Name: "azurekms:vault=;name=not-found?version=my-version", }}, nil, true}, {"fail id", fields{client}, args{&apiv1.GetPublicKeyRequest{ - Name: "azurekms:vault=;id=?version=my-version", + Name: "azurekms:vault=;name=?version=my-version", }}, nil, true}, } for _, tt := range tests { @@ -244,136 +244,136 @@ func TestKeyVault_CreateKey(t *testing.T) { wantErr bool }{ {"ok P-256", fields{client}, args{&apiv1.CreateKeyRequest{ - Name: "azurekms:vault=my-vault;id=my-key", + Name: "azurekms:vault=my-vault;name=my-key", SignatureAlgorithm: apiv1.ECDSAWithSHA256, ProtectionLevel: apiv1.Software, }}, &apiv1.CreateKeyResponse{ - Name: "azurekms:id=my-key;vault=my-vault", + Name: "azurekms:name=my-key;vault=my-vault", PublicKey: ecPub, CreateSignerRequest: apiv1.CreateSignerRequest{ - SigningKey: "azurekms:id=my-key;vault=my-vault", + SigningKey: "azurekms:name=my-key;vault=my-vault", }, }, false}, {"ok P-256 HSM", fields{client}, args{&apiv1.CreateKeyRequest{ - Name: "azurekms:vault=my-vault;id=my-key", + Name: "azurekms:vault=my-vault;name=my-key", SignatureAlgorithm: apiv1.ECDSAWithSHA256, ProtectionLevel: apiv1.HSM, }}, &apiv1.CreateKeyResponse{ - Name: "azurekms:id=my-key;vault=my-vault", + Name: "azurekms:name=my-key;vault=my-vault", PublicKey: ecPub, CreateSignerRequest: apiv1.CreateSignerRequest{ - SigningKey: "azurekms:id=my-key;vault=my-vault", + SigningKey: "azurekms:name=my-key;vault=my-vault", }, }, false}, {"ok P-256 Default", fields{client}, args{&apiv1.CreateKeyRequest{ - Name: "azurekms:vault=my-vault;id=my-key", + Name: "azurekms:vault=my-vault;name=my-key", }}, &apiv1.CreateKeyResponse{ - Name: "azurekms:id=my-key;vault=my-vault", + Name: "azurekms:name=my-key;vault=my-vault", PublicKey: ecPub, CreateSignerRequest: apiv1.CreateSignerRequest{ - SigningKey: "azurekms:id=my-key;vault=my-vault", + SigningKey: "azurekms:name=my-key;vault=my-vault", }, }, false}, {"ok P-384", fields{client}, args{&apiv1.CreateKeyRequest{ - Name: "azurekms:vault=my-vault;id=my-key", + Name: "azurekms:vault=my-vault;name=my-key", SignatureAlgorithm: apiv1.ECDSAWithSHA384, }}, &apiv1.CreateKeyResponse{ - Name: "azurekms:id=my-key;vault=my-vault", + Name: "azurekms:name=my-key;vault=my-vault", PublicKey: ecPub, CreateSignerRequest: apiv1.CreateSignerRequest{ - SigningKey: "azurekms:id=my-key;vault=my-vault", + SigningKey: "azurekms:name=my-key;vault=my-vault", }, }, false}, {"ok P-521", fields{client}, args{&apiv1.CreateKeyRequest{ - Name: "azurekms:vault=my-vault;id=my-key", + Name: "azurekms:vault=my-vault;name=my-key", SignatureAlgorithm: apiv1.ECDSAWithSHA512, }}, &apiv1.CreateKeyResponse{ - Name: "azurekms:id=my-key;vault=my-vault", + Name: "azurekms:name=my-key;vault=my-vault", PublicKey: ecPub, CreateSignerRequest: apiv1.CreateSignerRequest{ - SigningKey: "azurekms:id=my-key;vault=my-vault", + SigningKey: "azurekms:name=my-key;vault=my-vault", }, }, false}, {"ok RSA 0", fields{client}, args{&apiv1.CreateKeyRequest{ - Name: "azurekms:vault=my-vault;id=my-key", + Name: "azurekms:vault=my-vault;name=my-key", Bits: 0, SignatureAlgorithm: apiv1.SHA256WithRSA, ProtectionLevel: apiv1.Software, }}, &apiv1.CreateKeyResponse{ - Name: "azurekms:id=my-key;vault=my-vault", + Name: "azurekms:name=my-key;vault=my-vault", PublicKey: rsaPub, CreateSignerRequest: apiv1.CreateSignerRequest{ - SigningKey: "azurekms:id=my-key;vault=my-vault", + SigningKey: "azurekms:name=my-key;vault=my-vault", }, }, false}, {"ok RSA 0 HSM", fields{client}, args{&apiv1.CreateKeyRequest{ - Name: "azurekms:vault=my-vault;id=my-key", + Name: "azurekms:vault=my-vault;name=my-key", Bits: 0, SignatureAlgorithm: apiv1.SHA256WithRSAPSS, ProtectionLevel: apiv1.HSM, }}, &apiv1.CreateKeyResponse{ - Name: "azurekms:id=my-key;vault=my-vault", + Name: "azurekms:name=my-key;vault=my-vault", PublicKey: rsaPub, CreateSignerRequest: apiv1.CreateSignerRequest{ - SigningKey: "azurekms:id=my-key;vault=my-vault", + SigningKey: "azurekms:name=my-key;vault=my-vault", }, }, false}, {"ok RSA 2048", fields{client}, args{&apiv1.CreateKeyRequest{ - Name: "azurekms:vault=my-vault;id=my-key", + Name: "azurekms:vault=my-vault;name=my-key", Bits: 2048, SignatureAlgorithm: apiv1.SHA384WithRSA, }}, &apiv1.CreateKeyResponse{ - Name: "azurekms:id=my-key;vault=my-vault", + Name: "azurekms:name=my-key;vault=my-vault", PublicKey: rsaPub, CreateSignerRequest: apiv1.CreateSignerRequest{ - SigningKey: "azurekms:id=my-key;vault=my-vault", + SigningKey: "azurekms:name=my-key;vault=my-vault", }, }, false}, {"ok RSA 3072", fields{client}, args{&apiv1.CreateKeyRequest{ - Name: "azurekms:vault=my-vault;id=my-key", + Name: "azurekms:vault=my-vault;name=my-key", Bits: 3072, SignatureAlgorithm: apiv1.SHA512WithRSA, }}, &apiv1.CreateKeyResponse{ - Name: "azurekms:id=my-key;vault=my-vault", + Name: "azurekms:name=my-key;vault=my-vault", PublicKey: rsaPub, CreateSignerRequest: apiv1.CreateSignerRequest{ - SigningKey: "azurekms:id=my-key;vault=my-vault", + SigningKey: "azurekms:name=my-key;vault=my-vault", }, }, false}, {"ok RSA 4096", fields{client}, args{&apiv1.CreateKeyRequest{ - Name: "azurekms:vault=my-vault;id=my-key", + Name: "azurekms:vault=my-vault;name=my-key", Bits: 4096, SignatureAlgorithm: apiv1.SHA512WithRSAPSS, }}, &apiv1.CreateKeyResponse{ - Name: "azurekms:id=my-key;vault=my-vault", + Name: "azurekms:name=my-key;vault=my-vault", PublicKey: rsaPub, CreateSignerRequest: apiv1.CreateSignerRequest{ - SigningKey: "azurekms:id=my-key;vault=my-vault", + SigningKey: "azurekms:name=my-key;vault=my-vault", }, }, false}, {"fail createKey", fields{client}, args{&apiv1.CreateKeyRequest{ - Name: "azurekms:vault=my-vault;id=not-found", + Name: "azurekms:vault=my-vault;name=not-found", SignatureAlgorithm: apiv1.ECDSAWithSHA256, }}, nil, true}, {"fail convertKey", fields{client}, args{&apiv1.CreateKeyRequest{ - Name: "azurekms:vault=my-vault;id=not-found", + Name: "azurekms:vault=my-vault;name=not-found", SignatureAlgorithm: apiv1.ECDSAWithSHA256, }}, nil, true}, {"fail name", fields{client}, args{&apiv1.CreateKeyRequest{ Name: "", }}, nil, true}, {"fail vault", fields{client}, args{&apiv1.CreateKeyRequest{ - Name: "azurekms:vault=;id=not-found?version=my-version", + Name: "azurekms:vault=;name=not-found?version=my-version", }}, nil, true}, {"fail id", fields{client}, args{&apiv1.CreateKeyRequest{ - Name: "azurekms:vault=my-vault;id=?version=my-version", + Name: "azurekms:vault=my-vault;name=?version=my-version", }}, nil, true}, {"fail SignatureAlgorithm", fields{client}, args{&apiv1.CreateKeyRequest{ - Name: "azurekms:vault=my-vault;id=not-found", + Name: "azurekms:vault=my-vault;name=not-found", SignatureAlgorithm: apiv1.PureEd25519, }}, nil, true}, {"fail bit size", fields{client}, args{&apiv1.CreateKeyRequest{ - Name: "azurekms:vault=my-vault;id=not-found", + Name: "azurekms:vault=my-vault;name=not-found", SignatureAlgorithm: apiv1.SHA384WithRSAPSS, Bits: 1024, }}, nil, true}, @@ -426,7 +426,7 @@ func TestKeyVault_CreateSigner(t *testing.T) { wantErr bool }{ {"ok", fields{client}, args{&apiv1.CreateSignerRequest{ - SigningKey: "azurekms:vault=my-vault;id=my-key", + SigningKey: "azurekms:vault=my-vault;name=my-key", }}, &Signer{ client: client, vaultBaseURL: "https://my-vault.vault.azure.net/", @@ -435,7 +435,7 @@ func TestKeyVault_CreateSigner(t *testing.T) { publicKey: pub, }, false}, {"ok with version", fields{client}, args{&apiv1.CreateSignerRequest{ - SigningKey: "azurekms:vault=my-vault;id=my-key;version=my-version", + SigningKey: "azurekms:vault=my-vault;name=my-key;version=my-version", }}, &Signer{ client: client, vaultBaseURL: "https://my-vault.vault.azure.net/", @@ -444,7 +444,7 @@ func TestKeyVault_CreateSigner(t *testing.T) { publicKey: pub, }, false}, {"fail GetKey", fields{client}, args{&apiv1.CreateSignerRequest{ - SigningKey: "azurekms:vault=my-vault;id=not-found;version=my-version", + SigningKey: "azurekms:vault=my-vault;name=not-found;version=my-version", }}, nil, true}, {"fail SigningKey", fields{client}, args{&apiv1.CreateSignerRequest{ SigningKey: "", diff --git a/kms/azurekms/signer_test.go b/kms/azurekms/signer_test.go index 798d69f9..389f65b3 100644 --- a/kms/azurekms/signer_test.go +++ b/kms/azurekms/signer_test.go @@ -44,24 +44,24 @@ func TestNewSigner(t *testing.T) { want crypto.Signer wantErr bool }{ - {"ok", args{client, "azurekms:vault=my-vault;id=my-key"}, &Signer{ + {"ok", args{client, "azurekms:vault=my-vault;name=my-key"}, &Signer{ client: client, vaultBaseURL: "https://my-vault.vault.azure.net/", name: "my-key", version: "", publicKey: pub, }, false}, - {"ok with version", args{client, "azurekms:id=my-key;vault=my-vault?version=my-version"}, &Signer{ + {"ok with version", args{client, "azurekms:name=my-key;vault=my-vault?version=my-version"}, &Signer{ client: client, vaultBaseURL: "https://my-vault.vault.azure.net/", name: "my-key", version: "my-version", publicKey: pub, }, false}, - {"fail GetKey", args{client, "azurekms:id=not-found;vault=my-vault?version=my-version"}, nil, true}, - {"fail vault", args{client, "azurekms:id=not-found;vault="}, nil, true}, - {"fail id", args{client, "azurekms:id=;vault=my-vault?version=my-version"}, nil, true}, - {"fail scheme", args{client, "kms:id=not-found;vault=my-vault?version=my-version"}, nil, true}, + {"fail GetKey", args{client, "azurekms:name=not-found;vault=my-vault?version=my-version"}, nil, true}, + {"fail vault", args{client, "azurekms:name=not-found;vault="}, nil, true}, + {"fail id", args{client, "azurekms:name=;vault=my-vault?version=my-version"}, nil, true}, + {"fail scheme", args{client, "kms:name=not-found;vault=my-vault?version=my-version"}, nil, true}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/kms/azurekms/utils.go b/kms/azurekms/utils.go index 46263726..6b6d1511 100644 --- a/kms/azurekms/utils.go +++ b/kms/azurekms/utils.go @@ -4,6 +4,7 @@ import ( "context" "crypto" "encoding/json" + "net/url" "time" "github.com/Azure/azure-sdk-for-go/services/keyvault/v7.1/keyvault" @@ -17,9 +18,34 @@ func defaultContext() (context.Context, context.CancelFunc) { return context.WithTimeout(context.Background(), 15*time.Second) } -// parseKeyName returns the key vault, name and version for urls like -// azurekms:vault=key-vault;id=key-name?version=key-version. If version is not -// passed the latest version will be used. +// getKeyName returns the uri of the key vault key. +func getKeyName(vault, name string, bundle keyvault.KeyBundle) string { + if bundle.Key != nil && bundle.Key.Kid != nil { + sm := keyIDRegexp.FindAllStringSubmatch(*bundle.Key.Kid, 1) + if len(sm) == 1 && len(sm[0]) == 4 { + m := sm[0] + u := uri.New(Scheme, url.Values{ + "vault": []string{m[1]}, + "name": []string{m[2]}, + }) + u.RawQuery = url.Values{"version": []string{m[3]}}.Encode() + return u.String() + } + } + // Fallback to URI without id. + return uri.New(Scheme, url.Values{ + "vault": []string{vault}, + "name": []string{name}, + }).String() +} + +// parseKeyName returns the key vault, name and version from URIs like: +// +// - azurekms:vault=key-vault;name=key-name +// - azurekms:vault=key-vault;name=key-name;id=key-id +// +// The key-id defines the version of the key, if it is not passed the latest +// version will be used. func parseKeyName(rawURI string) (vault, name, version string, err error) { var u *uri.URI @@ -27,13 +53,13 @@ func parseKeyName(rawURI string) (vault, name, version string, err error) { if err != nil { return } - - if vault = u.Get("vault"); vault == "" { - err = errors.Errorf("key uri %s is not valid: vault is missing", rawURI) + if name = u.Get("name"); name == "" { + err = errors.Errorf("key uri %s is not valid: name is missing", rawURI) return } - if name = u.Get("id"); name == "" { - err = errors.Errorf("key uri %s is not valid: id is missing", rawURI) + if vault = u.Get("vault"); vault == "" { + err = errors.Errorf("key uri %s is not valid: vault is missing", rawURI) + name = "" return } version = u.Get("version") diff --git a/kms/azurekms/utils_test.go b/kms/azurekms/utils_test.go new file mode 100644 index 00000000..53ec4057 --- /dev/null +++ b/kms/azurekms/utils_test.go @@ -0,0 +1,83 @@ +package azurekms + +import ( + "testing" + + "github.com/Azure/azure-sdk-for-go/services/keyvault/v7.1/keyvault" +) + +func Test_getKeyName(t *testing.T) { + getBundle := func(kid string) keyvault.KeyBundle { + return keyvault.KeyBundle{ + Key: &keyvault.JSONWebKey{ + Kid: &kid, + }, + } + } + + type args struct { + vault string + name string + bundle keyvault.KeyBundle + } + tests := []struct { + name string + args args + want string + }{ + {"ok", args{"my-vault", "my-key", getBundle("https://my-vault.vault.azure.net/keys/my-key/my-version")}, "azurekms:name=my-key;vault=my-vault?version=my-version"}, + {"ok default", args{"my-vault", "my-key", getBundle("https://my-vault.foo.net/keys/my-key/my-version")}, "azurekms:name=my-key;vault=my-vault"}, + {"ok too short", args{"my-vault", "my-key", getBundle("https://my-vault.vault.azure.net/keys/my-version")}, "azurekms:name=my-key;vault=my-vault"}, + {"ok too long", args{"my-vault", "my-key", getBundle("https://my-vault.vault.azure.net/keys/my-key/my-version/sign")}, "azurekms:name=my-key;vault=my-vault"}, + {"ok nil key", args{"my-vault", "my-key", keyvault.KeyBundle{}}, "azurekms:name=my-key;vault=my-vault"}, + {"ok nil kid", args{"my-vault", "my-key", keyvault.KeyBundle{Key: &keyvault.JSONWebKey{}}}, "azurekms:name=my-key;vault=my-vault"}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := getKeyName(tt.args.vault, tt.args.name, tt.args.bundle); got != tt.want { + t.Errorf("getKeyName() = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_parseKeyName(t *testing.T) { + type args struct { + rawURI string + } + tests := []struct { + name string + args args + wantVault string + wantName string + wantVersion string + wantErr bool + }{ + {"ok", args{"azurekms:name=my-key;vault=my-vault?version=my-version"}, "my-vault", "my-key", "my-version", false}, + {"ok no version", args{"azurekms:name=my-key;vault=my-vault"}, "my-vault", "my-key", "", false}, + {"fail scheme", args{"azure:name=my-key;vault=my-vault"}, "", "", "", true}, + {"fail parse uri", args{"azurekms:name=%ZZ;vault=my-vault"}, "", "", "", true}, + {"fail no name", args{"azurekms:vault=my-vault"}, "", "", "", true}, + {"fail empty name", args{"azurekms:name=;vault=my-vault"}, "", "", "", true}, + {"fail no vault", args{"azurekms:name=my-key"}, "", "", "", true}, + {"fail empty vault", args{"azurekms:name=my-key;vault="}, "", "", "", true}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + gotVault, gotName, gotVersion, err := parseKeyName(tt.args.rawURI) + if (err != nil) != tt.wantErr { + t.Errorf("parseKeyName() error = %v, wantErr %v", err, tt.wantErr) + return + } + if gotVault != tt.wantVault { + t.Errorf("parseKeyName() gotVault = %v, want %v", gotVault, tt.wantVault) + } + if gotName != tt.wantName { + t.Errorf("parseKeyName() gotName = %v, want %v", gotName, tt.wantName) + } + if gotVersion != tt.wantVersion { + t.Errorf("parseKeyName() gotVersion = %v, want %v", gotVersion, tt.wantVersion) + } + }) + } +} From 505b1f3678365261439a10ae6cf0d89df5418fc6 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Wed, 6 Oct 2021 18:41:31 -0700 Subject: [PATCH 148/195] Add new test case with a version in the opaque string. --- kms/azurekms/utils_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/kms/azurekms/utils_test.go b/kms/azurekms/utils_test.go index 53ec4057..915ee74d 100644 --- a/kms/azurekms/utils_test.go +++ b/kms/azurekms/utils_test.go @@ -54,6 +54,7 @@ func Test_parseKeyName(t *testing.T) { wantErr bool }{ {"ok", args{"azurekms:name=my-key;vault=my-vault?version=my-version"}, "my-vault", "my-key", "my-version", false}, + {"ok opaque version", args{"azurekms:name=my-key;vault=my-vault;version=my-version"}, "my-vault", "my-key", "my-version", false}, {"ok no version", args{"azurekms:name=my-key;vault=my-vault"}, "my-vault", "my-key", "", false}, {"fail scheme", args{"azure:name=my-key;vault=my-vault"}, "", "", "", true}, {"fail parse uri", args{"azurekms:name=%ZZ;vault=my-vault"}, "", "", "", true}, From 08c9902f29a5c1ae78fd26181ce1e5bedbbe5771 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Wed, 6 Oct 2021 18:42:01 -0700 Subject: [PATCH 149/195] Add new alias in the kms package. --- kms/kms.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/kms/kms.go b/kms/kms.go index 3eddca93..e1b76f1a 100644 --- a/kms/kms.go +++ b/kms/kms.go @@ -18,6 +18,9 @@ type KeyManager = apiv1.KeyManager // store x509.Certificates. type CertificateManager = apiv1.CertificateManager +// Options are the KMS options. They represent the kms object in the ca.json. +type Options = apiv1.Options + // New initializes a new KMS from the given type. func New(ctx context.Context, opts apiv1.Options) (KeyManager, error) { if err := opts.Validate(); err != nil { From 48549bf31719d289498790f179ef9dddf31072c8 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Thu, 7 Oct 2021 11:09:32 -0700 Subject: [PATCH 150/195] Initialize windows terminal on all binaries. --- cmd/step-awskms-init/main.go | 4 ++++ cmd/step-ca/main.go | 5 +++++ cmd/step-cloudkms-init/main.go | 4 ++++ cmd/step-pkcs11-init/main.go | 4 ++++ cmd/step-yubikey-init/main.go | 4 ++++ go.mod | 2 +- go.sum | 8 ++++---- 7 files changed, 26 insertions(+), 5 deletions(-) diff --git a/cmd/step-awskms-init/main.go b/cmd/step-awskms-init/main.go index 0d686239..7b9dc7a3 100644 --- a/cmd/step-awskms-init/main.go +++ b/cmd/step-awskms-init/main.go @@ -31,6 +31,10 @@ func main() { flag.Usage = usage flag.Parse() + // Initialize windows terminal + ui.Init() + defer ui.Reset() + c, err := awskms.New(context.Background(), apiv1.Options{ Type: string(apiv1.AmazonKMS), Region: region, diff --git a/cmd/step-ca/main.go b/cmd/step-ca/main.go index aaf37df2..d9d17fed 100644 --- a/cmd/step-ca/main.go +++ b/cmd/step-ca/main.go @@ -22,6 +22,7 @@ import ( "go.step.sm/cli-utils/command" "go.step.sm/cli-utils/command/version" "go.step.sm/cli-utils/config" + "go.step.sm/cli-utils/ui" "go.step.sm/cli-utils/usage" // Enabled kms interfaces. @@ -90,6 +91,10 @@ Please send us a sentence or two, good or bad: **feedback@smallstep.com** or htt ` func main() { + // Initialize windows terminal + ui.Init() + defer ui.Reset() + // Override global framework components cli.VersionPrinter = func(c *cli.Context) { version.Command(c) diff --git a/cmd/step-cloudkms-init/main.go b/cmd/step-cloudkms-init/main.go index 69573c5d..b924f1a1 100644 --- a/cmd/step-cloudkms-init/main.go +++ b/cmd/step-cloudkms-init/main.go @@ -62,6 +62,10 @@ func main() { os.Exit(1) } + // Initialize windows terminal + ui.Init() + defer ui.Reset() + c, err := cloudkms.New(context.Background(), apiv1.Options{ Type: string(apiv1.CloudKMS), CredentialsFile: credentialsFile, diff --git a/cmd/step-pkcs11-init/main.go b/cmd/step-pkcs11-init/main.go index 34f9f8f8..5d9ba3e1 100644 --- a/cmd/step-pkcs11-init/main.go +++ b/cmd/step-pkcs11-init/main.go @@ -129,6 +129,10 @@ func main() { fatal(err) } + // Initialize windows terminal + ui.Init() + defer ui.Reset() + if u.Get("pin-value") == "" && u.Get("pin-source") == "" && c.Pin == "" { pin, err := ui.PromptPassword("What is the PKCS#11 PIN?") if err != nil { diff --git a/cmd/step-yubikey-init/main.go b/cmd/step-yubikey-init/main.go index df7b9ea8..cc55614a 100644 --- a/cmd/step-yubikey-init/main.go +++ b/cmd/step-yubikey-init/main.go @@ -87,6 +87,10 @@ func main() { fatal(err) } + // Initialize windows terminal + ui.Init() + defer ui.Reset() + pin, err := ui.PromptPassword("What is the YubiKey PIN?") if err != nil { fatal(err) diff --git a/go.mod b/go.mod index 04af53fc..0aab9189 100644 --- a/go.mod +++ b/go.mod @@ -26,7 +26,7 @@ require ( github.com/smallstep/nosql v0.3.8 github.com/urfave/cli v1.22.4 go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352 - go.step.sm/cli-utils v0.4.1 + go.step.sm/cli-utils v0.6.0 go.step.sm/crypto v0.11.0 go.step.sm/linkedca v0.5.0 golang.org/x/crypto v0.0.0-20210915214749-c084706c2272 diff --git a/go.sum b/go.sum index a6ff0f08..0c042a04 100644 --- a/go.sum +++ b/go.sum @@ -365,6 +365,8 @@ github.com/mattn/go-isatty v0.0.13 h1:qdl+GuBjcsKKDco5BsxPJlId98mSWNKqYA+Co0SC1y github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI= +github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= github.com/micromdm/scep/v2 v2.1.0 h1:2fS9Rla7qRR266hvUoEauBJ7J6FhgssEiq2OkSKXmaU= github.com/micromdm/scep/v2 v2.1.0/go.mod h1:BkF7TkPPhmgJAMtHfP+sFTKXmgzNJgLQlvvGoOExBcc= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= @@ -455,8 +457,6 @@ github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/samfoo/ansi v0.0.0-20160124022901-b6bd2ded7189 h1:CmSpbxmewNQbzqztaY0bke1qzHhyNyC29wYgh17Gxfo= -github.com/samfoo/ansi v0.0.0-20160124022901-b6bd2ded7189/go.mod h1:UUwuHEJ9zkkPDxspIHOa59PUeSkGFljESGzbxntLmIg= github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= @@ -534,8 +534,8 @@ go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.step.sm/cli-utils v0.4.1 h1:QztRUhGYjOPM1I2Nmi7V6XejQyVtcESmo+sbegxvX7Q= -go.step.sm/cli-utils v0.4.1/go.mod h1:hWYVOSlw8W9Pd+BwIbs/aftVVMRms3EG7Q2qLRwc0WA= +go.step.sm/cli-utils v0.6.0 h1:sH4FxBcjmbxyilKXheSyJuKF/QjpojpiW90ERwUWOgQ= +go.step.sm/cli-utils v0.6.0/go.mod h1:jklBMavFl2PbmGlyxgax08ZnB0uWpadjuOlSKKXz+0U= go.step.sm/crypto v0.9.0/go.mod h1:+CYG05Mek1YDqi5WK0ERc6cOpKly2i/a5aZmU1sfGj0= go.step.sm/crypto v0.11.0 h1:VDpeVgEmqme/FK2w5QINxkOQ1FWOm/Wi2TwQXiacKr8= go.step.sm/crypto v0.11.0/go.mod h1:5YzQ85BujYBu6NH18jw7nFjwuRnDch35nLzH0ES5sKg= From 205148ad1fbb397d325d3aa984e7da8c94a59baf Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Thu, 7 Oct 2021 12:43:24 -0700 Subject: [PATCH 151/195] Fix exit after defer. --- cmd/step-awskms-init/main.go | 5 ++++- cmd/step-ca/main.go | 10 ++++++++-- cmd/step-cloudkms-init/main.go | 5 ++++- cmd/step-pkcs11-init/main.go | 5 ++++- cmd/step-yubikey-init/main.go | 5 ++++- 5 files changed, 24 insertions(+), 6 deletions(-) diff --git a/cmd/step-awskms-init/main.go b/cmd/step-awskms-init/main.go index 7b9dc7a3..0678ef39 100644 --- a/cmd/step-awskms-init/main.go +++ b/cmd/step-awskms-init/main.go @@ -33,7 +33,6 @@ func main() { // Initialize windows terminal ui.Init() - defer ui.Reset() c, err := awskms.New(context.Background(), apiv1.Options{ Type: string(apiv1.AmazonKMS), @@ -54,10 +53,14 @@ func main() { fatal(err) } } + + // Reset windows terminal + ui.Reset() } func fatal(err error) { fmt.Fprintln(os.Stderr, err) + ui.Reset() os.Exit(1) } diff --git a/cmd/step-ca/main.go b/cmd/step-ca/main.go index d9d17fed..e0123678 100644 --- a/cmd/step-ca/main.go +++ b/cmd/step-ca/main.go @@ -53,6 +53,11 @@ func init() { rand.Seed(time.Now().UnixNano()) } +func exit(code int) { + ui.Reset() + os.Exit(code) +} + // appHelpTemplate contains the modified template for the main app var appHelpTemplate = `## NAME **{{.HelpName}}** -- {{.Usage}} @@ -93,7 +98,6 @@ Please send us a sentence or two, good or bad: **feedback@smallstep.com** or htt func main() { // Initialize windows terminal ui.Init() - defer ui.Reset() // Override global framework components cli.VersionPrinter = func(c *cli.Context) { @@ -169,8 +173,10 @@ $ step-ca $STEPPATH/config/ca.json --password-file ./password.txt } else { fmt.Fprintln(os.Stderr, err) } - os.Exit(1) + exit(1) } + + exit(0) } func flagValue(f cli.Flag) reflect.Value { diff --git a/cmd/step-cloudkms-init/main.go b/cmd/step-cloudkms-init/main.go index b924f1a1..14bf50f1 100644 --- a/cmd/step-cloudkms-init/main.go +++ b/cmd/step-cloudkms-init/main.go @@ -64,7 +64,6 @@ func main() { // Initialize windows terminal ui.Init() - defer ui.Reset() c, err := cloudkms.New(context.Background(), apiv1.Options{ Type: string(apiv1.CloudKMS), @@ -84,10 +83,14 @@ func main() { fatal(err) } } + + // Reset windows terminal + ui.Reset() } func fatal(err error) { fmt.Fprintln(os.Stderr, err) + ui.Reset() os.Exit(1) } diff --git a/cmd/step-pkcs11-init/main.go b/cmd/step-pkcs11-init/main.go index 5d9ba3e1..78c531c6 100644 --- a/cmd/step-pkcs11-init/main.go +++ b/cmd/step-pkcs11-init/main.go @@ -131,7 +131,6 @@ func main() { // Initialize windows terminal ui.Init() - defer ui.Reset() if u.Get("pin-value") == "" && u.Get("pin-source") == "" && c.Pin == "" { pin, err := ui.PromptPassword("What is the PKCS#11 PIN?") @@ -205,6 +204,9 @@ func main() { if err := createPKI(k, c); err != nil { fatalClose(err, k) } + + // Reset windows terminal + ui.Reset() } func fatal(err error) { @@ -213,6 +215,7 @@ func fatal(err error) { } else { fmt.Fprintln(os.Stderr, err) } + ui.Reset() os.Exit(1) } diff --git a/cmd/step-yubikey-init/main.go b/cmd/step-yubikey-init/main.go index cc55614a..163d0fcb 100644 --- a/cmd/step-yubikey-init/main.go +++ b/cmd/step-yubikey-init/main.go @@ -89,7 +89,6 @@ func main() { // Initialize windows terminal ui.Init() - defer ui.Reset() pin, err := ui.PromptPassword("What is the YubiKey PIN?") if err != nil { @@ -123,6 +122,9 @@ func main() { defer func() { _ = k.Close() }() + + // Reset windows terminal + ui.Reset() } func fatal(err error) { @@ -131,6 +133,7 @@ func fatal(err error) { } else { fmt.Fprintln(os.Stderr, err) } + ui.Reset() os.Exit(1) } From 52a18e0c2d0d28d12a1c8b7737e7a476e11b08ba Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Thu, 7 Oct 2021 14:19:39 -0700 Subject: [PATCH 152/195] Add key name to CreateCertificateAuthority --- cas/apiv1/requests.go | 6 +++++- cas/softcas/softcas.go | 1 + cas/softcas/softcas_test.go | 17 +++++++++++++++++ 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/cas/apiv1/requests.go b/cas/apiv1/requests.go index b47a9c13..bf745c17 100644 --- a/cas/apiv1/requests.go +++ b/cas/apiv1/requests.go @@ -108,6 +108,9 @@ type GetCertificateAuthorityResponse struct { RootCertificate *x509.Certificate } +// CreateKeyRequest is the request used to generate a new key using a KMS. +type CreateKeyRequest = apiv1.CreateKeyRequest + // CreateCertificateAuthorityRequest is the request used to generate a root or // intermediate certificate. type CreateCertificateAuthorityRequest struct { @@ -126,7 +129,7 @@ type CreateCertificateAuthorityRequest struct { // CreateKey defines the KMS CreateKeyRequest to use when creating a new // CertificateAuthority. If CreateKey is nil, a default algorithm will be // used. - CreateKey *apiv1.CreateKeyRequest + CreateKey *CreateKeyRequest } // CreateCertificateAuthorityResponse is the response for @@ -136,6 +139,7 @@ type CreateCertificateAuthorityResponse struct { Name string Certificate *x509.Certificate CertificateChain []*x509.Certificate + KeyName string PublicKey crypto.PublicKey PrivateKey crypto.PrivateKey Signer crypto.Signer diff --git a/cas/softcas/softcas.go b/cas/softcas/softcas.go index 23dac91b..e33a043a 100644 --- a/cas/softcas/softcas.go +++ b/cas/softcas/softcas.go @@ -174,6 +174,7 @@ func (c *SoftCAS) CreateCertificateAuthority(req *apiv1.CreateCertificateAuthori Name: cert.Subject.CommonName, Certificate: cert, CertificateChain: chain, + KeyName: key.Name, PublicKey: key.PublicKey, PrivateKey: key.PrivateKey, Signer: signer, diff --git a/cas/softcas/softcas_test.go b/cas/softcas/softcas_test.go index c8e1a8e9..b9b79250 100644 --- a/cas/softcas/softcas_test.go +++ b/cas/softcas/softcas_test.go @@ -106,6 +106,7 @@ func (m *mockKeyManager) CreateKey(req *kmsapi.CreateKeyRequest) (*kmsapi.Create signer = m.signer } return &kmsapi.CreateKeyResponse{ + Name: req.Name, PrivateKey: signer, PublicKey: signer.Public(), }, m.errCreateKey @@ -516,6 +517,22 @@ func TestSoftCAS_CreateCertificateAuthority(t *testing.T) { PrivateKey: saSigner, Signer: saSigner, }, false}, + {"ok createKey", fields{nil, nil, &mockKeyManager{}}, args{&apiv1.CreateCertificateAuthorityRequest{ + Type: apiv1.RootCA, + Template: testRootTemplate, + Lifetime: 24 * time.Hour, + CreateKey: &kmsapi.CreateKeyRequest{ + Name: "root_ca.crt", + SignatureAlgorithm: kmsapi.ECDSAWithSHA256, + }, + }}, &apiv1.CreateCertificateAuthorityResponse{ + Name: "Test Root CA", + Certificate: testSignedRootTemplate, + PublicKey: testSignedRootTemplate.PublicKey, + KeyName: "root_ca.crt", + PrivateKey: testSigner, + Signer: testSigner, + }, false}, {"fail template", fields{nil, nil, &mockKeyManager{}}, args{&apiv1.CreateCertificateAuthorityRequest{ Type: apiv1.RootCA, Lifetime: 24 * time.Hour, From 2026787ce4a8360d8b3e19a08edfd756e90d2d10 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Thu, 7 Oct 2021 15:01:11 -0700 Subject: [PATCH 153/195] Add some extra coverage. --- kms/azurekms/key_vault.go | 5 +-- kms/azurekms/key_vault_test.go | 70 ++++++++++++++++++++++++++++++---- 2 files changed, 64 insertions(+), 11 deletions(-) diff --git a/kms/azurekms/key_vault.go b/kms/azurekms/key_vault.go index f7b00ec7..c5dc56bf 100644 --- a/kms/azurekms/key_vault.go +++ b/kms/azurekms/key_vault.go @@ -38,9 +38,8 @@ var now = func() time.Time { } type keyType struct { - Kty keyvault.JSONWebKeyType - Curve keyvault.JSONWebKeyCurveName - KeySize int + Kty keyvault.JSONWebKeyType + Curve keyvault.JSONWebKeyCurveName } func (k keyType) KeyType(pl apiv1.ProtectionLevel) keyvault.JSONWebKeyType { diff --git a/kms/azurekms/key_vault_test.go b/kms/azurekms/key_vault_test.go index 1f09b2d5..4f98d274 100644 --- a/kms/azurekms/key_vault_test.go +++ b/kms/azurekms/key_vault_test.go @@ -42,17 +42,19 @@ func mockClient(t *testing.T) *mock.KeyVaultClient { return mock.NewKeyVaultClient(ctrl) } -func mockCreateClient(t *testing.T, ctrl *gomock.Controller) { +func mockCreateClient(t *testing.T) *mock.KeyVaultClient { t.Helper() + ctrl := gomock.NewController(t) + client := mock.NewKeyVaultClient(ctrl) old := createClient - createClient = func(ctx context.Context, opts apiv1.Options) (KeyVaultClient, error) { - return mock.NewKeyVaultClient(ctrl), nil + return client, nil } - t.Cleanup(func() { createClient = old + ctrl.Finish() }) + return client } func createJWK(t *testing.T, pub crypto.PublicKey) *keyvault.JSONWebKey { @@ -78,8 +80,11 @@ func Test_now(t *testing.T) { } func TestNew(t *testing.T) { - ctrl := gomock.NewController(t) - mockCreateClient(t, ctrl) + client := mockClient(t) + old := createClient + t.Cleanup(func() { + createClient = old + }) type args struct { ctx context.Context @@ -87,16 +92,27 @@ func TestNew(t *testing.T) { } tests := []struct { name string + setup func() args args want *KeyVault wantErr bool }{ - {"ok", args{context.Background(), apiv1.Options{}}, &KeyVault{ - baseClient: mock.NewKeyVaultClient(ctrl), + {"ok", func() { + createClient = func(ctx context.Context, opts apiv1.Options) (KeyVaultClient, error) { + return client, nil + } + }, args{context.Background(), apiv1.Options{}}, &KeyVault{ + baseClient: client, }, false}, + {"fail", func() { + createClient = func(ctx context.Context, opts apiv1.Options) (KeyVaultClient, error) { + return nil, errTest + } + }, args{context.Background(), apiv1.Options{}}, nil, true}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + tt.setup() got, err := New(tt.args.ctx, tt.args.opts) if (err != nil) != tt.wantErr { t.Errorf("New() error = %v, wantErr %v", err, tt.wantErr) @@ -148,6 +164,9 @@ func TestKeyVault_GetPublicKey(t *testing.T) { {"fail GetKey", fields{client}, args{&apiv1.GetPublicKeyRequest{ Name: "azurekms:vault=my-vault;name=not-found?version=my-version", }}, nil, true}, + {"fail empty", fields{client}, args{&apiv1.GetPublicKeyRequest{ + Name: "", + }}, nil, true}, {"fail vault", fields{client}, args{&apiv1.GetPublicKeyRequest{ Name: "azurekms:vault=;name=not-found?version=my-version", }}, nil, true}, @@ -490,3 +509,38 @@ func TestKeyVault_Close(t *testing.T) { }) } } + +func Test_keyType_KeyType(t *testing.T) { + type fields struct { + Kty keyvault.JSONWebKeyType + Curve keyvault.JSONWebKeyCurveName + } + type args struct { + pl apiv1.ProtectionLevel + } + tests := []struct { + name string + fields fields + args args + want keyvault.JSONWebKeyType + }{ + {"ec", fields{keyvault.EC, keyvault.P256}, args{apiv1.UnspecifiedProtectionLevel}, keyvault.EC}, + {"ec software", fields{keyvault.EC, keyvault.P384}, args{apiv1.Software}, keyvault.EC}, + {"ec hsm", fields{keyvault.EC, keyvault.P521}, args{apiv1.HSM}, keyvault.ECHSM}, + {"rsa", fields{keyvault.RSA, keyvault.P256}, args{apiv1.UnspecifiedProtectionLevel}, keyvault.RSA}, + {"rsa software", fields{keyvault.RSA, ""}, args{apiv1.Software}, keyvault.RSA}, + {"rsa hsm", fields{keyvault.RSA, ""}, args{apiv1.HSM}, keyvault.RSAHSM}, + {"empty", fields{"FOO", ""}, args{apiv1.UnspecifiedProtectionLevel}, ""}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + k := keyType{ + Kty: tt.fields.Kty, + Curve: tt.fields.Curve, + } + if got := k.KeyType(tt.args.pl); !reflect.DeepEqual(got, tt.want) { + t.Errorf("keyType.KeyType() = %v, want %v", got, tt.want) + } + }) + } +} From 500b540406f35c0ac2e46c48c97ace9f0a05e299 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Thu, 7 Oct 2021 15:35:21 -0700 Subject: [PATCH 154/195] Remove unused code. --- kms/azurekms/key_vault_test.go | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/kms/azurekms/key_vault_test.go b/kms/azurekms/key_vault_test.go index 4f98d274..f9446b0f 100644 --- a/kms/azurekms/key_vault_test.go +++ b/kms/azurekms/key_vault_test.go @@ -42,21 +42,6 @@ func mockClient(t *testing.T) *mock.KeyVaultClient { return mock.NewKeyVaultClient(ctrl) } -func mockCreateClient(t *testing.T) *mock.KeyVaultClient { - t.Helper() - ctrl := gomock.NewController(t) - client := mock.NewKeyVaultClient(ctrl) - old := createClient - createClient = func(ctx context.Context, opts apiv1.Options) (KeyVaultClient, error) { - return client, nil - } - t.Cleanup(func() { - createClient = old - ctrl.Finish() - }) - return client -} - func createJWK(t *testing.T, pub crypto.PublicKey) *keyvault.JSONWebKey { t.Helper() b, err := json.Marshal(&jose.JSONWebKey{ From f1ef3fb351ce0659c7540f5863397d9d3012e153 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Thu, 7 Oct 2021 15:48:11 -0700 Subject: [PATCH 155/195] Add GetBool(s string) bool to URI type. --- kms/uri/uri.go | 10 ++++++++++ kms/uri/uri_test.go | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/kms/uri/uri.go b/kms/uri/uri.go index 44271e74..3a1b8981 100644 --- a/kms/uri/uri.go +++ b/kms/uri/uri.go @@ -95,6 +95,16 @@ func (u *URI) Get(key string) string { return v } +// GetBool returns true if a given key has the value "true". It will returns +// false otherwise. +func (u *URI) GetBool(key string) bool { + v := u.Values.Get(key) + if v == "" { + v = u.URL.Query().Get(key) + } + return strings.EqualFold(v, "true") +} + // GetEncoded returns the first value in the uri with the given key, it will // return empty nil if that field is not present or is empty. If the return // value is hex encoded it will decode it and return it. diff --git a/kms/uri/uri_test.go b/kms/uri/uri_test.go index c2e0a9fe..01fbad0f 100644 --- a/kms/uri/uri_test.go +++ b/kms/uri/uri_test.go @@ -212,6 +212,40 @@ func TestURI_Get(t *testing.T) { } } +func TestURI_GetBool(t *testing.T) { + mustParse := func(s string) *URI { + u, err := Parse(s) + if err != nil { + t.Fatal(err) + } + return u + } + type args struct { + key string + } + tests := []struct { + name string + uri *URI + args args + want bool + }{ + {"true", mustParse("azurekms:name=foo;vault=bar;hsm=true"), args{"hsm"}, true}, + {"TRUE", mustParse("azurekms:name=foo;vault=bar;hsm=TRUE"), args{"hsm"}, true}, + {"tRUe query", mustParse("azurekms:name=foo;vault=bar?hsm=tRUe"), args{"hsm"}, true}, + {"false", mustParse("azurekms:name=foo;vault=bar;hsm=false"), args{"hsm"}, false}, + {"false query", mustParse("azurekms:name=foo;vault=bar?hsm=false"), args{"hsm"}, false}, + {"empty", mustParse("azurekms:name=foo;vault=bar;hsm=?bar=true"), args{"hsm"}, false}, + {"missing", mustParse("azurekms:name=foo;vault=bar"), args{"hsm"}, false}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := tt.uri.GetBool(tt.args.key); got != tt.want { + t.Errorf("URI.GetBool() = %v, want %v", got, tt.want) + } + }) + } +} + func TestURI_GetEncoded(t *testing.T) { mustParse := func(s string) *URI { u, err := Parse(s) From abdb56065d646dc77f5b45f406a309dc83f3c22a Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Thu, 7 Oct 2021 16:18:36 -0700 Subject: [PATCH 156/195] Allow o specify an hsm using the uri. --- kms/azurekms/key_vault.go | 17 +++++++++++++---- kms/azurekms/key_vault_test.go | 23 +++++++++++++++++++++++ kms/azurekms/signer.go | 2 +- kms/azurekms/signer_test.go | 9 +++++++++ kms/azurekms/utils.go | 9 +++++++-- kms/azurekms/utils_test.go | 26 ++++++++++++++++---------- 6 files changed, 69 insertions(+), 17 deletions(-) diff --git a/kms/azurekms/key_vault.go b/kms/azurekms/key_vault.go index c5dc56bf..4a927d4f 100644 --- a/kms/azurekms/key_vault.go +++ b/kms/azurekms/key_vault.go @@ -113,11 +113,13 @@ type KeyVaultClient interface { // // - azurekms:name=key-name;vault=vault-name // - azurekms:name=key-name;vault=vault-name?version=key-version +// - azurekms:name=key-name;vault=vault-name?hsm=true // // The scheme is "azurekms"; "name" is the key name; "vault" is the key vault // name where the key is located; "version" is an optional parameter that // defines the version of they key, if version is not given, the latest one will -// be used. +// be used; "hsm" defines if an HSM want to be used for this key, this is +// specially useful when this is used from `step`. // // TODO(mariano): The implementation is using /services/keyvault/v7.1/keyvault // package, at some point Azure might create a keyvault client with all the @@ -165,7 +167,7 @@ func (k *KeyVault) GetPublicKey(req *apiv1.GetPublicKeyRequest) (crypto.PublicKe return nil, errors.New("getPublicKeyRequest 'name' cannot be empty") } - vault, name, version, err := parseKeyName(req.Name) + vault, name, version, _, err := parseKeyName(req.Name) if err != nil { return nil, err } @@ -187,11 +189,18 @@ func (k *KeyVault) CreateKey(req *apiv1.CreateKeyRequest) (*apiv1.CreateKeyRespo return nil, errors.New("createKeyRequest 'name' cannot be empty") } - vault, name, _, err := parseKeyName(req.Name) + vault, name, _, hsm, err := parseKeyName(req.Name) if err != nil { return nil, err } + // Override protection level to HSM only if it's not specified, and is given + // in the uri. + protectionLevel := req.ProtectionLevel + if protectionLevel == apiv1.UnspecifiedProtectionLevel && hsm { + protectionLevel = apiv1.HSM + } + kt, ok := signatureAlgorithmMapping[req.SignatureAlgorithm] if !ok { return nil, errors.Errorf("keyVault does not support signature algorithm '%s'", req.SignatureAlgorithm) @@ -216,7 +225,7 @@ func (k *KeyVault) CreateKey(req *apiv1.CreateKeyRequest) (*apiv1.CreateKeyRespo defer cancel() resp, err := k.baseClient.CreateKey(ctx, vaultBaseURL(vault), name, keyvault.KeyCreateParameters{ - Kty: kt.KeyType(req.ProtectionLevel), + Kty: kt.KeyType(protectionLevel), KeySize: keySize, Curve: kt.Curve, KeyOps: &[]keyvault.JSONWebKeyOperation{ diff --git a/kms/azurekms/key_vault_test.go b/kms/azurekms/key_vault_test.go index f9446b0f..0f6d7e0e 100644 --- a/kms/azurekms/key_vault_test.go +++ b/kms/azurekms/key_vault_test.go @@ -202,11 +202,13 @@ func TestKeyVault_CreateKey(t *testing.T) { }{ {"P-256", keyvault.EC, nil, keyvault.P256, ecJWK}, {"P-256 HSM", keyvault.ECHSM, nil, keyvault.P256, ecJWK}, + {"P-256 HSM (uri)", keyvault.ECHSM, nil, keyvault.P256, ecJWK}, {"P-256 Default", keyvault.EC, nil, keyvault.P256, ecJWK}, {"P-384", keyvault.EC, nil, keyvault.P384, ecJWK}, {"P-521", keyvault.EC, nil, keyvault.P521, ecJWK}, {"RSA 0", keyvault.RSA, &value3072, "", rsaJWK}, {"RSA 0 HSM", keyvault.RSAHSM, &value3072, "", rsaJWK}, + {"RSA 0 HSM (uri)", keyvault.RSAHSM, &value3072, "", rsaJWK}, {"RSA 2048", keyvault.RSA, &value2048, "", rsaJWK}, {"RSA 3072", keyvault.RSA, &value3072, "", rsaJWK}, {"RSA 4096", keyvault.RSA, &value4096, "", rsaJWK}, @@ -269,6 +271,16 @@ func TestKeyVault_CreateKey(t *testing.T) { SigningKey: "azurekms:name=my-key;vault=my-vault", }, }, false}, + {"ok P-256 HSM (uri)", fields{client}, args{&apiv1.CreateKeyRequest{ + Name: "azurekms:vault=my-vault;name=my-key?hsm=true", + SignatureAlgorithm: apiv1.ECDSAWithSHA256, + }}, &apiv1.CreateKeyResponse{ + Name: "azurekms:name=my-key;vault=my-vault", + PublicKey: ecPub, + CreateSignerRequest: apiv1.CreateSignerRequest{ + SigningKey: "azurekms:name=my-key;vault=my-vault", + }, + }, false}, {"ok P-256 Default", fields{client}, args{&apiv1.CreateKeyRequest{ Name: "azurekms:vault=my-vault;name=my-key", }}, &apiv1.CreateKeyResponse{ @@ -322,6 +334,17 @@ func TestKeyVault_CreateKey(t *testing.T) { SigningKey: "azurekms:name=my-key;vault=my-vault", }, }, false}, + {"ok RSA 0 HSM (uri)", fields{client}, args{&apiv1.CreateKeyRequest{ + Name: "azurekms:vault=my-vault;name=my-key;hsm=true", + Bits: 0, + SignatureAlgorithm: apiv1.SHA256WithRSAPSS, + }}, &apiv1.CreateKeyResponse{ + Name: "azurekms:name=my-key;vault=my-vault", + PublicKey: rsaPub, + CreateSignerRequest: apiv1.CreateSignerRequest{ + SigningKey: "azurekms:name=my-key;vault=my-vault", + }, + }, false}, {"ok RSA 2048", fields{client}, args{&apiv1.CreateKeyRequest{ Name: "azurekms:vault=my-vault;name=my-key", Bits: 2048, diff --git a/kms/azurekms/signer.go b/kms/azurekms/signer.go index cb844bdf..cf0197fb 100644 --- a/kms/azurekms/signer.go +++ b/kms/azurekms/signer.go @@ -25,7 +25,7 @@ type Signer struct { // NewSigner creates a new signer using a key in the AWS KMS. func NewSigner(client KeyVaultClient, signingKey string) (crypto.Signer, error) { - vault, name, version, err := parseKeyName(signingKey) + vault, name, version, _, err := parseKeyName(signingKey) if err != nil { return nil, err } diff --git a/kms/azurekms/signer_test.go b/kms/azurekms/signer_test.go index 389f65b3..90740b9f 100644 --- a/kms/azurekms/signer_test.go +++ b/kms/azurekms/signer_test.go @@ -221,6 +221,12 @@ func TestSigner_Sign(t *testing.T) { {"fail sign length", "", keyvault.ES256, p256Digest, keyvault.KeyOperationResult{ Result: &rsaSHA256ResultSig, }, nil}, + {"fail base64", "", keyvault.ES256, p256Digest, keyvault.KeyOperationResult{ + Result: func() *string { + v := "😎" + return &v + }(), + }, nil}, } for _, e := range expects { value := base64.RawURLEncoding.EncodeToString(e.digest) @@ -291,6 +297,9 @@ func TestSigner_Sign(t *testing.T) { {"fail sign length", fields{client, "https://my-vault.vault.azure.net/", "my-key", "", p256}, args{ rand.Reader, p256Digest[:], crypto.SHA256, }, nil, true}, + {"fail base64", fields{client, "https://my-vault.vault.azure.net/", "my-key", "", p256}, args{ + rand.Reader, p256Digest[:], crypto.SHA256, + }, nil, true}, {"fail RSA-PSS salt length", fields{client, "https://my-vault.vault.azure.net/", "my-key", "", rsaPSSSHA256}, args{ rand.Reader, rsaPSSSHA256Digest[:], &rsa.PSSOptions{ SaltLength: 64, diff --git a/kms/azurekms/utils.go b/kms/azurekms/utils.go index 6b6d1511..52bed868 100644 --- a/kms/azurekms/utils.go +++ b/kms/azurekms/utils.go @@ -42,11 +42,15 @@ func getKeyName(vault, name string, bundle keyvault.KeyBundle) string { // parseKeyName returns the key vault, name and version from URIs like: // // - azurekms:vault=key-vault;name=key-name -// - azurekms:vault=key-vault;name=key-name;id=key-id +// - azurekms:vault=key-vault;name=key-name?version=key-id +// - azurekms:vault=key-vault;name=key-name?version=key-id&hsm=true // // The key-id defines the version of the key, if it is not passed the latest // version will be used. -func parseKeyName(rawURI string) (vault, name, version string, err error) { +// +// HSM can also be passed to define the protection level if this is not given in +// CreateQuery. +func parseKeyName(rawURI string) (vault, name, version string, hsm bool, err error) { var u *uri.URI u, err = uri.ParseWithScheme("azurekms", rawURI) @@ -63,6 +67,7 @@ func parseKeyName(rawURI string) (vault, name, version string, err error) { return } version = u.Get("version") + hsm = u.GetBool("hsm") return } diff --git a/kms/azurekms/utils_test.go b/kms/azurekms/utils_test.go index 915ee74d..03d3f6e2 100644 --- a/kms/azurekms/utils_test.go +++ b/kms/azurekms/utils_test.go @@ -51,21 +51,24 @@ func Test_parseKeyName(t *testing.T) { wantVault string wantName string wantVersion string + wantHsm bool wantErr bool }{ - {"ok", args{"azurekms:name=my-key;vault=my-vault?version=my-version"}, "my-vault", "my-key", "my-version", false}, - {"ok opaque version", args{"azurekms:name=my-key;vault=my-vault;version=my-version"}, "my-vault", "my-key", "my-version", false}, - {"ok no version", args{"azurekms:name=my-key;vault=my-vault"}, "my-vault", "my-key", "", false}, - {"fail scheme", args{"azure:name=my-key;vault=my-vault"}, "", "", "", true}, - {"fail parse uri", args{"azurekms:name=%ZZ;vault=my-vault"}, "", "", "", true}, - {"fail no name", args{"azurekms:vault=my-vault"}, "", "", "", true}, - {"fail empty name", args{"azurekms:name=;vault=my-vault"}, "", "", "", true}, - {"fail no vault", args{"azurekms:name=my-key"}, "", "", "", true}, - {"fail empty vault", args{"azurekms:name=my-key;vault="}, "", "", "", true}, + {"ok", args{"azurekms:name=my-key;vault=my-vault?version=my-version"}, "my-vault", "my-key", "my-version", false, false}, + {"ok opaque version", args{"azurekms:name=my-key;vault=my-vault;version=my-version"}, "my-vault", "my-key", "my-version", false, false}, + {"ok no version", args{"azurekms:name=my-key;vault=my-vault"}, "my-vault", "my-key", "", false, false}, + {"ok hsm", args{"azurekms:name=my-key;vault=my-vault?hsm=true"}, "my-vault", "my-key", "", true, false}, + {"ok hsm false", args{"azurekms:name=my-key;vault=my-vault?hsm=false"}, "my-vault", "my-key", "", false, false}, + {"fail scheme", args{"azure:name=my-key;vault=my-vault"}, "", "", "", false, true}, + {"fail parse uri", args{"azurekms:name=%ZZ;vault=my-vault"}, "", "", "", false, true}, + {"fail no name", args{"azurekms:vault=my-vault"}, "", "", "", false, true}, + {"fail empty name", args{"azurekms:name=;vault=my-vault"}, "", "", "", false, true}, + {"fail no vault", args{"azurekms:name=my-key"}, "", "", "", false, true}, + {"fail empty vault", args{"azurekms:name=my-key;vault="}, "", "", "", false, true}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - gotVault, gotName, gotVersion, err := parseKeyName(tt.args.rawURI) + gotVault, gotName, gotVersion, gotHsm, err := parseKeyName(tt.args.rawURI) if (err != nil) != tt.wantErr { t.Errorf("parseKeyName() error = %v, wantErr %v", err, tt.wantErr) return @@ -79,6 +82,9 @@ func Test_parseKeyName(t *testing.T) { if gotVersion != tt.wantVersion { t.Errorf("parseKeyName() gotVersion = %v, want %v", gotVersion, tt.wantVersion) } + if gotHsm != tt.wantHsm { + t.Errorf("parseKeyName() gotHsm = %v, want %v", gotHsm, tt.wantHsm) + } }) } } From 2240ebbadc8d3e96fde6b433dc44fd2abc31ec61 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Thu, 7 Oct 2021 17:19:55 -0700 Subject: [PATCH 157/195] Add NameValidator interface and implement it for azurekms. --- kms/apiv1/options.go | 6 ++++++ kms/azurekms/key_vault.go | 6 ++++++ kms/azurekms/key_vault_test.go | 27 +++++++++++++++++++++++++++ kms/azurekms/utils_test.go | 1 + 4 files changed, 40 insertions(+) diff --git a/kms/apiv1/options.go b/kms/apiv1/options.go index 37c1fd4c..1faf3e7e 100644 --- a/kms/apiv1/options.go +++ b/kms/apiv1/options.go @@ -29,6 +29,12 @@ type CertificateManager interface { StoreCertificate(req *StoreCertificateRequest) error } +// ValidateName is an interface that KeyManager can implement to validate a +// given name or URI. +type NameValidator interface { + ValidateName(s string) error +} + // ErrNotImplemented is the type of error returned if an operation is not // implemented. type ErrNotImplemented struct { diff --git a/kms/azurekms/key_vault.go b/kms/azurekms/key_vault.go index 4a927d4f..5bd31d30 100644 --- a/kms/azurekms/key_vault.go +++ b/kms/azurekms/key_vault.go @@ -268,3 +268,9 @@ func (k *KeyVault) CreateSigner(req *apiv1.CreateSignerRequest) (crypto.Signer, func (k *KeyVault) Close() error { return nil } + +// ValidateName validates that the given string is a valid URI. +func (k *KeyVault) ValidateName(s string) error { + _, _, _, _, err := parseKeyName(s) + return err +} diff --git a/kms/azurekms/key_vault_test.go b/kms/azurekms/key_vault_test.go index 0f6d7e0e..1f26e1ef 100644 --- a/kms/azurekms/key_vault_test.go +++ b/kms/azurekms/key_vault_test.go @@ -552,3 +552,30 @@ func Test_keyType_KeyType(t *testing.T) { }) } } + +func TestKeyVault_ValidateName(t *testing.T) { + type args struct { + s string + } + tests := []struct { + name string + args args + wantErr bool + }{ + {"ok", args{"azurekms:name=my-key;vault=my-vault"}, false}, + {"ok hsm", args{"azurekms:name=my-key;vault=my-vault?hsm=true"}, false}, + {"fail scheme", args{"azure:name=my-key;vault=my-vault"}, true}, + {"fail parse uri", args{"azurekms:name=%ZZ;vault=my-vault"}, true}, + {"fail no name", args{"azurekms:vault=my-vault"}, true}, + {"fail no vault", args{"azurekms:name=my-key"}, true}, + {"fail empty", args{""}, true}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + k := &KeyVault{} + if err := k.ValidateName(tt.args.s); (err != nil) != tt.wantErr { + t.Errorf("KeyVault.ValidateName() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/kms/azurekms/utils_test.go b/kms/azurekms/utils_test.go index 03d3f6e2..000a9d6b 100644 --- a/kms/azurekms/utils_test.go +++ b/kms/azurekms/utils_test.go @@ -65,6 +65,7 @@ func Test_parseKeyName(t *testing.T) { {"fail empty name", args{"azurekms:name=;vault=my-vault"}, "", "", "", false, true}, {"fail no vault", args{"azurekms:name=my-key"}, "", "", "", false, true}, {"fail empty vault", args{"azurekms:name=my-key;vault="}, "", "", "", false, true}, + {"fail empty", args{""}, "", "", "", false, true}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { From d8720c3723bbab5f6ba00ca58fbb6fc1020cd8a2 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Thu, 7 Oct 2021 17:21:40 -0700 Subject: [PATCH 158/195] Update linkedca package. --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 43590e4a..f5930ce2 100644 --- a/go.mod +++ b/go.mod @@ -33,7 +33,7 @@ require ( go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352 go.step.sm/cli-utils v0.4.1 go.step.sm/crypto v0.11.0 - go.step.sm/linkedca v0.5.0 + go.step.sm/linkedca v0.7.0 golang.org/x/crypto v0.0.0-20210915214749-c084706c2272 golang.org/x/net v0.0.0-20210913180222-943fd674d43e google.golang.org/api v0.47.0 diff --git a/go.sum b/go.sum index cf33febd..05b0f579 100644 --- a/go.sum +++ b/go.sum @@ -571,8 +571,8 @@ go.step.sm/cli-utils v0.4.1/go.mod h1:hWYVOSlw8W9Pd+BwIbs/aftVVMRms3EG7Q2qLRwc0W go.step.sm/crypto v0.9.0/go.mod h1:+CYG05Mek1YDqi5WK0ERc6cOpKly2i/a5aZmU1sfGj0= go.step.sm/crypto v0.11.0 h1:VDpeVgEmqme/FK2w5QINxkOQ1FWOm/Wi2TwQXiacKr8= go.step.sm/crypto v0.11.0/go.mod h1:5YzQ85BujYBu6NH18jw7nFjwuRnDch35nLzH0ES5sKg= -go.step.sm/linkedca v0.5.0 h1:oZVRSpElM7lAL1XN2YkjdHwI/oIZ+1ULOnuqYPM6xjY= -go.step.sm/linkedca v0.5.0/go.mod h1:5uTRjozEGSPAZal9xJqlaD38cvJcLe3o1VAFVjqcORo= +go.step.sm/linkedca v0.7.0 h1:ydYigs0CgLFkPGjOO4KJcAcAWbuPP8ECF1IsyHdftYc= +go.step.sm/linkedca v0.7.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.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= From 822a1e3bdb0d891dfd14d2c63b1f440ff340c84d Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Thu, 7 Oct 2021 17:23:56 -0700 Subject: [PATCH 159/195] Add variable with the default implementation. --- kms/kms.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/kms/kms.go b/kms/kms.go index e1b76f1a..92b544df 100644 --- a/kms/kms.go +++ b/kms/kms.go @@ -8,7 +8,7 @@ import ( "github.com/smallstep/certificates/kms/apiv1" // Enable default implementation - _ "github.com/smallstep/certificates/kms/softkms" + "github.com/smallstep/certificates/kms/softkms" ) // KeyManager is the interface implemented by all the KMS. @@ -21,6 +21,9 @@ type CertificateManager = apiv1.CertificateManager // Options are the KMS options. They represent the kms object in the ca.json. type Options = apiv1.Options +// Default is the implementation of the default KMS. +var Default = &softkms.SoftKMS{} + // New initializes a new KMS from the given type. func New(ctx context.Context, opts apiv1.Options) (KeyManager, error) { if err := opts.Validate(); err != nil { From ece67feffff32bfa6f4746e36cb38ebdb493f241 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Thu, 7 Oct 2021 17:28:39 -0700 Subject: [PATCH 160/195] Add support for kms in pki package. Adding support to kms in the pki packages opens the door to use kms implementations in `step ca init` --- pki/pki.go | 180 ++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 144 insertions(+), 36 deletions(-) diff --git a/pki/pki.go b/pki/pki.go index 12e71e47..41a644e1 100644 --- a/pki/pki.go +++ b/pki/pki.go @@ -26,13 +26,14 @@ import ( "github.com/smallstep/certificates/cas" "github.com/smallstep/certificates/cas/apiv1" "github.com/smallstep/certificates/db" + "github.com/smallstep/certificates/kms" + kmsapi "github.com/smallstep/certificates/kms/apiv1" "github.com/smallstep/nosql" "go.step.sm/cli-utils/config" "go.step.sm/cli-utils/errs" "go.step.sm/cli-utils/fileutil" "go.step.sm/cli-utils/ui" "go.step.sm/crypto/jose" - "go.step.sm/crypto/keyutil" "go.step.sm/crypto/pemutil" "go.step.sm/linkedca" "golang.org/x/crypto/ssh" @@ -168,14 +169,18 @@ func GetProvisionerKey(caURL, rootFile, kid string) (string, error) { } type options struct { - provisioner string - pkiOnly bool - enableACME bool - enableSSH bool - enableAdmin bool - noDB bool - isHelm bool - deploymentType DeploymentType + provisioner string + pkiOnly bool + enableACME bool + enableSSH bool + enableAdmin bool + noDB bool + isHelm bool + deploymentType DeploymentType + rootKeyURI string + intermediateKeyURI string + hostKeyURI string + userKeyURI string } // Option is the type of a configuration option on the pki constructor. @@ -258,6 +263,26 @@ func WithDeploymentType(dt DeploymentType) Option { } } +// WithKMS enabled the kms with the given name. +func WithKMS(name string) Option { + return func(p *PKI) { + typ := linkedca.KMS_Type_value[strings.ToUpper(name)] + p.Configuration.Kms = &linkedca.KMS{ + Type: linkedca.KMS_Type(typ), + } + } +} + +// WithKeyURIs defines the key uris for X.509 and SSH keys. +func WithKeyURIs(rootKey, intermediateKey, hostKey, userKey string) Option { + return func(p *PKI) { + p.options.rootKeyURI = rootKey + p.options.intermediateKeyURI = intermediateKey + p.options.hostKeyURI = hostKey + p.options.userKeyURI = userKey + } +} + // PKI represents the Public Key Infrastructure used by a certificate authority. type PKI struct { linkedca.Configuration @@ -265,6 +290,7 @@ type PKI struct { casOptions apiv1.Options caService apiv1.CertificateAuthorityService caCreator apiv1.CertificateAuthorityCreator + keyManager kmsapi.KeyManager config string defaults string ottPublicKey *jose.JSONWebKey @@ -303,8 +329,9 @@ func New(o apiv1.Options, opts ...Option) (*PKI, error) { Files: make(map[string][]byte), }, casOptions: o, - caCreator: caCreator, caService: caService, + caCreator: caCreator, + keyManager: o.KeyManager, options: &options{ provisioner: "step-cli", }, @@ -313,6 +340,11 @@ func New(o apiv1.Options, opts ...Option) (*PKI, error) { fn(p) } + // Use default key manager + if p.keyManager != nil { + p.keyManager = kms.Default + } + // Use /home/step as the step path in helm configurations. // Use the current step path when creating pki in files. var public, private, config string @@ -448,11 +480,18 @@ func (p *PKI) GenerateKeyPairs(pass []byte) error { // GenerateRootCertificate generates a root certificate with the given name // and using the default key type. func (p *PKI) GenerateRootCertificate(name, org, resource string, pass []byte) (*apiv1.CreateCertificateAuthorityResponse, error) { + if uri := p.options.rootKeyURI; uri != "" { + p.RootKey[0] = uri + } + resp, err := p.caCreator.CreateCertificateAuthority(&apiv1.CreateCertificateAuthorityRequest{ - Name: resource + "-Root-CA", - Type: apiv1.RootCA, - Lifetime: 10 * 365 * 24 * time.Hour, - CreateKey: nil, // use default + Name: resource + "-Root-CA", + Type: apiv1.RootCA, + Lifetime: 10 * 365 * 24 * time.Hour, + CreateKey: &apiv1.CreateKeyRequest{ + Name: p.RootKey[0], + SignatureAlgorithm: kmsapi.UnspecifiedSignAlgorithm, + }, Template: &x509.Certificate{ Subject: pkix.Name{ CommonName: name + " Root CA", @@ -469,6 +508,13 @@ func (p *PKI) GenerateRootCertificate(name, org, resource string, pass []byte) ( return nil, err } + // Replace key name with the one from the key manager if available. On + // softcas this will be the original filename, on any other kms will be the + // uri to the key. + if resp.KeyName != "" { + p.RootKey[0] = resp.KeyName + } + // PrivateKey will only be set if we have access to it (SoftCAS). if err := p.WriteRootCertificate(resp.Certificate, resp.PrivateKey, pass); err != nil { return nil, err @@ -495,11 +541,18 @@ func (p *PKI) WriteRootCertificate(rootCrt *x509.Certificate, rootKey interface{ // GenerateIntermediateCertificate generates an intermediate certificate with // the given name and using the default key type. func (p *PKI) GenerateIntermediateCertificate(name, org, resource string, parent *apiv1.CreateCertificateAuthorityResponse, pass []byte) error { + if uri := p.options.intermediateKeyURI; uri != "" { + p.IntermediateKey = uri + } + resp, err := p.caCreator.CreateCertificateAuthority(&apiv1.CreateCertificateAuthorityRequest{ - Name: resource + "-Intermediate-CA", - Type: apiv1.IntermediateCA, - Lifetime: 10 * 365 * 24 * time.Hour, - CreateKey: nil, // use default + Name: resource + "-Intermediate-CA", + Type: apiv1.IntermediateCA, + Lifetime: 10 * 365 * 24 * time.Hour, + CreateKey: &apiv1.CreateKeyRequest{ + Name: p.IntermediateKey, + SignatureAlgorithm: kmsapi.UnspecifiedSignAlgorithm, + }, Template: &x509.Certificate{ Subject: pkix.Name{ CommonName: name + " Intermediate CA", @@ -519,7 +572,19 @@ func (p *PKI) GenerateIntermediateCertificate(name, org, resource string, parent p.casOptions.CertificateAuthority = resp.Name p.Files[p.Intermediate] = encodeCertificate(resp.Certificate) - p.Files[p.IntermediateKey], err = encodePrivateKey(resp.PrivateKey, pass) + + // Replace the key name with the one from the key manager. On softcas this + // will be the original filename, on any other kms will be the uri to the + // key. + if resp.KeyName != "" { + p.IntermediateKey = resp.KeyName + } + + // If a kms is used it will not have the private key + if resp.PrivateKey != nil { + p.Files[p.IntermediateKey], err = encodePrivateKey(resp.PrivateKey, pass) + } + return err } @@ -564,27 +629,63 @@ func (p *PKI) GetCertificateAuthority() error { // GenerateSSHSigningKeys generates and encrypts a private key used for signing // SSH user certificates and a private key used for signing host certificates. func (p *PKI) GenerateSSHSigningKeys(password []byte) error { - var pubNames = []string{p.Ssh.HostPublicKey, p.Ssh.UserPublicKey} - var privNames = []string{p.Ssh.HostKey, p.Ssh.UserKey} - for i := 0; i < 2; i++ { - pub, priv, err := keyutil.GenerateDefaultKeyPair() - if err != nil { - return err - } - if _, ok := priv.(crypto.Signer); !ok { - return errors.Errorf("key of type %T is not a crypto.Signer", priv) - } - sshKey, err := ssh.NewPublicKey(pub) - if err != nil { - return errors.Wrapf(err, "error converting public key") - } - p.Files[pubNames[i]] = ssh.MarshalAuthorizedKey(sshKey) - p.Files[privNames[i]], err = encodePrivateKey(priv, password) + // Enable SSH + p.options.enableSSH = true + + // Create SSH key used to sign host certificates. Using + // kmsapi.UnspecifiedSignAlgorithm will default to the default algorithm. + name := p.Ssh.HostPublicKey + if uri := p.options.hostKeyURI; uri != "" { + name = uri + } + resp, err := p.keyManager.CreateKey(&kmsapi.CreateKeyRequest{ + Name: name, + SignatureAlgorithm: kmsapi.UnspecifiedSignAlgorithm, + }) + if err != nil { + return err + } + sshKey, err := ssh.NewPublicKey(resp.PublicKey) + if err != nil { + return errors.Wrapf(err, "error converting public key") + } + p.Files[resp.Name] = ssh.MarshalAuthorizedKey(sshKey) + + // On softkms we will have the private key + if resp.PrivateKey != nil { + p.Files[p.Ssh.HostKey], err = encodePrivateKey(resp.PrivateKey, password) if err != nil { return err } } - p.options.enableSSH = true + + // Create SSH key used to sign user certificates. Using + // kmsapi.UnspecifiedSignAlgorithm will default to the default algorithm. + name = p.Ssh.UserPublicKey + if uri := p.options.userKeyURI; uri != "" { + name = uri + } + resp, err = p.keyManager.CreateKey(&kmsapi.CreateKeyRequest{ + Name: name, + SignatureAlgorithm: kmsapi.UnspecifiedSignAlgorithm, + }) + if err != nil { + return err + } + sshKey, err = ssh.NewPublicKey(resp.PublicKey) + if err != nil { + return errors.Wrapf(err, "error converting public key") + } + p.Files[resp.Name] = ssh.MarshalAuthorizedKey(sshKey) + + // On softkms we will have the private key + if resp.PrivateKey != nil { + p.Files[p.Ssh.UserKey], err = encodePrivateKey(resp.PrivateKey, password) + if err != nil { + return err + } + } + return nil } @@ -684,6 +785,13 @@ func (p *PKI) GenerateConfig(opt ...ConfigOption) (*authconfig.Config, error) { config.AuthorityConfig.DeploymentType = LinkedDeployment.String() } + // Enable KMS if necessary + if p.Kms != nil { + config.KMS = &kmsapi.Options{ + Type: strings.ToLower(p.Kms.Type.String()), + } + } + // On standalone deployments add the provisioners to either the ca.json or // the database. var provisioners []provisioner.Interface From c638c282d8c12ab20f51ec61f74fd0dbe0669468 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Thu, 7 Oct 2021 17:30:28 -0700 Subject: [PATCH 161/195] Add omitempty to KMS options. --- kms/apiv1/options.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/kms/apiv1/options.go b/kms/apiv1/options.go index 1faf3e7e..79b07a60 100644 --- a/kms/apiv1/options.go +++ b/kms/apiv1/options.go @@ -89,18 +89,18 @@ type Options struct { Type string `json:"type"` // Path to the credentials file used in CloudKMS and AmazonKMS. - CredentialsFile string `json:"credentialsFile"` + CredentialsFile string `json:"credentialsFile,omitempty"` // URI is based on the PKCS #11 URI Scheme defined in // https://tools.ietf.org/html/rfc7512 and represents the configuration used // to connect to the KMS. // // Used by: pkcs11 - URI string `json:"uri"` + URI string `json:"uri,omitempty"` // Pin used to access the PKCS11 module. It can be defined in the URI using // the pin-value or pin-source properties. - Pin string `json:"pin"` + Pin string `json:"pin,omitempty"` // ManagementKey used in YubiKeys. Default management key is the hexadecimal // string 010203040506070801020304050607080102030405060708: @@ -109,13 +109,13 @@ type Options struct { // 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, // 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, // } - ManagementKey string `json:"managementKey"` + ManagementKey string `json:"managementKey,omitempty"` // Region to use in AmazonKMS. - Region string `json:"region"` + Region string `json:"region,omitempty"` // Profile to use in AmazonKMS. - Profile string `json:"profile"` + Profile string `json:"profile,omitempty"` } // Validate checks the fields in Options. From f6e69bf826be1b2ebbfb25e5cb39344d29ce4d55 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Thu, 7 Oct 2021 17:37:47 -0700 Subject: [PATCH 162/195] Fix typo. --- kms/azurekms/key_vault.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kms/azurekms/key_vault.go b/kms/azurekms/key_vault.go index 5bd31d30..1fb8572c 100644 --- a/kms/azurekms/key_vault.go +++ b/kms/azurekms/key_vault.go @@ -22,7 +22,7 @@ func init() { // Scheme is the scheme used for Azure Key Vault uris. const Scheme = "azurekms" -// keyIDRegexp is the regular experssion that Key Vault uses for on the kid. We +// keyIDRegexp is the regular expression that Key Vault uses for on the kid. We // can extract the vault, name and version of the key. var keyIDRegexp = regexp.MustCompile("^https://([0-9a-zA-Z-]+).vault.azure.net/keys/([0-9a-zA-Z-]+)/([0-9a-zA-Z-]+)$") From ca59ee43c57f0c7a297b4a2acf4521f463dc0b48 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Thu, 7 Oct 2021 17:41:33 -0700 Subject: [PATCH 163/195] Update changelog. --- CHANGELOG.md | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a902ee2f..3a726dc9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased - 0.17.5] - DATE ### Added +- Support for Azure Key Vault as a KMS. +- Adapt `pki` package to support key managers. ### Changed ### Deprecated ### Removed @@ -13,13 +15,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Security ## [0.17.4] - 2021-09-28 -### Added -### Changed -### Deprecated -### Removed ### Fixed - Support host-only or user-only SSH CA. -### Security ## [0.17.3] - 2021-09-24 ### Added @@ -55,4 +52,3 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Update TLS cipher suites to include 1.3 ### Security - Fix key version when SHA512WithRSA is used. There was a typo creating RSA keys with SHA256 digests instead of SHA512. - From 933b40a02ad99c27717e602bf719056b61e39459 Mon Sep 17 00:00:00 2001 From: max furman Date: Fri, 8 Oct 2021 14:59:57 -0400 Subject: [PATCH 164/195] Introduce gocritic linter and address warnings --- .golangci.yml | 24 ++- acme/api/account.go | 2 +- acme/api/account_test.go | 4 +- acme/api/handler_test.go | 16 +- acme/api/middleware.go | 4 +- acme/api/middleware_test.go | 56 +++---- acme/api/order_test.go | 18 +-- acme/challenge.go | 10 +- acme/challenge_test.go | 2 +- acme/db/nosql/account_test.go | 70 ++++----- acme/db/nosql/authz_test.go | 66 ++++---- acme/db/nosql/certificate_test.go | 22 ++- acme/db/nosql/challenge_test.go | 56 ++++--- acme/db/nosql/nonce.go | 2 +- acme/db/nosql/nonce_test.go | 8 +- acme/db/nosql/nosql.go | 2 +- acme/db/nosql/nosql_test.go | 4 +- acme/db/nosql/order_test.go | 89 +++++------ acme/order.go | 1 + api/api.go | 29 ++-- api/api_test.go | 36 ++--- api/errors.go | 10 +- api/ssh.go | 10 +- api/sshRekey.go | 2 +- api/sshRenew.go | 2 +- api/sshRevoke.go | 2 +- api/ssh_test.go | 2 +- authority/admin/api/middleware.go | 2 +- authority/admin/db/nosql/admin_test.go | 131 +++++++--------- authority/admin/db/nosql/nosql.go | 2 +- authority/admin/db/nosql/provisioner_test.go | 147 ++++++++---------- authority/administrator/collection.go | 4 +- authority/admins.go | 4 +- authority/authority.go | 6 +- authority/authorize.go | 12 +- authority/authorize_test.go | 2 +- authority/config/types.go | 2 +- authority/linkedca.go | 4 +- authority/options.go | 12 +- authority/provisioner/aws.go | 22 +-- authority/provisioner/aws_test.go | 8 +- authority/provisioner/azure.go | 14 +- authority/provisioner/azure_test.go | 8 +- authority/provisioner/collection.go | 15 +- authority/provisioner/gcp.go | 22 +-- authority/provisioner/gcp_test.go | 8 +- authority/provisioner/keystore.go | 2 +- authority/provisioner/noop.go | 2 +- authority/provisioner/oidc.go | 4 +- authority/provisioner/oidc_test.go | 46 +++--- authority/provisioner/options.go | 2 +- authority/provisioner/provisioner.go | 2 +- .../provisioner/sign_ssh_options_test.go | 16 +- authority/provisioner/sshpop_test.go | 8 +- authority/provisioner/utils_test.go | 4 +- authority/ssh.go | 6 +- authority/tls.go | 18 +-- authority/tls_test.go | 1 + ca/acmeClient.go | 2 +- ca/acmeClient_test.go | 1 + ca/adminClient.go | 18 ++- ca/bootstrap.go | 2 +- ca/ca.go | 52 +++---- ca/ca_test.go | 10 +- ca/client.go | 32 ++-- ca/client_test.go | 2 +- ca/identity/client_test.go | 7 +- ca/tls.go | 8 +- cas/cloudcas/cloudcas.go | 4 +- cas/cloudcas/cloudcas_test.go | 11 +- cas/softcas/softcas.go | 4 +- cas/softcas/softcas_test.go | 2 +- cas/stepcas/stepcas.go | 4 +- cas/stepcas/x5c_issuer.go | 4 +- cas/stepcas/x5c_issuer_test.go | 2 +- cmd/step-awskms-init/main.go | 14 +- cmd/step-ca/main.go | 8 +- cmd/step-cloudkms-init/main.go | 14 +- cmd/step-pkcs11-init/main.go | 8 +- cmd/step-yubikey-init/main.go | 8 +- commands/app.go | 10 +- commands/export.go | 12 +- commands/onboard.go | 34 ++-- db/db_test.go | 8 +- kms/sshagentkms/sshagentkms_test.go | 2 + pki/pki.go | 55 +++---- scep/api/api.go | 4 +- templates/templates.go | 14 +- 88 files changed, 699 insertions(+), 742 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 92af7723..cf389517 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -36,22 +36,30 @@ linters-settings: - performance - style - experimental + - diagnostic disabled-checks: - - wrapperFunc - - dupImport # https://github.com/go-critic/go-critic/issues/845 + - commentFormatting + - commentedOutCode + - evalOrder + - hugeParam + - octalLiteral + - rangeValCopy + - tooManyResultsChecker + - unnamedResult linters: disable-all: true enable: - - gofmt - - revive - - govet - - misspell - - ineffassign - deadcode + - gocritic + - gofmt + - gosimple + - govet + - ineffassign + - misspell + - revive - staticcheck - unused - - gosimple run: skip-dirs: diff --git a/acme/api/account.go b/acme/api/account.go index b733c679..259cb2a2 100644 --- a/acme/api/account.go +++ b/acme/api/account.go @@ -19,7 +19,7 @@ type NewAccountRequest struct { func validateContacts(cs []string) error { for _, c := range cs { - if len(c) == 0 { + if c == "" { return acme.NewError(acme.ErrorMalformedType, "contact cannot be empty string") } } diff --git a/acme/api/account_test.go b/acme/api/account_test.go index c4d7a812..a45751a0 100644 --- a/acme/api/account_test.go +++ b/acme/api/account_test.go @@ -178,7 +178,7 @@ func TestHandler_GetOrdersByAccountID(t *testing.T) { provName := url.PathEscape(prov.GetName()) baseURL := &url.URL{Scheme: "https", Host: "test.ca.smallstep.com"} - url := fmt.Sprintf("http://ca.smallstep.com/acme/%s/account/%s/orders", provName, accID) + u := fmt.Sprintf("http://ca.smallstep.com/acme/%s/account/%s/orders", provName, accID) oids := []string{"foo", "bar"} oidURLs := []string{ @@ -255,7 +255,7 @@ func TestHandler_GetOrdersByAccountID(t *testing.T) { tc := run(t) t.Run(name, func(t *testing.T) { h := &Handler{db: tc.db, linker: NewLinker("dns", "acme")} - req := httptest.NewRequest("GET", url, nil) + req := httptest.NewRequest("GET", u, nil) req = req.WithContext(tc.ctx) w := httptest.NewRecorder() h.GetOrdersByAccountID(w, req) diff --git a/acme/api/handler_test.go b/acme/api/handler_test.go index f354bbac..8112ad4c 100644 --- a/acme/api/handler_test.go +++ b/acme/api/handler_test.go @@ -148,7 +148,7 @@ func TestHandler_GetAuthorization(t *testing.T) { // Request with chi context chiCtx := chi.NewRouteContext() chiCtx.URLParams.Add("authzID", az.ID) - url := fmt.Sprintf("%s/acme/%s/authz/%s", + u := fmt.Sprintf("%s/acme/%s/authz/%s", baseURL.String(), provName, az.ID) type test struct { @@ -280,7 +280,7 @@ func TestHandler_GetAuthorization(t *testing.T) { expB, err := json.Marshal(az) assert.FatalError(t, err) assert.Equals(t, bytes.TrimSpace(body), expB) - assert.Equals(t, res.Header["Location"], []string{url}) + assert.Equals(t, res.Header["Location"], []string{u}) assert.Equals(t, res.Header["Content-Type"], []string{"application/json"}) } }) @@ -314,7 +314,7 @@ func TestHandler_GetCertificate(t *testing.T) { // Request with chi context chiCtx := chi.NewRouteContext() chiCtx.URLParams.Add("certID", certID) - url := fmt.Sprintf("%s/acme/%s/certificate/%s", + u := fmt.Sprintf("%s/acme/%s/certificate/%s", baseURL.String(), provName, certID) type test struct { @@ -396,7 +396,7 @@ func TestHandler_GetCertificate(t *testing.T) { tc := run(t) t.Run(name, func(t *testing.T) { h := &Handler{db: tc.db} - req := httptest.NewRequest("GET", url, nil) + req := httptest.NewRequest("GET", u, nil) req = req.WithContext(tc.ctx) w := httptest.NewRecorder() h.GetCertificate(w, req) @@ -434,7 +434,7 @@ func TestHandler_GetChallenge(t *testing.T) { baseURL := &url.URL{Scheme: "https", Host: "test.ca.smallstep.com"} - url := fmt.Sprintf("%s/acme/%s/challenge/%s/%s", + u := fmt.Sprintf("%s/acme/%s/challenge/%s/%s", baseURL.String(), provName, "authzID", "chID") type test struct { @@ -635,7 +635,7 @@ func TestHandler_GetChallenge(t *testing.T) { AuthorizationID: "authzID", Type: acme.HTTP01, AccountID: "accID", - URL: url, + URL: u, Error: acme.NewError(acme.ErrorConnectionType, "force"), }, vco: &acme.ValidateChallengeOptions{ @@ -652,7 +652,7 @@ func TestHandler_GetChallenge(t *testing.T) { tc := run(t) t.Run(name, func(t *testing.T) { h := &Handler{db: tc.db, linker: NewLinker("dns", "acme"), validateChallengeOptions: tc.vco} - req := httptest.NewRequest("GET", url, nil) + req := httptest.NewRequest("GET", u, nil) req = req.WithContext(tc.ctx) w := httptest.NewRecorder() h.GetChallenge(w, req) @@ -678,7 +678,7 @@ func TestHandler_GetChallenge(t *testing.T) { assert.FatalError(t, err) assert.Equals(t, bytes.TrimSpace(body), expB) assert.Equals(t, res.Header["Link"], []string{fmt.Sprintf("<%s/acme/%s/authz/%s>;rel=\"up\"", baseURL, provName, "authzID")}) - assert.Equals(t, res.Header["Location"], []string{url}) + assert.Equals(t, res.Header["Location"], []string{u}) assert.Equals(t, res.Header["Content-Type"], []string{"application/json"}) } }) diff --git a/acme/api/middleware.go b/acme/api/middleware.go index b2244dd7..bc67dbc6 100644 --- a/acme/api/middleware.go +++ b/acme/api/middleware.go @@ -223,7 +223,7 @@ func (h *Handler) validateJWS(next nextHTTP) nextHTTP { api.WriteError(w, acme.NewError(acme.ErrorMalformedType, "jwk and kid are mutually exclusive")) return } - if hdr.JSONWebKey == nil && len(hdr.KeyID) == 0 { + if hdr.JSONWebKey == nil && hdr.KeyID == "" { api.WriteError(w, acme.NewError(acme.ErrorMalformedType, "either jwk or kid must be defined in jws protected header")) return } @@ -367,7 +367,7 @@ func (h *Handler) verifyAndExtractJWSPayload(next nextHTTP) nextHTTP { api.WriteError(w, err) return } - if len(jwk.Algorithm) != 0 && jwk.Algorithm != jws.Signatures[0].Protected.Algorithm { + if jwk.Algorithm != "" && jwk.Algorithm != jws.Signatures[0].Protected.Algorithm { api.WriteError(w, acme.NewError(acme.ErrorMalformedType, "verifier and signature algorithm do not match")) return } diff --git a/acme/api/middleware_test.go b/acme/api/middleware_test.go index 40090e83..e8d22d53 100644 --- a/acme/api/middleware_test.go +++ b/acme/api/middleware_test.go @@ -108,7 +108,7 @@ func TestHandler_baseURLFromRequest(t *testing.T) { } func TestHandler_addNonce(t *testing.T) { - url := "https://ca.smallstep.com/acme/new-nonce" + u := "https://ca.smallstep.com/acme/new-nonce" type test struct { db acme.DB err *acme.Error @@ -141,7 +141,7 @@ func TestHandler_addNonce(t *testing.T) { tc := run(t) t.Run(name, func(t *testing.T) { h := &Handler{db: tc.db} - req := httptest.NewRequest("GET", url, nil) + req := httptest.NewRequest("GET", u, nil) w := httptest.NewRecorder() h.addNonce(testNext)(w, req) res := w.Result() @@ -230,7 +230,7 @@ func TestHandler_verifyContentType(t *testing.T) { prov := newProv() escProvName := url.PathEscape(prov.GetName()) baseURL := &url.URL{Scheme: "https", Host: "test.ca.smallstep.com"} - url := fmt.Sprintf("%s/acme/%s/certificate/abc123", baseURL.String(), escProvName) + u := fmt.Sprintf("%s/acme/%s/certificate/abc123", baseURL.String(), escProvName) type test struct { h Handler ctx context.Context @@ -245,7 +245,7 @@ func TestHandler_verifyContentType(t *testing.T) { h: Handler{ linker: NewLinker("dns", "acme"), }, - url: url, + url: u, ctx: context.Background(), contentType: "foo", statusCode: 500, @@ -257,7 +257,7 @@ func TestHandler_verifyContentType(t *testing.T) { h: Handler{ linker: NewLinker("dns", "acme"), }, - url: url, + url: u, ctx: context.WithValue(context.Background(), provisionerContextKey, prov), contentType: "foo", statusCode: 400, @@ -319,11 +319,11 @@ func TestHandler_verifyContentType(t *testing.T) { for name, run := range tests { tc := run(t) t.Run(name, func(t *testing.T) { - _url := url + _u := u if tc.url != "" { - _url = tc.url + _u = tc.url } - req := httptest.NewRequest("GET", _url, nil) + req := httptest.NewRequest("GET", _u, nil) req = req.WithContext(tc.ctx) req.Header.Add("Content-Type", tc.contentType) w := httptest.NewRecorder() @@ -353,7 +353,7 @@ func TestHandler_verifyContentType(t *testing.T) { } func TestHandler_isPostAsGet(t *testing.T) { - url := "https://ca.smallstep.com/acme/new-account" + u := "https://ca.smallstep.com/acme/new-account" type test struct { ctx context.Context err *acme.Error @@ -392,7 +392,7 @@ func TestHandler_isPostAsGet(t *testing.T) { tc := run(t) t.Run(name, func(t *testing.T) { h := &Handler{} - req := httptest.NewRequest("GET", url, nil) + req := httptest.NewRequest("GET", u, nil) req = req.WithContext(tc.ctx) w := httptest.NewRecorder() h.isPostAsGet(testNext)(w, req) @@ -430,7 +430,7 @@ func (errReader) Close() error { } func TestHandler_parseJWS(t *testing.T) { - url := "https://ca.smallstep.com/acme/new-account" + u := "https://ca.smallstep.com/acme/new-account" type test struct { next nextHTTP body io.Reader @@ -483,7 +483,7 @@ func TestHandler_parseJWS(t *testing.T) { tc := run(t) t.Run(name, func(t *testing.T) { h := &Handler{} - req := httptest.NewRequest("GET", url, tc.body) + req := httptest.NewRequest("GET", u, tc.body) w := httptest.NewRecorder() h.parseJWS(tc.next)(w, req) res := w.Result() @@ -528,7 +528,7 @@ func TestHandler_verifyAndExtractJWSPayload(t *testing.T) { assert.FatalError(t, err) parsedJWS, err := jose.ParseJWS(raw) assert.FatalError(t, err) - url := "https://ca.smallstep.com/acme/account/1234" + u := "https://ca.smallstep.com/acme/account/1234" type test struct { ctx context.Context next func(http.ResponseWriter, *http.Request) @@ -681,7 +681,7 @@ func TestHandler_verifyAndExtractJWSPayload(t *testing.T) { tc := run(t) t.Run(name, func(t *testing.T) { h := &Handler{} - req := httptest.NewRequest("GET", url, nil) + req := httptest.NewRequest("GET", u, nil) req = req.WithContext(tc.ctx) w := httptest.NewRecorder() h.verifyAndExtractJWSPayload(tc.next)(w, req) @@ -713,7 +713,7 @@ func TestHandler_lookupJWK(t *testing.T) { prov := newProv() provName := url.PathEscape(prov.GetName()) baseURL := &url.URL{Scheme: "https", Host: "test.ca.smallstep.com"} - url := fmt.Sprintf("%s/acme/%s/account/1234", + u := fmt.Sprintf("%s/acme/%s/account/1234", baseURL, provName) jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0) assert.FatalError(t, err) @@ -883,7 +883,7 @@ func TestHandler_lookupJWK(t *testing.T) { tc := run(t) t.Run(name, func(t *testing.T) { h := &Handler{db: tc.db, linker: tc.linker} - req := httptest.NewRequest("GET", url, nil) + req := httptest.NewRequest("GET", u, nil) req = req.WithContext(tc.ctx) w := httptest.NewRecorder() h.lookupJWK(tc.next)(w, req) @@ -934,7 +934,7 @@ func TestHandler_extractJWK(t *testing.T) { assert.FatalError(t, err) parsedJWS, err := jose.ParseJWS(raw) assert.FatalError(t, err) - url := fmt.Sprintf("https://ca.smallstep.com/acme/%s/account/1234", + u := fmt.Sprintf("https://ca.smallstep.com/acme/%s/account/1234", provName) type test struct { db acme.DB @@ -1079,7 +1079,7 @@ func TestHandler_extractJWK(t *testing.T) { tc := run(t) t.Run(name, func(t *testing.T) { h := &Handler{db: tc.db} - req := httptest.NewRequest("GET", url, nil) + req := httptest.NewRequest("GET", u, nil) req = req.WithContext(tc.ctx) w := httptest.NewRecorder() h.extractJWK(tc.next)(w, req) @@ -1108,7 +1108,7 @@ func TestHandler_extractJWK(t *testing.T) { } func TestHandler_validateJWS(t *testing.T) { - url := "https://ca.smallstep.com/acme/account/1234" + u := "https://ca.smallstep.com/acme/account/1234" type test struct { db acme.DB ctx context.Context @@ -1198,7 +1198,7 @@ func TestHandler_validateJWS(t *testing.T) { Algorithm: jose.RS256, JSONWebKey: &pub, ExtraHeaders: map[jose.HeaderKey]interface{}{ - "url": url, + "url": u, }, }, }, @@ -1226,7 +1226,7 @@ func TestHandler_validateJWS(t *testing.T) { Algorithm: jose.RS256, JSONWebKey: &pub, ExtraHeaders: map[jose.HeaderKey]interface{}{ - "url": url, + "url": u, }, }, }, @@ -1298,7 +1298,7 @@ func TestHandler_validateJWS(t *testing.T) { }, ctx: context.WithValue(context.Background(), jwsContextKey, jws), statusCode: 400, - err: acme.NewError(acme.ErrorMalformedType, "url header in JWS (foo) does not match request url (%s)", url), + err: acme.NewError(acme.ErrorMalformedType, "url header in JWS (foo) does not match request url (%s)", u), } }, "fail/both-jwk-kid": func(t *testing.T) test { @@ -1313,7 +1313,7 @@ func TestHandler_validateJWS(t *testing.T) { KeyID: "bar", JSONWebKey: &pub, ExtraHeaders: map[jose.HeaderKey]interface{}{ - "url": url, + "url": u, }, }, }, @@ -1337,7 +1337,7 @@ func TestHandler_validateJWS(t *testing.T) { Protected: jose.Header{ Algorithm: jose.ES256, ExtraHeaders: map[jose.HeaderKey]interface{}{ - "url": url, + "url": u, }, }, }, @@ -1362,7 +1362,7 @@ func TestHandler_validateJWS(t *testing.T) { Algorithm: jose.ES256, KeyID: "bar", ExtraHeaders: map[jose.HeaderKey]interface{}{ - "url": url, + "url": u, }, }, }, @@ -1392,7 +1392,7 @@ func TestHandler_validateJWS(t *testing.T) { Algorithm: jose.ES256, JSONWebKey: &pub, ExtraHeaders: map[jose.HeaderKey]interface{}{ - "url": url, + "url": u, }, }, }, @@ -1422,7 +1422,7 @@ func TestHandler_validateJWS(t *testing.T) { Algorithm: jose.RS256, JSONWebKey: &pub, ExtraHeaders: map[jose.HeaderKey]interface{}{ - "url": url, + "url": u, }, }, }, @@ -1446,7 +1446,7 @@ func TestHandler_validateJWS(t *testing.T) { tc := run(t) t.Run(name, func(t *testing.T) { h := &Handler{db: tc.db} - req := httptest.NewRequest("GET", url, nil) + req := httptest.NewRequest("GET", u, nil) req = req.WithContext(tc.ctx) w := httptest.NewRecorder() h.validateJWS(tc.next)(w, req) diff --git a/acme/api/order_test.go b/acme/api/order_test.go index afb23c3f..3c6d768f 100644 --- a/acme/api/order_test.go +++ b/acme/api/order_test.go @@ -264,7 +264,7 @@ func TestHandler_GetOrder(t *testing.T) { // Request with chi context chiCtx := chi.NewRouteContext() chiCtx.URLParams.Add("ordID", o.ID) - url := fmt.Sprintf("%s/acme/%s/order/%s", + u := fmt.Sprintf("%s/acme/%s/order/%s", baseURL.String(), escProvName, o.ID) type test struct { @@ -422,7 +422,7 @@ func TestHandler_GetOrder(t *testing.T) { tc := run(t) t.Run(name, func(t *testing.T) { h := &Handler{linker: NewLinker("dns", "acme"), db: tc.db} - req := httptest.NewRequest("GET", url, nil) + req := httptest.NewRequest("GET", u, nil) req = req.WithContext(tc.ctx) w := httptest.NewRecorder() h.GetOrder(w, req) @@ -448,7 +448,7 @@ func TestHandler_GetOrder(t *testing.T) { assert.FatalError(t, err) assert.Equals(t, bytes.TrimSpace(body), expB) - assert.Equals(t, res.Header["Location"], []string{url}) + assert.Equals(t, res.Header["Location"], []string{u}) assert.Equals(t, res.Header["Content-Type"], []string{"application/json"}) } }) @@ -663,7 +663,7 @@ func TestHandler_NewOrder(t *testing.T) { prov := newProv() escProvName := url.PathEscape(prov.GetName()) baseURL := &url.URL{Scheme: "https", Host: "test.ca.smallstep.com"} - url := fmt.Sprintf("%s/acme/%s/order/ordID", + u := fmt.Sprintf("%s/acme/%s/order/ordID", baseURL.String(), escProvName) type test struct { @@ -1335,7 +1335,7 @@ func TestHandler_NewOrder(t *testing.T) { tc := run(t) t.Run(name, func(t *testing.T) { h := &Handler{linker: NewLinker("dns", "acme"), db: tc.db} - req := httptest.NewRequest("GET", url, nil) + req := httptest.NewRequest("GET", u, nil) req = req.WithContext(tc.ctx) w := httptest.NewRecorder() h.NewOrder(w, req) @@ -1363,7 +1363,7 @@ func TestHandler_NewOrder(t *testing.T) { tc.vr(t, ro) } - assert.Equals(t, res.Header["Location"], []string{url}) + assert.Equals(t, res.Header["Location"], []string{u}) assert.Equals(t, res.Header["Content-Type"], []string{"application/json"}) } }) @@ -1406,7 +1406,7 @@ func TestHandler_FinalizeOrder(t *testing.T) { // Request with chi context chiCtx := chi.NewRouteContext() chiCtx.URLParams.Add("ordID", o.ID) - url := fmt.Sprintf("%s/acme/%s/order/%s", + u := fmt.Sprintf("%s/acme/%s/order/%s", baseURL.String(), escProvName, o.ID) _csr, err := pemutil.Read("../../authority/testdata/certs/foo.csr") @@ -1625,7 +1625,7 @@ func TestHandler_FinalizeOrder(t *testing.T) { tc := run(t) t.Run(name, func(t *testing.T) { h := &Handler{linker: NewLinker("dns", "acme"), db: tc.db} - req := httptest.NewRequest("GET", url, nil) + req := httptest.NewRequest("GET", u, nil) req = req.WithContext(tc.ctx) w := httptest.NewRecorder() h.FinalizeOrder(w, req) @@ -1654,7 +1654,7 @@ func TestHandler_FinalizeOrder(t *testing.T) { assert.FatalError(t, json.Unmarshal(body, ro)) assert.Equals(t, bytes.TrimSpace(body), expB) - assert.Equals(t, res.Header["Location"], []string{url}) + assert.Equals(t, res.Header["Location"], []string{u}) assert.Equals(t, res.Header["Content-Type"], []string{"application/json"}) } }) diff --git a/acme/challenge.go b/acme/challenge.go index 70c52578..b880708c 100644 --- a/acme/challenge.go +++ b/acme/challenge.go @@ -76,23 +76,23 @@ func (ch *Challenge) Validate(ctx context.Context, db DB, jwk *jose.JSONWebKey, } func http01Validate(ctx context.Context, ch *Challenge, db DB, jwk *jose.JSONWebKey, vo *ValidateChallengeOptions) error { - url := &url.URL{Scheme: "http", Host: ch.Value, Path: fmt.Sprintf("/.well-known/acme-challenge/%s", ch.Token)} + u := &url.URL{Scheme: "http", Host: ch.Value, Path: fmt.Sprintf("/.well-known/acme-challenge/%s", ch.Token)} - resp, err := vo.HTTPGet(url.String()) + resp, err := vo.HTTPGet(u.String()) if err != nil { return storeError(ctx, db, ch, false, WrapError(ErrorConnectionType, err, - "error doing http GET for url %s", url)) + "error doing http GET for url %s", u)) } defer resp.Body.Close() if resp.StatusCode >= 400 { return storeError(ctx, db, ch, false, NewError(ErrorConnectionType, - "error doing http GET for url %s with status code %d", url, resp.StatusCode)) + "error doing http GET for url %s with status code %d", u, resp.StatusCode)) } body, err := ioutil.ReadAll(resp.Body) if err != nil { return WrapErrorISE(err, "error reading "+ - "response body for url %s", url) + "response body for url %s", u) } keyAuth := strings.TrimSpace(string(body)) diff --git a/acme/challenge_test.go b/acme/challenge_test.go index 97c5e4cd..a522790f 100644 --- a/acme/challenge_test.go +++ b/acme/challenge_test.go @@ -1276,7 +1276,7 @@ func newTLSALPNValidationCert(keyAuthHash []byte, obsoleteOID, critical bool, na oid = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 1, 30, 1} } - keyAuthHashEnc, _ := asn1.Marshal(keyAuthHash[:]) + keyAuthHashEnc, _ := asn1.Marshal(keyAuthHash) certTemplate.ExtraExtensions = []pkix.Extension{ { diff --git a/acme/db/nosql/account_test.go b/acme/db/nosql/account_test.go index 5ba99a73..a02e93dc 100644 --- a/acme/db/nosql/account_test.go +++ b/acme/db/nosql/account_test.go @@ -93,8 +93,8 @@ func TestDB_getDBAccount(t *testing.T) { for name, run := range tests { tc := run(t) t.Run(name, func(t *testing.T) { - db := DB{db: tc.db} - if dbacc, err := db.getDBAccount(context.Background(), accID); err != nil { + d := DB{db: tc.db} + if dbacc, err := d.getDBAccount(context.Background(), accID); err != nil { switch k := err.(type) { case *acme.Error: if assert.NotNil(t, tc.acmeErr) { @@ -109,15 +109,13 @@ func TestDB_getDBAccount(t *testing.T) { assert.HasPrefix(t, err.Error(), tc.err.Error()) } } - } else { - if assert.Nil(t, tc.err) { - assert.Equals(t, dbacc.ID, tc.dbacc.ID) - assert.Equals(t, dbacc.Status, tc.dbacc.Status) - assert.Equals(t, dbacc.CreatedAt, tc.dbacc.CreatedAt) - assert.Equals(t, dbacc.DeactivatedAt, tc.dbacc.DeactivatedAt) - assert.Equals(t, dbacc.Contact, tc.dbacc.Contact) - assert.Equals(t, dbacc.Key.KeyID, tc.dbacc.Key.KeyID) - } + } else if assert.Nil(t, tc.err) { + assert.Equals(t, dbacc.ID, tc.dbacc.ID) + assert.Equals(t, dbacc.Status, tc.dbacc.Status) + assert.Equals(t, dbacc.CreatedAt, tc.dbacc.CreatedAt) + assert.Equals(t, dbacc.DeactivatedAt, tc.dbacc.DeactivatedAt) + assert.Equals(t, dbacc.Contact, tc.dbacc.Contact) + assert.Equals(t, dbacc.Key.KeyID, tc.dbacc.Key.KeyID) } }) } @@ -174,8 +172,8 @@ func TestDB_getAccountIDByKeyID(t *testing.T) { for name, run := range tests { tc := run(t) t.Run(name, func(t *testing.T) { - db := DB{db: tc.db} - if retAccID, err := db.getAccountIDByKeyID(context.Background(), kid); err != nil { + d := DB{db: tc.db} + if retAccID, err := d.getAccountIDByKeyID(context.Background(), kid); err != nil { switch k := err.(type) { case *acme.Error: if assert.NotNil(t, tc.acmeErr) { @@ -190,10 +188,8 @@ func TestDB_getAccountIDByKeyID(t *testing.T) { assert.HasPrefix(t, err.Error(), tc.err.Error()) } } - } else { - if assert.Nil(t, tc.err) { - assert.Equals(t, retAccID, accID) - } + } else if assert.Nil(t, tc.err) { + assert.Equals(t, retAccID, accID) } }) } @@ -250,8 +246,8 @@ func TestDB_GetAccount(t *testing.T) { for name, run := range tests { tc := run(t) t.Run(name, func(t *testing.T) { - db := DB{db: tc.db} - if acc, err := db.GetAccount(context.Background(), accID); err != nil { + d := DB{db: tc.db} + if acc, err := d.GetAccount(context.Background(), accID); err != nil { switch k := err.(type) { case *acme.Error: if assert.NotNil(t, tc.acmeErr) { @@ -266,13 +262,11 @@ func TestDB_GetAccount(t *testing.T) { assert.HasPrefix(t, err.Error(), tc.err.Error()) } } - } else { - if assert.Nil(t, tc.err) { - assert.Equals(t, acc.ID, tc.dbacc.ID) - assert.Equals(t, acc.Status, tc.dbacc.Status) - assert.Equals(t, acc.Contact, tc.dbacc.Contact) - assert.Equals(t, acc.Key.KeyID, tc.dbacc.Key.KeyID) - } + } else if assert.Nil(t, tc.err) { + assert.Equals(t, acc.ID, tc.dbacc.ID) + assert.Equals(t, acc.Status, tc.dbacc.Status) + assert.Equals(t, acc.Contact, tc.dbacc.Contact) + assert.Equals(t, acc.Key.KeyID, tc.dbacc.Key.KeyID) } }) } @@ -358,8 +352,8 @@ func TestDB_GetAccountByKeyID(t *testing.T) { for name, run := range tests { tc := run(t) t.Run(name, func(t *testing.T) { - db := DB{db: tc.db} - if acc, err := db.GetAccountByKeyID(context.Background(), kid); err != nil { + d := DB{db: tc.db} + if acc, err := d.GetAccountByKeyID(context.Background(), kid); err != nil { switch k := err.(type) { case *acme.Error: if assert.NotNil(t, tc.acmeErr) { @@ -374,13 +368,11 @@ func TestDB_GetAccountByKeyID(t *testing.T) { assert.HasPrefix(t, err.Error(), tc.err.Error()) } } - } else { - if assert.Nil(t, tc.err) { - assert.Equals(t, acc.ID, tc.dbacc.ID) - assert.Equals(t, acc.Status, tc.dbacc.Status) - assert.Equals(t, acc.Contact, tc.dbacc.Contact) - assert.Equals(t, acc.Key.KeyID, tc.dbacc.Key.KeyID) - } + } else if assert.Nil(t, tc.err) { + assert.Equals(t, acc.ID, tc.dbacc.ID) + assert.Equals(t, acc.Status, tc.dbacc.Status) + assert.Equals(t, acc.Contact, tc.dbacc.Contact) + assert.Equals(t, acc.Key.KeyID, tc.dbacc.Key.KeyID) } }) } @@ -527,8 +519,8 @@ func TestDB_CreateAccount(t *testing.T) { for name, run := range tests { tc := run(t) t.Run(name, func(t *testing.T) { - db := DB{db: tc.db} - if err := db.CreateAccount(context.Background(), tc.acc); err != nil { + d := DB{db: tc.db} + if err := d.CreateAccount(context.Background(), tc.acc); err != nil { if assert.NotNil(t, tc.err) { assert.HasPrefix(t, err.Error(), tc.err.Error()) } @@ -688,8 +680,8 @@ func TestDB_UpdateAccount(t *testing.T) { for name, run := range tests { tc := run(t) t.Run(name, func(t *testing.T) { - db := DB{db: tc.db} - if err := db.UpdateAccount(context.Background(), tc.acc); err != nil { + d := DB{db: tc.db} + if err := d.UpdateAccount(context.Background(), tc.acc); err != nil { if assert.NotNil(t, tc.err) { assert.HasPrefix(t, err.Error(), tc.err.Error()) } diff --git a/acme/db/nosql/authz_test.go b/acme/db/nosql/authz_test.go index 0c2cec50..01c255dc 100644 --- a/acme/db/nosql/authz_test.go +++ b/acme/db/nosql/authz_test.go @@ -97,8 +97,8 @@ func TestDB_getDBAuthz(t *testing.T) { for name, run := range tests { tc := run(t) t.Run(name, func(t *testing.T) { - db := DB{db: tc.db} - if dbaz, err := db.getDBAuthz(context.Background(), azID); err != nil { + d := DB{db: tc.db} + if dbaz, err := d.getDBAuthz(context.Background(), azID); err != nil { switch k := err.(type) { case *acme.Error: if assert.NotNil(t, tc.acmeErr) { @@ -113,18 +113,16 @@ func TestDB_getDBAuthz(t *testing.T) { assert.HasPrefix(t, err.Error(), tc.err.Error()) } } - } else { - if assert.Nil(t, tc.err) { - assert.Equals(t, dbaz.ID, tc.dbaz.ID) - assert.Equals(t, dbaz.AccountID, tc.dbaz.AccountID) - assert.Equals(t, dbaz.Identifier, tc.dbaz.Identifier) - assert.Equals(t, dbaz.Status, tc.dbaz.Status) - assert.Equals(t, dbaz.Token, tc.dbaz.Token) - assert.Equals(t, dbaz.CreatedAt, tc.dbaz.CreatedAt) - assert.Equals(t, dbaz.ExpiresAt, tc.dbaz.ExpiresAt) - assert.Equals(t, dbaz.Error.Error(), tc.dbaz.Error.Error()) - assert.Equals(t, dbaz.Wildcard, tc.dbaz.Wildcard) - } + } else if assert.Nil(t, tc.err) { + assert.Equals(t, dbaz.ID, tc.dbaz.ID) + assert.Equals(t, dbaz.AccountID, tc.dbaz.AccountID) + assert.Equals(t, dbaz.Identifier, tc.dbaz.Identifier) + assert.Equals(t, dbaz.Status, tc.dbaz.Status) + assert.Equals(t, dbaz.Token, tc.dbaz.Token) + assert.Equals(t, dbaz.CreatedAt, tc.dbaz.CreatedAt) + assert.Equals(t, dbaz.ExpiresAt, tc.dbaz.ExpiresAt) + assert.Equals(t, dbaz.Error.Error(), tc.dbaz.Error.Error()) + assert.Equals(t, dbaz.Wildcard, tc.dbaz.Wildcard) } }) } @@ -293,8 +291,8 @@ func TestDB_GetAuthorization(t *testing.T) { for name, run := range tests { tc := run(t) t.Run(name, func(t *testing.T) { - db := DB{db: tc.db} - if az, err := db.GetAuthorization(context.Background(), azID); err != nil { + d := DB{db: tc.db} + if az, err := d.GetAuthorization(context.Background(), azID); err != nil { switch k := err.(type) { case *acme.Error: if assert.NotNil(t, tc.acmeErr) { @@ -309,21 +307,19 @@ func TestDB_GetAuthorization(t *testing.T) { assert.HasPrefix(t, err.Error(), tc.err.Error()) } } - } else { - if assert.Nil(t, tc.err) { - assert.Equals(t, az.ID, tc.dbaz.ID) - assert.Equals(t, az.AccountID, tc.dbaz.AccountID) - assert.Equals(t, az.Identifier, tc.dbaz.Identifier) - assert.Equals(t, az.Status, tc.dbaz.Status) - assert.Equals(t, az.Token, tc.dbaz.Token) - assert.Equals(t, az.Wildcard, tc.dbaz.Wildcard) - assert.Equals(t, az.ExpiresAt, tc.dbaz.ExpiresAt) - assert.Equals(t, az.Challenges, []*acme.Challenge{ - {ID: "foo"}, - {ID: "bar"}, - }) - assert.Equals(t, az.Error.Error(), tc.dbaz.Error.Error()) - } + } else if assert.Nil(t, tc.err) { + assert.Equals(t, az.ID, tc.dbaz.ID) + assert.Equals(t, az.AccountID, tc.dbaz.AccountID) + assert.Equals(t, az.Identifier, tc.dbaz.Identifier) + assert.Equals(t, az.Status, tc.dbaz.Status) + assert.Equals(t, az.Token, tc.dbaz.Token) + assert.Equals(t, az.Wildcard, tc.dbaz.Wildcard) + assert.Equals(t, az.ExpiresAt, tc.dbaz.ExpiresAt) + assert.Equals(t, az.Challenges, []*acme.Challenge{ + {ID: "foo"}, + {ID: "bar"}, + }) + assert.Equals(t, az.Error.Error(), tc.dbaz.Error.Error()) } }) } @@ -445,8 +441,8 @@ func TestDB_CreateAuthorization(t *testing.T) { for name, run := range tests { tc := run(t) t.Run(name, func(t *testing.T) { - db := DB{db: tc.db} - if err := db.CreateAuthorization(context.Background(), tc.az); err != nil { + d := DB{db: tc.db} + if err := d.CreateAuthorization(context.Background(), tc.az); err != nil { if assert.NotNil(t, tc.err) { assert.HasPrefix(t, err.Error(), tc.err.Error()) } @@ -594,8 +590,8 @@ func TestDB_UpdateAuthorization(t *testing.T) { for name, run := range tests { tc := run(t) t.Run(name, func(t *testing.T) { - db := DB{db: tc.db} - if err := db.UpdateAuthorization(context.Background(), tc.az); err != nil { + d := DB{db: tc.db} + if err := d.UpdateAuthorization(context.Background(), tc.az); err != nil { if assert.NotNil(t, tc.err) { assert.HasPrefix(t, err.Error(), tc.err.Error()) } diff --git a/acme/db/nosql/certificate_test.go b/acme/db/nosql/certificate_test.go index 4ec4589e..37a61352 100644 --- a/acme/db/nosql/certificate_test.go +++ b/acme/db/nosql/certificate_test.go @@ -98,8 +98,8 @@ func TestDB_CreateCertificate(t *testing.T) { for name, run := range tests { tc := run(t) t.Run(name, func(t *testing.T) { - db := DB{db: tc.db} - if err := db.CreateCertificate(context.Background(), tc.cert); err != nil { + d := DB{db: tc.db} + if err := d.CreateCertificate(context.Background(), tc.cert); err != nil { if assert.NotNil(t, tc.err) { assert.HasPrefix(t, err.Error(), tc.err.Error()) } @@ -228,8 +228,8 @@ func TestDB_GetCertificate(t *testing.T) { for name, run := range tests { tc := run(t) t.Run(name, func(t *testing.T) { - db := DB{db: tc.db} - cert, err := db.GetCertificate(context.Background(), certID) + d := DB{db: tc.db} + cert, err := d.GetCertificate(context.Background(), certID) if err != nil { switch k := err.(type) { case *acme.Error: @@ -245,14 +245,12 @@ func TestDB_GetCertificate(t *testing.T) { assert.HasPrefix(t, err.Error(), tc.err.Error()) } } - } else { - if assert.Nil(t, tc.err) { - assert.Equals(t, cert.ID, certID) - assert.Equals(t, cert.AccountID, "accountID") - assert.Equals(t, cert.OrderID, "orderID") - assert.Equals(t, cert.Leaf, leaf) - assert.Equals(t, cert.Intermediates, []*x509.Certificate{inter, root}) - } + } else if assert.Nil(t, tc.err) { + assert.Equals(t, cert.ID, certID) + assert.Equals(t, cert.AccountID, "accountID") + assert.Equals(t, cert.OrderID, "orderID") + assert.Equals(t, cert.Leaf, leaf) + assert.Equals(t, cert.Intermediates, []*x509.Certificate{inter, root}) } }) } diff --git a/acme/db/nosql/challenge_test.go b/acme/db/nosql/challenge_test.go index b39395e8..4da5679b 100644 --- a/acme/db/nosql/challenge_test.go +++ b/acme/db/nosql/challenge_test.go @@ -92,8 +92,8 @@ func TestDB_getDBChallenge(t *testing.T) { for name, run := range tests { tc := run(t) t.Run(name, func(t *testing.T) { - db := DB{db: tc.db} - if ch, err := db.getDBChallenge(context.Background(), chID); err != nil { + d := DB{db: tc.db} + if ch, err := d.getDBChallenge(context.Background(), chID); err != nil { switch k := err.(type) { case *acme.Error: if assert.NotNil(t, tc.acmeErr) { @@ -108,17 +108,15 @@ func TestDB_getDBChallenge(t *testing.T) { assert.HasPrefix(t, err.Error(), tc.err.Error()) } } - } else { - if assert.Nil(t, tc.err) { - assert.Equals(t, ch.ID, tc.dbc.ID) - assert.Equals(t, ch.AccountID, tc.dbc.AccountID) - assert.Equals(t, ch.Type, tc.dbc.Type) - assert.Equals(t, ch.Status, tc.dbc.Status) - assert.Equals(t, ch.Token, tc.dbc.Token) - assert.Equals(t, ch.Value, tc.dbc.Value) - assert.Equals(t, ch.ValidatedAt, tc.dbc.ValidatedAt) - assert.Equals(t, ch.Error.Error(), tc.dbc.Error.Error()) - } + } else if assert.Nil(t, tc.err) { + assert.Equals(t, ch.ID, tc.dbc.ID) + assert.Equals(t, ch.AccountID, tc.dbc.AccountID) + assert.Equals(t, ch.Type, tc.dbc.Type) + assert.Equals(t, ch.Status, tc.dbc.Status) + assert.Equals(t, ch.Token, tc.dbc.Token) + assert.Equals(t, ch.Value, tc.dbc.Value) + assert.Equals(t, ch.ValidatedAt, tc.dbc.ValidatedAt) + assert.Equals(t, ch.Error.Error(), tc.dbc.Error.Error()) } }) } @@ -206,8 +204,8 @@ func TestDB_CreateChallenge(t *testing.T) { for name, run := range tests { tc := run(t) t.Run(name, func(t *testing.T) { - db := DB{db: tc.db} - if err := db.CreateChallenge(context.Background(), tc.ch); err != nil { + d := DB{db: tc.db} + if err := d.CreateChallenge(context.Background(), tc.ch); err != nil { if assert.NotNil(t, tc.err) { assert.HasPrefix(t, err.Error(), tc.err.Error()) } @@ -286,8 +284,8 @@ func TestDB_GetChallenge(t *testing.T) { for name, run := range tests { tc := run(t) t.Run(name, func(t *testing.T) { - db := DB{db: tc.db} - if ch, err := db.GetChallenge(context.Background(), chID, azID); err != nil { + d := DB{db: tc.db} + if ch, err := d.GetChallenge(context.Background(), chID, azID); err != nil { switch k := err.(type) { case *acme.Error: if assert.NotNil(t, tc.acmeErr) { @@ -302,17 +300,15 @@ func TestDB_GetChallenge(t *testing.T) { assert.HasPrefix(t, err.Error(), tc.err.Error()) } } - } else { - if assert.Nil(t, tc.err) { - assert.Equals(t, ch.ID, tc.dbc.ID) - assert.Equals(t, ch.AccountID, tc.dbc.AccountID) - assert.Equals(t, ch.Type, tc.dbc.Type) - assert.Equals(t, ch.Status, tc.dbc.Status) - assert.Equals(t, ch.Token, tc.dbc.Token) - assert.Equals(t, ch.Value, tc.dbc.Value) - assert.Equals(t, ch.ValidatedAt, tc.dbc.ValidatedAt) - assert.Equals(t, ch.Error.Error(), tc.dbc.Error.Error()) - } + } else if assert.Nil(t, tc.err) { + assert.Equals(t, ch.ID, tc.dbc.ID) + assert.Equals(t, ch.AccountID, tc.dbc.AccountID) + assert.Equals(t, ch.Type, tc.dbc.Type) + assert.Equals(t, ch.Status, tc.dbc.Status) + assert.Equals(t, ch.Token, tc.dbc.Token) + assert.Equals(t, ch.Value, tc.dbc.Value) + assert.Equals(t, ch.ValidatedAt, tc.dbc.ValidatedAt) + assert.Equals(t, ch.Error.Error(), tc.dbc.Error.Error()) } }) } @@ -442,8 +438,8 @@ func TestDB_UpdateChallenge(t *testing.T) { for name, run := range tests { tc := run(t) t.Run(name, func(t *testing.T) { - db := DB{db: tc.db} - if err := db.UpdateChallenge(context.Background(), tc.ch); err != nil { + d := DB{db: tc.db} + if err := d.UpdateChallenge(context.Background(), tc.ch); err != nil { if assert.NotNil(t, tc.err) { assert.HasPrefix(t, err.Error(), tc.err.Error()) } diff --git a/acme/db/nosql/nonce.go b/acme/db/nosql/nonce.go index 9badae87..e438c9ed 100644 --- a/acme/db/nosql/nonce.go +++ b/acme/db/nosql/nonce.go @@ -31,7 +31,7 @@ func (db *DB) CreateNonce(ctx context.Context) (acme.Nonce, error) { ID: id, CreatedAt: clock.Now(), } - if err = db.save(ctx, id, n, nil, "nonce", nonceTable); err != nil { + if err := db.save(ctx, id, n, nil, "nonce", nonceTable); err != nil { return "", err } return acme.Nonce(id), nil diff --git a/acme/db/nosql/nonce_test.go b/acme/db/nosql/nonce_test.go index 05d73d52..7dc5cc91 100644 --- a/acme/db/nosql/nonce_test.go +++ b/acme/db/nosql/nonce_test.go @@ -67,8 +67,8 @@ func TestDB_CreateNonce(t *testing.T) { for name, run := range tests { tc := run(t) t.Run(name, func(t *testing.T) { - db := DB{db: tc.db} - if n, err := db.CreateNonce(context.Background()); err != nil { + d := DB{db: tc.db} + if n, err := d.CreateNonce(context.Background()); err != nil { if assert.NotNil(t, tc.err) { assert.HasPrefix(t, err.Error(), tc.err.Error()) } @@ -144,8 +144,8 @@ func TestDB_DeleteNonce(t *testing.T) { for name, run := range tests { tc := run(t) t.Run(name, func(t *testing.T) { - db := DB{db: tc.db} - if err := db.DeleteNonce(context.Background(), acme.Nonce(nonceID)); err != nil { + d := DB{db: tc.db} + if err := d.DeleteNonce(context.Background(), acme.Nonce(nonceID)); err != nil { switch k := err.(type) { case *acme.Error: if assert.NotNil(t, tc.acmeErr) { diff --git a/acme/db/nosql/nosql.go b/acme/db/nosql/nosql.go index 052f5729..b1547373 100644 --- a/acme/db/nosql/nosql.go +++ b/acme/db/nosql/nosql.go @@ -41,7 +41,7 @@ func New(db nosqlDB.DB) (*DB, error) { // save writes the new data to the database, overwriting the old data if it // existed. -func (db *DB) save(ctx context.Context, id string, nu interface{}, old interface{}, typ string, table []byte) error { +func (db *DB) save(ctx context.Context, id string, nu, old interface{}, typ string, table []byte) error { var ( err error newB []byte diff --git a/acme/db/nosql/nosql_test.go b/acme/db/nosql/nosql_test.go index 4396acc8..d9c0b484 100644 --- a/acme/db/nosql/nosql_test.go +++ b/acme/db/nosql/nosql_test.go @@ -126,8 +126,8 @@ func TestDB_save(t *testing.T) { } for name, tc := range tests { t.Run(name, func(t *testing.T) { - db := &DB{db: tc.db} - if err := db.save(context.Background(), "id", tc.nu, tc.old, "challenge", challengeTable); err != nil { + d := &DB{db: tc.db} + if err := d.save(context.Background(), "id", tc.nu, tc.old, "challenge", challengeTable); err != nil { if assert.NotNil(t, tc.err) { assert.HasPrefix(t, err.Error(), tc.err.Error()) } diff --git a/acme/db/nosql/order_test.go b/acme/db/nosql/order_test.go index 8882fd82..e92eb684 100644 --- a/acme/db/nosql/order_test.go +++ b/acme/db/nosql/order_test.go @@ -13,7 +13,6 @@ import ( "github.com/smallstep/certificates/db" "github.com/smallstep/nosql" "github.com/smallstep/nosql/database" - nosqldb "github.com/smallstep/nosql/database" ) func TestDB_getDBOrder(t *testing.T) { @@ -32,7 +31,7 @@ func TestDB_getDBOrder(t *testing.T) { assert.Equals(t, bucket, orderTable) assert.Equals(t, string(key), orderID) - return nil, nosqldb.ErrNotFound + return nil, database.ErrNotFound }, }, acmeErr: acme.NewError(acme.ErrorMalformedType, "order orderID not found"), @@ -101,8 +100,8 @@ func TestDB_getDBOrder(t *testing.T) { for name, run := range tests { tc := run(t) t.Run(name, func(t *testing.T) { - db := DB{db: tc.db} - if dbo, err := db.getDBOrder(context.Background(), orderID); err != nil { + d := DB{db: tc.db} + if dbo, err := d.getDBOrder(context.Background(), orderID); err != nil { switch k := err.(type) { case *acme.Error: if assert.NotNil(t, tc.acmeErr) { @@ -117,20 +116,18 @@ func TestDB_getDBOrder(t *testing.T) { assert.HasPrefix(t, err.Error(), tc.err.Error()) } } - } else { - if assert.Nil(t, tc.err) { - assert.Equals(t, dbo.ID, tc.dbo.ID) - assert.Equals(t, dbo.ProvisionerID, tc.dbo.ProvisionerID) - assert.Equals(t, dbo.CertificateID, tc.dbo.CertificateID) - assert.Equals(t, dbo.Status, tc.dbo.Status) - assert.Equals(t, dbo.CreatedAt, tc.dbo.CreatedAt) - assert.Equals(t, dbo.ExpiresAt, tc.dbo.ExpiresAt) - assert.Equals(t, dbo.NotBefore, tc.dbo.NotBefore) - assert.Equals(t, dbo.NotAfter, tc.dbo.NotAfter) - assert.Equals(t, dbo.Identifiers, tc.dbo.Identifiers) - assert.Equals(t, dbo.AuthorizationIDs, tc.dbo.AuthorizationIDs) - assert.Equals(t, dbo.Error.Error(), tc.dbo.Error.Error()) - } + } else if assert.Nil(t, tc.err) { + assert.Equals(t, dbo.ID, tc.dbo.ID) + assert.Equals(t, dbo.ProvisionerID, tc.dbo.ProvisionerID) + assert.Equals(t, dbo.CertificateID, tc.dbo.CertificateID) + assert.Equals(t, dbo.Status, tc.dbo.Status) + assert.Equals(t, dbo.CreatedAt, tc.dbo.CreatedAt) + assert.Equals(t, dbo.ExpiresAt, tc.dbo.ExpiresAt) + assert.Equals(t, dbo.NotBefore, tc.dbo.NotBefore) + assert.Equals(t, dbo.NotAfter, tc.dbo.NotAfter) + assert.Equals(t, dbo.Identifiers, tc.dbo.Identifiers) + assert.Equals(t, dbo.AuthorizationIDs, tc.dbo.AuthorizationIDs) + assert.Equals(t, dbo.Error.Error(), tc.dbo.Error.Error()) } }) } @@ -165,7 +162,7 @@ func TestDB_GetOrder(t *testing.T) { assert.Equals(t, bucket, orderTable) assert.Equals(t, string(key), orderID) - return nil, nosqldb.ErrNotFound + return nil, database.ErrNotFound }, }, acmeErr: acme.NewError(acme.ErrorMalformedType, "order orderID not found"), @@ -207,8 +204,8 @@ func TestDB_GetOrder(t *testing.T) { for name, run := range tests { tc := run(t) t.Run(name, func(t *testing.T) { - db := DB{db: tc.db} - if o, err := db.GetOrder(context.Background(), orderID); err != nil { + d := DB{db: tc.db} + if o, err := d.GetOrder(context.Background(), orderID); err != nil { switch k := err.(type) { case *acme.Error: if assert.NotNil(t, tc.acmeErr) { @@ -223,20 +220,18 @@ func TestDB_GetOrder(t *testing.T) { assert.HasPrefix(t, err.Error(), tc.err.Error()) } } - } else { - if assert.Nil(t, tc.err) { - assert.Equals(t, o.ID, tc.dbo.ID) - assert.Equals(t, o.AccountID, tc.dbo.AccountID) - assert.Equals(t, o.ProvisionerID, tc.dbo.ProvisionerID) - assert.Equals(t, o.CertificateID, tc.dbo.CertificateID) - assert.Equals(t, o.Status, tc.dbo.Status) - assert.Equals(t, o.ExpiresAt, tc.dbo.ExpiresAt) - assert.Equals(t, o.NotBefore, tc.dbo.NotBefore) - assert.Equals(t, o.NotAfter, tc.dbo.NotAfter) - assert.Equals(t, o.Identifiers, tc.dbo.Identifiers) - assert.Equals(t, o.AuthorizationIDs, tc.dbo.AuthorizationIDs) - assert.Equals(t, o.Error.Error(), tc.dbo.Error.Error()) - } + } else if assert.Nil(t, tc.err) { + assert.Equals(t, o.ID, tc.dbo.ID) + assert.Equals(t, o.AccountID, tc.dbo.AccountID) + assert.Equals(t, o.ProvisionerID, tc.dbo.ProvisionerID) + assert.Equals(t, o.CertificateID, tc.dbo.CertificateID) + assert.Equals(t, o.Status, tc.dbo.Status) + assert.Equals(t, o.ExpiresAt, tc.dbo.ExpiresAt) + assert.Equals(t, o.NotBefore, tc.dbo.NotBefore) + assert.Equals(t, o.NotAfter, tc.dbo.NotAfter) + assert.Equals(t, o.Identifiers, tc.dbo.Identifiers) + assert.Equals(t, o.AuthorizationIDs, tc.dbo.AuthorizationIDs) + assert.Equals(t, o.Error.Error(), tc.dbo.Error.Error()) } }) } @@ -367,8 +362,8 @@ func TestDB_UpdateOrder(t *testing.T) { for name, run := range tests { tc := run(t) t.Run(name, func(t *testing.T) { - db := DB{db: tc.db} - if err := db.UpdateOrder(context.Background(), tc.o); err != nil { + d := DB{db: tc.db} + if err := d.UpdateOrder(context.Background(), tc.o); err != nil { if assert.NotNil(t, tc.err) { assert.HasPrefix(t, err.Error(), tc.err.Error()) } @@ -512,7 +507,7 @@ func TestDB_CreateOrder(t *testing.T) { MGet: func(bucket, key []byte) ([]byte, error) { assert.Equals(t, string(bucket), string(ordersByAccountIDTable)) assert.Equals(t, string(key), o.AccountID) - return nil, nosqldb.ErrNotFound + return nil, database.ErrNotFound }, MCmpAndSwap: func(bucket, key, old, nu []byte) ([]byte, bool, error) { switch string(bucket) { @@ -558,8 +553,8 @@ func TestDB_CreateOrder(t *testing.T) { for name, run := range tests { tc := run(t) t.Run(name, func(t *testing.T) { - db := DB{db: tc.db} - if err := db.CreateOrder(context.Background(), tc.o); err != nil { + d := DB{db: tc.db} + if err := d.CreateOrder(context.Background(), tc.o); err != nil { if assert.NotNil(t, tc.err) { assert.HasPrefix(t, err.Error(), tc.err.Error()) } @@ -681,7 +676,7 @@ func TestDB_updateAddOrderIDs(t *testing.T) { MGet: func(bucket, key []byte) ([]byte, error) { assert.Equals(t, bucket, ordersByAccountIDTable) assert.Equals(t, key, []byte(accID)) - return nil, nosqldb.ErrNotFound + return nil, database.ErrNotFound }, MCmpAndSwap: func(bucket, key, old, nu []byte) ([]byte, bool, error) { assert.Equals(t, bucket, ordersByAccountIDTable) @@ -996,15 +991,15 @@ func TestDB_updateAddOrderIDs(t *testing.T) { for name, run := range tests { tc := run(t) t.Run(name, func(t *testing.T) { - db := DB{db: tc.db} + d := DB{db: tc.db} var ( res []string err error ) if tc.addOids == nil { - res, err = db.updateAddOrderIDs(context.Background(), accID) + res, err = d.updateAddOrderIDs(context.Background(), accID) } else { - res, err = db.updateAddOrderIDs(context.Background(), accID, tc.addOids...) + res, err = d.updateAddOrderIDs(context.Background(), accID, tc.addOids...) } if err != nil { @@ -1022,10 +1017,8 @@ func TestDB_updateAddOrderIDs(t *testing.T) { assert.HasPrefix(t, err.Error(), tc.err.Error()) } } - } else { - if assert.Nil(t, tc.err) { - assert.True(t, reflect.DeepEqual(res, tc.res)) - } + } else if assert.Nil(t, tc.err) { + assert.True(t, reflect.DeepEqual(res, tc.res)) } }) } diff --git a/acme/order.go b/acme/order.go index fd8956f7..237c6979 100644 --- a/acme/order.go +++ b/acme/order.go @@ -289,6 +289,7 @@ func canonicalize(csr *x509.CertificateRequest) (canonicalized *x509.Certificate // name or in an extensionRequest attribute [RFC2985] requesting a // subjectAltName extension, or both. if csr.Subject.CommonName != "" { + // nolint:gocritic canonicalized.DNSNames = append(csr.DNSNames, csr.Subject.CommonName) } canonicalized.DNSNames = uniqueSortedLowerNames(csr.DNSNames) diff --git a/api/api.go b/api/api.go index 5be9ecc1..30ba03f9 100644 --- a/api/api.go +++ b/api/api.go @@ -240,9 +240,9 @@ type caHandler struct { } // New creates a new RouterHandler with the CA endpoints. -func New(authority Authority) RouterHandler { +func New(auth Authority) RouterHandler { return &caHandler{ - Authority: authority, + Authority: auth, } } @@ -295,7 +295,7 @@ func (h *caHandler) Health(w http.ResponseWriter, r *http.Request) { // certificate for the given SHA256. func (h *caHandler) Root(w http.ResponseWriter, r *http.Request) { sha := chi.URLParam(r, "sha") - sum := strings.ToLower(strings.Replace(sha, "-", "", -1)) + sum := strings.ToLower(strings.ReplaceAll(sha, "-", "")) // Load root certificate with the cert, err := h.Authority.Root(sum) if err != nil { @@ -409,19 +409,20 @@ func LogCertificate(w http.ResponseWriter, cert *x509.Certificate) { "certificate": base64.StdEncoding.EncodeToString(cert.Raw), } for _, ext := range cert.Extensions { - if ext.Id.Equal(oidStepProvisioner) { - val := &stepProvisioner{} - rest, err := asn1.Unmarshal(ext.Value, val) - if err != nil || len(rest) > 0 { - break - } - if len(val.CredentialID) > 0 { - m["provisioner"] = fmt.Sprintf("%s (%s)", val.Name, val.CredentialID) - } else { - m["provisioner"] = string(val.Name) - } + if !ext.Id.Equal(oidStepProvisioner) { + continue + } + val := &stepProvisioner{} + rest, err := asn1.Unmarshal(ext.Value, val) + if err != nil || len(rest) > 0 { break } + if len(val.CredentialID) > 0 { + m["provisioner"] = fmt.Sprintf("%s (%s)", val.Name, val.CredentialID) + } else { + m["provisioner"] = string(val.Name) + } + break } rl.WithFields(m) } diff --git a/api/api_test.go b/api/api_test.go index 33d2bae7..89596165 100644 --- a/api/api_test.go +++ b/api/api_test.go @@ -186,8 +186,8 @@ func TestCertificate_MarshalJSON(t *testing.T) { }{ {"nil", fields{Certificate: nil}, []byte("null"), false}, {"empty", fields{Certificate: &x509.Certificate{Raw: nil}}, []byte(`"-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----\n"`), false}, - {"root", fields{Certificate: parseCertificate(rootPEM)}, []byte(`"` + strings.Replace(rootPEM, "\n", `\n`, -1) + `\n"`), false}, - {"cert", fields{Certificate: parseCertificate(certPEM)}, []byte(`"` + strings.Replace(certPEM, "\n", `\n`, -1) + `\n"`), false}, + {"root", fields{Certificate: parseCertificate(rootPEM)}, []byte(`"` + strings.ReplaceAll(rootPEM, "\n", `\n`) + `\n"`), false}, + {"cert", fields{Certificate: parseCertificate(certPEM)}, []byte(`"` + strings.ReplaceAll(certPEM, "\n", `\n`) + `\n"`), false}, } for _, tt := range tests { @@ -219,11 +219,11 @@ func TestCertificate_UnmarshalJSON(t *testing.T) { {"invalid string", []byte(`"foobar"`), false, true}, {"invalid bytes 0", []byte{}, false, true}, {"invalid bytes 1", []byte{1}, false, true}, {"empty csr", []byte(`"-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE----\n"`), false, true}, - {"invalid type", []byte(`"` + strings.Replace(csrPEM, "\n", `\n`, -1) + `"`), false, true}, + {"invalid type", []byte(`"` + strings.ReplaceAll(csrPEM, "\n", `\n`) + `"`), false, true}, {"empty string", []byte(`""`), false, false}, {"json null", []byte(`null`), false, false}, - {"valid root", []byte(`"` + strings.Replace(rootPEM, "\n", `\n`, -1) + `"`), true, false}, - {"valid cert", []byte(`"` + strings.Replace(certPEM, "\n", `\n`, -1) + `"`), true, false}, + {"valid root", []byte(`"` + strings.ReplaceAll(rootPEM, "\n", `\n`) + `"`), true, false}, + {"valid cert", []byte(`"` + strings.ReplaceAll(certPEM, "\n", `\n`) + `"`), true, false}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -251,7 +251,7 @@ func TestCertificate_UnmarshalJSON_json(t *testing.T) { {"empty crt (null)", `{"crt":null}`, false, false}, {"empty crt (string)", `{"crt":""}`, false, false}, {"empty crt", `{"crt":"-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE----\n"}`, false, true}, - {"valid crt", `{"crt":"` + strings.Replace(certPEM, "\n", `\n`, -1) + `"}`, true, false}, + {"valid crt", `{"crt":"` + strings.ReplaceAll(certPEM, "\n", `\n`) + `"}`, true, false}, } type request struct { @@ -297,7 +297,7 @@ func TestCertificateRequest_MarshalJSON(t *testing.T) { }{ {"nil", fields{CertificateRequest: nil}, []byte("null"), false}, {"empty", fields{CertificateRequest: &x509.CertificateRequest{}}, []byte(`"-----BEGIN CERTIFICATE REQUEST-----\n-----END CERTIFICATE REQUEST-----\n"`), false}, - {"csr", fields{CertificateRequest: parseCertificateRequest(csrPEM)}, []byte(`"` + strings.Replace(csrPEM, "\n", `\n`, -1) + `\n"`), false}, + {"csr", fields{CertificateRequest: parseCertificateRequest(csrPEM)}, []byte(`"` + strings.ReplaceAll(csrPEM, "\n", `\n`) + `\n"`), false}, } for _, tt := range tests { @@ -329,10 +329,10 @@ func TestCertificateRequest_UnmarshalJSON(t *testing.T) { {"invalid string", []byte(`"foobar"`), false, true}, {"invalid bytes 0", []byte{}, false, true}, {"invalid bytes 1", []byte{1}, false, true}, {"empty csr", []byte(`"-----BEGIN CERTIFICATE REQUEST-----\n-----END CERTIFICATE REQUEST----\n"`), false, true}, - {"invalid type", []byte(`"` + strings.Replace(rootPEM, "\n", `\n`, -1) + `"`), false, true}, + {"invalid type", []byte(`"` + strings.ReplaceAll(rootPEM, "\n", `\n`) + `"`), false, true}, {"empty string", []byte(`""`), false, false}, {"json null", []byte(`null`), false, false}, - {"valid csr", []byte(`"` + strings.Replace(csrPEM, "\n", `\n`, -1) + `"`), true, false}, + {"valid csr", []byte(`"` + strings.ReplaceAll(csrPEM, "\n", `\n`) + `"`), true, false}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -360,7 +360,7 @@ func TestCertificateRequest_UnmarshalJSON_json(t *testing.T) { {"empty csr (null)", `{"csr":null}`, false, false}, {"empty csr (string)", `{"csr":""}`, false, false}, {"empty csr", `{"csr":"-----BEGIN CERTIFICATE REQUEST-----\n-----END CERTIFICATE REQUEST----\n"}`, false, true}, - {"valid csr", `{"csr":"` + strings.Replace(csrPEM, "\n", `\n`, -1) + `"}`, true, false}, + {"valid csr", `{"csr":"` + strings.ReplaceAll(csrPEM, "\n", `\n`) + `"}`, true, false}, } type request struct { @@ -739,7 +739,7 @@ func (m *mockAuthority) CheckSSHHost(ctx context.Context, principal, token strin return m.ret1.(bool), m.err } -func (m *mockAuthority) GetSSHBastion(ctx context.Context, user string, hostname string) (*authority.Bastion, error) { +func (m *mockAuthority) GetSSHBastion(ctx context.Context, user, hostname string) (*authority.Bastion, error) { if m.getSSHBastion != nil { return m.getSSHBastion(ctx, user, hostname) } @@ -816,7 +816,7 @@ func Test_caHandler_Root(t *testing.T) { req := httptest.NewRequest("GET", "http://example.com/root/efc7d6b475a56fe587650bcdb999a4a308f815ba44db4bf0371ea68a786ccd36", nil) req = req.WithContext(context.WithValue(context.Background(), chi.RouteCtxKey, chiCtx)) - expected := []byte(`{"ca":"` + strings.Replace(rootPEM, "\n", `\n`, -1) + `\n"}`) + expected := []byte(`{"ca":"` + strings.ReplaceAll(rootPEM, "\n", `\n`) + `\n"}`) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -860,8 +860,8 @@ func Test_caHandler_Sign(t *testing.T) { t.Fatal(err) } - expected1 := []byte(`{"crt":"` + strings.Replace(certPEM, "\n", `\n`, -1) + `\n","ca":"` + strings.Replace(rootPEM, "\n", `\n`, -1) + `\n","certChain":["` + strings.Replace(certPEM, "\n", `\n`, -1) + `\n","` + strings.Replace(rootPEM, "\n", `\n`, -1) + `\n"]}`) - expected2 := []byte(`{"crt":"` + strings.Replace(stepCertPEM, "\n", `\n`, -1) + `\n","ca":"` + strings.Replace(rootPEM, "\n", `\n`, -1) + `\n","certChain":["` + strings.Replace(stepCertPEM, "\n", `\n`, -1) + `\n","` + strings.Replace(rootPEM, "\n", `\n`, -1) + `\n"]}`) + expected1 := []byte(`{"crt":"` + strings.ReplaceAll(certPEM, "\n", `\n`) + `\n","ca":"` + strings.ReplaceAll(rootPEM, "\n", `\n`) + `\n","certChain":["` + strings.ReplaceAll(certPEM, "\n", `\n`) + `\n","` + strings.ReplaceAll(rootPEM, "\n", `\n`) + `\n"]}`) + expected2 := []byte(`{"crt":"` + strings.ReplaceAll(stepCertPEM, "\n", `\n`) + `\n","ca":"` + strings.ReplaceAll(rootPEM, "\n", `\n`) + `\n","certChain":["` + strings.ReplaceAll(stepCertPEM, "\n", `\n`) + `\n","` + strings.ReplaceAll(rootPEM, "\n", `\n`) + `\n"]}`) tests := []struct { name string @@ -934,7 +934,7 @@ func Test_caHandler_Renew(t *testing.T) { {"renew error", cs, nil, nil, errs.Forbidden("an error"), http.StatusForbidden}, } - expected := []byte(`{"crt":"` + strings.Replace(certPEM, "\n", `\n`, -1) + `\n","ca":"` + strings.Replace(rootPEM, "\n", `\n`, -1) + `\n","certChain":["` + strings.Replace(certPEM, "\n", `\n`, -1) + `\n","` + strings.Replace(rootPEM, "\n", `\n`, -1) + `\n"]}`) + expected := []byte(`{"crt":"` + strings.ReplaceAll(certPEM, "\n", `\n`) + `\n","ca":"` + strings.ReplaceAll(rootPEM, "\n", `\n`) + `\n","certChain":["` + strings.ReplaceAll(certPEM, "\n", `\n`) + `\n","` + strings.ReplaceAll(rootPEM, "\n", `\n`) + `\n"]}`) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -995,7 +995,7 @@ func Test_caHandler_Rekey(t *testing.T) { {"json read error", "{", cs, nil, nil, nil, http.StatusBadRequest}, } - expected := []byte(`{"crt":"` + strings.Replace(certPEM, "\n", `\n`, -1) + `\n","ca":"` + strings.Replace(rootPEM, "\n", `\n`, -1) + `\n","certChain":["` + strings.Replace(certPEM, "\n", `\n`, -1) + `\n","` + strings.Replace(rootPEM, "\n", `\n`, -1) + `\n"]}`) + expected := []byte(`{"crt":"` + strings.ReplaceAll(certPEM, "\n", `\n`) + `\n","ca":"` + strings.ReplaceAll(rootPEM, "\n", `\n`) + `\n","certChain":["` + strings.ReplaceAll(certPEM, "\n", `\n`) + `\n","` + strings.ReplaceAll(rootPEM, "\n", `\n`) + `\n"]}`) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -1210,7 +1210,7 @@ func Test_caHandler_Roots(t *testing.T) { {"fail", cs, nil, nil, fmt.Errorf("an error"), http.StatusForbidden}, } - expected := []byte(`{"crts":["` + strings.Replace(rootPEM, "\n", `\n`, -1) + `\n"]}`) + expected := []byte(`{"crts":["` + strings.ReplaceAll(rootPEM, "\n", `\n`) + `\n"]}`) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -1256,7 +1256,7 @@ func Test_caHandler_Federation(t *testing.T) { {"fail", cs, nil, nil, fmt.Errorf("an error"), http.StatusForbidden}, } - expected := []byte(`{"crts":["` + strings.Replace(rootPEM, "\n", `\n`, -1) + `\n"]}`) + expected := []byte(`{"crts":["` + strings.ReplaceAll(rootPEM, "\n", `\n`) + `\n"]}`) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/api/errors.go b/api/errors.go index db3bc3e2..bff46b55 100644 --- a/api/errors.go +++ b/api/errors.go @@ -50,12 +50,10 @@ func WriteError(w http.ResponseWriter, err error) { rl.WithFields(map[string]interface{}{ "stack-trace": fmt.Sprintf("%+v", e), }) - } else { - if e, ok := cause.(errs.StackTracer); ok { - rl.WithFields(map[string]interface{}{ - "stack-trace": fmt.Sprintf("%+v", e), - }) - } + } else if e, ok := cause.(errs.StackTracer); ok { + rl.WithFields(map[string]interface{}{ + "stack-trace": fmt.Sprintf("%+v", e), + }) } } } diff --git a/api/ssh.go b/api/ssh.go index 8c0c1aa3..7c7a5acd 100644 --- a/api/ssh.go +++ b/api/ssh.go @@ -52,7 +52,7 @@ func (s *SSHSignRequest) Validate() error { return errors.Errorf("unknown certType %s", s.CertType) case len(s.PublicKey) == 0: return errors.New("missing or empty publicKey") - case len(s.OTT) == 0: + case s.OTT == "": return errors.New("missing or empty ott") default: // Validate identity signature if provided @@ -408,18 +408,18 @@ func (h *caHandler) SSHConfig(w http.ResponseWriter, r *http.Request) { return } - var config SSHConfigResponse + var cfg SSHConfigResponse switch body.Type { case provisioner.SSHUserCert: - config.UserTemplates = ts + cfg.UserTemplates = ts case provisioner.SSHHostCert: - config.HostTemplates = ts + cfg.HostTemplates = ts default: WriteError(w, errs.InternalServer("it should hot get here")) return } - JSON(w, config) + JSON(w, cfg) } // SSHCheckHost is the HTTP handler that returns if a hosts certificate exists or not. diff --git a/api/sshRekey.go b/api/sshRekey.go index 3d8e7c47..9d9e17cf 100644 --- a/api/sshRekey.go +++ b/api/sshRekey.go @@ -19,7 +19,7 @@ type SSHRekeyRequest struct { // Validate validates the SSHSignRekey. func (s *SSHRekeyRequest) Validate() error { switch { - case len(s.OTT) == 0: + case s.OTT == "": return errors.New("missing or empty ott") case len(s.PublicKey) == 0: return errors.New("missing or empty public key") diff --git a/api/sshRenew.go b/api/sshRenew.go index cb6ec5fd..d0633ecf 100644 --- a/api/sshRenew.go +++ b/api/sshRenew.go @@ -18,7 +18,7 @@ type SSHRenewRequest struct { // Validate validates the SSHSignRequest. func (s *SSHRenewRequest) Validate() error { switch { - case len(s.OTT) == 0: + case s.OTT == "": return errors.New("missing or empty ott") default: return nil diff --git a/api/sshRevoke.go b/api/sshRevoke.go index 5a1c858c..c6ebe99d 100644 --- a/api/sshRevoke.go +++ b/api/sshRevoke.go @@ -36,7 +36,7 @@ func (r *SSHRevokeRequest) Validate() (err error) { if !r.Passive { return errs.NotImplemented("non-passive revocation not implemented") } - if len(r.OTT) == 0 { + if r.OTT == "" { return errs.BadRequest("missing ott") } return diff --git a/api/ssh_test.go b/api/ssh_test.go index 1873a96d..a2e8748f 100644 --- a/api/ssh_test.go +++ b/api/ssh_test.go @@ -284,7 +284,7 @@ func Test_caHandler_SSHSign(t *testing.T) { identityCerts := []*x509.Certificate{ parseCertificate(certPEM), } - identityCertsPEM := []byte(`"` + strings.Replace(certPEM, "\n", `\n`, -1) + `\n"`) + identityCertsPEM := []byte(`"` + strings.ReplaceAll(certPEM, "\n", `\n`) + `\n"`) tests := []struct { name string diff --git a/authority/admin/api/middleware.go b/authority/admin/api/middleware.go index 90289f85..19025a9d 100644 --- a/authority/admin/api/middleware.go +++ b/authority/admin/api/middleware.go @@ -27,7 +27,7 @@ func (h *Handler) requireAPIEnabled(next nextHTTP) nextHTTP { func (h *Handler) extractAuthorizeTokenAdmin(next nextHTTP) nextHTTP { return func(w http.ResponseWriter, r *http.Request) { tok := r.Header.Get("Authorization") - if len(tok) == 0 { + if tok == "" { api.WriteError(w, admin.NewError(admin.ErrorUnauthorizedType, "missing authorization header token")) return diff --git a/authority/admin/db/nosql/admin_test.go b/authority/admin/db/nosql/admin_test.go index 092d72db..4234d526 100644 --- a/authority/admin/db/nosql/admin_test.go +++ b/authority/admin/db/nosql/admin_test.go @@ -12,7 +12,6 @@ import ( "github.com/smallstep/certificates/db" "github.com/smallstep/nosql" "github.com/smallstep/nosql/database" - nosqldb "github.com/smallstep/nosql/database" "go.step.sm/linkedca" "google.golang.org/protobuf/types/known/timestamppb" ) @@ -32,7 +31,7 @@ func TestDB_getDBAdminBytes(t *testing.T) { assert.Equals(t, bucket, adminsTable) assert.Equals(t, string(key), adminID) - return nil, nosqldb.ErrNotFound + return nil, database.ErrNotFound }, }, adminErr: admin.NewError(admin.ErrorNotFoundType, "admin adminID not found"), @@ -67,8 +66,8 @@ func TestDB_getDBAdminBytes(t *testing.T) { for name, run := range tests { tc := run(t) t.Run(name, func(t *testing.T) { - db := DB{db: tc.db} - if b, err := db.getDBAdminBytes(context.Background(), adminID); err != nil { + d := DB{db: tc.db} + if b, err := d.getDBAdminBytes(context.Background(), adminID); err != nil { switch k := err.(type) { case *admin.Error: if assert.NotNil(t, tc.adminErr) { @@ -83,10 +82,8 @@ func TestDB_getDBAdminBytes(t *testing.T) { assert.HasPrefix(t, err.Error(), tc.err.Error()) } } - } else { - if assert.Nil(t, tc.err) { - assert.Equals(t, string(b), "foo") - } + } else if assert.Nil(t, tc.err) { + assert.Equals(t, string(b), "foo") } }) } @@ -108,7 +105,7 @@ func TestDB_getDBAdmin(t *testing.T) { assert.Equals(t, bucket, adminsTable) assert.Equals(t, string(key), adminID) - return nil, nosqldb.ErrNotFound + return nil, database.ErrNotFound }, }, adminErr: admin.NewError(admin.ErrorNotFoundType, "admin adminID not found"), @@ -193,8 +190,8 @@ func TestDB_getDBAdmin(t *testing.T) { for name, run := range tests { tc := run(t) t.Run(name, func(t *testing.T) { - db := DB{db: tc.db, authorityID: admin.DefaultAuthorityID} - if dba, err := db.getDBAdmin(context.Background(), adminID); err != nil { + d := DB{db: tc.db, authorityID: admin.DefaultAuthorityID} + if dba, err := d.getDBAdmin(context.Background(), adminID); err != nil { switch k := err.(type) { case *admin.Error: if assert.NotNil(t, tc.adminErr) { @@ -209,16 +206,14 @@ func TestDB_getDBAdmin(t *testing.T) { assert.HasPrefix(t, err.Error(), tc.err.Error()) } } - } else { - if assert.Nil(t, tc.err) && assert.Nil(t, tc.adminErr) { - assert.Equals(t, dba.ID, adminID) - assert.Equals(t, dba.AuthorityID, tc.dba.AuthorityID) - assert.Equals(t, dba.ProvisionerID, tc.dba.ProvisionerID) - assert.Equals(t, dba.Subject, tc.dba.Subject) - assert.Equals(t, dba.Type, tc.dba.Type) - assert.Equals(t, dba.CreatedAt, tc.dba.CreatedAt) - assert.Fatal(t, dba.DeletedAt.IsZero()) - } + } else if assert.Nil(t, tc.err) && assert.Nil(t, tc.adminErr) { + assert.Equals(t, dba.ID, adminID) + assert.Equals(t, dba.AuthorityID, tc.dba.AuthorityID) + assert.Equals(t, dba.ProvisionerID, tc.dba.ProvisionerID) + assert.Equals(t, dba.Subject, tc.dba.Subject) + assert.Equals(t, dba.Type, tc.dba.Type) + assert.Equals(t, dba.CreatedAt, tc.dba.CreatedAt) + assert.Fatal(t, dba.DeletedAt.IsZero()) } }) } @@ -283,8 +278,8 @@ func TestDB_unmarshalDBAdmin(t *testing.T) { for name, run := range tests { tc := run(t) t.Run(name, func(t *testing.T) { - db := DB{authorityID: admin.DefaultAuthorityID} - if dba, err := db.unmarshalDBAdmin(tc.in, adminID); err != nil { + d := DB{authorityID: admin.DefaultAuthorityID} + if dba, err := d.unmarshalDBAdmin(tc.in, adminID); err != nil { switch k := err.(type) { case *admin.Error: if assert.NotNil(t, tc.adminErr) { @@ -299,16 +294,14 @@ func TestDB_unmarshalDBAdmin(t *testing.T) { assert.HasPrefix(t, err.Error(), tc.err.Error()) } } - } else { - if assert.Nil(t, tc.err) && assert.Nil(t, tc.adminErr) { - assert.Equals(t, dba.ID, adminID) - assert.Equals(t, dba.AuthorityID, tc.dba.AuthorityID) - assert.Equals(t, dba.ProvisionerID, tc.dba.ProvisionerID) - assert.Equals(t, dba.Subject, tc.dba.Subject) - assert.Equals(t, dba.Type, tc.dba.Type) - assert.Equals(t, dba.CreatedAt, tc.dba.CreatedAt) - assert.Fatal(t, dba.DeletedAt.IsZero()) - } + } else if assert.Nil(t, tc.err) && assert.Nil(t, tc.adminErr) { + assert.Equals(t, dba.ID, adminID) + assert.Equals(t, dba.AuthorityID, tc.dba.AuthorityID) + assert.Equals(t, dba.ProvisionerID, tc.dba.ProvisionerID) + assert.Equals(t, dba.Subject, tc.dba.Subject) + assert.Equals(t, dba.Type, tc.dba.Type) + assert.Equals(t, dba.CreatedAt, tc.dba.CreatedAt) + assert.Fatal(t, dba.DeletedAt.IsZero()) } }) } @@ -360,8 +353,8 @@ func TestDB_unmarshalAdmin(t *testing.T) { for name, run := range tests { tc := run(t) t.Run(name, func(t *testing.T) { - db := DB{authorityID: admin.DefaultAuthorityID} - if adm, err := db.unmarshalAdmin(tc.in, adminID); err != nil { + d := DB{authorityID: admin.DefaultAuthorityID} + if adm, err := d.unmarshalAdmin(tc.in, adminID); err != nil { switch k := err.(type) { case *admin.Error: if assert.NotNil(t, tc.adminErr) { @@ -376,16 +369,14 @@ func TestDB_unmarshalAdmin(t *testing.T) { assert.HasPrefix(t, err.Error(), tc.err.Error()) } } - } else { - if assert.Nil(t, tc.err) && assert.Nil(t, tc.adminErr) { - assert.Equals(t, adm.Id, adminID) - assert.Equals(t, adm.AuthorityId, tc.dba.AuthorityID) - assert.Equals(t, adm.ProvisionerId, tc.dba.ProvisionerID) - assert.Equals(t, adm.Subject, tc.dba.Subject) - assert.Equals(t, adm.Type, tc.dba.Type) - assert.Equals(t, adm.CreatedAt, timestamppb.New(tc.dba.CreatedAt)) - assert.Equals(t, adm.DeletedAt, timestamppb.New(tc.dba.DeletedAt)) - } + } else if assert.Nil(t, tc.err) && assert.Nil(t, tc.adminErr) { + assert.Equals(t, adm.Id, adminID) + assert.Equals(t, adm.AuthorityId, tc.dba.AuthorityID) + assert.Equals(t, adm.ProvisionerId, tc.dba.ProvisionerID) + assert.Equals(t, adm.Subject, tc.dba.Subject) + assert.Equals(t, adm.Type, tc.dba.Type) + assert.Equals(t, adm.CreatedAt, timestamppb.New(tc.dba.CreatedAt)) + assert.Equals(t, adm.DeletedAt, timestamppb.New(tc.dba.DeletedAt)) } }) } @@ -407,7 +398,7 @@ func TestDB_GetAdmin(t *testing.T) { assert.Equals(t, bucket, adminsTable) assert.Equals(t, string(key), adminID) - return nil, nosqldb.ErrNotFound + return nil, database.ErrNotFound }, }, adminErr: admin.NewError(admin.ErrorNotFoundType, "admin adminID not found"), @@ -516,8 +507,8 @@ func TestDB_GetAdmin(t *testing.T) { for name, run := range tests { tc := run(t) t.Run(name, func(t *testing.T) { - db := DB{db: tc.db, authorityID: admin.DefaultAuthorityID} - if adm, err := db.GetAdmin(context.Background(), adminID); err != nil { + d := DB{db: tc.db, authorityID: admin.DefaultAuthorityID} + if adm, err := d.GetAdmin(context.Background(), adminID); err != nil { switch k := err.(type) { case *admin.Error: if assert.NotNil(t, tc.adminErr) { @@ -532,16 +523,14 @@ func TestDB_GetAdmin(t *testing.T) { assert.HasPrefix(t, err.Error(), tc.err.Error()) } } - } else { - if assert.Nil(t, tc.err) && assert.Nil(t, tc.adminErr) { - assert.Equals(t, adm.Id, adminID) - assert.Equals(t, adm.AuthorityId, tc.dba.AuthorityID) - assert.Equals(t, adm.ProvisionerId, tc.dba.ProvisionerID) - assert.Equals(t, adm.Subject, tc.dba.Subject) - assert.Equals(t, adm.Type, tc.dba.Type) - assert.Equals(t, adm.CreatedAt, timestamppb.New(tc.dba.CreatedAt)) - assert.Equals(t, adm.DeletedAt, timestamppb.New(tc.dba.DeletedAt)) - } + } else if assert.Nil(t, tc.err) && assert.Nil(t, tc.adminErr) { + assert.Equals(t, adm.Id, adminID) + assert.Equals(t, adm.AuthorityId, tc.dba.AuthorityID) + assert.Equals(t, adm.ProvisionerId, tc.dba.ProvisionerID) + assert.Equals(t, adm.Subject, tc.dba.Subject) + assert.Equals(t, adm.Type, tc.dba.Type) + assert.Equals(t, adm.CreatedAt, timestamppb.New(tc.dba.CreatedAt)) + assert.Equals(t, adm.DeletedAt, timestamppb.New(tc.dba.DeletedAt)) } }) } @@ -562,7 +551,7 @@ func TestDB_DeleteAdmin(t *testing.T) { assert.Equals(t, bucket, adminsTable) assert.Equals(t, string(key), adminID) - return nil, nosqldb.ErrNotFound + return nil, database.ErrNotFound }, }, adminErr: admin.NewError(admin.ErrorNotFoundType, "admin adminID not found"), @@ -670,8 +659,8 @@ func TestDB_DeleteAdmin(t *testing.T) { for name, run := range tests { tc := run(t) t.Run(name, func(t *testing.T) { - db := DB{db: tc.db, authorityID: admin.DefaultAuthorityID} - if err := db.DeleteAdmin(context.Background(), adminID); err != nil { + d := DB{db: tc.db, authorityID: admin.DefaultAuthorityID} + if err := d.DeleteAdmin(context.Background(), adminID); err != nil { switch k := err.(type) { case *admin.Error: if assert.NotNil(t, tc.adminErr) { @@ -708,7 +697,7 @@ func TestDB_UpdateAdmin(t *testing.T) { assert.Equals(t, bucket, adminsTable) assert.Equals(t, string(key), adminID) - return nil, nosqldb.ErrNotFound + return nil, database.ErrNotFound }, }, adminErr: admin.NewError(admin.ErrorNotFoundType, "admin adminID not found"), @@ -821,8 +810,8 @@ func TestDB_UpdateAdmin(t *testing.T) { for name, run := range tests { tc := run(t) t.Run(name, func(t *testing.T) { - db := DB{db: tc.db, authorityID: admin.DefaultAuthorityID} - if err := db.UpdateAdmin(context.Background(), tc.adm); err != nil { + d := DB{db: tc.db, authorityID: admin.DefaultAuthorityID} + if err := d.UpdateAdmin(context.Background(), tc.adm); err != nil { switch k := err.(type) { case *admin.Error: if assert.NotNil(t, tc.adminErr) { @@ -919,8 +908,8 @@ func TestDB_CreateAdmin(t *testing.T) { for name, run := range tests { tc := run(t) t.Run(name, func(t *testing.T) { - db := DB{db: tc.db, authorityID: admin.DefaultAuthorityID} - if err := db.CreateAdmin(context.Background(), tc.adm); err != nil { + d := DB{db: tc.db, authorityID: admin.DefaultAuthorityID} + if err := d.CreateAdmin(context.Background(), tc.adm); err != nil { switch k := err.(type) { case *admin.Error: if assert.NotNil(t, tc.adminErr) { @@ -1095,8 +1084,8 @@ func TestDB_GetAdmins(t *testing.T) { for name, run := range tests { tc := run(t) t.Run(name, func(t *testing.T) { - db := DB{db: tc.db, authorityID: admin.DefaultAuthorityID} - if admins, err := db.GetAdmins(context.Background()); err != nil { + d := DB{db: tc.db, authorityID: admin.DefaultAuthorityID} + if admins, err := d.GetAdmins(context.Background()); err != nil { switch k := err.(type) { case *admin.Error: if assert.NotNil(t, tc.adminErr) { @@ -1111,10 +1100,8 @@ func TestDB_GetAdmins(t *testing.T) { assert.HasPrefix(t, err.Error(), tc.err.Error()) } } - } else { - if assert.Nil(t, tc.err) && assert.Nil(t, tc.adminErr) { - tc.verify(t, admins) - } + } else if assert.Nil(t, tc.err) && assert.Nil(t, tc.adminErr) { + tc.verify(t, admins) } }) } diff --git a/authority/admin/db/nosql/nosql.go b/authority/admin/db/nosql/nosql.go index 18599b02..22b049f5 100644 --- a/authority/admin/db/nosql/nosql.go +++ b/authority/admin/db/nosql/nosql.go @@ -35,7 +35,7 @@ func New(db nosqlDB.DB, authorityID string) (*DB, error) { // save writes the new data to the database, overwriting the old data if it // existed. -func (db *DB) save(ctx context.Context, id string, nu interface{}, old interface{}, typ string, table []byte) error { +func (db *DB) save(ctx context.Context, id string, nu, old interface{}, typ string, table []byte) error { var ( err error newB []byte diff --git a/authority/admin/db/nosql/provisioner_test.go b/authority/admin/db/nosql/provisioner_test.go index 95811f26..e599ea04 100644 --- a/authority/admin/db/nosql/provisioner_test.go +++ b/authority/admin/db/nosql/provisioner_test.go @@ -12,7 +12,6 @@ import ( "github.com/smallstep/certificates/db" "github.com/smallstep/nosql" "github.com/smallstep/nosql/database" - nosqldb "github.com/smallstep/nosql/database" "go.step.sm/linkedca" ) @@ -31,7 +30,7 @@ func TestDB_getDBProvisionerBytes(t *testing.T) { assert.Equals(t, bucket, provisionersTable) assert.Equals(t, string(key), provID) - return nil, nosqldb.ErrNotFound + return nil, database.ErrNotFound }, }, adminErr: admin.NewError(admin.ErrorNotFoundType, "provisioner provID not found"), @@ -66,8 +65,8 @@ func TestDB_getDBProvisionerBytes(t *testing.T) { for name, run := range tests { tc := run(t) t.Run(name, func(t *testing.T) { - db := DB{db: tc.db} - if b, err := db.getDBProvisionerBytes(context.Background(), provID); err != nil { + d := DB{db: tc.db} + if b, err := d.getDBProvisionerBytes(context.Background(), provID); err != nil { switch k := err.(type) { case *admin.Error: if assert.NotNil(t, tc.adminErr) { @@ -82,10 +81,8 @@ func TestDB_getDBProvisionerBytes(t *testing.T) { assert.HasPrefix(t, err.Error(), tc.err.Error()) } } - } else { - if assert.Nil(t, tc.err) && assert.Nil(t, tc.adminErr) { - assert.Equals(t, string(b), "foo") - } + } else if assert.Nil(t, tc.err) && assert.Nil(t, tc.adminErr) { + assert.Equals(t, string(b), "foo") } }) } @@ -107,7 +104,7 @@ func TestDB_getDBProvisioner(t *testing.T) { assert.Equals(t, bucket, provisionersTable) assert.Equals(t, string(key), provID) - return nil, nosqldb.ErrNotFound + return nil, database.ErrNotFound }, }, adminErr: admin.NewError(admin.ErrorNotFoundType, "provisioner provID not found"), @@ -190,8 +187,8 @@ func TestDB_getDBProvisioner(t *testing.T) { for name, run := range tests { tc := run(t) t.Run(name, func(t *testing.T) { - db := DB{db: tc.db, authorityID: admin.DefaultAuthorityID} - if dbp, err := db.getDBProvisioner(context.Background(), provID); err != nil { + d := DB{db: tc.db, authorityID: admin.DefaultAuthorityID} + if dbp, err := d.getDBProvisioner(context.Background(), provID); err != nil { switch k := err.(type) { case *admin.Error: if assert.NotNil(t, tc.adminErr) { @@ -206,15 +203,13 @@ func TestDB_getDBProvisioner(t *testing.T) { assert.HasPrefix(t, err.Error(), tc.err.Error()) } } - } else { - if assert.Nil(t, tc.err) && assert.Nil(t, tc.adminErr) { - assert.Equals(t, dbp.ID, provID) - assert.Equals(t, dbp.AuthorityID, tc.dbp.AuthorityID) - assert.Equals(t, dbp.Type, tc.dbp.Type) - assert.Equals(t, dbp.Name, tc.dbp.Name) - assert.Equals(t, dbp.CreatedAt, tc.dbp.CreatedAt) - assert.Fatal(t, dbp.DeletedAt.IsZero()) - } + } else if assert.Nil(t, tc.err) && assert.Nil(t, tc.adminErr) { + assert.Equals(t, dbp.ID, provID) + assert.Equals(t, dbp.AuthorityID, tc.dbp.AuthorityID) + assert.Equals(t, dbp.Type, tc.dbp.Type) + assert.Equals(t, dbp.Name, tc.dbp.Name) + assert.Equals(t, dbp.CreatedAt, tc.dbp.CreatedAt) + assert.Fatal(t, dbp.DeletedAt.IsZero()) } }) } @@ -278,8 +273,8 @@ func TestDB_unmarshalDBProvisioner(t *testing.T) { for name, run := range tests { tc := run(t) t.Run(name, func(t *testing.T) { - db := DB{authorityID: admin.DefaultAuthorityID} - if dbp, err := db.unmarshalDBProvisioner(tc.in, provID); err != nil { + d := DB{authorityID: admin.DefaultAuthorityID} + if dbp, err := d.unmarshalDBProvisioner(tc.in, provID); err != nil { switch k := err.(type) { case *admin.Error: if assert.NotNil(t, tc.adminErr) { @@ -294,19 +289,17 @@ func TestDB_unmarshalDBProvisioner(t *testing.T) { assert.HasPrefix(t, err.Error(), tc.err.Error()) } } - } else { - if assert.Nil(t, tc.err) && assert.Nil(t, tc.adminErr) { - assert.Equals(t, dbp.ID, provID) - assert.Equals(t, dbp.AuthorityID, tc.dbp.AuthorityID) - assert.Equals(t, dbp.Type, tc.dbp.Type) - assert.Equals(t, dbp.Name, tc.dbp.Name) - assert.Equals(t, dbp.Details, tc.dbp.Details) - assert.Equals(t, dbp.Claims, tc.dbp.Claims) - assert.Equals(t, dbp.X509Template, tc.dbp.X509Template) - assert.Equals(t, dbp.SSHTemplate, tc.dbp.SSHTemplate) - assert.Equals(t, dbp.CreatedAt, tc.dbp.CreatedAt) - assert.Fatal(t, dbp.DeletedAt.IsZero()) - } + } else if assert.Nil(t, tc.err) && assert.Nil(t, tc.adminErr) { + assert.Equals(t, dbp.ID, provID) + assert.Equals(t, dbp.AuthorityID, tc.dbp.AuthorityID) + assert.Equals(t, dbp.Type, tc.dbp.Type) + assert.Equals(t, dbp.Name, tc.dbp.Name) + assert.Equals(t, dbp.Details, tc.dbp.Details) + assert.Equals(t, dbp.Claims, tc.dbp.Claims) + assert.Equals(t, dbp.X509Template, tc.dbp.X509Template) + assert.Equals(t, dbp.SSHTemplate, tc.dbp.SSHTemplate) + assert.Equals(t, dbp.CreatedAt, tc.dbp.CreatedAt) + assert.Fatal(t, dbp.DeletedAt.IsZero()) } }) } @@ -402,8 +395,8 @@ func TestDB_unmarshalProvisioner(t *testing.T) { for name, run := range tests { tc := run(t) t.Run(name, func(t *testing.T) { - db := DB{authorityID: admin.DefaultAuthorityID} - if prov, err := db.unmarshalProvisioner(tc.in, provID); err != nil { + d := DB{authorityID: admin.DefaultAuthorityID} + if prov, err := d.unmarshalProvisioner(tc.in, provID); err != nil { switch k := err.(type) { case *admin.Error: if assert.NotNil(t, tc.adminErr) { @@ -418,20 +411,18 @@ func TestDB_unmarshalProvisioner(t *testing.T) { assert.HasPrefix(t, err.Error(), tc.err.Error()) } } - } else { - if assert.Nil(t, tc.err) && assert.Nil(t, tc.adminErr) { - assert.Equals(t, prov.Id, provID) - assert.Equals(t, prov.AuthorityId, tc.dbp.AuthorityID) - assert.Equals(t, prov.Type, tc.dbp.Type) - assert.Equals(t, prov.Name, tc.dbp.Name) - assert.Equals(t, prov.Claims, tc.dbp.Claims) - assert.Equals(t, prov.X509Template, tc.dbp.X509Template) - assert.Equals(t, prov.SshTemplate, tc.dbp.SSHTemplate) + } else if assert.Nil(t, tc.err) && assert.Nil(t, tc.adminErr) { + assert.Equals(t, prov.Id, provID) + assert.Equals(t, prov.AuthorityId, tc.dbp.AuthorityID) + assert.Equals(t, prov.Type, tc.dbp.Type) + assert.Equals(t, prov.Name, tc.dbp.Name) + assert.Equals(t, prov.Claims, tc.dbp.Claims) + assert.Equals(t, prov.X509Template, tc.dbp.X509Template) + assert.Equals(t, prov.SshTemplate, tc.dbp.SSHTemplate) - retDetailsBytes, err := json.Marshal(prov.Details.GetData()) - assert.FatalError(t, err) - assert.Equals(t, retDetailsBytes, tc.dbp.Details) - } + retDetailsBytes, err := json.Marshal(prov.Details.GetData()) + assert.FatalError(t, err) + assert.Equals(t, retDetailsBytes, tc.dbp.Details) } }) } @@ -453,7 +444,7 @@ func TestDB_GetProvisioner(t *testing.T) { assert.Equals(t, bucket, provisionersTable) assert.Equals(t, string(key), provID) - return nil, nosqldb.ErrNotFound + return nil, database.ErrNotFound }, }, adminErr: admin.NewError(admin.ErrorNotFoundType, "provisioner provID not found"), @@ -542,8 +533,8 @@ func TestDB_GetProvisioner(t *testing.T) { for name, run := range tests { tc := run(t) t.Run(name, func(t *testing.T) { - db := DB{db: tc.db, authorityID: admin.DefaultAuthorityID} - if prov, err := db.GetProvisioner(context.Background(), provID); err != nil { + d := DB{db: tc.db, authorityID: admin.DefaultAuthorityID} + if prov, err := d.GetProvisioner(context.Background(), provID); err != nil { switch k := err.(type) { case *admin.Error: if assert.NotNil(t, tc.adminErr) { @@ -558,20 +549,18 @@ func TestDB_GetProvisioner(t *testing.T) { assert.HasPrefix(t, err.Error(), tc.err.Error()) } } - } else { - if assert.Nil(t, tc.err) && assert.Nil(t, tc.adminErr) { - assert.Equals(t, prov.Id, provID) - assert.Equals(t, prov.AuthorityId, tc.dbp.AuthorityID) - assert.Equals(t, prov.Type, tc.dbp.Type) - assert.Equals(t, prov.Name, tc.dbp.Name) - assert.Equals(t, prov.Claims, tc.dbp.Claims) - assert.Equals(t, prov.X509Template, tc.dbp.X509Template) - assert.Equals(t, prov.SshTemplate, tc.dbp.SSHTemplate) + } else if assert.Nil(t, tc.err) && assert.Nil(t, tc.adminErr) { + assert.Equals(t, prov.Id, provID) + assert.Equals(t, prov.AuthorityId, tc.dbp.AuthorityID) + assert.Equals(t, prov.Type, tc.dbp.Type) + assert.Equals(t, prov.Name, tc.dbp.Name) + assert.Equals(t, prov.Claims, tc.dbp.Claims) + assert.Equals(t, prov.X509Template, tc.dbp.X509Template) + assert.Equals(t, prov.SshTemplate, tc.dbp.SSHTemplate) - retDetailsBytes, err := json.Marshal(prov.Details.GetData()) - assert.FatalError(t, err) - assert.Equals(t, retDetailsBytes, tc.dbp.Details) - } + retDetailsBytes, err := json.Marshal(prov.Details.GetData()) + assert.FatalError(t, err) + assert.Equals(t, retDetailsBytes, tc.dbp.Details) } }) } @@ -592,7 +581,7 @@ func TestDB_DeleteProvisioner(t *testing.T) { assert.Equals(t, bucket, provisionersTable) assert.Equals(t, string(key), provID) - return nil, nosqldb.ErrNotFound + return nil, database.ErrNotFound }, }, adminErr: admin.NewError(admin.ErrorNotFoundType, "provisioner provID not found"), @@ -692,8 +681,8 @@ func TestDB_DeleteProvisioner(t *testing.T) { for name, run := range tests { tc := run(t) t.Run(name, func(t *testing.T) { - db := DB{db: tc.db, authorityID: admin.DefaultAuthorityID} - if err := db.DeleteProvisioner(context.Background(), provID); err != nil { + d := DB{db: tc.db, authorityID: admin.DefaultAuthorityID} + if err := d.DeleteProvisioner(context.Background(), provID); err != nil { switch k := err.(type) { case *admin.Error: if assert.NotNil(t, tc.adminErr) { @@ -853,8 +842,8 @@ func TestDB_GetProvisioners(t *testing.T) { for name, run := range tests { tc := run(t) t.Run(name, func(t *testing.T) { - db := DB{db: tc.db, authorityID: admin.DefaultAuthorityID} - if provs, err := db.GetProvisioners(context.Background()); err != nil { + d := DB{db: tc.db, authorityID: admin.DefaultAuthorityID} + if provs, err := d.GetProvisioners(context.Background()); err != nil { switch k := err.(type) { case *admin.Error: if assert.NotNil(t, tc.adminErr) { @@ -869,10 +858,8 @@ func TestDB_GetProvisioners(t *testing.T) { assert.HasPrefix(t, err.Error(), tc.err.Error()) } } - } else { - if assert.Nil(t, tc.err) && assert.Nil(t, tc.adminErr) { - tc.verify(t, provs) - } + } else if assert.Nil(t, tc.err) && assert.Nil(t, tc.adminErr) { + tc.verify(t, provs) } }) } @@ -963,8 +950,8 @@ func TestDB_CreateProvisioner(t *testing.T) { for name, run := range tests { tc := run(t) t.Run(name, func(t *testing.T) { - db := DB{db: tc.db, authorityID: admin.DefaultAuthorityID} - if err := db.CreateProvisioner(context.Background(), tc.prov); err != nil { + d := DB{db: tc.db, authorityID: admin.DefaultAuthorityID} + if err := d.CreateProvisioner(context.Background(), tc.prov); err != nil { switch k := err.(type) { case *admin.Error: if assert.NotNil(t, tc.adminErr) { @@ -1001,7 +988,7 @@ func TestDB_UpdateProvisioner(t *testing.T) { assert.Equals(t, bucket, provisionersTable) assert.Equals(t, string(key), provID) - return nil, nosqldb.ErrNotFound + return nil, database.ErrNotFound }, }, adminErr: admin.NewError(admin.ErrorNotFoundType, "provisioner provID not found"), @@ -1199,8 +1186,8 @@ func TestDB_UpdateProvisioner(t *testing.T) { for name, run := range tests { tc := run(t) t.Run(name, func(t *testing.T) { - db := DB{db: tc.db, authorityID: admin.DefaultAuthorityID} - if err := db.UpdateProvisioner(context.Background(), tc.prov); err != nil { + d := DB{db: tc.db, authorityID: admin.DefaultAuthorityID} + if err := d.UpdateProvisioner(context.Background(), tc.prov); err != nil { switch k := err.(type) { case *admin.Error: if assert.NotNil(t, tc.adminErr) { diff --git a/authority/administrator/collection.go b/authority/administrator/collection.go index ff04a41f..88d7bb2c 100644 --- a/authority/administrator/collection.go +++ b/authority/administrator/collection.go @@ -55,8 +55,8 @@ type subProv struct { provisioner string } -func newSubProv(subject, provisioner string) subProv { - return subProv{subject, provisioner} +func newSubProv(subject, prov string) subProv { + return subProv{subject, prov} } // LoadBySubProv a admin by the subject and provisioner name. diff --git a/authority/admins.go b/authority/admins.go index dcaf9b49..b975297a 100644 --- a/authority/admins.go +++ b/authority/admins.go @@ -16,10 +16,10 @@ func (a *Authority) LoadAdminByID(id string) (*linkedca.Admin, bool) { } // LoadAdminBySubProv returns an *linkedca.Admin with the given ID. -func (a *Authority) LoadAdminBySubProv(subject, provisioner string) (*linkedca.Admin, bool) { +func (a *Authority) LoadAdminBySubProv(subject, prov string) (*linkedca.Admin, bool) { a.adminMutex.RLock() defer a.adminMutex.RUnlock() - return a.admins.LoadBySubProv(subject, provisioner) + return a.admins.LoadBySubProv(subject, prov) } // GetAdmins returns a map listing each provisioner and the JWK Key Set diff --git a/authority/authority.go b/authority/authority.go index 3f97ceab..aa8698d7 100644 --- a/authority/authority.go +++ b/authority/authority.go @@ -78,14 +78,14 @@ type Authority struct { } // New creates and initiates a new Authority type. -func New(config *config.Config, opts ...Option) (*Authority, error) { - err := config.Validate() +func New(cfg *config.Config, opts ...Option) (*Authority, error) { + err := cfg.Validate() if err != nil { return nil, err } var a = &Authority{ - config: config, + config: cfg, certificates: new(sync.Map), } diff --git a/authority/authorize.go b/authority/authorize.go index 816699f7..a4e7e591 100644 --- a/authority/authorize.go +++ b/authority/authorize.go @@ -54,7 +54,7 @@ func (a *Authority) authorizeToken(ctx context.Context, token string) (provision // key in order to verify the claims and we need the issuer from the claims // before we can look up the provisioner. var claims Claims - if err = tok.UnsafeClaimsWithoutVerification(&claims); err != nil { + if err := tok.UnsafeClaimsWithoutVerification(&claims); err != nil { return nil, errs.Wrap(http.StatusUnauthorized, err, "authority.authorizeToken") } @@ -77,7 +77,7 @@ func (a *Authority) authorizeToken(ctx context.Context, token string) (provision // Store the token to protect against reuse unless it's skipped. // If we cannot get a token id from the provisioner, just hash the token. if !SkipTokenReuseFromContext(ctx) { - if err = a.UseToken(token, p); err != nil { + if err := a.UseToken(token, p); err != nil { return nil, err } } @@ -112,7 +112,7 @@ func (a *Authority) AuthorizeAdminToken(r *http.Request, token string) (*linkedc // to the public certificate in the `x5c` header of the token. // 2. Asserts that the claims are valid - have not been tampered with. var claims jose.Claims - if err = jwt.Claims(leaf.PublicKey, &claims); err != nil { + if err := jwt.Claims(leaf.PublicKey, &claims); err != nil { return nil, admin.WrapError(admin.ErrorUnauthorizedType, err, "adminHandler.authorizeToken; error parsing x5c claims") } @@ -122,13 +122,13 @@ func (a *Authority) AuthorizeAdminToken(r *http.Request, token string) (*linkedc } // Check that the token has not been used. - if err = a.UseToken(token, prov); err != nil { + if err := a.UseToken(token, prov); err != nil { return nil, admin.WrapError(admin.ErrorUnauthorizedType, err, "adminHandler.authorizeToken; error with reuse token") } // According to "rfc7519 JSON Web Token" acceptable skew should be no // more than a few minutes. - if err = claims.ValidateWithLeeway(jose.Expected{ + if err := claims.ValidateWithLeeway(jose.Expected{ Issuer: prov.GetName(), Time: time.Now().UTC(), }, time.Minute); err != nil { @@ -262,7 +262,7 @@ func (a *Authority) authorizeRevoke(ctx context.Context, token string) error { if err != nil { return errs.Wrap(http.StatusInternalServerError, err, "authority.authorizeRevoke") } - if err = p.AuthorizeRevoke(ctx, token); err != nil { + if err := p.AuthorizeRevoke(ctx, token); err != nil { return errs.Wrap(http.StatusInternalServerError, err, "authority.authorizeRevoke") } return nil diff --git a/authority/authorize_test.go b/authority/authorize_test.go index f308ec28..6d524a25 100644 --- a/authority/authorize_test.go +++ b/authority/authorize_test.go @@ -917,7 +917,7 @@ func createSSHCert(cert *ssh.Certificate, signer ssh.Signer) (*ssh.Certificate, if err != nil { return nil, nil, err } - if err = cert.SignCert(rand.Reader, signer); err != nil { + if err := cert.SignCert(rand.Reader, signer); err != nil { return nil, nil, err } return cert, jwk, nil diff --git a/authority/config/types.go b/authority/config/types.go index 6d7b9389..5ca3b15f 100644 --- a/authority/config/types.go +++ b/authority/config/types.go @@ -25,7 +25,7 @@ func (s multiString) HasEmpties() bool { return true } for _, ss := range s { - if len(ss) == 0 { + if ss == "" { return true } } diff --git a/authority/linkedca.go b/authority/linkedca.go index 9c816e1e..b568dcbb 100644 --- a/authority/linkedca.go +++ b/authority/linkedca.go @@ -272,12 +272,12 @@ func (c *linkedCaClient) Revoke(crt *x509.Certificate, rci *db.RevokedCertificat return errors.Wrap(err, "error revoking certificate") } -func (c *linkedCaClient) RevokeSSH(ssh *ssh.Certificate, rci *db.RevokedCertificateInfo) error { +func (c *linkedCaClient) RevokeSSH(cert *ssh.Certificate, rci *db.RevokedCertificateInfo) error { ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) defer cancel() _, err := c.client.RevokeSSHCertificate(ctx, &linkedca.RevokeSSHCertificateRequest{ Serial: rci.Serial, - Certificate: serializeSSHCertificate(ssh), + Certificate: serializeSSHCertificate(cert), Reason: rci.Reason, ReasonCode: linkedca.RevocationReasonCode(rci.ReasonCode), Passive: true, diff --git a/authority/options.go b/authority/options.go index 5c8a6e66..0f80cbbf 100644 --- a/authority/options.go +++ b/authority/options.go @@ -22,9 +22,9 @@ type Option func(*Authority) error // WithConfig replaces the current config with the given one. No validation is // performed in the given value. -func WithConfig(config *config.Config) Option { +func WithConfig(cfg *config.Config) Option { return func(a *Authority) error { - a.config = config + a.config = cfg return nil } } @@ -76,9 +76,9 @@ func WithIssuerPassword(password []byte) Option { // WithDatabase sets an already initialized authority database to a new // authority. This option is intended to be use on graceful reloads. -func WithDatabase(db db.AuthDB) Option { +func WithDatabase(d db.AuthDB) Option { return func(a *Authority) error { - a.db = db + a.db = d return nil } } @@ -225,9 +225,9 @@ func WithX509FederatedBundle(pemCerts []byte) Option { } // WithAdminDB is an option to set the database backing the admin APIs. -func WithAdminDB(db admin.DB) Option { +func WithAdminDB(d admin.DB) Option { return func(a *Authority) error { - a.adminDB = db + a.adminDB = d return nil } } diff --git a/authority/provisioner/aws.go b/authority/provisioner/aws.go index cdd06f00..cd129b7b 100644 --- a/authority/provisioner/aws.go +++ b/authority/provisioner/aws.go @@ -312,7 +312,7 @@ func (p *AWS) GetType() Type { } // GetEncryptedKey is not available in an AWS provisioner. -func (p *AWS) GetEncryptedKey() (kid string, key string, ok bool) { +func (p *AWS) GetEncryptedKey() (kid, key string, ok bool) { return "", "", false } @@ -449,13 +449,15 @@ func (p *AWS) AuthorizeSign(ctx context.Context, token string) ([]SignOption, er // There's no way to trust them other than TOFU. var so []SignOption if p.DisableCustomSANs { - dnsName := fmt.Sprintf("ip-%s.%s.compute.internal", strings.Replace(doc.PrivateIP, ".", "-", -1), doc.Region) - so = append(so, dnsNamesValidator([]string{dnsName})) - so = append(so, ipAddressesValidator([]net.IP{ - net.ParseIP(doc.PrivateIP), - })) - so = append(so, emailAddressesValidator(nil)) - so = append(so, urisValidator(nil)) + dnsName := fmt.Sprintf("ip-%s.%s.compute.internal", strings.ReplaceAll(doc.PrivateIP, ".", "-"), doc.Region) + so = append(so, + dnsNamesValidator([]string{dnsName}), + ipAddressesValidator([]net.IP{ + net.ParseIP(doc.PrivateIP), + }), + emailAddressesValidator(nil), + urisValidator(nil), + ) // Template options data.SetSANs([]string{dnsName, doc.PrivateIP}) @@ -669,7 +671,7 @@ func (p *AWS) authorizeToken(token string) (*awsPayload, error) { if p.DisableCustomSANs { if payload.Subject != doc.InstanceID && payload.Subject != doc.PrivateIP && - payload.Subject != fmt.Sprintf("ip-%s.%s.compute.internal", strings.Replace(doc.PrivateIP, ".", "-", -1), doc.Region) { + payload.Subject != fmt.Sprintf("ip-%s.%s.compute.internal", strings.ReplaceAll(doc.PrivateIP, ".", "-"), doc.Region) { return nil, errs.Unauthorized("aws.authorizeToken; invalid token - invalid subject claim (sub)") } } @@ -720,7 +722,7 @@ func (p *AWS) AuthorizeSSHSign(ctx context.Context, token string) ([]SignOption, // Validated principals. principals := []string{ doc.PrivateIP, - fmt.Sprintf("ip-%s.%s.compute.internal", strings.Replace(doc.PrivateIP, ".", "-", -1), doc.Region), + fmt.Sprintf("ip-%s.%s.compute.internal", strings.ReplaceAll(doc.PrivateIP, ".", "-"), doc.Region), } // Only enforce known principals if disable custom sans is true. diff --git a/authority/provisioner/aws_test.go b/authority/provisioner/aws_test.go index aff0aecb..0d2786db 100644 --- a/authority/provisioner/aws_test.go +++ b/authority/provisioner/aws_test.go @@ -663,15 +663,15 @@ func TestAWS_AuthorizeSign(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { ctx := NewContextWithMethod(context.Background(), SignMethod) - got, err := tt.aws.AuthorizeSign(ctx, tt.args.token) - if (err != nil) != tt.wantErr { + switch got, err := tt.aws.AuthorizeSign(ctx, tt.args.token); { + case (err != nil) != tt.wantErr: t.Errorf("AWS.AuthorizeSign() error = %v, wantErr %v", err, tt.wantErr) return - } else if err != nil { + case err != nil: sc, ok := err.(errs.StatusCoder) assert.Fatal(t, ok, "error does not implement StatusCoder interface") assert.Equals(t, sc.StatusCode(), tt.code) - } else { + default: assert.Len(t, tt.wantLen, got) for _, o := range got { switch v := o.(type) { diff --git a/authority/provisioner/azure.go b/authority/provisioner/azure.go index fee50658..a90d1728 100644 --- a/authority/provisioner/azure.go +++ b/authority/provisioner/azure.go @@ -152,7 +152,7 @@ func (p *Azure) GetType() Type { } // GetEncryptedKey is not available in an Azure provisioner. -func (p *Azure) GetEncryptedKey() (kid string, key string, ok bool) { +func (p *Azure) GetEncryptedKey() (kid, key string, ok bool) { return "", "", false } @@ -303,11 +303,13 @@ func (p *Azure) AuthorizeSign(ctx context.Context, token string) ([]SignOption, var so []SignOption if p.DisableCustomSANs { // name will work only inside the virtual network - so = append(so, commonNameValidator(name)) - so = append(so, dnsNamesValidator([]string{name})) - so = append(so, ipAddressesValidator(nil)) - so = append(so, emailAddressesValidator(nil)) - so = append(so, urisValidator(nil)) + so = append(so, + commonNameValidator(name), + dnsNamesValidator([]string{name}), + ipAddressesValidator(nil), + emailAddressesValidator(nil), + urisValidator(nil), + ) // Enforce SANs in the template. data.SetSANs([]string{name}) diff --git a/authority/provisioner/azure_test.go b/authority/provisioner/azure_test.go index 8033d345..b7c321a6 100644 --- a/authority/provisioner/azure_test.go +++ b/authority/provisioner/azure_test.go @@ -446,15 +446,15 @@ func TestAzure_AuthorizeSign(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { ctx := NewContextWithMethod(context.Background(), SignMethod) - got, err := tt.azure.AuthorizeSign(ctx, tt.args.token) - if (err != nil) != tt.wantErr { + switch got, err := tt.azure.AuthorizeSign(ctx, tt.args.token); { + case (err != nil) != tt.wantErr: t.Errorf("Azure.AuthorizeSign() error = %v, wantErr %v", err, tt.wantErr) return - } else if err != nil { + case err != nil: sc, ok := err.(errs.StatusCoder) assert.Fatal(t, ok, "error does not implement StatusCoder interface") assert.Equals(t, sc.StatusCode(), tt.code) - } else { + default: assert.Len(t, tt.wantLen, got) for _, o := range got { switch v := o.(type) { diff --git a/authority/provisioner/collection.go b/authority/provisioner/collection.go index caf46ca9..1bec8689 100644 --- a/authority/provisioner/collection.go +++ b/authority/provisioner/collection.go @@ -229,14 +229,15 @@ func (c *Collection) Remove(id string) error { var found bool for i, elem := range c.sorted { - if elem.provisioner.GetID() == id { - // Remove index in sorted list - copy(c.sorted[i:], c.sorted[i+1:]) // Shift a[i+1:] left one index. - c.sorted[len(c.sorted)-1] = uidProvisioner{} // Erase last element (write zero value). - c.sorted = c.sorted[:len(c.sorted)-1] // Truncate slice. - found = true - break + if elem.provisioner.GetID() != id { + continue } + // Remove index in sorted list + copy(c.sorted[i:], c.sorted[i+1:]) // Shift a[i+1:] left one index. + c.sorted[len(c.sorted)-1] = uidProvisioner{} // Erase last element (write zero value). + c.sorted = c.sorted[:len(c.sorted)-1] // Truncate slice. + found = true + break } if !found { return admin.NewError(admin.ErrorNotFoundType, "provisioner %s not found in sorted list", prov.GetName()) diff --git a/authority/provisioner/gcp.go b/authority/provisioner/gcp.go index 1b599fb3..98d776d1 100644 --- a/authority/provisioner/gcp.go +++ b/authority/provisioner/gcp.go @@ -150,7 +150,7 @@ func (p *GCP) GetType() Type { } // GetEncryptedKey is not available in a GCP provisioner. -func (p *GCP) GetEncryptedKey() (kid string, key string, ok bool) { +func (p *GCP) GetEncryptedKey() (kid, key string, ok bool) { return "", "", false } @@ -244,15 +244,17 @@ func (p *GCP) AuthorizeSign(ctx context.Context, token string) ([]SignOption, er if p.DisableCustomSANs { dnsName1 := fmt.Sprintf("%s.c.%s.internal", ce.InstanceName, ce.ProjectID) dnsName2 := fmt.Sprintf("%s.%s.c.%s.internal", ce.InstanceName, ce.Zone, ce.ProjectID) - so = append(so, commonNameSliceValidator([]string{ - ce.InstanceName, ce.InstanceID, dnsName1, dnsName2, - })) - so = append(so, dnsNamesValidator([]string{ - dnsName1, dnsName2, - })) - so = append(so, ipAddressesValidator(nil)) - so = append(so, emailAddressesValidator(nil)) - so = append(so, urisValidator(nil)) + so = append(so, + commonNameSliceValidator([]string{ + ce.InstanceName, ce.InstanceID, dnsName1, dnsName2, + }), + dnsNamesValidator([]string{ + dnsName1, dnsName2, + }), + ipAddressesValidator(nil), + emailAddressesValidator(nil), + urisValidator(nil), + ) // Template SANs data.SetSANs([]string{dnsName1, dnsName2}) diff --git a/authority/provisioner/gcp_test.go b/authority/provisioner/gcp_test.go index d6c4054c..5f6f9bc7 100644 --- a/authority/provisioner/gcp_test.go +++ b/authority/provisioner/gcp_test.go @@ -535,15 +535,15 @@ func TestGCP_AuthorizeSign(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { ctx := NewContextWithMethod(context.Background(), SignMethod) - got, err := tt.gcp.AuthorizeSign(ctx, tt.args.token) - if (err != nil) != tt.wantErr { + switch got, err := tt.gcp.AuthorizeSign(ctx, tt.args.token); { + case (err != nil) != tt.wantErr: t.Errorf("GCP.AuthorizeSign() error = %v, wantErr %v", err, tt.wantErr) return - } else if err != nil { + case err != nil: sc, ok := err.(errs.StatusCoder) assert.Fatal(t, ok, "error does not implement StatusCoder interface") assert.Equals(t, sc.StatusCode(), tt.code) - } else { + default: assert.Len(t, tt.wantLen, got) for _, o := range got { switch v := o.(type) { diff --git a/authority/provisioner/keystore.go b/authority/provisioner/keystore.go index f775e150..d1811fab 100644 --- a/authority/provisioner/keystore.go +++ b/authority/provisioner/keystore.go @@ -18,7 +18,7 @@ const ( defaultCacheJitter = 1 * time.Hour ) -var maxAgeRegex = regexp.MustCompile("max-age=([0-9]+)") +var maxAgeRegex = regexp.MustCompile(`max-age=(\d+)`) type keyStore struct { sync.RWMutex diff --git a/authority/provisioner/noop.go b/authority/provisioner/noop.go index 18a38331..1709fbca 100644 --- a/authority/provisioner/noop.go +++ b/authority/provisioner/noop.go @@ -29,7 +29,7 @@ func (p *noop) GetType() Type { return noopType } -func (p *noop) GetEncryptedKey() (kid string, key string, ok bool) { +func (p *noop) GetEncryptedKey() (kid, key string, ok bool) { return "", "", false } diff --git a/authority/provisioner/oidc.go b/authority/provisioner/oidc.go index 3786f54b..ac1f2a25 100644 --- a/authority/provisioner/oidc.go +++ b/authority/provisioner/oidc.go @@ -148,7 +148,7 @@ func (o *OIDC) GetType() Type { } // GetEncryptedKey is not available in an OIDC provisioner. -func (o *OIDC) GetEncryptedKey() (kid string, key string, ok bool) { +func (o *OIDC) GetEncryptedKey() (kid, key string, ok bool) { return "", "", false } @@ -193,7 +193,7 @@ func (o *OIDC) Init(config Config) (err error) { } // Replace {tenantid} with the configured one if o.TenantID != "" { - o.configuration.Issuer = strings.Replace(o.configuration.Issuer, "{tenantid}", o.TenantID, -1) + o.configuration.Issuer = strings.ReplaceAll(o.configuration.Issuer, "{tenantid}", o.TenantID) } // Get JWK key set o.keyStore, err = newKeyStore(o.configuration.JWKSetURI) diff --git a/authority/provisioner/oidc_test.go b/authority/provisioner/oidc_test.go index 532bd2e0..7bf6ad7a 100644 --- a/authority/provisioner/oidc_test.go +++ b/authority/provisioner/oidc_test.go @@ -321,32 +321,26 @@ func TestOIDC_AuthorizeSign(t *testing.T) { assert.Fatal(t, ok, "error does not implement StatusCoder interface") assert.Equals(t, sc.StatusCode(), tt.code) assert.Nil(t, got) - } else { - if assert.NotNil(t, got) { - if tt.name == "admin" { - assert.Len(t, 5, got) - } else { - assert.Len(t, 5, got) - } - for _, o := range got { - switch v := o.(type) { - case certificateOptionsFunc: - case *provisionerExtensionOption: - assert.Equals(t, v.Type, int(TypeOIDC)) - assert.Equals(t, v.Name, tt.prov.GetName()) - assert.Equals(t, v.CredentialID, tt.prov.ClientID) - assert.Len(t, 0, v.KeyValuePairs) - case profileDefaultDuration: - assert.Equals(t, time.Duration(v), tt.prov.claimer.DefaultTLSCertDuration()) - case defaultPublicKeyValidator: - case *validityValidator: - assert.Equals(t, v.min, tt.prov.claimer.MinTLSCertDuration()) - assert.Equals(t, v.max, tt.prov.claimer.MaxTLSCertDuration()) - case emailOnlyIdentity: - assert.Equals(t, string(v), "name@smallstep.com") - default: - assert.FatalError(t, errors.Errorf("unexpected sign option of type %T", v)) - } + } else if assert.NotNil(t, got) { + assert.Len(t, 5, got) + for _, o := range got { + switch v := o.(type) { + case certificateOptionsFunc: + case *provisionerExtensionOption: + assert.Equals(t, v.Type, int(TypeOIDC)) + assert.Equals(t, v.Name, tt.prov.GetName()) + assert.Equals(t, v.CredentialID, tt.prov.ClientID) + assert.Len(t, 0, v.KeyValuePairs) + case profileDefaultDuration: + assert.Equals(t, time.Duration(v), tt.prov.claimer.DefaultTLSCertDuration()) + case defaultPublicKeyValidator: + case *validityValidator: + assert.Equals(t, v.min, tt.prov.claimer.MinTLSCertDuration()) + assert.Equals(t, v.max, tt.prov.claimer.MaxTLSCertDuration()) + case emailOnlyIdentity: + assert.Equals(t, string(v), "name@smallstep.com") + default: + assert.FatalError(t, errors.Errorf("unexpected sign option of type %T", v)) } } } diff --git a/authority/provisioner/options.go b/authority/provisioner/options.go index 100aa588..f86c4863 100644 --- a/authority/provisioner/options.go +++ b/authority/provisioner/options.go @@ -138,7 +138,7 @@ func unsafeParseSigned(s string) (map[string]interface{}, error) { return nil, err } claims := make(map[string]interface{}) - if err = token.UnsafeClaimsWithoutVerification(&claims); err != nil { + if err := token.UnsafeClaimsWithoutVerification(&claims); err != nil { return nil, err } return claims, nil diff --git a/authority/provisioner/provisioner.go b/authority/provisioner/provisioner.go index 652cb888..5d6b2f80 100644 --- a/authority/provisioner/provisioner.go +++ b/authority/provisioner/provisioner.go @@ -123,7 +123,7 @@ func (a Audiences) WithFragment(fragment string) Audiences { // generateSignAudience generates a sign audience with the format // https:///1.0/sign#provisionerID -func generateSignAudience(caURL string, provisionerID string) (string, error) { +func generateSignAudience(caURL, provisionerID string) (string, error) { u, err := url.Parse(caURL) if err != nil { return "", errors.Wrapf(err, "error parsing %s", caURL) diff --git a/authority/provisioner/sign_ssh_options_test.go b/authority/provisioner/sign_ssh_options_test.go index 693690f6..3a1ff324 100644 --- a/authority/provisioner/sign_ssh_options_test.go +++ b/authority/provisioner/sign_ssh_options_test.go @@ -44,7 +44,7 @@ func TestSSHOptions_Modify(t *testing.T) { valid func(*ssh.Certificate) err error } - tests := map[string](func() test){ + tests := map[string]func() test{ "fail/unexpected-cert-type": func() test { return test{ so: SignSSHOptions{CertType: "foo"}, @@ -117,7 +117,7 @@ func TestSSHOptions_Match(t *testing.T) { cmp SignSSHOptions err error } - tests := map[string](func() test){ + tests := map[string]func() test{ "fail/cert-type": func() test { return test{ so: SignSSHOptions{CertType: "foo"}, @@ -208,7 +208,7 @@ func Test_sshCertPrincipalsModifier_Modify(t *testing.T) { cert *ssh.Certificate expected []string } - tests := map[string](func() test){ + tests := map[string]func() test{ "ok": func() test { a := []string{"foo", "bar"} return test{ @@ -234,7 +234,7 @@ func Test_sshCertKeyIDModifier_Modify(t *testing.T) { cert *ssh.Certificate expected string } - tests := map[string](func() test){ + tests := map[string]func() test{ "ok": func() test { a := "foo" return test{ @@ -260,7 +260,7 @@ func Test_sshCertTypeModifier_Modify(t *testing.T) { cert *ssh.Certificate expected uint32 } - tests := map[string](func() test){ + tests := map[string]func() test{ "ok/user": func() test { return test{ modifier: sshCertTypeModifier("user"), @@ -299,7 +299,7 @@ func Test_sshCertValidAfterModifier_Modify(t *testing.T) { cert *ssh.Certificate expected uint64 } - tests := map[string](func() test){ + tests := map[string]func() test{ "ok": func() test { return test{ modifier: sshCertValidAfterModifier(15), @@ -324,7 +324,7 @@ func Test_sshCertDefaultsModifier_Modify(t *testing.T) { cert *ssh.Certificate valid func(*ssh.Certificate) } - tests := map[string](func() test){ + tests := map[string]func() test{ "ok/changes": func() test { n := time.Now() va := NewTimeDuration(n.Add(1 * time.Minute)) @@ -388,7 +388,7 @@ func Test_sshDefaultExtensionModifier_Modify(t *testing.T) { valid func(*ssh.Certificate) err error } - tests := map[string](func() test){ + tests := map[string]func() test{ "fail/unexpected-cert-type": func() test { cert := &ssh.Certificate{CertType: 3} return test{ diff --git a/authority/provisioner/sshpop_test.go b/authority/provisioner/sshpop_test.go index 79d82e00..3d343967 100644 --- a/authority/provisioner/sshpop_test.go +++ b/authority/provisioner/sshpop_test.go @@ -46,7 +46,7 @@ func createSSHCert(cert *ssh.Certificate, signer ssh.Signer) (*ssh.Certificate, if err != nil { return nil, nil, err } - if err = cert.SignCert(rand.Reader, signer); err != nil { + if err := cert.SignCert(rand.Reader, signer); err != nil { return nil, nil, err } return cert, jwk, nil @@ -214,10 +214,8 @@ func TestSSHPOP_authorizeToken(t *testing.T) { if assert.NotNil(t, tc.err) { assert.HasPrefix(t, err.Error(), tc.err.Error()) } - } else { - if assert.Nil(t, tc.err) { - assert.NotNil(t, claims) - } + } else if assert.Nil(t, tc.err) { + assert.NotNil(t, claims) } }) } diff --git a/authority/provisioner/utils_test.go b/authority/provisioner/utils_test.go index 534e83cf..e39efbcf 100644 --- a/authority/provisioner/utils_test.go +++ b/authority/provisioner/utils_test.go @@ -732,7 +732,7 @@ func withSSHPOPFile(cert *ssh.Certificate) tokOption { } } -func generateToken(sub, iss, aud string, email string, sans []string, iat time.Time, jwk *jose.JSONWebKey, tokOpts ...tokOption) (string, error) { +func generateToken(sub, iss, aud, email string, sans []string, iat time.Time, jwk *jose.JSONWebKey, tokOpts ...tokOption) (string, error) { so := new(jose.SignerOptions) so.WithType("JWT") so.WithHeader("kid", jwk.KeyID) @@ -773,7 +773,7 @@ func generateToken(sub, iss, aud string, email string, sans []string, iat time.T return jose.Signed(sig).Claims(claims).CompactSerialize() } -func generateOIDCToken(sub, iss, aud string, email string, preferredUsername string, iat time.Time, jwk *jose.JSONWebKey, tokOpts ...tokOption) (string, error) { +func generateOIDCToken(sub, iss, aud, email, preferredUsername string, iat time.Time, jwk *jose.JSONWebKey, tokOpts ...tokOption) (string, error) { so := new(jose.SignerOptions) so.WithType("JWT") so.WithHeader("kid", jwk.KeyID) diff --git a/authority/ssh.go b/authority/ssh.go index 1c873279..762319ae 100644 --- a/authority/ssh.go +++ b/authority/ssh.go @@ -108,7 +108,7 @@ func (a *Authority) GetSSHConfig(ctx context.Context, typ string, data map[strin // GetSSHBastion returns the bastion configuration, for the given pair user, // hostname. -func (a *Authority) GetSSHBastion(ctx context.Context, user string, hostname string) (*config.Bastion, error) { +func (a *Authority) GetSSHBastion(ctx context.Context, user, hostname string) (*config.Bastion, error) { if a.sshBastionFunc != nil { bs, err := a.sshBastionFunc(ctx, user, hostname) return bs, errs.Wrap(http.StatusInternalServerError, err, "authority.GetSSHBastion") @@ -477,7 +477,7 @@ func (a *Authority) SignSSHAddUser(ctx context.Context, key ssh.PublicKey, subje } // CheckSSHHost checks the given principal has been registered before. -func (a *Authority) CheckSSHHost(ctx context.Context, principal string, token string) (bool, error) { +func (a *Authority) CheckSSHHost(ctx context.Context, principal, token string) (bool, error) { if a.sshCheckHostFunc != nil { exists, err := a.sshCheckHostFunc(ctx, principal, token, a.GetRootCertificates()) if err != nil { @@ -531,5 +531,5 @@ func (a *Authority) getAddUserCommand(principal string) string { } else { cmd = a.config.SSH.AddUserCommand } - return strings.Replace(cmd, "", principal, -1) + return strings.ReplaceAll(cmd, "", principal) } diff --git a/authority/tls.go b/authority/tls.go index b434be55..839866a2 100644 --- a/authority/tls.go +++ b/authority/tls.go @@ -55,10 +55,10 @@ func withDefaultASN1DN(def *config.ASN1DN) provisioner.CertificateModifierFunc { if len(crt.Subject.StreetAddress) == 0 && def.StreetAddress != "" { crt.Subject.StreetAddress = append(crt.Subject.StreetAddress, def.StreetAddress) } - if len(crt.Subject.SerialNumber) == 0 && def.SerialNumber != "" { + if crt.Subject.SerialNumber == "" && def.SerialNumber != "" { crt.Subject.SerialNumber = def.SerialNumber } - if len(crt.Subject.CommonName) == 0 && def.CommonName != "" { + if crt.Subject.CommonName == "" && def.CommonName != "" { crt.Subject.CommonName = def.CommonName } return nil @@ -387,14 +387,14 @@ func (a *Authority) Revoke(ctx context.Context, revokeOpts *RevokeOptions) error return errs.Wrap(http.StatusInternalServerError, err, "authority.Revoke; could not get ID for token") } - opts = append(opts, errs.WithKeyVal("provisionerID", rci.ProvisionerID)) - opts = append(opts, errs.WithKeyVal("tokenID", rci.TokenID)) - } else { + opts = append(opts, + errs.WithKeyVal("provisionerID", rci.ProvisionerID), + errs.WithKeyVal("tokenID", rci.TokenID), + ) + } else if p, err = a.LoadProvisionerByCertificate(revokeOpts.Crt); err == nil { // Load the Certificate provisioner if one exists. - if p, err = a.LoadProvisionerByCertificate(revokeOpts.Crt); err == nil { - rci.ProvisionerID = p.GetID() - opts = append(opts, errs.WithKeyVal("provisionerID", rci.ProvisionerID)) - } + rci.ProvisionerID = p.GetID() + opts = append(opts, errs.WithKeyVal("provisionerID", rci.ProvisionerID)) } if provisioner.MethodFromContext(ctx) == provisioner.SSHRevokeMethod { diff --git a/authority/tls_test.go b/authority/tls_test.go index cdd4c59a..f1d1748d 100644 --- a/authority/tls_test.go +++ b/authority/tls_test.go @@ -426,6 +426,7 @@ ZYtQ9Ot36qc= {Id: stepOIDProvisioner, Value: []byte("foo")}, {Id: []int{1, 1, 1}, Value: []byte("bar")}})) now := time.Now().UTC() + // nolint:gocritic enforcedExtraOptions := append(extraOpts, &certificateDurationEnforcer{ NotBefore: now, NotAfter: now.Add(365 * 24 * time.Hour), diff --git a/ca/acmeClient.go b/ca/acmeClient.go index 5633dac5..d1f40f32 100644 --- a/ca/acmeClient.go +++ b/ca/acmeClient.go @@ -345,7 +345,7 @@ func readACMEError(r io.ReadCloser) error { ae := new(acme.Error) err = json.Unmarshal(b, &ae) // If we successfully marshaled to an ACMEError then return the ACMEError. - if err != nil || len(ae.Error()) == 0 { + if err != nil || ae.Error() == "" { fmt.Printf("b = %s\n", b) // Throw up our hands. return errors.Errorf("%s", b) diff --git a/ca/acmeClient_test.go b/ca/acmeClient_test.go index f5963de4..656a82cf 100644 --- a/ca/acmeClient_test.go +++ b/ca/acmeClient_test.go @@ -1247,6 +1247,7 @@ func TestACMEClient_GetCertificate(t *testing.T) { Type: "Certificate", Bytes: leaf.Raw, }) + // nolint:gocritic certBytes := append(leafb, leafb...) certBytes = append(certBytes, leafb...) ac := &ACMEClient{ diff --git a/ca/adminClient.go b/ca/adminClient.go index 2f3d4b5d..6022f677 100644 --- a/ca/adminClient.go +++ b/ca/adminClient.go @@ -70,7 +70,7 @@ func NewAdminClient(endpoint string, opts ...ClientOption) (*AdminClient, error) }, nil } -func (c *AdminClient) generateAdminToken(path string) (string, error) { +func (c *AdminClient) generateAdminToken(urlPath string) (string, error) { // A random jwt id will be used to identify duplicated tokens jwtID, err := randutil.Hex(64) // 256 bits if err != nil { @@ -82,7 +82,7 @@ func (c *AdminClient) generateAdminToken(path string) (string, error) { token.WithJWTID(jwtID), token.WithKid(c.x5cJWK.KeyID), token.WithIssuer(c.x5cIssuer), - token.WithAudience(path), + token.WithAudience(urlPath), token.WithValidity(now, now.Add(token.DefaultValidity)), token.WithX5CCerts(c.x5cCertStrs), } @@ -348,14 +348,15 @@ func (c *AdminClient) GetProvisioner(opts ...ProvisionerOption) (*linkedca.Provi return nil, err } var u *url.URL - if len(o.id) > 0 { + switch { + case len(o.id) > 0: u = c.endpoint.ResolveReference(&url.URL{ Path: "/admin/provisioners/id", RawQuery: o.rawQuery(), }) - } else if len(o.name) > 0 { + case len(o.name) > 0: u = c.endpoint.ResolveReference(&url.URL{Path: path.Join(adminURLPrefix, "provisioners", o.name)}) - } else { + default: return nil, errors.New("must set either name or id in method options") } tok, err := c.generateAdminToken(u.Path) @@ -456,14 +457,15 @@ func (c *AdminClient) RemoveProvisioner(opts ...ProvisionerOption) error { return err } - if len(o.id) > 0 { + switch { + case len(o.id) > 0: u = c.endpoint.ResolveReference(&url.URL{ Path: path.Join(adminURLPrefix, "provisioners/id"), RawQuery: o.rawQuery(), }) - } else if len(o.name) > 0 { + case len(o.name) > 0: u = c.endpoint.ResolveReference(&url.URL{Path: path.Join(adminURLPrefix, "provisioners", o.name)}) - } else { + default: return errors.New("must set either name or id in method options") } tok, err := c.generateAdminToken(u.Path) diff --git a/ca/bootstrap.go b/ca/bootstrap.go index 5f06e986..42087985 100644 --- a/ca/bootstrap.go +++ b/ca/bootstrap.go @@ -30,7 +30,7 @@ func Bootstrap(token string) (*Client, error) { // Validate bootstrap token switch { - case len(claims.SHA) == 0: + case claims.SHA == "": return nil, errors.New("invalid bootstrap token: sha claim is not present") case !strings.HasPrefix(strings.ToLower(claims.Audience[0]), "http"): return nil, errors.New("invalid bootstrap token: aud claim is not a url") diff --git a/ca/ca.go b/ca/ca.go index 00a5970a..c76e8c0a 100644 --- a/ca/ca.go +++ b/ca/ca.go @@ -88,9 +88,9 @@ func WithIssuerPassword(password []byte) Option { } // WithDatabase sets the given authority database to the CA options. -func WithDatabase(db db.AuthDB) Option { +func WithDatabase(d db.AuthDB) Option { return func(o *options) { - o.database = db + o.database = d } } @@ -113,17 +113,17 @@ type CA struct { } // New creates and initializes the CA with the given configuration and options. -func New(config *config.Config, opts ...Option) (*CA, error) { +func New(cfg *config.Config, opts ...Option) (*CA, error) { ca := &CA{ - config: config, + config: cfg, opts: new(options), } ca.opts.apply(opts) - return ca.Init(config) + return ca.Init(cfg) } // Init initializes the CA with the given configuration. -func (ca *CA) Init(config *config.Config) (*CA, error) { +func (ca *CA) Init(cfg *config.Config) (*CA, error) { // Set password, it's ok to set nil password, the ca will prompt for them if // they are required. opts := []authority.Option{ @@ -140,7 +140,7 @@ func (ca *CA) Init(config *config.Config) (*CA, error) { opts = append(opts, authority.WithDatabase(ca.opts.database)) } - auth, err := authority.New(config, opts...) + auth, err := authority.New(cfg, opts...) if err != nil { return nil, err } @@ -166,8 +166,8 @@ func (ca *CA) Init(config *config.Config) (*CA, error) { }) //Add ACME api endpoints in /acme and /1.0/acme - dns := config.DNSNames[0] - u, err := url.Parse("https://" + config.Address) + dns := cfg.DNSNames[0] + u, err := url.Parse("https://" + cfg.Address) if err != nil { return nil, err } @@ -179,7 +179,7 @@ func (ca *CA) Init(config *config.Config) (*CA, error) { // ACME Router prefix := "acme" var acmeDB acme.DB - if config.DB == nil { + if cfg.DB == nil { acmeDB = nil } else { acmeDB, err = acmeNoSQL.New(auth.GetDatabase().(nosql.DB)) @@ -188,7 +188,7 @@ func (ca *CA) Init(config *config.Config) (*CA, error) { } } acmeHandler := acmeAPI.NewHandler(acmeAPI.HandlerOptions{ - Backdate: *config.AuthorityConfig.Backdate, + Backdate: *cfg.AuthorityConfig.Backdate, DB: acmeDB, DNS: dns, Prefix: prefix, @@ -204,7 +204,7 @@ func (ca *CA) Init(config *config.Config) (*CA, error) { }) // Admin API Router - if config.AuthorityConfig.EnableAdmin { + if cfg.AuthorityConfig.EnableAdmin { adminDB := auth.GetAdminDatabase() if adminDB != nil { adminHandler := adminAPI.NewHandler(auth) @@ -248,8 +248,8 @@ func (ca *CA) Init(config *config.Config) (*CA, error) { //dumpRoutes(mux) // Add monitoring if configured - if len(config.Monitoring) > 0 { - m, err := monitoring.New(config.Monitoring) + if len(cfg.Monitoring) > 0 { + m, err := monitoring.New(cfg.Monitoring) if err != nil { return nil, err } @@ -258,8 +258,8 @@ func (ca *CA) Init(config *config.Config) (*CA, error) { } // Add logger if configured - if len(config.Logger) > 0 { - logger, err := logging.New("ca", config.Logger) + if len(cfg.Logger) > 0 { + logger, err := logging.New("ca", cfg.Logger) if err != nil { return nil, err } @@ -267,16 +267,16 @@ func (ca *CA) Init(config *config.Config) (*CA, error) { insecureHandler = logger.Middleware(insecureHandler) } - ca.srv = server.New(config.Address, handler, tlsConfig) + ca.srv = server.New(cfg.Address, handler, tlsConfig) // only start the insecure server if the insecure address is configured // and, currently, also only when it should serve SCEP endpoints. - if ca.shouldServeSCEPEndpoints() && config.InsecureAddress != "" { + if ca.shouldServeSCEPEndpoints() && cfg.InsecureAddress != "" { // TODO: instead opt for having a single server.Server but two // http.Servers handling the HTTP and HTTPS handler? The latter // will probably introduce more complexity in terms of graceful // reload. - ca.insecureSrv = server.New(config.InsecureAddress, insecureHandler, nil) + ca.insecureSrv = server.New(cfg.InsecureAddress, insecureHandler, nil) } return ca, nil @@ -285,24 +285,24 @@ func (ca *CA) Init(config *config.Config) (*CA, error) { // Run starts the CA calling to the server ListenAndServe method. func (ca *CA) Run() error { var wg sync.WaitGroup - errors := make(chan error, 1) + errs := make(chan error, 1) if ca.insecureSrv != nil { wg.Add(1) go func() { defer wg.Done() - errors <- ca.insecureSrv.ListenAndServe() + errs <- ca.insecureSrv.ListenAndServe() }() } wg.Add(1) go func() { defer wg.Done() - errors <- ca.srv.ListenAndServe() + errs <- ca.srv.ListenAndServe() }() // wait till error occurs; ensures the servers keep listening - err := <-errors + err := <-errs wg.Wait() @@ -331,7 +331,7 @@ func (ca *CA) Stop() error { // Reload reloads the configuration of the CA and calls to the server Reload // method. func (ca *CA) Reload() error { - config, err := config.LoadConfiguration(ca.opts.configFile) + cfg, err := config.LoadConfiguration(ca.opts.configFile) if err != nil { return errors.Wrap(err, "error reloading ca configuration") } @@ -343,12 +343,12 @@ func (ca *CA) Reload() error { } // Do not allow reload if the database configuration has changed. - if !reflect.DeepEqual(ca.config.DB, config.DB) { + if !reflect.DeepEqual(ca.config.DB, cfg.DB) { logContinue("Reload failed because the database configuration has changed.") return errors.New("error reloading ca: database configuration cannot change") } - newCA, err := New(config, + newCA, err := New(cfg, WithPassword(ca.opts.password), WithSSHHostPassword(ca.opts.sshHostPassword), WithSSHUserPassword(ca.opts.sshUserPassword), diff --git a/ca/ca_test.go b/ca/ca_test.go index 6e297733..ff264db7 100644 --- a/ca/ca_test.go +++ b/ca/ca_test.go @@ -322,7 +322,7 @@ ZEp7knvU2psWRw== assert.Equals(t, intermediate, realIntermediate) } else { err := readError(body) - if len(tc.errMsg) == 0 { + if tc.errMsg == "" { assert.FatalError(t, errors.New("must validate response error")) } assert.HasPrefix(t, err.Error(), tc.errMsg) @@ -375,7 +375,7 @@ func TestCAProvisioners(t *testing.T) { assert.Equals(t, a, b) } else { err := readError(body) - if len(tc.errMsg) == 0 { + if tc.errMsg == "" { assert.FatalError(t, errors.New("must validate response error")) } assert.HasPrefix(t, err.Error(), tc.errMsg) @@ -436,7 +436,7 @@ func TestCAProvisionerEncryptedKey(t *testing.T) { assert.Equals(t, ek.Key, tc.expectedKey) } else { err := readError(body) - if len(tc.errMsg) == 0 { + if tc.errMsg == "" { assert.FatalError(t, errors.New("must validate response error")) } assert.HasPrefix(t, err.Error(), tc.errMsg) @@ -497,7 +497,7 @@ func TestCARoot(t *testing.T) { assert.Equals(t, root.RootPEM.Certificate, rootCrt) } else { err := readError(body) - if len(tc.errMsg) == 0 { + if tc.errMsg == "" { assert.FatalError(t, errors.New("must validate response error")) } assert.HasPrefix(t, err.Error(), tc.errMsg) @@ -665,7 +665,7 @@ func TestCARenew(t *testing.T) { assert.Equals(t, *sign.TLSOptions, authority.DefaultTLSOptions) } else { err := readError(body) - if len(tc.errMsg) == 0 { + if tc.errMsg == "" { assert.FatalError(t, errors.New("must validate response error")) } assert.HasPrefix(t, err.Error(), tc.errMsg) diff --git a/ca/client.go b/ca/client.go index 8997fbd5..cfeddba0 100644 --- a/ca/client.go +++ b/ca/client.go @@ -74,17 +74,17 @@ func (c *uaClient) SetTransport(tr http.RoundTripper) { c.Client.Transport = tr } -func (c *uaClient) Get(url string) (*http.Response, error) { - req, err := http.NewRequest("GET", url, nil) +func (c *uaClient) Get(u string) (*http.Response, error) { + req, err := http.NewRequest("GET", u, nil) if err != nil { - return nil, errors.Wrapf(err, "new request GET %s failed", url) + return nil, errors.Wrapf(err, "new request GET %s failed", u) } req.Header.Set("User-Agent", UserAgent) return c.Client.Do(req) } -func (c *uaClient) Post(url, contentType string, body io.Reader) (*http.Response, error) { - req, err := http.NewRequest("POST", url, body) +func (c *uaClient) Post(u, contentType string, body io.Reader) (*http.Response, error) { + req, err := http.NewRequest("POST", u, body) if err != nil { return nil, err } @@ -305,7 +305,7 @@ func WithAdminX5C(certs []*x509.Certificate, key interface{}, passwordFile strin err error opts []jose.Option ) - if len(passwordFile) != 0 { + if passwordFile != "" { opts = append(opts, jose.WithPasswordFile(passwordFile)) } blk, err := pemutil.Serialize(key) @@ -326,14 +326,14 @@ func WithAdminX5C(certs []*x509.Certificate, key interface{}, passwordFile strin for _, e := range o.x5cCert.Extensions { if e.Id.Equal(stepOIDProvisioner) { - var provisioner stepProvisionerASN1 - if _, err := asn1.Unmarshal(e.Value, &provisioner); err != nil { + var prov stepProvisionerASN1 + if _, err := asn1.Unmarshal(e.Value, &prov); err != nil { return errors.Wrap(err, "error unmarshaling provisioner OID from certificate") } - o.x5cIssuer = string(provisioner.Name) + o.x5cIssuer = string(prov.Name) } } - if len(o.x5cIssuer) == 0 { + if o.x5cIssuer == "" { return errors.New("provisioner extension not found in certificate") } @@ -631,7 +631,7 @@ retry: // do not match. func (c *Client) Root(sha256Sum string) (*api.RootResponse, error) { var retried bool - sha256Sum = strings.ToLower(strings.Replace(sha256Sum, "-", "", -1)) + sha256Sum = strings.ToLower(strings.ReplaceAll(sha256Sum, "-", "")) u := c.endpoint.ResolveReference(&url.URL{Path: "/root/" + sha256Sum}) retry: resp, err := newInsecureClient().Get(u.String()) @@ -651,7 +651,7 @@ retry: } // verify the sha256 sum := sha256.Sum256(root.RootPEM.Raw) - if sha256Sum != strings.ToLower(hex.EncodeToString(sum[:])) { + if !strings.EqualFold(sha256Sum, strings.ToLower(hex.EncodeToString(sum[:]))) { return nil, errs.BadRequest("client.Root; root certificate SHA256 fingerprint do not match") } return &root, nil @@ -1066,16 +1066,16 @@ retry: } return nil, readError(resp.Body) } - var config api.SSHConfigResponse - if err := readJSON(resp.Body, &config); err != nil { + var cfg api.SSHConfigResponse + if err := readJSON(resp.Body, &cfg); err != nil { return nil, errors.Wrapf(err, "error reading %s", u) } - return &config, nil + return &cfg, nil } // SSHCheckHost performs the POST /ssh/check-host request to the CA with the // given principal. -func (c *Client) SSHCheckHost(principal string, token string) (*api.SSHCheckPrincipalResponse, error) { +func (c *Client) SSHCheckHost(principal, token string) (*api.SSHCheckPrincipalResponse, error) { var retried bool body, err := json.Marshal(&api.SSHCheckPrincipalRequest{ Type: provisioner.SSHHostCert, diff --git a/ca/client_test.go b/ca/client_test.go index 30669e6e..187066f0 100644 --- a/ca/client_test.go +++ b/ca/client_test.go @@ -135,7 +135,7 @@ func parseCertificateRequest(data string) *x509.CertificateRequest { return csr } -func equalJSON(t *testing.T, a interface{}, b interface{}) bool { +func equalJSON(t *testing.T, a, b interface{}) bool { if reflect.DeepEqual(a, b) { return true } diff --git a/ca/identity/client_test.go b/ca/identity/client_test.go index c792a6dc..402ec7b8 100644 --- a/ca/identity/client_test.go +++ b/ca/identity/client_test.go @@ -187,11 +187,12 @@ func TestLoadClient(t *testing.T) { } else { gotTransport := got.Client.Transport.(*http.Transport) wantTransport := tt.want.Client.Transport.(*http.Transport) - if gotTransport.TLSClientConfig.GetClientCertificate == nil { + switch { + case gotTransport.TLSClientConfig.GetClientCertificate == nil: t.Error("LoadClient() transport does not define GetClientCertificate") - } else if !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) || !reflect.DeepEqual(gotTransport.TLSClientConfig.RootCAs.Subjects(), wantTransport.TLSClientConfig.RootCAs.Subjects()): t.Errorf("LoadClient() = %#v, want %#v", got, tt.want) - } else { + default: crt, err := gotTransport.TLSClientConfig.GetClientCertificate(nil) if err != nil { t.Errorf("LoadClient() GetClientCertificate error = %v", err) diff --git a/ca/tls.go b/ca/tls.go index cb9f4707..3a3b6766 100644 --- a/ca/tls.go +++ b/ca/tls.go @@ -105,7 +105,7 @@ func (c *Client) getClientTLSConfig(ctx context.Context, sign *api.SignResponse, tr := getDefaultTransport(tlsConfig) // Use mutable tls.Config on renew - tr.DialTLS = c.buildDialTLS(tlsCtx) // nolint:staticcheck + tr.DialTLS = c.buildDialTLS(tlsCtx) // nolint:staticcheck,gocritic // tr.DialTLSContext = c.buildDialTLSContext(tlsCtx) renewer.RenewCertificate = getRenewFunc(tlsCtx, c, tr, pk) @@ -154,7 +154,7 @@ func (c *Client) GetServerTLSConfig(ctx context.Context, sign *api.SignResponse, // Update renew function with transport tr := getDefaultTransport(tlsConfig) // Use mutable tls.Config on renew - tr.DialTLS = c.buildDialTLS(tlsCtx) // nolint:staticcheck + tr.DialTLS = c.buildDialTLS(tlsCtx) // nolint:staticcheck,gocritic // tr.DialTLSContext = c.buildDialTLSContext(tlsCtx) renewer.RenewCertificate = getRenewFunc(tlsCtx, c, tr, pk) @@ -195,7 +195,7 @@ func (c *Client) buildDialTLS(ctx *TLSOptionCtx) func(network, addr string) (net } // buildDialTLSContext returns an implementation of DialTLSContext callback in http.Transport. -// nolint:unused +// nolint:unused,gocritic func (c *Client) buildDialTLSContext(tlsCtx *TLSOptionCtx) func(ctx context.Context, network, addr string) (net.Conn, error) { return func(ctx context.Context, network, addr string) (net.Conn, error) { d := getDefaultDialer() @@ -253,6 +253,8 @@ func TLSCertificate(sign *api.SignResponse, pk crypto.PrivateKey) (*tls.Certific return nil, err } + // nolint:gocritic + // using a new variable for clarity chain := append(certPEM, caPEM...) cert, err := tls.X509KeyPair(chain, keyPEM) if err != nil { diff --git a/cas/cloudcas/cloudcas.go b/cas/cloudcas/cloudcas.go index 2e9da260..e3e956a9 100644 --- a/cas/cloudcas/cloudcas.go +++ b/cas/cloudcas/cloudcas.go @@ -29,9 +29,7 @@ func init() { }) } -var now = func() time.Time { - return time.Now() -} +var now = time.Now // The actual regular expression that matches a certificate authority is: // ^projects/[a-z][a-z0-9-]{4,28}[a-z0-9]/locations/[a-z0-9-]+/caPools/[a-zA-Z0-9-_]+/certificateAuthorities/[a-zA-Z0-9-_]+$ diff --git a/cas/cloudcas/cloudcas_test.go b/cas/cloudcas/cloudcas_test.go index 0561000c..7f996c15 100644 --- a/cas/cloudcas/cloudcas_test.go +++ b/cas/cloudcas/cloudcas_test.go @@ -12,7 +12,6 @@ import ( "encoding/pem" "fmt" "io" - "log" "net" "os" "reflect" @@ -103,7 +102,7 @@ MHcCAQEEIN51Rgg6YcQVLeCRzumdw4pjM3VWqFIdCbnsV3Up1e/goAoGCCqGSM49 AwEHoUQDQgAEjJIcDhvvxi7gu4aFkiW/8+E3BfPhmhXU5RlDQusre+MHXc7XYMtk Lm6PXPeTF1DNdS21Ju1G/j1yUykGJOmxkg== -----END EC PRIVATE KEY-----` - // nolint:unused,deadcode + // nolint:unused,deadcode,gocritic testIntermediateKey = `-----BEGIN EC PRIVATE KEY----- MHcCAQEEIMMX/XkXGnRDD4fYu7Z4rHACdJn/iyOy2UTwsv+oZ0C+oAoGCCqGSM49 AwEHoUQDQgAE8u6rGAFj5CZpdzzMogLwUyCMnp0X9wtv4OKDRcpzkYf9PU5GuGA6 @@ -190,7 +189,7 @@ func (b *badSigner) Public() crypto.PublicKey { return b.pub } -func (b *badSigner) Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts) ([]byte, error) { +func (b *badSigner) Sign(rnd io.Reader, digest []byte, opts crypto.SignerOpts) ([]byte, error) { return nil, fmt.Errorf("💥") } @@ -730,7 +729,7 @@ func TestCloudCAS_RevokeCertificate(t *testing.T) { func Test_createCertificateID(t *testing.T) { buf := new(bytes.Buffer) setTeeReader(t, buf) - uuid, err := uuid.NewRandomFromReader(rand.Reader) + id, err := uuid.NewRandomFromReader(rand.Reader) if err != nil { t.Fatal(err) } @@ -741,7 +740,7 @@ func Test_createCertificateID(t *testing.T) { want string wantErr bool }{ - {"ok", uuid.String(), false}, + {"ok", id.String(), false}, {"fail", "", true}, } for _, tt := range tests { @@ -858,7 +857,7 @@ func TestCloudCAS_CreateCertificateAuthority(t *testing.T) { return lis.Dial() })) if err != nil { - log.Fatal(err) + t.Fatal(err) } client, err := lroauto.NewOperationsClient(context.Background(), option.WithGRPCConn(conn)) diff --git a/cas/softcas/softcas.go b/cas/softcas/softcas.go index 23dac91b..87dfa5c5 100644 --- a/cas/softcas/softcas.go +++ b/cas/softcas/softcas.go @@ -19,9 +19,7 @@ func init() { }) } -var now = func() time.Time { - return time.Now() -} +var now = time.Now // SoftCAS implements a Certificate Authority Service using Golang or KMS // crypto. This is the default CAS used in step-ca. diff --git a/cas/softcas/softcas_test.go b/cas/softcas/softcas_test.go index c8e1a8e9..bd13f310 100644 --- a/cas/softcas/softcas_test.go +++ b/cas/softcas/softcas_test.go @@ -133,7 +133,7 @@ func (b *badSigner) Public() crypto.PublicKey { return testSigner.Public() } -func (b *badSigner) Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts) ([]byte, error) { +func (b *badSigner) Sign(_ io.Reader, _ []byte, _ crypto.SignerOpts) ([]byte, error) { return nil, fmt.Errorf("💥") } diff --git a/cas/stepcas/stepcas.go b/cas/stepcas/stepcas.go index a124b4ae..9fcbd36c 100644 --- a/cas/stepcas/stepcas.go +++ b/cas/stepcas/stepcas.go @@ -90,9 +90,9 @@ func (s *StepCAS) RenewCertificate(req *apiv1.RenewCertificateRequest) (*apiv1.R return nil, apiv1.ErrNotImplemented{Message: "stepCAS does not support mTLS renewals"} } +// RevokeCertificate revokes a certificate. func (s *StepCAS) RevokeCertificate(req *apiv1.RevokeCertificateRequest) (*apiv1.RevokeCertificateResponse, error) { - switch { - case req.SerialNumber == "" && req.Certificate == nil: + if req.SerialNumber == "" && req.Certificate == nil { return nil, errors.New("revokeCertificateRequest `serialNumber` or `certificate` are required") } diff --git a/cas/stepcas/x5c_issuer.go b/cas/stepcas/x5c_issuer.go index 636d22f9..76ed9c3c 100644 --- a/cas/stepcas/x5c_issuer.go +++ b/cas/stepcas/x5c_issuer.go @@ -19,9 +19,7 @@ const defaultValidity = 5 * time.Minute // timeNow returns the current time. // This method is used for unit testing purposes. -var timeNow = func() time.Time { - return time.Now() -} +var timeNow = time.Now type x5cIssuer struct { caURL *url.URL diff --git a/cas/stepcas/x5c_issuer_test.go b/cas/stepcas/x5c_issuer_test.go index a3190255..b1bc653d 100644 --- a/cas/stepcas/x5c_issuer_test.go +++ b/cas/stepcas/x5c_issuer_test.go @@ -22,7 +22,7 @@ func (b noneSigner) Public() crypto.PublicKey { return []byte(b) } -func (b noneSigner) Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts) (signature []byte, err error) { +func (b noneSigner) Sign(rnd io.Reader, digest []byte, opts crypto.SignerOpts) (signature []byte, err error) { return digest, nil } diff --git a/cmd/step-awskms-init/main.go b/cmd/step-awskms-init/main.go index 0678ef39..8e30745f 100644 --- a/cmd/step-awskms-init/main.go +++ b/cmd/step-awskms-init/main.go @@ -24,10 +24,10 @@ import ( func main() { var credentialsFile, region string - var ssh bool + var enableSSH bool flag.StringVar(&credentialsFile, "credentials-file", "", "Path to the `file` containing the AWS KMS credentials.") flag.StringVar(®ion, "region", "", "AWS KMS region name.") - flag.BoolVar(&ssh, "ssh", false, "Create SSH keys.") + flag.BoolVar(&enableSSH, "ssh", false, "Create SSH keys.") flag.Usage = usage flag.Parse() @@ -47,7 +47,7 @@ func main() { fatal(err) } - if ssh { + if enableSSH { ui.Println() if err := createSSH(c); err != nil { fatal(err) @@ -120,7 +120,7 @@ func createX509(c *awskms.KMS) error { return err } - if err = fileutil.WriteFile("root_ca.crt", pem.EncodeToMemory(&pem.Block{ + if err := fileutil.WriteFile("root_ca.crt", pem.EncodeToMemory(&pem.Block{ Type: "CERTIFICATE", Bytes: b, }), 0600); err != nil { @@ -163,7 +163,7 @@ func createX509(c *awskms.KMS) error { return err } - if err = fileutil.WriteFile("intermediate_ca.crt", pem.EncodeToMemory(&pem.Block{ + if err := fileutil.WriteFile("intermediate_ca.crt", pem.EncodeToMemory(&pem.Block{ Type: "CERTIFICATE", Bytes: b, }), 0600); err != nil { @@ -193,7 +193,7 @@ func createSSH(c *awskms.KMS) error { return err } - if err = fileutil.WriteFile("ssh_user_ca_key.pub", ssh.MarshalAuthorizedKey(key), 0600); err != nil { + if err := fileutil.WriteFile("ssh_user_ca_key.pub", ssh.MarshalAuthorizedKey(key), 0600); err != nil { return err } @@ -214,7 +214,7 @@ func createSSH(c *awskms.KMS) error { return err } - if err = fileutil.WriteFile("ssh_host_ca_key.pub", ssh.MarshalAuthorizedKey(key), 0600); err != nil { + if err := fileutil.WriteFile("ssh_host_ca_key.pub", ssh.MarshalAuthorizedKey(key), 0600); err != nil { return err } diff --git a/cmd/step-ca/main.go b/cmd/step-ca/main.go index e0123678..bed1c14a 100644 --- a/cmd/step-ca/main.go +++ b/cmd/step-ca/main.go @@ -116,7 +116,7 @@ func main() { app.HelpName = "step-ca" app.Version = config.Version() app.Usage = "an online certificate authority for secure automated certificate management" - app.UsageText = `**step-ca** [**--password-file**=] + app.UsageText = `**step-ca** [**--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 @@ -191,8 +191,8 @@ var placeholderString = regexp.MustCompile(`<.*?>`) func stringifyFlag(f cli.Flag) string { fv := flagValue(f) - usage := fv.FieldByName("Usage").String() - placeholder := placeholderString.FindString(usage) + usg := fv.FieldByName("Usage").String() + placeholder := placeholderString.FindString(usg) if placeholder == "" { switch f.(type) { case cli.BoolFlag, cli.BoolTFlag: @@ -200,5 +200,5 @@ func stringifyFlag(f cli.Flag) string { placeholder = "" } } - return cli.FlagNamePrefixer(fv.FieldByName("Name").String(), placeholder) + "\t" + usage + return cli.FlagNamePrefixer(fv.FieldByName("Name").String(), placeholder) + "\t" + usg } diff --git a/cmd/step-cloudkms-init/main.go b/cmd/step-cloudkms-init/main.go index 14bf50f1..27dc82ad 100644 --- a/cmd/step-cloudkms-init/main.go +++ b/cmd/step-cloudkms-init/main.go @@ -27,13 +27,13 @@ func main() { var credentialsFile string var project, location, ring string var protectionLevelName string - var ssh bool + var enableSSH bool flag.StringVar(&credentialsFile, "credentials-file", "", "Path to the `file` containing the Google's Cloud KMS credentials.") flag.StringVar(&project, "project", "", "Google Cloud Project ID.") flag.StringVar(&location, "location", "global", "Cloud KMS location name.") flag.StringVar(&ring, "ring", "pki", "Cloud KMS ring name.") flag.StringVar(&protectionLevelName, "protection-level", "SOFTWARE", "Protection level to use, SOFTWARE or HSM.") - flag.BoolVar(&ssh, "ssh", false, "Create SSH keys.") + flag.BoolVar(&enableSSH, "ssh", false, "Create SSH keys.") flag.Usage = usage flag.Parse() @@ -77,7 +77,7 @@ func main() { fatal(err) } - if ssh { + if enableSSH { ui.Println() if err := createSSH(c, project, location, ring, protectionLevel); err != nil { fatal(err) @@ -153,7 +153,7 @@ func createPKI(c *cloudkms.CloudKMS, project, location, keyRing string, protecti return err } - if err = fileutil.WriteFile("root_ca.crt", pem.EncodeToMemory(&pem.Block{ + if err := fileutil.WriteFile("root_ca.crt", pem.EncodeToMemory(&pem.Block{ Type: "CERTIFICATE", Bytes: b, }), 0600); err != nil { @@ -197,7 +197,7 @@ func createPKI(c *cloudkms.CloudKMS, project, location, keyRing string, protecti return err } - if err = fileutil.WriteFile("intermediate_ca.crt", pem.EncodeToMemory(&pem.Block{ + if err := fileutil.WriteFile("intermediate_ca.crt", pem.EncodeToMemory(&pem.Block{ Type: "CERTIFICATE", Bytes: b, }), 0600); err != nil { @@ -230,7 +230,7 @@ func createSSH(c *cloudkms.CloudKMS, project, location, keyRing string, protecti return err } - if err = fileutil.WriteFile("ssh_user_ca_key.pub", ssh.MarshalAuthorizedKey(key), 0600); err != nil { + if err := fileutil.WriteFile("ssh_user_ca_key.pub", ssh.MarshalAuthorizedKey(key), 0600); err != nil { return err } @@ -252,7 +252,7 @@ func createSSH(c *cloudkms.CloudKMS, project, location, keyRing string, protecti return err } - if err = fileutil.WriteFile("ssh_host_ca_key.pub", ssh.MarshalAuthorizedKey(key), 0600); err != nil { + if err := fileutil.WriteFile("ssh_host_ca_key.pub", ssh.MarshalAuthorizedKey(key), 0600); err != nil { return err } diff --git a/cmd/step-pkcs11-init/main.go b/cmd/step-pkcs11-init/main.go index 78c531c6..8e7bc075 100644 --- a/cmd/step-pkcs11-init/main.go +++ b/cmd/step-pkcs11-init/main.go @@ -329,7 +329,7 @@ func createPKI(k kms.KeyManager, c Config) error { } if cm, ok := k.(kms.CertificateManager); ok && !c.NoCerts { - if err = cm.StoreCertificate(&apiv1.StoreCertificateRequest{ + if err := cm.StoreCertificate(&apiv1.StoreCertificateRequest{ Name: c.RootObject, Certificate: root, }); err != nil { @@ -337,7 +337,7 @@ func createPKI(k kms.KeyManager, c Config) error { } } - if err = fileutil.WriteFile(c.RootPath, pem.EncodeToMemory(&pem.Block{ + if err := fileutil.WriteFile(c.RootPath, pem.EncodeToMemory(&pem.Block{ Type: "CERTIFICATE", Bytes: b, }), 0600); err != nil { @@ -406,7 +406,7 @@ func createPKI(k kms.KeyManager, c Config) error { } if cm, ok := k.(kms.CertificateManager); ok && !c.NoCerts { - if err = cm.StoreCertificate(&apiv1.StoreCertificateRequest{ + if err := cm.StoreCertificate(&apiv1.StoreCertificateRequest{ Name: c.CrtObject, Certificate: intermediate, }); err != nil { @@ -414,7 +414,7 @@ func createPKI(k kms.KeyManager, c Config) error { } } - if err = fileutil.WriteFile(c.CrtPath, pem.EncodeToMemory(&pem.Block{ + if err := fileutil.WriteFile(c.CrtPath, pem.EncodeToMemory(&pem.Block{ Type: "CERTIFICATE", Bytes: b, }), 0600); err != nil { diff --git a/cmd/step-yubikey-init/main.go b/cmd/step-yubikey-init/main.go index 163d0fcb..8b0ffab5 100644 --- a/cmd/step-yubikey-init/main.go +++ b/cmd/step-yubikey-init/main.go @@ -228,7 +228,7 @@ func createPKI(k kms.KeyManager, c Config) error { } if cm, ok := k.(kms.CertificateManager); ok { - if err = cm.StoreCertificate(&apiv1.StoreCertificateRequest{ + if err := cm.StoreCertificate(&apiv1.StoreCertificateRequest{ Name: c.RootSlot, Certificate: root, }); err != nil { @@ -236,7 +236,7 @@ func createPKI(k kms.KeyManager, c Config) error { } } - if err = fileutil.WriteFile("root_ca.crt", pem.EncodeToMemory(&pem.Block{ + if err := fileutil.WriteFile("root_ca.crt", pem.EncodeToMemory(&pem.Block{ Type: "CERTIFICATE", Bytes: b, }), 0600); err != nil { @@ -305,7 +305,7 @@ func createPKI(k kms.KeyManager, c Config) error { } if cm, ok := k.(kms.CertificateManager); ok { - if err = cm.StoreCertificate(&apiv1.StoreCertificateRequest{ + if err := cm.StoreCertificate(&apiv1.StoreCertificateRequest{ Name: c.CrtSlot, Certificate: intermediate, }); err != nil { @@ -313,7 +313,7 @@ func createPKI(k kms.KeyManager, c Config) error { } } - if err = fileutil.WriteFile("intermediate_ca.crt", pem.EncodeToMemory(&pem.Block{ + if err := fileutil.WriteFile("intermediate_ca.crt", pem.EncodeToMemory(&pem.Block{ Type: "CERTIFICATE", Bytes: b, }), 0600); err != nil { diff --git a/commands/app.go b/commands/app.go index 3aaee0f5..84232a6c 100644 --- a/commands/app.go +++ b/commands/app.go @@ -24,7 +24,7 @@ var AppCommand = cli.Command{ Name: "start", Action: appAction, UsageText: `**step-ca** [**--password-file**=] -[**--ssh-host-password-file**=] [**--ssh-user-password-file**=] +[**--ssh-host-password-file**=] [**--ssh-user-password-file**=] [**--issuer-password-file**=] [**--resolver**=]`, Flags: []cli.Flag{ cli.StringFlag{ @@ -79,13 +79,13 @@ func appAction(ctx *cli.Context) error { } configFile := ctx.Args().Get(0) - config, err := config.LoadConfiguration(configFile) + cfg, err := config.LoadConfiguration(configFile) if err != nil { fatal(err) } - if config.AuthorityConfig != nil { - if token == "" && strings.EqualFold(config.AuthorityConfig.DeploymentType, pki.LinkedDeployment.String()) { + if cfg.AuthorityConfig != nil { + if token == "" && strings.EqualFold(cfg.AuthorityConfig.DeploymentType, pki.LinkedDeployment.String()) { return errors.New(`'step-ca' requires the '--token' flag for linked deploy type. To get a linked authority token: @@ -136,7 +136,7 @@ To get a linked authority token: } } - srv, err := ca.New(config, + srv, err := ca.New(cfg, ca.WithConfigFile(configFile), ca.WithPassword(password), ca.WithSSHHostPassword(sshHostPassword), diff --git a/commands/export.go b/commands/export.go index be6d88e5..5586f576 100644 --- a/commands/export.go +++ b/commands/export.go @@ -63,11 +63,11 @@ func exportAction(ctx *cli.Context) error { passwordFile := ctx.String("password-file") issuerPasswordFile := ctx.String("issuer-password-file") - config, err := config.LoadConfiguration(configFile) + cfg, err := config.LoadConfiguration(configFile) if err != nil { return err } - if err := config.Validate(); err != nil { + if err := cfg.Validate(); err != nil { return err } @@ -76,19 +76,19 @@ func exportAction(ctx *cli.Context) error { if err != nil { return errors.Wrapf(err, "error reading %s", passwordFile) } - config.Password = string(bytes.TrimRightFunc(b, unicode.IsSpace)) + cfg.Password = string(bytes.TrimRightFunc(b, unicode.IsSpace)) } if issuerPasswordFile != "" { b, err := ioutil.ReadFile(issuerPasswordFile) if err != nil { return errors.Wrapf(err, "error reading %s", issuerPasswordFile) } - if config.AuthorityConfig.CertificateIssuer != nil { - config.AuthorityConfig.CertificateIssuer.Password = string(bytes.TrimRightFunc(b, unicode.IsSpace)) + if cfg.AuthorityConfig.CertificateIssuer != nil { + cfg.AuthorityConfig.CertificateIssuer.Password = string(bytes.TrimRightFunc(b, unicode.IsSpace)) } } - auth, err := authority.New(config) + auth, err := authority.New(cfg) if err != nil { return err } diff --git a/commands/onboard.go b/commands/onboard.go index eb8285aa..ebd468f5 100644 --- a/commands/onboard.go +++ b/commands/onboard.go @@ -103,8 +103,8 @@ func onboardAction(ctx *cli.Context) error { return errors.Wrap(msg, "error receiving onboarding guide") } - var config onboardingConfiguration - if err := readJSON(res.Body, &config); err != nil { + var cfg onboardingConfiguration + if err := readJSON(res.Body, &cfg); err != nil { return errors.Wrap(err, "error unmarshaling response") } @@ -112,16 +112,16 @@ func onboardAction(ctx *cli.Context) error { if err != nil { return err } - config.password = []byte(password) + cfg.password = []byte(password) ui.Println("Initializing step-ca with the following configuration:") - ui.PrintSelected("Name", config.Name) - ui.PrintSelected("DNS", config.DNS) - ui.PrintSelected("Address", config.Address) + ui.PrintSelected("Name", cfg.Name) + ui.PrintSelected("DNS", cfg.DNS) + ui.PrintSelected("Address", cfg.Address) ui.PrintSelected("Password", password) ui.Println() - caConfig, fp, err := onboardPKI(config) + caConfig, fp, err := onboardPKI(cfg) if err != nil { return err } @@ -149,23 +149,23 @@ func onboardAction(ctx *cli.Context) error { ui.Println("Initialized!") ui.Println("Step CA is starting. Please return to the onboarding guide in your browser to continue.") - srv, err := ca.New(caConfig, ca.WithPassword(config.password)) + srv, err := ca.New(caConfig, ca.WithPassword(cfg.password)) if err != nil { fatal(err) } go ca.StopReloaderHandler(srv) - if err = srv.Run(); err != nil && err != http.ErrServerClosed { + if err := srv.Run(); err != nil && err != http.ErrServerClosed { fatal(err) } return nil } -func onboardPKI(config onboardingConfiguration) (*config.Config, string, error) { +func onboardPKI(cfg onboardingConfiguration) (*config.Config, string, error) { var opts = []pki.Option{ - pki.WithAddress(config.Address), - pki.WithDNSNames([]string{config.DNS}), + pki.WithAddress(cfg.Address), + pki.WithDNSNames([]string{cfg.DNS}), pki.WithProvisioner("admin"), } @@ -179,25 +179,25 @@ func onboardPKI(config onboardingConfiguration) (*config.Config, string, error) // Generate pki ui.Println("Generating root certificate...") - root, err := p.GenerateRootCertificate(config.Name, config.Name, config.Name, config.password) + root, err := p.GenerateRootCertificate(cfg.Name, cfg.Name, cfg.Name, cfg.password) if err != nil { return nil, "", err } ui.Println("Generating intermediate certificate...") - err = p.GenerateIntermediateCertificate(config.Name, config.Name, config.Name, root, config.password) + err = p.GenerateIntermediateCertificate(cfg.Name, cfg.Name, cfg.Name, root, cfg.password) if err != nil { return nil, "", err } // Write files to disk - if err = p.WriteFiles(); err != nil { + if err := p.WriteFiles(); err != nil { return nil, "", err } // Generate provisioner ui.Println("Generating admin provisioner...") - if err = p.GenerateKeyPairs(config.password); err != nil { + if err := p.GenerateKeyPairs(cfg.password); err != nil { return nil, "", err } @@ -211,7 +211,7 @@ func onboardPKI(config onboardingConfiguration) (*config.Config, string, error) if err != nil { return nil, "", errors.Wrapf(err, "error marshaling %s", p.GetCAConfigPath()) } - if err = fileutil.WriteFile(p.GetCAConfigPath(), b, 0666); err != nil { + if err := fileutil.WriteFile(p.GetCAConfigPath(), b, 0666); err != nil { return nil, "", errs.FileError(err, p.GetCAConfigPath()) } diff --git a/db/db_test.go b/db/db_test.go index 7efc623e..40f59215 100644 --- a/db/db_test.go +++ b/db/db_test.go @@ -144,15 +144,15 @@ func TestUseToken(t *testing.T) { } for name, tc := range tests { t.Run(name, func(t *testing.T) { - ok, err := tc.db.UseToken(tc.id, tc.tok) - if err != nil { + switch ok, err := tc.db.UseToken(tc.id, tc.tok); { + case err != nil: if assert.NotNil(t, tc.want.err) { assert.HasPrefix(t, err.Error(), tc.want.err.Error()) } assert.False(t, ok) - } else if ok { + case ok: assert.True(t, tc.want.ok) - } else { + default: assert.False(t, tc.want.ok) } }) diff --git a/kms/sshagentkms/sshagentkms_test.go b/kms/sshagentkms/sshagentkms_test.go index 30edd5d1..d3a9e9f5 100644 --- a/kms/sshagentkms/sshagentkms_test.go +++ b/kms/sshagentkms/sshagentkms_test.go @@ -378,6 +378,7 @@ func TestSSHAgentKMS_CreateSigner(t *testing.T) { t.Errorf("SSHAgentKMS.CreateSigner() error = %v, wantErr %v", err, tt.wantErr) return } + // nolint:gocritic switch s := got.(type) { case *WrappedSSHSigner: gotPkS := s.Sshsigner.PublicKey().(*agent.Key).String() + "\n" @@ -562,6 +563,7 @@ func TestSSHAgentKMS_GetPublicKey(t *testing.T) { t.Errorf("SSHAgentKMS.GetPublicKey() error = %v, wantErr %v", err, tt.wantErr) return } + // nolint:gocritic switch tt.want.(type) { case ssh.PublicKey: // If we want a ssh.PublicKey, protote got to a diff --git a/pki/pki.go b/pki/pki.go index 12e71e47..18cd0dda 100644 --- a/pki/pki.go +++ b/pki/pki.go @@ -128,7 +128,7 @@ func GetTemplatesPath() string { // GetProvisioners returns the map of provisioners on the given CA. func GetProvisioners(caURL, rootFile string) (provisioner.List, error) { - if len(rootFile) == 0 { + if rootFile == "" { rootFile = GetRootCAPath() } client, err := ca.NewClient(caURL, ca.WithRootFile(rootFile)) @@ -153,7 +153,7 @@ func GetProvisioners(caURL, rootFile string) (provisioner.List, error) { // GetProvisionerKey returns the encrypted provisioner key with the for the // given kid. func GetProvisionerKey(caURL, rootFile, kid string) (string, error) { - if len(rootFile) == 0 { + if rootFile == "" { rootFile = GetRootCAPath() } client, err := ca.NewClient(caURL, ca.WithRootFile(rootFile)) @@ -315,17 +315,17 @@ func New(o apiv1.Options, opts ...Option) (*PKI, error) { // Use /home/step as the step path in helm configurations. // Use the current step path when creating pki in files. - var public, private, config string + var public, private, cfg string if p.options.isHelm { public = "/home/step/certs" private = "/home/step/secrets" - config = "/home/step/config" + cfg = "/home/step/config" } else { public = GetPublicPath() private = GetSecretsPath() - config = GetConfigPath() + cfg = GetConfigPath() // Create directories - dirs := []string{public, private, config, GetTemplatesPath()} + dirs := []string{public, private, cfg, GetTemplatesPath()} for _, name := range dirs { if _, err := os.Stat(name); os.IsNotExist(err) { if err = os.MkdirAll(name, 0700); err != nil { @@ -380,10 +380,10 @@ func New(o apiv1.Options, opts ...Option) (*PKI, error) { if p.Ssh.UserKey, err = getPath(private, "ssh_user_ca_key"); err != nil { return nil, err } - if p.defaults, err = getPath(config, "defaults.json"); err != nil { + if p.defaults, err = getPath(cfg, "defaults.json"); err != nil { return nil, err } - if p.config, err = getPath(config, "ca.json"); err != nil { + if p.config, err = getPath(cfg, "ca.json"); err != nil { return nil, err } p.Defaults.CaConfig = p.config @@ -620,16 +620,17 @@ func (p *PKI) askFeedback() { func (p *PKI) tellPKI() { ui.Println() - if p.casOptions.Is(apiv1.SoftCAS) { + switch { + case p.casOptions.Is(apiv1.SoftCAS): ui.PrintSelected("Root certificate", p.Root[0]) ui.PrintSelected("Root private key", p.RootKey[0]) ui.PrintSelected("Root fingerprint", p.Defaults.Fingerprint) ui.PrintSelected("Intermediate certificate", p.Intermediate) ui.PrintSelected("Intermediate private key", p.IntermediateKey) - } else if p.Defaults.Fingerprint != "" { + case p.Defaults.Fingerprint != "": ui.PrintSelected("Root certificate", p.Root[0]) ui.PrintSelected("Root fingerprint", p.Defaults.Fingerprint) - } else { + default: ui.Printf(`{{ "%s" | red }} {{ "Root certificate:" | bold }} failed to retrieve it from RA`+"\n", ui.IconBad) } if p.options.enableSSH { @@ -657,7 +658,7 @@ func (p *PKI) GenerateConfig(opt ...ConfigOption) (*authconfig.Config, error) { authorityOptions = &p.casOptions } - config := &authconfig.Config{ + cfg := &authconfig.Config{ Root: p.Root, FederatedRoots: p.FederatedRoots, IntermediateCert: p.Intermediate, @@ -681,7 +682,7 @@ func (p *PKI) GenerateConfig(opt ...ConfigOption) (*authconfig.Config, error) { // Add linked as a deployment type to detect it on start and provide a // message if the token is not given. if p.options.deploymentType == LinkedDeployment { - config.AuthorityConfig.DeploymentType = LinkedDeployment.String() + cfg.AuthorityConfig.DeploymentType = LinkedDeployment.String() } // On standalone deployments add the provisioners to either the ca.json or @@ -711,7 +712,7 @@ func (p *PKI) GenerateConfig(opt ...ConfigOption) (*authconfig.Config, error) { if p.options.enableSSH { enableSSHCA := true - config.SSH = &authconfig.SSHConfig{ + cfg.SSH = &authconfig.SSHConfig{ HostKey: p.Ssh.HostKey, UserKey: p.Ssh.UserKey, } @@ -733,19 +734,19 @@ func (p *PKI) GenerateConfig(opt ...ConfigOption) (*authconfig.Config, error) { // Apply configuration modifiers for _, o := range opt { - if err := o(config); err != nil { + if err := o(cfg); err != nil { return nil, err } } // Set authority.enableAdmin to true if p.options.enableAdmin { - config.AuthorityConfig.EnableAdmin = true + cfg.AuthorityConfig.EnableAdmin = true } if p.options.deploymentType == StandaloneDeployment { - if !config.AuthorityConfig.EnableAdmin { - config.AuthorityConfig.Provisioners = provisioners + if !cfg.AuthorityConfig.EnableAdmin { + cfg.AuthorityConfig.Provisioners = provisioners } else { // At this moment this code path is never used because `step ca // init` will always set enableAdmin to false for a standalone @@ -754,11 +755,11 @@ func (p *PKI) GenerateConfig(opt ...ConfigOption) (*authconfig.Config, error) { // // Note that we might want to be able to define the database as a // flag in `step ca init` so we can write to the proper place. - db, err := db.New(config.DB) + _db, err := db.New(cfg.DB) if err != nil { return nil, err } - adminDB, err := admindb.New(db.(nosql.DB), admin.DefaultAuthorityID) + adminDB, err := admindb.New(_db.(nosql.DB), admin.DefaultAuthorityID) if err != nil { return nil, err } @@ -788,7 +789,7 @@ func (p *PKI) GenerateConfig(opt ...ConfigOption) (*authconfig.Config, error) { } } - return config, nil + return cfg, nil } // Save stores the pki on a json file that will be used as the certificate @@ -804,12 +805,12 @@ func (p *PKI) Save(opt ...ConfigOption) error { // Generate and write ca.json if !p.options.pkiOnly { - config, err := p.GenerateConfig(opt...) + cfg, err := p.GenerateConfig(opt...) if err != nil { return err } - b, err := json.MarshalIndent(config, "", "\t") + b, err := json.MarshalIndent(cfg, "", "\t") if err != nil { return errors.Wrapf(err, "error marshaling %s", p.config) } @@ -833,14 +834,14 @@ func (p *PKI) Save(opt ...ConfigOption) error { } // Generate and write templates - if err := generateTemplates(config.Templates); err != nil { + if err := generateTemplates(cfg.Templates); err != nil { return err } - if config.DB != nil { - ui.PrintSelected("Database folder", config.DB.DataSource) + if cfg.DB != nil { + ui.PrintSelected("Database folder", cfg.DB.DataSource) } - if config.Templates != nil { + if cfg.Templates != nil { ui.PrintSelected("Templates folder", GetTemplatesPath()) } diff --git a/scep/api/api.go b/scep/api/api.go index e64eef83..4e02d4a1 100644 --- a/scep/api/api.go +++ b/scep/api/api.go @@ -198,14 +198,14 @@ func (h *Handler) lookupProvisioner(next nextHTTP) nextHTTP { return } - provisioner, ok := p.(*provisioner.SCEP) + prov, ok := p.(*provisioner.SCEP) if !ok { api.WriteError(w, errors.New("provisioner must be of type SCEP")) return } ctx := r.Context() - ctx = context.WithValue(ctx, scep.ProvisionerContextKey, scep.Provisioner(provisioner)) + ctx = context.WithValue(ctx, scep.ProvisionerContextKey, scep.Provisioner(prov)) next(w, r.WithContext(ctx)) } } diff --git a/templates/templates.go b/templates/templates.go index f98fb866..16e891d9 100644 --- a/templates/templates.go +++ b/templates/templates.go @@ -5,6 +5,7 @@ import ( "io/ioutil" "os" "path/filepath" + "strings" "text/template" "github.com/Masterminds/sprig/v3" @@ -226,14 +227,11 @@ func (t *Template) Output(data interface{}) (Output, error) { // backfill updates old templates with the required data. func (t *Template) backfill(b []byte) { - switch t.Name { - case "sshd_config.tpl": - if len(t.RequiredData) == 0 { - a := bytes.TrimSpace(b) - b := bytes.TrimSpace([]byte(DefaultSSHTemplateData[t.Name])) - if bytes.Equal(a, b) { - t.RequiredData = []string{"Certificate", "Key"} - } + if strings.EqualFold(t.Name, "sshd_config.tpl") && len(t.RequiredData) == 0 { + a := bytes.TrimSpace(b) + b := bytes.TrimSpace([]byte(DefaultSSHTemplateData[t.Name])) + if bytes.Equal(a, b) { + t.RequiredData = []string{"Certificate", "Key"} } } } From 5fc24c697cd433536707719456f6d577206be5a8 Mon Sep 17 00:00:00 2001 From: max furman Date: Fri, 8 Oct 2021 15:26:01 -0400 Subject: [PATCH 165/195] Fix a few more linter warnings and remove GOFLAGS from make lint --- Makefile | 2 +- kms/pkcs11/other_test.go | 4 ++-- kms/pkcs11/pkcs11.go | 11 +++++------ 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/Makefile b/Makefile index 108efa1d..09e342df 100644 --- a/Makefile +++ b/Makefile @@ -154,7 +154,7 @@ fmt: $Q gofmt -l -w $(SRC) lint: - $Q $(GOFLAGS) LOG_LEVEL=error golangci-lint run --timeout=30m + $Q golangci-lint run --timeout=30m lintcgo: $Q LOG_LEVEL=error golangci-lint run --timeout=30m diff --git a/kms/pkcs11/other_test.go b/kms/pkcs11/other_test.go index 680d3860..3e168716 100644 --- a/kms/pkcs11/other_test.go +++ b/kms/pkcs11/other_test.go @@ -166,10 +166,10 @@ func (s *privateKey) Delete() error { return nil } -func (s *privateKey) Decrypt(rand io.Reader, msg []byte, opts crypto.DecrypterOpts) (plaintext []byte, err error) { +func (s *privateKey) Decrypt(rnd io.Reader, msg []byte, opts crypto.DecrypterOpts) (plaintext []byte, err error) { k, ok := s.Signer.(*rsa.PrivateKey) if !ok { return nil, errors.New("key is not an rsa key") } - return k.Decrypt(rand, msg, opts) + return k.Decrypt(rnd, msg, opts) } diff --git a/kms/pkcs11/pkcs11.go b/kms/pkcs11/pkcs11.go index 07d40c05..7924f106 100644 --- a/kms/pkcs11/pkcs11.go +++ b/kms/pkcs11/pkcs11.go @@ -145,8 +145,7 @@ func (k *PKCS11) CreateKey(req *apiv1.CreateKeyRequest) (*apiv1.CreateKeyRespons // CreateSigner creates a signer using the key present in the PKCS#11 MODULE signature // slot. func (k *PKCS11) CreateSigner(req *apiv1.CreateSignerRequest) (crypto.Signer, error) { - switch { - case req.SigningKey == "": + if req.SigningKey == "" { return nil, errors.New("createSignerRequest 'signingKey' cannot be empty") } @@ -204,8 +203,8 @@ func (k *PKCS11) StoreCertificate(req *apiv1.StoreCertificateRequest) error { } // DeleteKey is a utility function to delete a key given an uri. -func (k *PKCS11) DeleteKey(uri string) error { - id, object, err := parseObject(uri) +func (k *PKCS11) DeleteKey(u string) error { + id, object, err := parseObject(u) if err != nil { return errors.Wrap(err, "deleteKey failed") } @@ -223,8 +222,8 @@ func (k *PKCS11) DeleteKey(uri string) error { } // DeleteCertificate is a utility function to delete a certificate given an uri. -func (k *PKCS11) DeleteCertificate(uri string) error { - id, object, err := parseObject(uri) +func (k *PKCS11) DeleteCertificate(u string) error { + id, object, err := parseObject(u) if err != nil { return errors.Wrap(err, "deleteCertificate failed") } From bdc9ffbe9039c292e4cf55b1e2119e79160553de Mon Sep 17 00:00:00 2001 From: max furman Date: Fri, 8 Oct 2021 15:44:04 -0400 Subject: [PATCH 166/195] changelog update --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a902ee2f..c5319526 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,10 +6,12 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased - 0.17.5] - DATE ### Added +- gocritic linter ### Changed ### Deprecated ### Removed ### Fixed +- gocritic warnings ### Security ## [0.17.4] - 2021-09-28 From 781d5fb6e8a0754c3b93ff7be27e21d64724a820 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Fri, 8 Oct 2021 14:25:24 -0700 Subject: [PATCH 167/195] Fix creation of ssh certificates on step ca init. --- pki/pki.go | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/pki/pki.go b/pki/pki.go index 41a644e1..b4ac26da 100644 --- a/pki/pki.go +++ b/pki/pki.go @@ -341,7 +341,7 @@ func New(o apiv1.Options, opts ...Option) (*PKI, error) { } // Use default key manager - if p.keyManager != nil { + if p.keyManager == nil { p.keyManager = kms.Default } @@ -634,7 +634,7 @@ func (p *PKI) GenerateSSHSigningKeys(password []byte) error { // Create SSH key used to sign host certificates. Using // kmsapi.UnspecifiedSignAlgorithm will default to the default algorithm. - name := p.Ssh.HostPublicKey + name := p.Ssh.HostKey if uri := p.options.hostKeyURI; uri != "" { name = uri } @@ -649,7 +649,7 @@ func (p *PKI) GenerateSSHSigningKeys(password []byte) error { if err != nil { return errors.Wrapf(err, "error converting public key") } - p.Files[resp.Name] = ssh.MarshalAuthorizedKey(sshKey) + p.Files[p.Ssh.HostPublicKey] = ssh.MarshalAuthorizedKey(sshKey) // On softkms we will have the private key if resp.PrivateKey != nil { @@ -657,11 +657,13 @@ func (p *PKI) GenerateSSHSigningKeys(password []byte) error { if err != nil { return err } + } else { + p.Ssh.HostKey = resp.Name } // Create SSH key used to sign user certificates. Using // kmsapi.UnspecifiedSignAlgorithm will default to the default algorithm. - name = p.Ssh.UserPublicKey + name = p.Ssh.UserKey if uri := p.options.userKeyURI; uri != "" { name = uri } @@ -676,7 +678,7 @@ func (p *PKI) GenerateSSHSigningKeys(password []byte) error { if err != nil { return errors.Wrapf(err, "error converting public key") } - p.Files[resp.Name] = ssh.MarshalAuthorizedKey(sshKey) + p.Files[p.Ssh.UserPublicKey] = ssh.MarshalAuthorizedKey(sshKey) // On softkms we will have the private key if resp.PrivateKey != nil { @@ -684,6 +686,8 @@ func (p *PKI) GenerateSSHSigningKeys(password []byte) error { if err != nil { return err } + } else { + p.Ssh.UserKey = resp.Name } return nil From 5d0bd7d1557985fa76443aff78ce848437d09a78 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Tue, 12 Oct 2021 15:14:01 -0700 Subject: [PATCH 168/195] Fix grammar in comments. --- kms/azurekms/key_vault.go | 8 ++++---- kms/azurekms/signer.go | 2 +- pki/pki.go | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/kms/azurekms/key_vault.go b/kms/azurekms/key_vault.go index 1fb8572c..b9a17b1c 100644 --- a/kms/azurekms/key_vault.go +++ b/kms/azurekms/key_vault.go @@ -19,7 +19,7 @@ func init() { }) } -// Scheme is the scheme used for Azure Key Vault uris. +// Scheme is the scheme used for the Azure Key Vault uris. const Scheme = "azurekms" // keyIDRegexp is the regular expression that Key Vault uses for on the kid. We @@ -96,11 +96,11 @@ var signatureAlgorithmMapping = map[apiv1.SignatureAlgorithm]keyType{ }, } -// vaultResource is that the client will use as audience. +// vaultResource is the value the client will use as audience. const vaultResource = "https://vault.azure.net" -// KeyVaultClient is the interface implemented by keyvault.BaseClient. It it -// will be used for testing purposes. +// KeyVaultClient is the interface implemented by keyvault.BaseClient. It will +// be used for testing purposes. type KeyVaultClient interface { GetKey(ctx context.Context, vaultBaseURL string, keyName string, keyVersion string) (keyvault.KeyBundle, error) CreateKey(ctx context.Context, vaultBaseURL string, keyName string, parameters keyvault.KeyCreateParameters) (keyvault.KeyBundle, error) diff --git a/kms/azurekms/signer.go b/kms/azurekms/signer.go index cf0197fb..405c625a 100644 --- a/kms/azurekms/signer.go +++ b/kms/azurekms/signer.go @@ -99,7 +99,7 @@ func (s *Signer) Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts) ([] return sig, nil } - // Convert to ans1 + // Convert to asn1 if len(sig) != octetSize*2 { return nil, errors.Errorf("keyVault Sign failed: unexpected signature length") } diff --git a/pki/pki.go b/pki/pki.go index b4ac26da..8a61d025 100644 --- a/pki/pki.go +++ b/pki/pki.go @@ -263,7 +263,7 @@ func WithDeploymentType(dt DeploymentType) Option { } } -// WithKMS enabled the kms with the given name. +// WithKMS enables the kms with the given name. func WithKMS(name string) Option { return func(p *PKI) { typ := linkedca.KMS_Type_value[strings.ToUpper(name)] From 2aee71b4c0772a2e9a8b9bb9df1b9a510f9fa9e0 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Tue, 12 Oct 2021 15:18:17 -0700 Subject: [PATCH 169/195] Fix typo. --- kms/azurekms/key_vault.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kms/azurekms/key_vault.go b/kms/azurekms/key_vault.go index b9a17b1c..27090f30 100644 --- a/kms/azurekms/key_vault.go +++ b/kms/azurekms/key_vault.go @@ -22,8 +22,8 @@ func init() { // Scheme is the scheme used for the Azure Key Vault uris. const Scheme = "azurekms" -// keyIDRegexp is the regular expression that Key Vault uses for on the kid. We -// can extract the vault, name and version of the key. +// keyIDRegexp is the regular expression that Key Vault uses on the kid. We can +// extract the vault, name and version of the key. var keyIDRegexp = regexp.MustCompile("^https://([0-9a-zA-Z-]+).vault.azure.net/keys/([0-9a-zA-Z-]+)/([0-9a-zA-Z-]+)$") var ( From a2b03083c85c204f2cbb9d8687086cfbbb9bfab5 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Tue, 12 Oct 2021 15:28:08 -0700 Subject: [PATCH 170/195] Fix gocritic warnings. --- kms/azurekms/key_vault.go | 5 ++--- kms/azurekms/signer_test.go | 31 ++++++++++++++++--------------- pki/pki.go | 2 +- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/kms/azurekms/key_vault.go b/kms/azurekms/key_vault.go index 27090f30..93be8241 100644 --- a/kms/azurekms/key_vault.go +++ b/kms/azurekms/key_vault.go @@ -24,7 +24,7 @@ const Scheme = "azurekms" // keyIDRegexp is the regular expression that Key Vault uses on the kid. We can // extract the vault, name and version of the key. -var keyIDRegexp = regexp.MustCompile("^https://([0-9a-zA-Z-]+).vault.azure.net/keys/([0-9a-zA-Z-]+)/([0-9a-zA-Z-]+)$") +var keyIDRegexp = regexp.MustCompile(`^https://([0-9a-zA-Z-]+)\.vault\.azure\.net/keys/([0-9a-zA-Z-]+)/([0-9a-zA-Z-]+)$`) var ( valueTrue = true @@ -162,8 +162,7 @@ func New(ctx context.Context, opts apiv1.Options) (*KeyVault, error) { // GetPublicKey loads a public key from Azure Key Vault by its resource name. func (k *KeyVault) GetPublicKey(req *apiv1.GetPublicKeyRequest) (crypto.PublicKey, error) { - switch { - case req.Name == "": + if req.Name == "" { return nil, errors.New("getPublicKeyRequest 'name' cannot be empty") } diff --git a/kms/azurekms/signer_test.go b/kms/azurekms/signer_test.go index 90740b9f..01921e2a 100644 --- a/kms/azurekms/signer_test.go +++ b/kms/azurekms/signer_test.go @@ -134,6 +134,7 @@ func TestSigner_Sign(t *testing.T) { sBytes := s.Bytes() sBytesPadded := make([]byte, keyBytes) copy(sBytesPadded[keyBytes-len(sBytes):], sBytes) + // nolint:gocritic resultSig = append(rBytesPadded, sBytesPadded...) var b cryptobyte.Builder @@ -256,61 +257,61 @@ func TestSigner_Sign(t *testing.T) { wantErr bool }{ {"ok P-256", fields{client, "https://my-vault.vault.azure.net/", "my-key", "", p256}, args{ - rand.Reader, p256Digest[:], crypto.SHA256, + rand.Reader, p256Digest, crypto.SHA256, }, p256Sig, false}, {"ok P-384", fields{client, "https://my-vault.vault.azure.net/", "my-key", "my-version", p384}, args{ - rand.Reader, p384Digest[:], crypto.SHA384, + rand.Reader, p384Digest, crypto.SHA384, }, p384Sig, false}, {"ok P-521", fields{client, "https://my-vault.vault.azure.net/", "my-key", "my-version", p521}, args{ - rand.Reader, p521Digest[:], crypto.SHA512, + rand.Reader, p521Digest, crypto.SHA512, }, p521Sig, false}, {"ok RSA SHA256", fields{client, "https://my-vault.vault.azure.net/", "my-key", "", rsaSHA256}, args{ - rand.Reader, rsaSHA256Digest[:], crypto.SHA256, + rand.Reader, rsaSHA256Digest, crypto.SHA256, }, rsaSHA256Sig, false}, {"ok RSA SHA384", fields{client, "https://my-vault.vault.azure.net/", "my-key", "", rsaSHA384}, args{ - rand.Reader, rsaSHA384Digest[:], crypto.SHA384, + rand.Reader, rsaSHA384Digest, crypto.SHA384, }, rsaSHA384Sig, false}, {"ok RSA SHA512", fields{client, "https://my-vault.vault.azure.net/", "my-key", "", rsaSHA512}, args{ - rand.Reader, rsaSHA512Digest[:], crypto.SHA512, + rand.Reader, rsaSHA512Digest, crypto.SHA512, }, rsaSHA512Sig, false}, {"ok RSA-PSS SHA256", fields{client, "https://my-vault.vault.azure.net/", "my-key", "", rsaPSSSHA256}, args{ - rand.Reader, rsaPSSSHA256Digest[:], &rsa.PSSOptions{ + rand.Reader, rsaPSSSHA256Digest, &rsa.PSSOptions{ SaltLength: rsa.PSSSaltLengthAuto, Hash: crypto.SHA256, }, }, rsaPSSSHA256Sig, false}, {"ok RSA-PSS SHA384", fields{client, "https://my-vault.vault.azure.net/", "my-key", "", rsaPSSSHA384}, args{ - rand.Reader, rsaPSSSHA384Digest[:], &rsa.PSSOptions{ + rand.Reader, rsaPSSSHA384Digest, &rsa.PSSOptions{ SaltLength: rsa.PSSSaltLengthEqualsHash, Hash: crypto.SHA384, }, }, rsaPSSSHA384Sig, false}, {"ok RSA-PSS SHA512", fields{client, "https://my-vault.vault.azure.net/", "my-key", "", rsaPSSSHA512}, args{ - rand.Reader, rsaPSSSHA512Digest[:], &rsa.PSSOptions{ + rand.Reader, rsaPSSSHA512Digest, &rsa.PSSOptions{ SaltLength: 64, Hash: crypto.SHA512, }, }, rsaPSSSHA512Sig, false}, {"fail Sign", fields{client, "https://my-vault.vault.azure.net/", "my-key", "", rsaSHA256}, args{ - rand.Reader, rsaSHA256Digest[:], crypto.SHA256, + rand.Reader, rsaSHA256Digest, crypto.SHA256, }, nil, true}, {"fail sign length", fields{client, "https://my-vault.vault.azure.net/", "my-key", "", p256}, args{ - rand.Reader, p256Digest[:], crypto.SHA256, + rand.Reader, p256Digest, crypto.SHA256, }, nil, true}, {"fail base64", fields{client, "https://my-vault.vault.azure.net/", "my-key", "", p256}, args{ - rand.Reader, p256Digest[:], crypto.SHA256, + rand.Reader, p256Digest, crypto.SHA256, }, nil, true}, {"fail RSA-PSS salt length", fields{client, "https://my-vault.vault.azure.net/", "my-key", "", rsaPSSSHA256}, args{ - rand.Reader, rsaPSSSHA256Digest[:], &rsa.PSSOptions{ + rand.Reader, rsaPSSSHA256Digest, &rsa.PSSOptions{ SaltLength: 64, Hash: crypto.SHA256, }, }, nil, true}, {"fail RSA Hash", fields{client, "https://my-vault.vault.azure.net/", "my-key", "", rsaSHA256}, args{ - rand.Reader, rsaSHA256Digest[:], crypto.SHA1, + rand.Reader, rsaSHA256Digest, crypto.SHA1, }, nil, true}, {"fail ECDSA Hash", fields{client, "https://my-vault.vault.azure.net/", "my-key", "", p256}, args{ - rand.Reader, p256Digest[:], crypto.MD5, + rand.Reader, p256Digest, crypto.MD5, }, nil, true}, {"fail Ed25519", fields{client, "https://my-vault.vault.azure.net/", "my-key", "", ed25519Key}, args{ rand.Reader, []byte("message"), crypto.Hash(0), diff --git a/pki/pki.go b/pki/pki.go index 92d640cf..61e20b6b 100644 --- a/pki/pki.go +++ b/pki/pki.go @@ -792,7 +792,7 @@ func (p *PKI) GenerateConfig(opt ...ConfigOption) (*authconfig.Config, error) { // Enable KMS if necessary if p.Kms != nil { - config.KMS = &kmsapi.Options{ + cfg.KMS = &kmsapi.Options{ Type: strings.ToLower(p.Kms.Type.String()), } } From 44f0d61354ae4cfdd894a27842f932a0749a2d4c Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Tue, 12 Oct 2021 15:41:41 -0700 Subject: [PATCH 171/195] Fix typo. --- kms/uri/uri.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kms/uri/uri.go b/kms/uri/uri.go index 3a1b8981..36e15e7d 100644 --- a/kms/uri/uri.go +++ b/kms/uri/uri.go @@ -95,8 +95,8 @@ func (u *URI) Get(key string) string { return v } -// GetBool returns true if a given key has the value "true". It will returns -// false otherwise. +// GetBool returns true if a given key has the value "true". It returns false +// otherwise. func (u *URI) GetBool(key string) bool { v := u.Values.Get(key) if v == "" { From 02d601861b040b29bd7ed099441979ef506fc3f8 Mon Sep 17 00:00:00 2001 From: max furman Date: Tue, 12 Oct 2021 15:44:04 -0700 Subject: [PATCH 172/195] [action] Simply goreleaser targets --- .goreleaser.yml | 29 ++++++++++------------------- 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/.goreleaser.yml b/.goreleaser.yml index 97b9c24c..a2f9969d 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -12,25 +12,16 @@ builds: id: step-ca env: - CGO_ENABLED=0 - goos: - - linux - - darwin - - windows - goarch: - - amd64 - - arm - - arm64 - - 386 - goarm: - - 6 - - 7 - ignore: - - goos: windows - goarch: 386 - - goos: windows - goarm: 6 - - goos: windows - goarm: 7 + targets: + - darwin_amd64 + - darwin_arm64 + - linux_386 + - linux_amd64 + - linux_arm64 + - linux_arm_6 + - linux_arm_7 + - windows_amd64 + - windows_arm64 flags: - -trimpath main: ./cmd/step-ca/main.go From 9f8ffcf19625d7952f570af748afbece63481a3f Mon Sep 17 00:00:00 2001 From: max furman Date: Tue, 12 Oct 2021 16:40:24 -0700 Subject: [PATCH 173/195] [action] remove windows_amd64, add freebsd_amd64 --- .goreleaser.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.goreleaser.yml b/.goreleaser.yml index a2f9969d..60eff7e7 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -15,13 +15,13 @@ builds: targets: - darwin_amd64 - darwin_arm64 + - freebsd_amd64 - linux_386 - linux_amd64 - linux_arm64 - linux_arm_6 - linux_arm_7 - windows_amd64 - - windows_arm64 flags: - -trimpath main: ./cmd/step-ca/main.go From edd475b81bb0ee9b65ec8df9c041910b0e4edf19 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Tue, 12 Oct 2021 18:24:58 -0700 Subject: [PATCH 174/195] Allow to configure azurekms using the URI With an URI, azurekms can be configured with client credentials, and it can define a default vault and protection level. --- go.mod | 1 + kms/azurekms/key_vault.go | 79 +++++++++++++++++++++++++++++++--- kms/azurekms/key_vault_test.go | 72 +++++++++++++++++++++++++++++++ kms/azurekms/signer.go | 4 +- kms/azurekms/signer_test.go | 27 +++++++++--- kms/azurekms/utils.go | 22 +++++++--- kms/azurekms/utils_test.go | 33 ++++++++------ 7 files changed, 203 insertions(+), 35 deletions(-) diff --git a/go.mod b/go.mod index f3d2e358..791e0927 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ go 1.15 require ( cloud.google.com/go v0.83.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 github.com/Azure/go-autorest/autorest/date v0.3.0 github.com/Azure/go-autorest/autorest/to v0.4.0 // indirect diff --git a/kms/azurekms/key_vault.go b/kms/azurekms/key_vault.go index 93be8241..34d9c3f1 100644 --- a/kms/azurekms/key_vault.go +++ b/kms/azurekms/key_vault.go @@ -7,10 +7,12 @@ import ( "time" "github.com/Azure/azure-sdk-for-go/services/keyvault/v7.1/keyvault" + "github.com/Azure/go-autorest/autorest/azure" "github.com/Azure/go-autorest/autorest/azure/auth" "github.com/Azure/go-autorest/autorest/date" "github.com/pkg/errors" "github.com/smallstep/certificates/kms/apiv1" + "github.com/smallstep/certificates/kms/uri" ) func init() { @@ -126,9 +128,60 @@ type KeyVaultClient interface { // functionality in /sdk/keyvault, we should migrate to that once available. type KeyVault struct { baseClient KeyVaultClient + defaults DefaultOptions +} + +// DefaultOptions are custom options that can be passed as defaults using the +// URI in apiv1.Options. +type DefaultOptions struct { + Vault string + ProtectionLevel apiv1.ProtectionLevel } var createClient = func(ctx context.Context, opts apiv1.Options) (KeyVaultClient, error) { + baseClient := keyvault.New() + + // With an URI, try to log in only using client credentials in the URI. + // Client credentials requires: + // - client-id + // - client-secret + // - tenant-id + // And optionally the aad-endpoint to support custom clouds: + // - aad-endpoint (defaults to https://login.microsoftonline.com/) + if opts.URI != "" { + u, err := uri.ParseWithScheme(Scheme, opts.URI) + if err != nil { + return nil, err + } + + // Required options + clientID := u.Get("client-id") + clientSecret := u.Get("client-secret") + tenantID := u.Get("tenant-id") + // optional + aadEndpoint := u.Get("aad-endpoint") + + if clientID != "" && clientSecret != "" && tenantID != "" { + s := auth.EnvironmentSettings{ + Values: map[string]string{ + auth.ClientID: clientID, + auth.ClientSecret: clientSecret, + auth.TenantID: tenantID, + auth.Resource: vaultResource, + }, + Environment: azure.PublicCloud, + } + if aadEndpoint != "" { + s.Environment.ActiveDirectoryEndpoint = aadEndpoint + } + baseClient.Authorizer, err = s.GetAuthorizer() + if err != nil { + return nil, err + } + return baseClient, nil + } + } + // Attempt to authorize with the following methods: // 1. Environment variables. // - Client credentials @@ -143,8 +196,6 @@ var createClient = func(ctx context.Context, opts apiv1.Options) (KeyVaultClient return nil, errors.Wrap(err, "error getting authorizer for key vault") } } - - baseClient := keyvault.New() baseClient.Authorizer = authorizer return &baseClient, nil } @@ -155,8 +206,24 @@ func New(ctx context.Context, opts apiv1.Options) (*KeyVault, error) { if err != nil { return nil, err } + + // step and step-ca do not need and URI, but having a default vault and + // protection level is useful if this package is used as an api + var defaults DefaultOptions + if opts.URI != "" { + u, err := uri.ParseWithScheme(Scheme, opts.URI) + if err != nil { + return nil, err + } + defaults.Vault = u.Get("vault") + if u.GetBool("hsm") { + defaults.ProtectionLevel = apiv1.HSM + } + } + return &KeyVault{ baseClient: baseClient, + defaults: defaults, }, nil } @@ -166,7 +233,7 @@ func (k *KeyVault) GetPublicKey(req *apiv1.GetPublicKeyRequest) (crypto.PublicKe return nil, errors.New("getPublicKeyRequest 'name' cannot be empty") } - vault, name, version, _, err := parseKeyName(req.Name) + vault, name, version, _, err := parseKeyName(req.Name, k.defaults) if err != nil { return nil, err } @@ -188,7 +255,7 @@ func (k *KeyVault) CreateKey(req *apiv1.CreateKeyRequest) (*apiv1.CreateKeyRespo return nil, errors.New("createKeyRequest 'name' cannot be empty") } - vault, name, _, hsm, err := parseKeyName(req.Name) + vault, name, _, hsm, err := parseKeyName(req.Name, k.defaults) if err != nil { return nil, err } @@ -260,7 +327,7 @@ func (k *KeyVault) CreateSigner(req *apiv1.CreateSignerRequest) (crypto.Signer, if req.SigningKey == "" { return nil, errors.New("createSignerRequest 'signingKey' cannot be empty") } - return NewSigner(k.baseClient, req.SigningKey) + return NewSigner(k.baseClient, req.SigningKey, k.defaults) } // Close closes the client connection to the Azure Key Vault. This is a noop. @@ -270,6 +337,6 @@ func (k *KeyVault) Close() error { // ValidateName validates that the given string is a valid URI. func (k *KeyVault) ValidateName(s string) error { - _, _, _, _, err := parseKeyName(s) + _, _, _, _, err := parseKeyName(s, k.defaults) return err } diff --git a/kms/azurekms/key_vault_test.go b/kms/azurekms/key_vault_test.go index 1f26e1ef..8f968189 100644 --- a/kms/azurekms/key_vault_test.go +++ b/kms/azurekms/key_vault_test.go @@ -89,11 +89,44 @@ func TestNew(t *testing.T) { }, args{context.Background(), apiv1.Options{}}, &KeyVault{ baseClient: client, }, false}, + {"ok with vault", func() { + createClient = func(ctx context.Context, opts apiv1.Options) (KeyVaultClient, error) { + return client, nil + } + }, args{context.Background(), apiv1.Options{ + URI: "azurekms:vault=my-vault", + }}, &KeyVault{ + baseClient: client, + defaults: DefaultOptions{ + Vault: "my-vault", + ProtectionLevel: apiv1.UnspecifiedProtectionLevel, + }, + }, false}, + {"ok with vault + hsm", func() { + createClient = func(ctx context.Context, opts apiv1.Options) (KeyVaultClient, error) { + return client, nil + } + }, args{context.Background(), apiv1.Options{ + URI: "azurekms:vault=my-vault;hsm=true", + }}, &KeyVault{ + baseClient: client, + defaults: DefaultOptions{ + Vault: "my-vault", + ProtectionLevel: apiv1.HSM, + }, + }, false}, {"fail", func() { createClient = func(ctx context.Context, opts apiv1.Options) (KeyVaultClient, error) { return nil, errTest } }, args{context.Background(), apiv1.Options{}}, nil, true}, + {"fail uri", func() { + createClient = func(ctx context.Context, opts apiv1.Options) (KeyVaultClient, error) { + return client, nil + } + }, args{context.Background(), apiv1.Options{ + URI: "kms:vault=my-vault;hsm=true", + }}, nil, true}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -110,6 +143,45 @@ func TestNew(t *testing.T) { } } +func TestKeyVault_createClient(t *testing.T) { + type args struct { + ctx context.Context + opts apiv1.Options + } + tests := []struct { + name string + args args + skip bool + wantErr bool + }{ + {"ok", args{context.Background(), apiv1.Options{}}, true, false}, + {"ok with uri", args{context.Background(), apiv1.Options{ + URI: "azurekms:client-id=id;client-secret=secret;tenant-id=id", + }}, false, false}, + {"ok with uri+aad", args{context.Background(), apiv1.Options{ + URI: "azurekms:client-id=id;client-secret=secret;tenant-id=id;aad-enpoint=https%3A%2F%2Flogin.microsoftonline.us%2F", + }}, false, false}, + {"ok with uri no config", args{context.Background(), apiv1.Options{ + URI: "azurekms:", + }}, true, false}, + {"fail uri", args{context.Background(), apiv1.Options{ + URI: "kms:client-id=id;client-secret=secret;tenant-id=id", + }}, false, true}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if tt.skip { + t.SkipNow() + } + _, err := createClient(tt.args.ctx, tt.args.opts) + if (err != nil) != tt.wantErr { + t.Errorf("New() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + func TestKeyVault_GetPublicKey(t *testing.T) { key, err := keyutil.GenerateDefaultSigner() if err != nil { diff --git a/kms/azurekms/signer.go b/kms/azurekms/signer.go index 405c625a..e3aca5fe 100644 --- a/kms/azurekms/signer.go +++ b/kms/azurekms/signer.go @@ -24,8 +24,8 @@ type Signer struct { } // NewSigner creates a new signer using a key in the AWS KMS. -func NewSigner(client KeyVaultClient, signingKey string) (crypto.Signer, error) { - vault, name, version, _, err := parseKeyName(signingKey) +func NewSigner(client KeyVaultClient, signingKey string, defaults DefaultOptions) (crypto.Signer, error) { + vault, name, version, _, err := parseKeyName(signingKey, defaults) if err != nil { return nil, err } diff --git a/kms/azurekms/signer_test.go b/kms/azurekms/signer_test.go index 01921e2a..381c3577 100644 --- a/kms/azurekms/signer_test.go +++ b/kms/azurekms/signer_test.go @@ -12,6 +12,7 @@ import ( "github.com/Azure/azure-sdk-for-go/services/keyvault/v7.1/keyvault" "github.com/golang/mock/gomock" + "github.com/smallstep/certificates/kms/apiv1" "go.step.sm/crypto/keyutil" "golang.org/x/crypto/cryptobyte" "golang.org/x/crypto/cryptobyte/asn1" @@ -32,11 +33,16 @@ func TestNewSigner(t *testing.T) { client.EXPECT().GetKey(gomock.Any(), "https://my-vault.vault.azure.net/", "my-key", "my-version").Return(keyvault.KeyBundle{ Key: jwk, }, nil) + client.EXPECT().GetKey(gomock.Any(), "https://my-vault.vault.azure.net/", "my-key", "my-version").Return(keyvault.KeyBundle{ + Key: jwk, + }, nil) client.EXPECT().GetKey(gomock.Any(), "https://my-vault.vault.azure.net/", "not-found", "my-version").Return(keyvault.KeyBundle{}, errTest) + var noOptions DefaultOptions type args struct { client KeyVaultClient signingKey string + defaults DefaultOptions } tests := []struct { name string @@ -44,28 +50,35 @@ func TestNewSigner(t *testing.T) { want crypto.Signer wantErr bool }{ - {"ok", args{client, "azurekms:vault=my-vault;name=my-key"}, &Signer{ + {"ok", args{client, "azurekms:vault=my-vault;name=my-key", noOptions}, &Signer{ client: client, vaultBaseURL: "https://my-vault.vault.azure.net/", name: "my-key", version: "", publicKey: pub, }, false}, - {"ok with version", args{client, "azurekms:name=my-key;vault=my-vault?version=my-version"}, &Signer{ + {"ok with version", args{client, "azurekms:name=my-key;vault=my-vault?version=my-version", noOptions}, &Signer{ client: client, vaultBaseURL: "https://my-vault.vault.azure.net/", name: "my-key", version: "my-version", publicKey: pub, }, false}, - {"fail GetKey", args{client, "azurekms:name=not-found;vault=my-vault?version=my-version"}, nil, true}, - {"fail vault", args{client, "azurekms:name=not-found;vault="}, nil, true}, - {"fail id", args{client, "azurekms:name=;vault=my-vault?version=my-version"}, nil, true}, - {"fail scheme", args{client, "kms:name=not-found;vault=my-vault?version=my-version"}, nil, true}, + {"ok with options", args{client, "azurekms:name=my-key?version=my-version", DefaultOptions{Vault: "my-vault", ProtectionLevel: apiv1.HSM}}, &Signer{ + client: client, + vaultBaseURL: "https://my-vault.vault.azure.net/", + name: "my-key", + version: "my-version", + publicKey: pub, + }, false}, + {"fail GetKey", args{client, "azurekms:name=not-found;vault=my-vault?version=my-version", noOptions}, nil, true}, + {"fail vault", args{client, "azurekms:name=not-found;vault=", noOptions}, nil, true}, + {"fail id", args{client, "azurekms:name=;vault=my-vault?version=my-version", noOptions}, nil, true}, + {"fail scheme", args{client, "kms:name=not-found;vault=my-vault?version=my-version", noOptions}, nil, true}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := NewSigner(tt.args.client, tt.args.signingKey) + got, err := NewSigner(tt.args.client, tt.args.signingKey, tt.args.defaults) if (err != nil) != tt.wantErr { t.Errorf("NewSigner() error = %v, wantErr %v", err, tt.wantErr) return diff --git a/kms/azurekms/utils.go b/kms/azurekms/utils.go index 52bed868..d4201907 100644 --- a/kms/azurekms/utils.go +++ b/kms/azurekms/utils.go @@ -9,6 +9,7 @@ import ( "github.com/Azure/azure-sdk-for-go/services/keyvault/v7.1/keyvault" "github.com/pkg/errors" + "github.com/smallstep/certificates/kms/apiv1" "github.com/smallstep/certificates/kms/uri" "go.step.sm/crypto/jose" ) @@ -50,10 +51,10 @@ func getKeyName(vault, name string, bundle keyvault.KeyBundle) string { // // HSM can also be passed to define the protection level if this is not given in // CreateQuery. -func parseKeyName(rawURI string) (vault, name, version string, hsm bool, err error) { +func parseKeyName(rawURI string, defaults DefaultOptions) (vault, name, version string, hsm bool, err error) { var u *uri.URI - u, err = uri.ParseWithScheme("azurekms", rawURI) + u, err = uri.ParseWithScheme(Scheme, rawURI) if err != nil { return } @@ -62,12 +63,21 @@ func parseKeyName(rawURI string) (vault, name, version string, hsm bool, err err return } if vault = u.Get("vault"); vault == "" { - err = errors.Errorf("key uri %s is not valid: vault is missing", rawURI) - name = "" - return + if defaults.Vault == "" { + name = "" + err = errors.Errorf("key uri %s is not valid: vault is missing", rawURI) + return + } + vault = defaults.Vault } + if u.Get("hsm") == "" { + hsm = (defaults.ProtectionLevel == apiv1.HSM) + } else { + hsm = u.GetBool("hsm") + } + version = u.Get("version") - hsm = u.GetBool("hsm") + return } diff --git a/kms/azurekms/utils_test.go b/kms/azurekms/utils_test.go index 000a9d6b..cded50ea 100644 --- a/kms/azurekms/utils_test.go +++ b/kms/azurekms/utils_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/Azure/azure-sdk-for-go/services/keyvault/v7.1/keyvault" + "github.com/smallstep/certificates/kms/apiv1" ) func Test_getKeyName(t *testing.T) { @@ -42,8 +43,10 @@ func Test_getKeyName(t *testing.T) { } func Test_parseKeyName(t *testing.T) { + var noOptions DefaultOptions type args struct { - rawURI string + rawURI string + defaults DefaultOptions } tests := []struct { name string @@ -54,22 +57,24 @@ func Test_parseKeyName(t *testing.T) { wantHsm bool wantErr bool }{ - {"ok", args{"azurekms:name=my-key;vault=my-vault?version=my-version"}, "my-vault", "my-key", "my-version", false, false}, - {"ok opaque version", args{"azurekms:name=my-key;vault=my-vault;version=my-version"}, "my-vault", "my-key", "my-version", false, false}, - {"ok no version", args{"azurekms:name=my-key;vault=my-vault"}, "my-vault", "my-key", "", false, false}, - {"ok hsm", args{"azurekms:name=my-key;vault=my-vault?hsm=true"}, "my-vault", "my-key", "", true, false}, - {"ok hsm false", args{"azurekms:name=my-key;vault=my-vault?hsm=false"}, "my-vault", "my-key", "", false, false}, - {"fail scheme", args{"azure:name=my-key;vault=my-vault"}, "", "", "", false, true}, - {"fail parse uri", args{"azurekms:name=%ZZ;vault=my-vault"}, "", "", "", false, true}, - {"fail no name", args{"azurekms:vault=my-vault"}, "", "", "", false, true}, - {"fail empty name", args{"azurekms:name=;vault=my-vault"}, "", "", "", false, true}, - {"fail no vault", args{"azurekms:name=my-key"}, "", "", "", false, true}, - {"fail empty vault", args{"azurekms:name=my-key;vault="}, "", "", "", false, true}, - {"fail empty", args{""}, "", "", "", false, true}, + {"ok", args{"azurekms:name=my-key;vault=my-vault?version=my-version", noOptions}, "my-vault", "my-key", "my-version", false, false}, + {"ok opaque version", args{"azurekms:name=my-key;vault=my-vault;version=my-version", noOptions}, "my-vault", "my-key", "my-version", false, false}, + {"ok no version", args{"azurekms:name=my-key;vault=my-vault", noOptions}, "my-vault", "my-key", "", false, false}, + {"ok hsm", args{"azurekms:name=my-key;vault=my-vault?hsm=true", noOptions}, "my-vault", "my-key", "", true, false}, + {"ok hsm false", args{"azurekms:name=my-key;vault=my-vault?hsm=false", noOptions}, "my-vault", "my-key", "", false, false}, + {"ok default vault", args{"azurekms:name=my-key?version=my-version", DefaultOptions{Vault: "my-vault"}}, "my-vault", "my-key", "my-version", false, false}, + {"ok default hsm", args{"azurekms:name=my-key;vault=my-vault?version=my-version", DefaultOptions{Vault: "other-vault", ProtectionLevel: apiv1.HSM}}, "my-vault", "my-key", "my-version", true, false}, + {"fail scheme", args{"azure:name=my-key;vault=my-vault", noOptions}, "", "", "", false, true}, + {"fail parse uri", args{"azurekms:name=%ZZ;vault=my-vault", noOptions}, "", "", "", false, true}, + {"fail no name", args{"azurekms:vault=my-vault", noOptions}, "", "", "", false, true}, + {"fail empty name", args{"azurekms:name=;vault=my-vault", noOptions}, "", "", "", false, true}, + {"fail no vault", args{"azurekms:name=my-key", noOptions}, "", "", "", false, true}, + {"fail empty vault", args{"azurekms:name=my-key;vault=", noOptions}, "", "", "", false, true}, + {"fail empty", args{"", noOptions}, "", "", "", false, true}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - gotVault, gotName, gotVersion, gotHsm, err := parseKeyName(tt.args.rawURI) + gotVault, gotName, gotVersion, gotHsm, err := parseKeyName(tt.args.rawURI, tt.args.defaults) if (err != nil) != tt.wantErr { t.Errorf("parseKeyName() error = %v, wantErr %v", err, tt.wantErr) return From 36b622bfc2832652bab668255be1beae735954f8 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Fri, 15 Oct 2021 14:12:43 -0700 Subject: [PATCH 175/195] Use Golang's default keep-alive. Since Go 1.13 a net.Listen keep-alive is enabled by default if the protocol and OS supports it. The new one is 15s to match the net.Dial default one. Previously http.Server ListenAndServe and ListenAndServeTLS used to add a wrapper with 3m that we replicated. See https://github.com/golang/go/issues/31510 --- ca/tls.go | 4 ++-- examples/basic-client/client.go | 1 - server/server.go | 22 ++-------------------- 3 files changed, 4 insertions(+), 23 deletions(-) diff --git a/ca/tls.go b/ca/tls.go index 3a3b6766..0738d0e0 100644 --- a/ca/tls.go +++ b/ca/tls.go @@ -279,9 +279,9 @@ func getDefaultTLSConfig(sign *api.SignResponse) *tls.Config { // getDefaultDialer returns a new dialer with the default configuration. func getDefaultDialer() *net.Dialer { + // With the KeepAlive parameter set to 0, it will be use Golang's default. return &net.Dialer{ - Timeout: 30 * time.Second, - KeepAlive: 30 * time.Second, + Timeout: 30 * time.Second, } } diff --git a/examples/basic-client/client.go b/examples/basic-client/client.go index db6092bf..42358ac8 100644 --- a/examples/basic-client/client.go +++ b/examples/basic-client/client.go @@ -116,7 +116,6 @@ func main() { Proxy: http.ProxyFromEnvironment, DialContext: (&net.Dialer{ Timeout: 30 * time.Second, - KeepAlive: 30 * time.Second, DualStack: true, }).DialContext, MaxIdleConns: 100, diff --git a/server/server.go b/server/server.go index d3968c4a..2b864148 100644 --- a/server/server.go +++ b/server/server.go @@ -72,10 +72,10 @@ func (srv *Server) Serve(ln net.Listener) error { // Start server if srv.TLSConfig == nil || (len(srv.TLSConfig.Certificates) == 0 && srv.TLSConfig.GetCertificate == nil) { log.Printf("Serving HTTP on %s ...", srv.Addr) - err = srv.Server.Serve(tcpKeepAliveListener{ln.(*net.TCPListener)}) + err = srv.Server.Serve(ln) } else { log.Printf("Serving HTTPS on %s ...", srv.Addr) - err = srv.Server.ServeTLS(tcpKeepAliveListener{ln.(*net.TCPListener)}, "", "") + err = srv.Server.ServeTLS(ln, "", "") } // log unexpected errors @@ -155,21 +155,3 @@ func (srv *Server) Forbidden(w http.ResponseWriter) { w.WriteHeader(http.StatusForbidden) w.Write([]byte("Forbidden.\n")) } - -// tcpKeepAliveListener sets TCP keep-alive timeouts on accepted -// connections. It's used by ListenAndServe and ListenAndServeTLS so -// dead TCP connections (e.g. closing laptop mid-download) eventually -// go away. -type tcpKeepAliveListener struct { - *net.TCPListener -} - -func (ln tcpKeepAliveListener) Accept() (c net.Conn, err error) { - tc, err := ln.AcceptTCP() - if err != nil { - return - } - tc.SetKeepAlive(true) - tc.SetKeepAlivePeriod(3 * time.Minute) - return tc, nil -} From 482482e71729e41c22d4d9f731452eae71d5e4d8 Mon Sep 17 00:00:00 2001 From: Carl Tashian Date: Tue, 19 Oct 2021 15:22:30 -0700 Subject: [PATCH 176/195] install-step-ra.sh: Don't try to create a JWK provisioner, because the web app's OAuth flow doesn't support OOB with STEP_CONSOLE=true. --- scripts/install-step-ra.sh | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/scripts/install-step-ra.sh b/scripts/install-step-ra.sh index 1920b17d..227af5db 100644 --- a/scripts/install-step-ra.sh +++ b/scripts/install-step-ra.sh @@ -126,25 +126,17 @@ fi echo "Bootstrapping with the CA..." export STEPPATH=$(mktemp -d) -export STEP_CONSOLE=true step ca bootstrap --ca-url $CA_URL --fingerprint $CA_FINGERPRINT if [ -z "$CA_PROVISIONER_NAME" ]; then declare -a provisioners readarray -t provisioners < <(step ca provisioner list | jq -r '.[] | select(.type == "JWK") | .name') - provisioners+=("Create provisioner") printf '%s\n' "${provisioners[@]}" printf "%b" "\nSelect a JWK provisioner:\n" >&2 select provisioner in "${provisioners[@]}"; do - if [ "$provisioner" == "Create provisioner" ]; then - echo "Creating a JWK provisioner on the upstream CA..." - echo "" - read -p "Label your provisioner (e.g. example-ra): " CA_PROVISIONER_NAME < /dev/tty - step beta ca provisioner add $CA_PROVISIONER_NAME --type JWK --create - break - elif [ -n "$provisioner" ]; then + if [ -n "$provisioner" ]; then echo "Using existing provisioner $provisioner." CA_PROVISIONER_NAME=$provisioner break From 655d7f59fde2bebcae6a2b716aeabf18e32f00ec Mon Sep 17 00:00:00 2001 From: Carl Tashian Date: Tue, 19 Oct 2021 16:14:41 -0700 Subject: [PATCH 177/195] install-step-ra.sh: Properly quote the RA DNS names in ca.json --- scripts/install-step-ra.sh | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/scripts/install-step-ra.sh b/scripts/install-step-ra.sh index 227af5db..1da64ed6 100644 --- a/scripts/install-step-ra.sh +++ b/scripts/install-step-ra.sh @@ -154,6 +154,27 @@ if [ -z "$RA_DNS_NAMES" ]; then done fi + +count=0 +ra_dns_names_quoted="" + +for i in ${RA_DNS_NAMES//,/ } +do + if [ "$count" = "0" ]; then + ra_dns_names_quoted="\"$i\"" + else + ra_dns_names_quoted="${ra_dns_names_quoted}, \"$i\"" + fi + count=$((count+1)) +done + +if [ "$count" = "0" ]; then + echo "You must supply at least one RA DNS name" + exit 1 +fi + +echo "Got here" + if [ -z "$RA_ADDRESS" ]; then RA_ADDRESS="" while [[ $RA_ADDRESS = "" ]] ; do @@ -189,7 +210,7 @@ mkdir -p $(step path)/config cat < $(step path)/config/ca.json { "address": "$RA_ADDRESS", - "dnsNames": ["$RA_DNS_NAMES"], + "dnsNames": [$ra_dns_names_quoted], "db": { "type": "badgerV2", "dataSource": "/etc/step-ca/db" From 6f1693877495a071641478736ba2487b4211e9b0 Mon Sep 17 00:00:00 2001 From: Carl Tashian Date: Tue, 19 Oct 2021 16:53:41 -0700 Subject: [PATCH 178/195] Update README.md * Add SCEP support * Fix ACME tutorial URLs --- README.md | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 64458929..bfc056b4 100644 --- a/README.md +++ b/README.md @@ -66,7 +66,8 @@ You can issue certificates in exchange for: - [Cloud instance identity documents](https://smallstep.com/blog/embarrassingly-easy-certificates-on-aws-azure-gcp/), for VMs on AWS, GCP, and Azure - [Single-use, short-lived JWK tokens](https://smallstep.com/docs/step-ca/provisioners#jwk) issued by your CD tool — Puppet, Chef, Ansible, Terraform, etc. - A trusted X.509 certificate (X5C provisioner) -- Expiring SSH host certificates needing rotation (the SSHPOP provisioner) +- A SCEP challenge (SCEP provisioner) +- An SSH host certificates needing renewal (the SSHPOP provisioner) - Learn more in our [provisioner documentation](https://smallstep.com/docs/step-ca/provisioners) ### 🏔 Your own private ACME server @@ -80,16 +81,17 @@ ACME is the protocol used by Let's Encrypt to automate the issuance of HTTPS cer - For `tls-alpn-01`, respond to the challenge at the TLS layer ([as Caddy does](https://caddy.community/t/caddy-supports-the-acme-tls-alpn-challenge/4860)) to prove that you control the web server - Works with any ACME client. We've written examples for: - - [certbot](https://smallstep.com/blog/private-acme-server/#certbotuploadsacme-certbotpng-certbot-example) - - [acme.sh](https://smallstep.com/blog/private-acme-server/#acmeshuploadsacme-acme-shpng-acmesh-example) - - [Caddy](https://smallstep.com/blog/private-acme-server/#caddyuploadsacme-caddypng-caddy-example) - - [Traefik](https://smallstep.com/blog/private-acme-server/#traefikuploadsacme-traefikpng-traefik-example) - - [Apache](https://smallstep.com/blog/private-acme-server/#apacheuploadsacme-apachepng-apache-example) - - [nginx](https://smallstep.com/blog/private-acme-server/#nginxuploadsacme-nginxpng-nginx-example) + - [certbot](https://smallstep.com/docs/tutorials/acme-protocol-acme-clients#certbot) + - [acme.sh](https://smallstep.com/docs/tutorials/acme-protocol-acme-clients#acmesh) + - [win-acme](https://smallstep.com/docs/tutorials/acme-protocol-acme-clients#win-acme) + - [Caddy](https://smallstep.com/docs/tutorials/acme-protocol-acme-clients#caddy-v2) + - [Traefik](https://smallstep.com/docs/tutorials/acme-protocol-acme-clients#traefik) + - [Apache](https://smallstep.com/docs/tutorials/acme-protocol-acme-clients#apache) + - [nginx](https://smallstep.com/docs/tutorials/acme-protocol-acme-clients#nginx) - Get certificates programmatically using ACME, using these libraries: - - [`lego`](https://github.com/go-acme/lego) for Golang ([example usage](https://smallstep.com/blog/private-acme-server/#golanguploadsacme-golangpng-go-example)) - - certbot's [`acme` module](https://github.com/certbot/certbot/tree/master/acme) for Python ([example usage](https://smallstep.com/blog/private-acme-server/#pythonuploadsacme-pythonpng-python-example)) - - [`acme-client`](https://github.com/publishlab/node-acme-client) for Node.js ([example usage](https://smallstep.com/blog/private-acme-server/#nodejsuploadsacme-node-jspng-nodejs-example)) + - [`lego`](https://github.com/go-acme/lego) for Golang ([example usage](https://smallstep.com/docs/tutorials/acme-protocol-acme-clients#golang)) + - certbot's [`acme` module](https://github.com/certbot/certbot/tree/master/acme) for Python ([example usage](https://smallstep.com/docs/tutorials/acme-protocol-acme-clients#python)) + - [`acme-client`](https://github.com/publishlab/node-acme-client) for Node.js ([example usage](https://smallstep.com/docs/tutorials/acme-protocol-acme-clients#node)) - Our own [`step` CLI tool](https://github.com/smallstep/cli) is also an ACME client! - See our [ACME tutorial](https://smallstep.com/docs/tutorials/acme-challenge) for more From 12b32b0a905a8cd58ff58ccc36c0654a8ebe65ae Mon Sep 17 00:00:00 2001 From: max furman Date: Wed, 20 Oct 2021 13:41:26 -0700 Subject: [PATCH 179/195] Changelog update for v0.17.5 --- CHANGELOG.md | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 65ddbc15..4f031a5a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,18 +4,22 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). -## [Unreleased - 0.17.5] - DATE +## [Unreleased - 0.17.6] - DATE ### Added -- Support for Azure Key Vault as a KMS. -- Adapt `pki` package to support key managers. -- gocritic linter ### Changed ### Deprecated ### Removed ### Fixed -- gocritic warnings ### Security +## [0.17.5] - 2021-10-20 +### Added +- Support for Azure Key Vault as a KMS. +- Adapt `pki` package to support key managers. +- gocritic linter +### Fixed +- gocritic warnings + ## [0.17.4] - 2021-09-28 ### Fixed - Support host-only or user-only SSH CA. From 5c71e8a0ee61f1a7c15422a4a167297154d70671 Mon Sep 17 00:00:00 2001 From: max furman Date: Wed, 20 Oct 2021 14:10:40 -0700 Subject: [PATCH 180/195] [action] replace goreleaser complicated build targets with 'targets' --- .goreleaser.yml | 58 +++++++++++++++++-------------------------------- 1 file changed, 20 insertions(+), 38 deletions(-) diff --git a/.goreleaser.yml b/.goreleaser.yml index 60eff7e7..207c75bd 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -32,25 +32,16 @@ builds: id: step-cloudkms-init env: - CGO_ENABLED=0 - goos: - - linux - - darwin - - windows - goarch: - - amd64 - - arm - - arm64 - - 386 - goarm: - - 6 - - 7 - ignore: - - goos: windows - goarch: 386 - - goos: windows - goarm: 6 - - goos: windows - goarm: 7 + targets: + - darwin_amd64 + - darwin_arm64 + - freebsd_amd64 + - linux_386 + - linux_amd64 + - linux_arm64 + - linux_arm_6 + - linux_arm_7 + - windows_amd64 flags: - -trimpath main: ./cmd/step-cloudkms-init/main.go @@ -61,25 +52,16 @@ builds: id: step-awskms-init env: - CGO_ENABLED=0 - goos: - - linux - - darwin - - windows - goarch: - - amd64 - - arm - - arm64 - - 386 - goarm: - - 6 - - 7 - ignore: - - goos: windows - goarch: 386 - - goos: windows - goarm: 6 - - goos: windows - goarm: 7 + targets: + - darwin_amd64 + - darwin_arm64 + - freebsd_amd64 + - linux_386 + - linux_amd64 + - linux_arm64 + - linux_arm_6 + - linux_arm_7 + - windows_amd64 flags: - -trimpath main: ./cmd/step-awskms-init/main.go From da3c6af10fb85a8b813a5617f937806ba45bee2b Mon Sep 17 00:00:00 2001 From: max furman Date: Wed, 20 Oct 2021 14:31:33 -0700 Subject: [PATCH 181/195] changelog update --- CHANGELOG.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4f031a5a..ca792f55 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). -## [Unreleased - 0.17.6] - DATE +## [Unreleased - 0.17.7] - DATE ### Added ### Changed ### Deprecated @@ -12,6 +12,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Fixed ### Security +## [0.17.6] - 2021-10-20 +### Notes +- 0.17.5 failed in CI/CD + ## [0.17.5] - 2021-10-20 ### Added - Support for Azure Key Vault as a KMS. From 66a8158f26d86c36d23fbd2d73b737b688bbbb9d Mon Sep 17 00:00:00 2001 From: Carl Tashian Date: Wed, 20 Oct 2021 15:53:04 -0700 Subject: [PATCH 182/195] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bfc056b4..65116b38 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ To get up and running quickly, or as an alternative to running your own `step-ca --- -**Questions? Find us in [Discussions](https://github.com/smallstep/certificates/discussions) or [Join our Discord](https://bit.ly/step-discord).** +**Questions? Find us in [Discussions](https://github.com/smallstep/certificates/discussions) or [Join our Discord](https://u.step.sm/discord).** [Website](https://smallstep.com/certificates) | [Documentation](https://smallstep.com/docs) | From ead394fba7de7d1aaaad18402aad89780ce3b59a Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Wed, 20 Oct 2021 18:09:50 -0700 Subject: [PATCH 183/195] Add strategy to retry the sign operation if the key is not yet ready --- kms/azurekms/signer.go | 36 +++++++-- kms/azurekms/signer_test.go | 141 ++++++++++++++++++++++++++++++++++++ 2 files changed, 170 insertions(+), 7 deletions(-) diff --git a/kms/azurekms/signer.go b/kms/azurekms/signer.go index e3aca5fe..2fb5951a 100644 --- a/kms/azurekms/signer.go +++ b/kms/azurekms/signer.go @@ -7,8 +7,10 @@ import ( "encoding/base64" "io" "math/big" + "time" "github.com/Azure/azure-sdk-for-go/services/keyvault/v7.1/keyvault" + "github.com/Azure/go-autorest/autorest/azure" "github.com/pkg/errors" "golang.org/x/crypto/cryptobyte" "golang.org/x/crypto/cryptobyte/asn1" @@ -69,15 +71,10 @@ func (s *Signer) Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts) ([] return nil, err } - ctx, cancel := defaultContext() - defer cancel() - b64 := base64.RawURLEncoding.EncodeToString(digest) - resp, err := s.client.Sign(ctx, s.vaultBaseURL, s.name, s.version, keyvault.KeySignParameters{ - Algorithm: alg, - Value: &b64, - }) + // Sign with retry if the key is not ready + resp, err := s.signWithRetry(alg, b64, 3) if err != nil { return nil, errors.Wrap(err, "keyVault Sign failed") } @@ -111,6 +108,31 @@ func (s *Signer) Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts) ([] return b.Bytes() } +func (s *Signer) signWithRetry(alg keyvault.JSONWebKeySignatureAlgorithm, b64 string, retryAttemps int) (keyvault.KeyOperationResult, error) { +retry: + ctx, cancel := defaultContext() + defer cancel() + + resp, err := s.client.Sign(ctx, s.vaultBaseURL, s.name, s.version, keyvault.KeySignParameters{ + Algorithm: alg, + Value: &b64, + }) + if err != nil && retryAttemps > 0 { + var requestError *azure.RequestError + if errors.As(err, &requestError) { + if se := requestError.ServiceError; se != nil && se.InnerError != nil { + code, ok := se.InnerError["code"].(string) + if ok && code == "KeyNotYetValid" { + time.Sleep(time.Second / time.Duration(retryAttemps)) + retryAttemps-- + goto retry + } + } + } + } + return resp, err +} + func getSigningAlgorithm(key crypto.PublicKey, opts crypto.SignerOpts) (keyvault.JSONWebKeySignatureAlgorithm, error) { switch key.(type) { case *rsa.PublicKey: diff --git a/kms/azurekms/signer_test.go b/kms/azurekms/signer_test.go index 381c3577..bd072b25 100644 --- a/kms/azurekms/signer_test.go +++ b/kms/azurekms/signer_test.go @@ -11,6 +11,8 @@ import ( "testing" "github.com/Azure/azure-sdk-for-go/services/keyvault/v7.1/keyvault" + "github.com/Azure/go-autorest/autorest" + "github.com/Azure/go-autorest/autorest/azure" "github.com/golang/mock/gomock" "github.com/smallstep/certificates/kms/apiv1" "go.step.sm/crypto/keyutil" @@ -350,3 +352,142 @@ func TestSigner_Sign(t *testing.T) { }) } } + +func TestSigner_Sign_signWithRetry(t *testing.T) { + sign := func(kty, crv string, bits int, opts crypto.SignerOpts) (crypto.PublicKey, []byte, string, []byte) { + key, err := keyutil.GenerateSigner(kty, crv, bits) + if err != nil { + t.Fatal(err) + } + h := opts.HashFunc().New() + h.Write([]byte("random-data")) + sum := h.Sum(nil) + + var sig, resultSig []byte + if priv, ok := key.(*ecdsa.PrivateKey); ok { + r, s, err := ecdsa.Sign(rand.Reader, priv, sum) + if err != nil { + t.Fatal(err) + } + curveBits := priv.Params().BitSize + keyBytes := curveBits / 8 + if curveBits%8 > 0 { + keyBytes++ + } + rBytes := r.Bytes() + rBytesPadded := make([]byte, keyBytes) + copy(rBytesPadded[keyBytes-len(rBytes):], rBytes) + + sBytes := s.Bytes() + sBytesPadded := make([]byte, keyBytes) + copy(sBytesPadded[keyBytes-len(sBytes):], sBytes) + // nolint:gocritic + resultSig = append(rBytesPadded, sBytesPadded...) + + var b cryptobyte.Builder + b.AddASN1(asn1.SEQUENCE, func(b *cryptobyte.Builder) { + b.AddASN1BigInt(r) + b.AddASN1BigInt(s) + }) + sig, err = b.Bytes() + if err != nil { + t.Fatal(err) + } + } else { + sig, err = key.Sign(rand.Reader, sum, opts) + if err != nil { + t.Fatal(err) + } + resultSig = sig + } + + return key.Public(), h.Sum(nil), base64.RawURLEncoding.EncodeToString(resultSig), sig + } + + p256, p256Digest, p256ResultSig, p256Sig := sign("EC", "P-256", 0, crypto.SHA256) + okResult := keyvault.KeyOperationResult{ + Result: &p256ResultSig, + } + failResult := keyvault.KeyOperationResult{} + retryError := autorest.DetailedError{ + Original: &azure.RequestError{ + ServiceError: &azure.ServiceError{ + InnerError: map[string]interface{}{ + "code": "KeyNotYetValid", + }, + }, + }, + } + + client := mockClient(t) + expects := []struct { + name string + keyVersion string + alg keyvault.JSONWebKeySignatureAlgorithm + digest []byte + result keyvault.KeyOperationResult + err error + }{ + {"ok 1", "", keyvault.ES256, p256Digest, failResult, retryError}, + {"ok 2", "", keyvault.ES256, p256Digest, failResult, retryError}, + {"ok 3", "", keyvault.ES256, p256Digest, failResult, retryError}, + {"ok 4", "", keyvault.ES256, p256Digest, okResult, nil}, + {"fail", "fail-version", keyvault.ES256, p256Digest, failResult, retryError}, + {"fail", "fail-version", keyvault.ES256, p256Digest, failResult, retryError}, + {"fail", "fail-version", keyvault.ES256, p256Digest, failResult, retryError}, + {"fail", "fail-version", keyvault.ES256, p256Digest, failResult, retryError}, + } + for _, e := range expects { + value := base64.RawURLEncoding.EncodeToString(e.digest) + client.EXPECT().Sign(gomock.Any(), "https://my-vault.vault.azure.net/", "my-key", e.keyVersion, keyvault.KeySignParameters{ + Algorithm: e.alg, + Value: &value, + }).Return(e.result, e.err) + } + + type fields struct { + client KeyVaultClient + vaultBaseURL string + name string + version string + publicKey crypto.PublicKey + } + type args struct { + rand io.Reader + digest []byte + opts crypto.SignerOpts + } + tests := []struct { + name string + fields fields + args args + want []byte + wantErr bool + }{ + {"ok", fields{client, "https://my-vault.vault.azure.net/", "my-key", "", p256}, args{ + rand.Reader, p256Digest, crypto.SHA256, + }, p256Sig, false}, + {"fail", fields{client, "https://my-vault.vault.azure.net/", "my-key", "fail-version", p256}, args{ + rand.Reader, p256Digest, crypto.SHA256, + }, nil, true}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + s := &Signer{ + client: tt.fields.client, + vaultBaseURL: tt.fields.vaultBaseURL, + name: tt.fields.name, + version: tt.fields.version, + publicKey: tt.fields.publicKey, + } + got, err := s.Sign(tt.args.rand, tt.args.digest, tt.args.opts) + if (err != nil) != tt.wantErr { + t.Errorf("Signer.Sign() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("Signer.Sign() = %v, want %v", got, tt.want) + } + }) + } +} From bef50bd7d981908ac62944e4ce9824d1f90d059e Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Tue, 26 Oct 2021 17:57:59 -0700 Subject: [PATCH 184/195] Fix typo in variable name. --- kms/azurekms/signer.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/kms/azurekms/signer.go b/kms/azurekms/signer.go index 2fb5951a..b0349108 100644 --- a/kms/azurekms/signer.go +++ b/kms/azurekms/signer.go @@ -108,7 +108,7 @@ func (s *Signer) Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts) ([] return b.Bytes() } -func (s *Signer) signWithRetry(alg keyvault.JSONWebKeySignatureAlgorithm, b64 string, retryAttemps int) (keyvault.KeyOperationResult, error) { +func (s *Signer) signWithRetry(alg keyvault.JSONWebKeySignatureAlgorithm, b64 string, retryAttempts int) (keyvault.KeyOperationResult, error) { retry: ctx, cancel := defaultContext() defer cancel() @@ -117,14 +117,14 @@ retry: Algorithm: alg, Value: &b64, }) - if err != nil && retryAttemps > 0 { + if err != nil && retryAttempts > 0 { var requestError *azure.RequestError if errors.As(err, &requestError) { if se := requestError.ServiceError; se != nil && se.InnerError != nil { code, ok := se.InnerError["code"].(string) if ok && code == "KeyNotYetValid" { - time.Sleep(time.Second / time.Duration(retryAttemps)) - retryAttemps-- + time.Sleep(time.Second / time.Duration(retryAttempts)) + retryAttempts-- goto retry } } From 0927e0d22a90d2e52c912f84d63d2ef6777ada36 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Wed, 27 Oct 2021 11:48:29 -0700 Subject: [PATCH 185/195] Upgrade go.step.sm/crypto dependency The new version removes "env" and "expandenv" sprig functions. --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 791e0927..04ff3bca 100644 --- a/go.mod +++ b/go.mod @@ -33,7 +33,7 @@ require ( github.com/urfave/cli v1.22.4 go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352 go.step.sm/cli-utils v0.6.0 - go.step.sm/crypto v0.11.0 + go.step.sm/crypto v0.13.0 go.step.sm/linkedca v0.7.0 golang.org/x/crypto v0.0.0-20210915214749-c084706c2272 golang.org/x/net v0.0.0-20210913180222-943fd674d43e diff --git a/go.sum b/go.sum index c0855569..ece817f0 100644 --- a/go.sum +++ b/go.sum @@ -569,8 +569,8 @@ go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqe go.step.sm/cli-utils v0.6.0 h1:sH4FxBcjmbxyilKXheSyJuKF/QjpojpiW90ERwUWOgQ= go.step.sm/cli-utils v0.6.0/go.mod h1:jklBMavFl2PbmGlyxgax08ZnB0uWpadjuOlSKKXz+0U= go.step.sm/crypto v0.9.0/go.mod h1:+CYG05Mek1YDqi5WK0ERc6cOpKly2i/a5aZmU1sfGj0= -go.step.sm/crypto v0.11.0 h1:VDpeVgEmqme/FK2w5QINxkOQ1FWOm/Wi2TwQXiacKr8= -go.step.sm/crypto v0.11.0/go.mod h1:5YzQ85BujYBu6NH18jw7nFjwuRnDch35nLzH0ES5sKg= +go.step.sm/crypto v0.13.0 h1:mQuP9Uu2FNmqCJNO0OTbvolnYXzONy4wdUBtUVcP1s8= +go.step.sm/crypto v0.13.0/go.mod h1:5YzQ85BujYBu6NH18jw7nFjwuRnDch35nLzH0ES5sKg= go.step.sm/linkedca v0.7.0 h1:ydYigs0CgLFkPGjOO4KJcAcAWbuPP8ECF1IsyHdftYc= go.step.sm/linkedca v0.7.0/go.mod h1:5uTRjozEGSPAZal9xJqlaD38cvJcLe3o1VAFVjqcORo= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= From 0f63d43a91eaba3292d942760ce6b87998d2b3c1 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Wed, 27 Oct 2021 11:50:55 -0700 Subject: [PATCH 186/195] Remove sprig "env" and "expandenv" functions. --- pki/helm.go | 8 +++++++- templates/templates.go | 11 ++++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/pki/helm.go b/pki/helm.go index 817c1bf4..852e5aa4 100644 --- a/pki/helm.go +++ b/pki/helm.go @@ -21,8 +21,14 @@ type helmVariables struct { Provisioners []provisioner.Interface } +// WriteHelmTemplate a helm template to configure the +// smallstep/step-certificates helm chart. func (p *PKI) WriteHelmTemplate(w io.Writer) error { - tmpl, err := template.New("helm").Funcs(sprig.TxtFuncMap()).Parse(helmTemplate) + funcs := sprig.TxtFuncMap() + delete(funcs, "env") + delete(funcs, "expandenv") + + tmpl, err := template.New("helm").Funcs(funcs).Parse(helmTemplate) if err != nil { return errors.Wrap(err, "error writing helm template") } diff --git a/templates/templates.go b/templates/templates.go index 16e891d9..8f10d8a4 100644 --- a/templates/templates.go +++ b/templates/templates.go @@ -183,7 +183,7 @@ func (t *Template) Load() error { // the template fails. func (t *Template) LoadBytes(b []byte) error { t.backfill(b) - tmpl, err := template.New(t.Name).Funcs(sprig.TxtFuncMap()).Parse(string(b)) + tmpl, err := template.New(t.Name).Funcs(getFuncMap()).Parse(string(b)) if err != nil { return errors.Wrapf(err, "error parsing template %s", t.Name) } @@ -270,3 +270,12 @@ func mkdir(path string, perm os.FileMode) error { } return nil } + +// getFuncMap returns sprig.TxtFuncMap but removing the "env" and "expandenv" +// functions to avoid any leak of information. +func getFuncMap() template.FuncMap { + m := sprig.TxtFuncMap() + delete(m, "env") + delete(m, "expandenv") + return m +} From 9958e0645f7edacadd018a2c2cc7a983794ca2ab Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Wed, 27 Oct 2021 12:38:16 -0700 Subject: [PATCH 187/195] Replace promptui with apache-compatible fork. Promptui depends on github.com/juju/ansiterm that is licensed under LGPL. The fork replaces ansiterm.TabWriter with the one in the standard library. --- go.mod | 6 +++++- go.sum | 12 ++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index 04ff3bca..48299d6a 100644 --- a/go.mod +++ b/go.mod @@ -32,7 +32,7 @@ require ( github.com/smallstep/nosql v0.3.8 github.com/urfave/cli v1.22.4 go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352 - go.step.sm/cli-utils v0.6.0 + go.step.sm/cli-utils v0.6.1 go.step.sm/crypto v0.13.0 go.step.sm/linkedca v0.7.0 golang.org/x/crypto v0.0.0-20210915214749-c084706c2272 @@ -44,6 +44,10 @@ require ( gopkg.in/square/go-jose.v2 v2.6.0 ) +// avoid license conflict from juju/ansiterm until https://github.com/manifoldco/promptui/pull/181 +// is merged or other dependency in path currently in violation fixes compliance +replace github.com/manifoldco/promptui => github.com/nguyer/promptui v0.8.1-0.20210517132806-70ccd4709797 + // replace github.com/smallstep/nosql => ../nosql // replace go.step.sm/crypto => ../crypto // replace go.step.sm/cli-utils => ../cli-utils diff --git a/go.sum b/go.sum index ece817f0..252832ea 100644 --- a/go.sum +++ b/go.sum @@ -357,8 +357,6 @@ github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/u github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= -github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a h1:FaWFmfWdAUKbSCtOU2QjDaorUexogfaMgbipgYATUMU= -github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a/go.mod h1:UJSiEoRfvx3hP73CvoARgeLjaIOjybY9vj8PUPPFGeU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= @@ -377,12 +375,8 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= github.com/lunixbochs/vtclean v0.0.0-20180621232353-2d01aacdc34a/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= -github.com/lunixbochs/vtclean v1.0.0 h1:xu2sLAri4lGiovBDQKxl5mrXyESr3gUr5m5SM5+LVb8= -github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/manifoldco/promptui v0.8.0 h1:R95mMF+McvXZQ7j1g8ucVZE1gLP3Sv6j9vlF9kyRqQo= -github.com/manifoldco/promptui v0.8.0/go.mod h1:n4zTdgP0vr0S3w7/O/g98U+e0gwLScEXGwov2nIKuGQ= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= @@ -432,6 +426,8 @@ github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxzi github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/newrelic/go-agent v2.15.0+incompatible h1:IB0Fy+dClpBq9aEoIrLyQXzU34JyI1xVTanPLB/+jvU= github.com/newrelic/go-agent v2.15.0+incompatible/go.mod h1:a8Fv1b/fYhFSReoTU6HDkTYIMZeSVNffmoS726Y0LzQ= +github.com/nguyer/promptui v0.8.1-0.20210517132806-70ccd4709797 h1:unCiBzwNjcuVbP3bgM76z0ORyIuI4sspop1qhkQJ044= +github.com/nguyer/promptui v0.8.1-0.20210517132806-70ccd4709797/go.mod h1:CBMXL3a2sC3Q8TjpLcQt8w/3aQ23VSy6r7UFeCG6phA= github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= @@ -566,8 +562,8 @@ go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.step.sm/cli-utils v0.6.0 h1:sH4FxBcjmbxyilKXheSyJuKF/QjpojpiW90ERwUWOgQ= -go.step.sm/cli-utils v0.6.0/go.mod h1:jklBMavFl2PbmGlyxgax08ZnB0uWpadjuOlSKKXz+0U= +go.step.sm/cli-utils v0.6.1 h1:v31ctEh/BFPGU067fF9Y8u2EIg6LRldUbN2dc/+u/V8= +go.step.sm/cli-utils v0.6.1/go.mod h1:stgyXHHHi9KwcR86sgzDdFC6e/tAmpF4NbqwSK7q/GM= go.step.sm/crypto v0.9.0/go.mod h1:+CYG05Mek1YDqi5WK0ERc6cOpKly2i/a5aZmU1sfGj0= go.step.sm/crypto v0.13.0 h1:mQuP9Uu2FNmqCJNO0OTbvolnYXzONy4wdUBtUVcP1s8= go.step.sm/crypto v0.13.0/go.mod h1:5YzQ85BujYBu6NH18jw7nFjwuRnDch35nLzH0ES5sKg= From cb4a2a5f9a0d51a950a0c67a34a3b7d34f646fa9 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Wed, 27 Oct 2021 16:11:47 -0700 Subject: [PATCH 188/195] Use the same method to return the templating functions. --- pki/helm.go | 8 ++------ templates/templates.go | 6 +++--- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/pki/helm.go b/pki/helm.go index 852e5aa4..0a2f7f02 100644 --- a/pki/helm.go +++ b/pki/helm.go @@ -4,11 +4,11 @@ import ( "io" "text/template" - "github.com/Masterminds/sprig/v3" "github.com/pkg/errors" "github.com/smallstep/certificates/authority" authconfig "github.com/smallstep/certificates/authority/config" "github.com/smallstep/certificates/authority/provisioner" + "github.com/smallstep/certificates/templates" "go.step.sm/linkedca" ) @@ -24,11 +24,7 @@ type helmVariables struct { // WriteHelmTemplate a helm template to configure the // smallstep/step-certificates helm chart. func (p *PKI) WriteHelmTemplate(w io.Writer) error { - funcs := sprig.TxtFuncMap() - delete(funcs, "env") - delete(funcs, "expandenv") - - tmpl, err := template.New("helm").Funcs(funcs).Parse(helmTemplate) + tmpl, err := template.New("helm").Funcs(templates.StepFuncMap()).Parse(helmTemplate) if err != nil { return errors.Wrap(err, "error writing helm template") } diff --git a/templates/templates.go b/templates/templates.go index 8f10d8a4..09416b68 100644 --- a/templates/templates.go +++ b/templates/templates.go @@ -183,7 +183,7 @@ func (t *Template) Load() error { // the template fails. func (t *Template) LoadBytes(b []byte) error { t.backfill(b) - tmpl, err := template.New(t.Name).Funcs(getFuncMap()).Parse(string(b)) + tmpl, err := template.New(t.Name).Funcs(StepFuncMap()).Parse(string(b)) if err != nil { return errors.Wrapf(err, "error parsing template %s", t.Name) } @@ -271,9 +271,9 @@ func mkdir(path string, perm os.FileMode) error { return nil } -// getFuncMap returns sprig.TxtFuncMap but removing the "env" and "expandenv" +// StepFuncMap returns sprig.TxtFuncMap but removing the "env" and "expandenv" // functions to avoid any leak of information. -func getFuncMap() template.FuncMap { +func StepFuncMap() template.FuncMap { m := sprig.TxtFuncMap() delete(m, "env") delete(m, "expandenv") From 6be383da34046384a4a5fbd029f238bf119ca21b Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Thu, 28 Oct 2021 18:04:11 -0700 Subject: [PATCH 189/195] Refactor pkcs#11 extractable certs and keys. --- kms/pkcs11/other_test.go | 40 +++++++++++++++++++++++-- kms/pkcs11/pkcs11.go | 65 +++++++++++++++++++++++----------------- 2 files changed, 75 insertions(+), 30 deletions(-) diff --git a/kms/pkcs11/other_test.go b/kms/pkcs11/other_test.go index 835587f7..51732853 100644 --- a/kms/pkcs11/other_test.go +++ b/kms/pkcs11/other_test.go @@ -1,3 +1,4 @@ +//go:build cgo && !softhsm2 && !yubihsm2 && !opensc // +build cgo,!softhsm2,!yubihsm2,!opensc package pkcs11 @@ -79,10 +80,23 @@ func (s *stubPKCS11) FindCertificate(id, label []byte, serial *big.Int) (*x509.C } +func (s *stubPKCS11) ImportCertificateWithAttributes(template crypto11.AttributeSet, cert *x509.Certificate) error { + var id, label []byte + if v := template[crypto11.CkaId]; v != nil { + id = v.Value + } + if v := template[crypto11.CkaLabel]; v != nil { + label = v.Value + } + return s.ImportCertificateWithLabel(id, label, cert) +} + func (s *stubPKCS11) ImportCertificateWithLabel(id, label []byte, cert *x509.Certificate) error { switch { - case id == nil && label == nil: - return errors.New("id and label cannot both be nil") + case id == nil: + return errors.New("id cannot both be nil") + case label == nil: + return errors.New("label cannot both be nil") case cert == nil: return errors.New("certificate cannot be nil") } @@ -110,6 +124,17 @@ func (s *stubPKCS11) DeleteCertificate(id, label []byte, serial *big.Int) error return nil } +func (s *stubPKCS11) GenerateRSAKeyPairWithAttributes(public, private crypto11.AttributeSet, bits int) (crypto11.SignerDecrypter, error) { + var id, label []byte + if v := public[crypto11.CkaId]; v != nil { + id = v.Value + } + if v := public[crypto11.CkaLabel]; v != nil { + label = v.Value + } + return s.GenerateRSAKeyPairWithLabel(id, label, bits) +} + func (s *stubPKCS11) GenerateRSAKeyPairWithLabel(id, label []byte, bits int) (crypto11.SignerDecrypter, error) { if id == nil && label == nil { return nil, errors.New("id and label cannot both be nil") @@ -130,6 +155,17 @@ func (s *stubPKCS11) GenerateRSAKeyPairWithLabel(id, label []byte, bits int) (cr return k, nil } +func (s *stubPKCS11) GenerateECDSAKeyPairWithAttributes(public, private crypto11.AttributeSet, curve elliptic.Curve) (crypto11.Signer, error) { + var id, label []byte + if v := public[crypto11.CkaId]; v != nil { + id = v.Value + } + if v := public[crypto11.CkaLabel]; v != nil { + label = v.Value + } + return s.GenerateECDSAKeyPairWithLabel(id, label, curve) +} + func (s *stubPKCS11) GenerateECDSAKeyPairWithLabel(id, label []byte, curve elliptic.Curve) (crypto11.Signer, error) { if id == nil && label == nil { return nil, errors.New("id and label cannot both be nil") diff --git a/kms/pkcs11/pkcs11.go b/kms/pkcs11/pkcs11.go index 98b08c58..7a418e19 100644 --- a/kms/pkcs11/pkcs11.go +++ b/kms/pkcs11/pkcs11.go @@ -1,3 +1,4 @@ +//go:build cgo // +build cgo package pkcs11 @@ -32,11 +33,9 @@ const DefaultRSASize = 3072 type P11 interface { FindKeyPair(id, label []byte) (crypto11.Signer, error) FindCertificate(id, label []byte, serial *big.Int) (*x509.Certificate, error) - ImportCertificateWithLabel(id, label []byte, cert *x509.Certificate) error ImportCertificateWithAttributes(template crypto11.AttributeSet, certificate *x509.Certificate) error DeleteCertificate(id, label []byte, serial *big.Int) error - GenerateRSAKeyPairWithLabel(id, label []byte, bits int) (crypto11.SignerDecrypter, error) - GenerateECDSAKeyPairWithLabel(id, label []byte, curve elliptic.Curve) (crypto11.Signer, error) + GenerateRSAKeyPairWithAttributes(public, private crypto11.AttributeSet, bits int) (crypto11.SignerDecrypter, error) GenerateECDSAKeyPairWithAttributes(public, private crypto11.AttributeSet, curve elliptic.Curve) (crypto11.Signer, error) Close() error } @@ -188,6 +187,12 @@ func (k *PKCS11) StoreCertificate(req *apiv1.StoreCertificateRequest) error { return errors.Wrap(err, "storeCertificate failed") } + // Enforce the use of both id and labels. This is not strictly necessary in + // PKCS #11, but it's a good practice. + if len(id) == 0 || len(object) == 0 { + return errors.Errorf("key with uri %s is not valid, id and object are required", req.Name) + } + cert, err := k.p11.FindCertificate(id, object, nil) if err != nil { return errors.Wrap(err, "storeCertificate failed") @@ -198,31 +203,23 @@ func (k *PKCS11) StoreCertificate(req *apiv1.StoreCertificateRequest) error { }, "storeCertificate failed") } - if err := ImportCertificateWithLabel(k.p11, id, object, req.Certificate, req.Extractable); err != nil { + // Import certificate with the necessary attributes. + template, err := crypto11.NewAttributeSetWithIDAndLabel(id, object) + if err != nil { + return errors.Wrap(err, "storeCertificate failed") + } + if req.Extractable { + template.AddIfNotPresent([]*pkcs11.Attribute{ + pkcs11.NewAttribute(pkcs11.CKA_EXTRACTABLE, true), + }) + } + if err := k.p11.ImportCertificateWithAttributes(template, cert); err != nil { return errors.Wrap(err, "storeCertificate failed") } return nil } -func ImportCertificateWithLabel(ctx P11, id []byte, label []byte, certificate *x509.Certificate, extractable bool) error { - if id == nil { - return errors.New("id cannot be nil") - } - if label == nil { - return errors.New("label cannot be nil") - } - - template, err := crypto11.NewAttributeSetWithIDAndLabel(id, label) - if err != nil { - return err - } - template.AddIfNotPresent([]*pkcs11.Attribute{ - pkcs11.NewAttribute(pkcs11.CKA_EXTRACTABLE, extractable), - }) - return ctx.ImportCertificateWithAttributes(template, certificate) -} - // DeleteKey is a utility function to delete a key given an uri. func (k *PKCS11) DeleteKey(uri string) error { id, object, err := parseObject(uri) @@ -305,6 +302,18 @@ func generateKey(ctx P11, req *apiv1.CreateKeyRequest) (crypto11.Signer, error) return nil, errors.Errorf("key with uri %s is not valid, id and object are required", req.Name) } + // Create template for public and private keys + public, err := crypto11.NewAttributeSetWithIDAndLabel(id, object) + if err != nil { + return nil, err + } + private := public.Copy() + if req.Extractable { + private.AddIfNotPresent([]*pkcs11.Attribute{ + pkcs11.NewAttribute(pkcs11.CKA_EXTRACTABLE, true), + }) + } + bits := req.Bits if bits == 0 { bits = DefaultRSASize @@ -312,17 +321,17 @@ func generateKey(ctx P11, req *apiv1.CreateKeyRequest) (crypto11.Signer, error) switch req.SignatureAlgorithm { case apiv1.UnspecifiedSignAlgorithm: - return GenerateECDSAKeyPairWithLabel(ctx, id, object, elliptic.P256(), req.Extractable) + return ctx.GenerateECDSAKeyPairWithAttributes(public, private, elliptic.P256()) case apiv1.SHA256WithRSA, apiv1.SHA384WithRSA, apiv1.SHA512WithRSA: - return ctx.GenerateRSAKeyPairWithLabel(id, object, bits) + return ctx.GenerateRSAKeyPairWithAttributes(public, private, bits) case apiv1.SHA256WithRSAPSS, apiv1.SHA384WithRSAPSS, apiv1.SHA512WithRSAPSS: - return ctx.GenerateRSAKeyPairWithLabel(id, object, bits) + return ctx.GenerateRSAKeyPairWithAttributes(public, private, bits) case apiv1.ECDSAWithSHA256: - return GenerateECDSAKeyPairWithLabel(ctx, id, object, elliptic.P256(), req.Extractable) + return ctx.GenerateECDSAKeyPairWithAttributes(public, private, elliptic.P256()) case apiv1.ECDSAWithSHA384: - return GenerateECDSAKeyPairWithLabel(ctx, id, object, elliptic.P384(), req.Extractable) + return ctx.GenerateECDSAKeyPairWithAttributes(public, private, elliptic.P384()) case apiv1.ECDSAWithSHA512: - return GenerateECDSAKeyPairWithLabel(ctx, id, object, elliptic.P521(), req.Extractable) + return ctx.GenerateECDSAKeyPairWithAttributes(public, private, elliptic.P521()) case apiv1.PureEd25519: return nil, fmt.Errorf("signature algorithm %s is not supported", req.SignatureAlgorithm) default: From 886b9a1d8db24970c5b0ca0a386229579785d4af Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Thu, 28 Oct 2021 18:16:16 -0700 Subject: [PATCH 190/195] Store the certificate passed. --- kms/pkcs11/pkcs11.go | 2 +- kms/pkcs11/setup_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/kms/pkcs11/pkcs11.go b/kms/pkcs11/pkcs11.go index a0c8cea6..cec05d33 100644 --- a/kms/pkcs11/pkcs11.go +++ b/kms/pkcs11/pkcs11.go @@ -209,7 +209,7 @@ func (k *PKCS11) StoreCertificate(req *apiv1.StoreCertificateRequest) error { if req.Extractable { template.Set(crypto11.CkaExtractable, true) } - if err := k.p11.ImportCertificateWithAttributes(template, cert); err != nil { + if err := k.p11.ImportCertificateWithAttributes(template, req.Certificate); err != nil { return errors.Wrap(err, "storeCertificate failed") } diff --git a/kms/pkcs11/setup_test.go b/kms/pkcs11/setup_test.go index 52dc5207..8aba2aaa 100644 --- a/kms/pkcs11/setup_test.go +++ b/kms/pkcs11/setup_test.go @@ -105,7 +105,7 @@ func setup(t TBTesting, k *PKCS11) { }); err != nil && !errors.Is(errors.Cause(err), apiv1.ErrAlreadyExists{ Message: c.Name + " already exists", }) { - t.Errorf("PKCS1.StoreCertificate() error = %+v", err) + t.Errorf("PKCS1.StoreCertificate() error = %v", err) continue } testCerts[i].Certificates = append(testCerts[i].Certificates, cert) From fa11e82b67378f8044d4a235e5fbe85934983e1f Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Thu, 28 Oct 2021 19:45:19 -0700 Subject: [PATCH 191/195] Add tests with extractable property. --- kms/pkcs11/pkcs11_test.go | 29 +++++++++++++++++++++++++++-- kms/pkcs11/setup_test.go | 1 + 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/kms/pkcs11/pkcs11_test.go b/kms/pkcs11/pkcs11_test.go index 6df9b92a..409cfb3f 100644 --- a/kms/pkcs11/pkcs11_test.go +++ b/kms/pkcs11/pkcs11_test.go @@ -208,6 +208,16 @@ func TestPKCS11_CreateKey(t *testing.T) { SigningKey: testObject, }, }, false}, + {"default extractable", args{&apiv1.CreateKeyRequest{ + Name: testObject, + Extractable: true, + }}, &apiv1.CreateKeyResponse{ + Name: testObject, + PublicKey: &ecdsa.PublicKey{}, + CreateSignerRequest: apiv1.CreateSignerRequest{ + SigningKey: testObject, + }, + }, false}, {"RSA SHA256WithRSA", args{&apiv1.CreateKeyRequest{ Name: testObject, SignatureAlgorithm: apiv1.SHA256WithRSA, @@ -563,6 +573,7 @@ func TestPKCS11_StoreCertificate(t *testing.T) { // Make sure to delete the created certificate t.Cleanup(func() { k.DeleteCertificate(testObject) + k.DeleteCertificate(testObjectAlt) }) type args struct { @@ -577,6 +588,11 @@ func TestPKCS11_StoreCertificate(t *testing.T) { Name: testObject, Certificate: cert, }}, false}, + {"ok extractable", args{&apiv1.StoreCertificateRequest{ + Name: testObjectAlt, + Certificate: cert, + Extractable: true, + }}, false}, {"fail already exists", args{&apiv1.StoreCertificateRequest{ Name: testObject, Certificate: cert, @@ -593,13 +609,22 @@ func TestPKCS11_StoreCertificate(t *testing.T) { Name: "http:id=7770;object=create-cert", Certificate: cert, }}, true}, - {"fail ImportCertificateWithLabel", args{&apiv1.StoreCertificateRequest{ - Name: "pkcs11:foo=bar", + {"fail missing id", args{&apiv1.StoreCertificateRequest{ + Name: "pkcs11:object=create-cert", + Certificate: cert, + }}, true}, + {"fail missing object", args{&apiv1.StoreCertificateRequest{ + Name: "pkcs11:id=7770;object=", Certificate: cert, }}, true}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + if tt.args.req.Extractable { + if testModule == "SoftHSM2" { + t.Skip("Extractable certificates are not supported on SoftHSM2") + } + } if err := k.StoreCertificate(tt.args.req); (err != nil) != tt.wantErr { t.Errorf("PKCS11.StoreCertificate() error = %v, wantErr %v", err, tt.wantErr) } diff --git a/kms/pkcs11/setup_test.go b/kms/pkcs11/setup_test.go index 8aba2aaa..902d89ac 100644 --- a/kms/pkcs11/setup_test.go +++ b/kms/pkcs11/setup_test.go @@ -18,6 +18,7 @@ import ( var ( testModule = "" testObject = "pkcs11:id=7370;object=test-name" + testObjectAlt = "pkcs11:id=7377;object=alt-test-name" testObjectByID = "pkcs11:id=7370" testObjectByLabel = "pkcs11:object=test-name" testKeys = []struct { From 614ee794896a46c89bebb5734f744fbc6729c0cc Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Fri, 29 Oct 2021 12:02:24 -0700 Subject: [PATCH 192/195] Remove extractable from StoreCertificate. --- cmd/step-pkcs11-init/main.go | 2 -- kms/apiv1/requests.go | 14 ++++++-------- kms/pkcs11/pkcs11.go | 12 ++---------- kms/pkcs11/pkcs11_test.go | 17 +++-------------- 4 files changed, 11 insertions(+), 34 deletions(-) diff --git a/cmd/step-pkcs11-init/main.go b/cmd/step-pkcs11-init/main.go index 0db1e4d9..df98aa8c 100644 --- a/cmd/step-pkcs11-init/main.go +++ b/cmd/step-pkcs11-init/main.go @@ -335,7 +335,6 @@ func createPKI(k kms.KeyManager, c Config) error { if err := cm.StoreCertificate(&apiv1.StoreCertificateRequest{ Name: c.RootObject, Certificate: root, - Extractable: c.Extractable, }); err != nil { return err } @@ -414,7 +413,6 @@ func createPKI(k kms.KeyManager, c Config) error { if err := cm.StoreCertificate(&apiv1.StoreCertificateRequest{ Name: c.CrtObject, Certificate: intermediate, - Extractable: c.Extractable, }); err != nil { return err } diff --git a/kms/apiv1/requests.go b/kms/apiv1/requests.go index 94d832f9..c2d1d49a 100644 --- a/kms/apiv1/requests.go +++ b/kms/apiv1/requests.go @@ -100,7 +100,7 @@ type GetPublicKeyRequest struct { type CreateKeyRequest struct { // Name represents the key name or label used to identify a key. // - // Used by: awskms, cloudkms, pkcs11, yubikey. + // Used by: awskms, cloudkms, azurekms, pkcs11, yubikey. Name string // SignatureAlgorithm represents the type of key to create. @@ -110,11 +110,13 @@ type CreateKeyRequest struct { Bits int // ProtectionLevel specifies how cryptographic operations are performed. - // Used by: cloudkms + // Used by: cloudkms, azurekms ProtectionLevel ProtectionLevel - // Whether the key may be exported from the HSM under a wrap key. - // Sets the CKA_EXTRACTABLE bit. + // Extractable defines if the new key may be exported from the HSM under a + // wrap key. On pkcs11 sets the CKA_EXTRACTABLE bit. + // + // Used by: pkcs11 Extractable bool } @@ -156,8 +158,4 @@ type LoadCertificateRequest struct { type StoreCertificateRequest struct { Name string Certificate *x509.Certificate - - // Whether the key may be exported from the HSM under a wrap key. - // Sets the CKA_EXTRACTABLE bit. - Extractable bool } diff --git a/kms/pkcs11/pkcs11.go b/kms/pkcs11/pkcs11.go index cec05d33..3e14debe 100644 --- a/kms/pkcs11/pkcs11.go +++ b/kms/pkcs11/pkcs11.go @@ -32,7 +32,7 @@ const DefaultRSASize = 3072 type P11 interface { FindKeyPair(id, label []byte) (crypto11.Signer, error) FindCertificate(id, label []byte, serial *big.Int) (*x509.Certificate, error) - ImportCertificateWithAttributes(template crypto11.AttributeSet, certificate *x509.Certificate) error + ImportCertificateWithLabel(id, label []byte, certificate *x509.Certificate) error DeleteCertificate(id, label []byte, serial *big.Int) error GenerateRSAKeyPairWithAttributes(public, private crypto11.AttributeSet, bits int) (crypto11.SignerDecrypter, error) GenerateECDSAKeyPairWithAttributes(public, private crypto11.AttributeSet, curve elliptic.Curve) (crypto11.Signer, error) @@ -201,15 +201,7 @@ func (k *PKCS11) StoreCertificate(req *apiv1.StoreCertificateRequest) error { }, "storeCertificate failed") } - // Import certificate with the necessary attributes. - template, err := crypto11.NewAttributeSetWithIDAndLabel(id, object) - if err != nil { - return errors.Wrap(err, "storeCertificate failed") - } - if req.Extractable { - template.Set(crypto11.CkaExtractable, true) - } - if err := k.p11.ImportCertificateWithAttributes(template, req.Certificate); err != nil { + if err := k.p11.ImportCertificateWithLabel(id, object, req.Certificate); err != nil { return errors.Wrap(err, "storeCertificate failed") } diff --git a/kms/pkcs11/pkcs11_test.go b/kms/pkcs11/pkcs11_test.go index 409cfb3f..dfb63753 100644 --- a/kms/pkcs11/pkcs11_test.go +++ b/kms/pkcs11/pkcs11_test.go @@ -209,13 +209,13 @@ func TestPKCS11_CreateKey(t *testing.T) { }, }, false}, {"default extractable", args{&apiv1.CreateKeyRequest{ - Name: testObject, + Name: testObjectAlt, Extractable: true, }}, &apiv1.CreateKeyResponse{ - Name: testObject, + Name: testObjectAlt, PublicKey: &ecdsa.PublicKey{}, CreateSignerRequest: apiv1.CreateSignerRequest{ - SigningKey: testObject, + SigningKey: testObjectAlt, }, }, false}, {"RSA SHA256WithRSA", args{&apiv1.CreateKeyRequest{ @@ -573,7 +573,6 @@ func TestPKCS11_StoreCertificate(t *testing.T) { // Make sure to delete the created certificate t.Cleanup(func() { k.DeleteCertificate(testObject) - k.DeleteCertificate(testObjectAlt) }) type args struct { @@ -588,11 +587,6 @@ func TestPKCS11_StoreCertificate(t *testing.T) { Name: testObject, Certificate: cert, }}, false}, - {"ok extractable", args{&apiv1.StoreCertificateRequest{ - Name: testObjectAlt, - Certificate: cert, - Extractable: true, - }}, false}, {"fail already exists", args{&apiv1.StoreCertificateRequest{ Name: testObject, Certificate: cert, @@ -620,11 +614,6 @@ func TestPKCS11_StoreCertificate(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if tt.args.req.Extractable { - if testModule == "SoftHSM2" { - t.Skip("Extractable certificates are not supported on SoftHSM2") - } - } if err := k.StoreCertificate(tt.args.req); (err != nil) != tt.wantErr { t.Errorf("PKCS11.StoreCertificate() error = %v, wantErr %v", err, tt.wantErr) } From 8366b7ddf197f741c783b1809afa7c2b76b8bd21 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Fri, 29 Oct 2021 14:45:10 -0700 Subject: [PATCH 193/195] Revert "Remove extractable from StoreCertificate." This reverts commit 614ee794896a46c89bebb5734f744fbc6729c0cc. --- cmd/step-pkcs11-init/main.go | 2 ++ kms/apiv1/requests.go | 14 ++++++++------ kms/pkcs11/pkcs11.go | 12 ++++++++++-- kms/pkcs11/pkcs11_test.go | 17 ++++++++++++++--- 4 files changed, 34 insertions(+), 11 deletions(-) diff --git a/cmd/step-pkcs11-init/main.go b/cmd/step-pkcs11-init/main.go index df98aa8c..0db1e4d9 100644 --- a/cmd/step-pkcs11-init/main.go +++ b/cmd/step-pkcs11-init/main.go @@ -335,6 +335,7 @@ func createPKI(k kms.KeyManager, c Config) error { if err := cm.StoreCertificate(&apiv1.StoreCertificateRequest{ Name: c.RootObject, Certificate: root, + Extractable: c.Extractable, }); err != nil { return err } @@ -413,6 +414,7 @@ func createPKI(k kms.KeyManager, c Config) error { if err := cm.StoreCertificate(&apiv1.StoreCertificateRequest{ Name: c.CrtObject, Certificate: intermediate, + Extractable: c.Extractable, }); err != nil { return err } diff --git a/kms/apiv1/requests.go b/kms/apiv1/requests.go index c2d1d49a..94d832f9 100644 --- a/kms/apiv1/requests.go +++ b/kms/apiv1/requests.go @@ -100,7 +100,7 @@ type GetPublicKeyRequest struct { type CreateKeyRequest struct { // Name represents the key name or label used to identify a key. // - // Used by: awskms, cloudkms, azurekms, pkcs11, yubikey. + // Used by: awskms, cloudkms, pkcs11, yubikey. Name string // SignatureAlgorithm represents the type of key to create. @@ -110,13 +110,11 @@ type CreateKeyRequest struct { Bits int // ProtectionLevel specifies how cryptographic operations are performed. - // Used by: cloudkms, azurekms + // Used by: cloudkms ProtectionLevel ProtectionLevel - // Extractable defines if the new key may be exported from the HSM under a - // wrap key. On pkcs11 sets the CKA_EXTRACTABLE bit. - // - // Used by: pkcs11 + // Whether the key may be exported from the HSM under a wrap key. + // Sets the CKA_EXTRACTABLE bit. Extractable bool } @@ -158,4 +156,8 @@ type LoadCertificateRequest struct { type StoreCertificateRequest struct { Name string Certificate *x509.Certificate + + // Whether the key may be exported from the HSM under a wrap key. + // Sets the CKA_EXTRACTABLE bit. + Extractable bool } diff --git a/kms/pkcs11/pkcs11.go b/kms/pkcs11/pkcs11.go index 3e14debe..cec05d33 100644 --- a/kms/pkcs11/pkcs11.go +++ b/kms/pkcs11/pkcs11.go @@ -32,7 +32,7 @@ const DefaultRSASize = 3072 type P11 interface { FindKeyPair(id, label []byte) (crypto11.Signer, error) FindCertificate(id, label []byte, serial *big.Int) (*x509.Certificate, error) - ImportCertificateWithLabel(id, label []byte, certificate *x509.Certificate) error + ImportCertificateWithAttributes(template crypto11.AttributeSet, certificate *x509.Certificate) error DeleteCertificate(id, label []byte, serial *big.Int) error GenerateRSAKeyPairWithAttributes(public, private crypto11.AttributeSet, bits int) (crypto11.SignerDecrypter, error) GenerateECDSAKeyPairWithAttributes(public, private crypto11.AttributeSet, curve elliptic.Curve) (crypto11.Signer, error) @@ -201,7 +201,15 @@ func (k *PKCS11) StoreCertificate(req *apiv1.StoreCertificateRequest) error { }, "storeCertificate failed") } - if err := k.p11.ImportCertificateWithLabel(id, object, req.Certificate); err != nil { + // Import certificate with the necessary attributes. + template, err := crypto11.NewAttributeSetWithIDAndLabel(id, object) + if err != nil { + return errors.Wrap(err, "storeCertificate failed") + } + if req.Extractable { + template.Set(crypto11.CkaExtractable, true) + } + if err := k.p11.ImportCertificateWithAttributes(template, req.Certificate); err != nil { return errors.Wrap(err, "storeCertificate failed") } diff --git a/kms/pkcs11/pkcs11_test.go b/kms/pkcs11/pkcs11_test.go index dfb63753..409cfb3f 100644 --- a/kms/pkcs11/pkcs11_test.go +++ b/kms/pkcs11/pkcs11_test.go @@ -209,13 +209,13 @@ func TestPKCS11_CreateKey(t *testing.T) { }, }, false}, {"default extractable", args{&apiv1.CreateKeyRequest{ - Name: testObjectAlt, + Name: testObject, Extractable: true, }}, &apiv1.CreateKeyResponse{ - Name: testObjectAlt, + Name: testObject, PublicKey: &ecdsa.PublicKey{}, CreateSignerRequest: apiv1.CreateSignerRequest{ - SigningKey: testObjectAlt, + SigningKey: testObject, }, }, false}, {"RSA SHA256WithRSA", args{&apiv1.CreateKeyRequest{ @@ -573,6 +573,7 @@ func TestPKCS11_StoreCertificate(t *testing.T) { // Make sure to delete the created certificate t.Cleanup(func() { k.DeleteCertificate(testObject) + k.DeleteCertificate(testObjectAlt) }) type args struct { @@ -587,6 +588,11 @@ func TestPKCS11_StoreCertificate(t *testing.T) { Name: testObject, Certificate: cert, }}, false}, + {"ok extractable", args{&apiv1.StoreCertificateRequest{ + Name: testObjectAlt, + Certificate: cert, + Extractable: true, + }}, false}, {"fail already exists", args{&apiv1.StoreCertificateRequest{ Name: testObject, Certificate: cert, @@ -614,6 +620,11 @@ func TestPKCS11_StoreCertificate(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + if tt.args.req.Extractable { + if testModule == "SoftHSM2" { + t.Skip("Extractable certificates are not supported on SoftHSM2") + } + } if err := k.StoreCertificate(tt.args.req); (err != nil) != tt.wantErr { t.Errorf("PKCS11.StoreCertificate() error = %v, wantErr %v", err, tt.wantErr) } From 7ec1424cb60e9afb5461a76638d28186a8a07a4e Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Fri, 29 Oct 2021 14:47:57 -0700 Subject: [PATCH 194/195] Fix help. --- kms/apiv1/requests.go | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/kms/apiv1/requests.go b/kms/apiv1/requests.go index 94d832f9..762d9dd8 100644 --- a/kms/apiv1/requests.go +++ b/kms/apiv1/requests.go @@ -100,7 +100,7 @@ type GetPublicKeyRequest struct { type CreateKeyRequest struct { // Name represents the key name or label used to identify a key. // - // Used by: awskms, cloudkms, pkcs11, yubikey. + // Used by: awskms, cloudkms, azurekms, pkcs11, yubikey. Name string // SignatureAlgorithm represents the type of key to create. @@ -110,11 +110,13 @@ type CreateKeyRequest struct { Bits int // ProtectionLevel specifies how cryptographic operations are performed. - // Used by: cloudkms + // Used by: cloudkms, azurekms. ProtectionLevel ProtectionLevel - // Whether the key may be exported from the HSM under a wrap key. - // Sets the CKA_EXTRACTABLE bit. + // Extractable defines if the new key may be exported from the HSM under a + // wrap key. On pkcs11 sets the CKA_EXTRACTABLE bit. + // + // Used by: pkcs11 Extractable bool } @@ -157,7 +159,9 @@ type StoreCertificateRequest struct { Name string Certificate *x509.Certificate - // Whether the key may be exported from the HSM under a wrap key. - // Sets the CKA_EXTRACTABLE bit. + // Extractable defines if the new certificate may be exported from the HSM + // under a wrap key. On pkcs11 sets the CKA_EXTRACTABLE bit. + // + // Used by: pkcs11 Extractable bool } From 91fb57e8aac9ce8057eb5894180653e64ae098e7 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Fri, 29 Oct 2021 15:09:53 -0700 Subject: [PATCH 195/195] Add entry to changelog. --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ca792f55..a902e001 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased - 0.17.7] - DATE ### Added +- Support for generate extractable keys and certificates on a pkcs#11 module. ### Changed ### Deprecated ### Removed