From 9a9f4a9d6e61bb6c72907b14fb3a7455d8fa4706 Mon Sep 17 00:00:00 2001 From: Christopher Swenson Date: Mon, 2 May 2022 13:49:56 -0700 Subject: [PATCH] Add option to allow all of IAT, NBF, and EXP to be missing (#50) Add option to allow all of IAT, NBF, and EXP to be missing This is necessary for Kubernetes 1.20 auth tokens, which don't include any of iat/exp/nbf, so this library has no way to deal with them. (Which blocks vault-plugin-auth-kubernetes from using this library, since we still support Kubernetes 1.20.) Also did a small amount of cleanup: Generate a single 4096-bit RSA key in the tests, which speeds them up by a few seconds. Update go.mod in ldap cli example to use commit that exists (otherwise the tests appear to fail) --- CHANGELOG.md | 2 ++ jwt/jwt.go | 55 ++++++++++++++++++++--------- jwt/jwt_test.go | 76 +++++++++++++++++++++++++++++++++++----- ldap/examples/cli/go.mod | 20 +++++------ ldap/examples/cli/go.sum | 48 ++++++++++++------------- 5 files changed, 141 insertions(+), 60 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 57bf198..b1c49fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ Canonical reference for changes, improvements, and bugfixes for cap. ## Next +* Add Validator `ValidateAllowMissingIatNbfExp` method to allow all of iat/nbf/exp to be missing. + ## 0.1.1 (2021/06/24) ### Bug Fixes diff --git a/jwt/jwt.go b/jwt/jwt.go index 3d41129..155ea3b 100644 --- a/jwt/jwt.go +++ b/jwt/jwt.go @@ -93,6 +93,26 @@ type Expected struct { // (Issued At) claim, with configurable leeway. See Expected.Now() for details // on how the current time is provided for validation. func (v *Validator) Validate(ctx context.Context, token string, expected Expected) (map[string]interface{}, error) { + return v.validateAll(ctx, token, expected, false) +} + +// ValidateAllowMissingIatNbfExp validates JWTs of the JWS compact serialization form. +// +// The given JWT is considered valid if: +// 1. Its signature is successfully verified. +// 2. Its claims set and header parameter values match what's given by Expected. +// 3. It's valid with respect to the current time. This means that the current +// time must be within the times (inclusive) given by the "nbf" (Not Before) +// and "exp" (Expiration Time) claims and after the time given by the "iat" +// (Issued At) claim, with configurable leeway, if they are present. If all +// of "nbf", "exp", and "iat" are missing, then this check is skipped. See +// Expected.Now() for details on how the current time is provided for +// validation. +func (v *Validator) ValidateAllowMissingIatNbfExp(ctx context.Context, token string, expected Expected) (map[string]interface{}, error) { + return v.validateAll(ctx, token, expected, true) +} + +func (v *Validator) validateAll(ctx context.Context, token string, expected Expected, allowMissingIatExpNbf bool) (map[string]interface{}, error) { // First, verify the signature to ensure subsequent validation is against verified claims allClaims, err := v.keySet.VerifySignature(ctx, token) if err != nil { @@ -114,8 +134,20 @@ func (v *Validator) Validate(ctx context.Context, token string, expected Expecte return nil, err } - // At least one of the "nbf" (Not Before), "exp" (Expiration Time), or "iat" (Issued At) - // claims are required to be set. + // Validate claims by asserting that they're as expected + if expected.Issuer != "" && expected.Issuer != claims.Issuer { + return nil, fmt.Errorf("invalid issuer (iss) claim") + } + if expected.Subject != "" && expected.Subject != claims.Subject { + return nil, fmt.Errorf("invalid subject (sub) claim") + } + if expected.ID != "" && expected.ID != claims.ID { + return nil, fmt.Errorf("invalid ID (jti) claim") + } + if err := validateAudience(expected.Audiences, claims.Audience); err != nil { + return nil, fmt.Errorf("invalid audience (aud) claim: %w", err) + } + if claims.IssuedAt == nil { claims.IssuedAt = new(jwt.NumericDate) } @@ -125,7 +157,12 @@ func (v *Validator) Validate(ctx context.Context, token string, expected Expecte if claims.NotBefore == nil { claims.NotBefore = new(jwt.NumericDate) } + // At least one of the "nbf" (Not Before), "exp" (Expiration Time), or "iat" (Issued At) + // claims are required to be set unless allowMissingIatExpNbf is set. if *claims.IssuedAt == 0 && *claims.Expiry == 0 && *claims.NotBefore == 0 { + if allowMissingIatExpNbf { + return allClaims, nil + } return nil, errors.New("no issued at (iat), not before (nbf), or expiration time (exp) claims in token") } @@ -169,20 +206,6 @@ func (v *Validator) Validate(ctx context.Context, token string, expected Expecte cksLeeway = jwt.DefaultLeeway } - // Validate claims by asserting they're as expected - if expected.Issuer != "" && expected.Issuer != claims.Issuer { - return nil, fmt.Errorf("invalid issuer (iss) claim") - } - if expected.Subject != "" && expected.Subject != claims.Subject { - return nil, fmt.Errorf("invalid subject (sub) claim") - } - if expected.ID != "" && expected.ID != claims.ID { - return nil, fmt.Errorf("invalid ID (jti) claim") - } - if err := validateAudience(expected.Audiences, claims.Audience); err != nil { - return nil, fmt.Errorf("invalid audience (aud) claim: %w", err) - } - // Validate that the token is not expired with respect to the current time now := time.Now() if expected.Now != nil { diff --git a/jwt/jwt_test.go b/jwt/jwt_test.go index f8ca85e..6a87041 100644 --- a/jwt/jwt_test.go +++ b/jwt/jwt_test.go @@ -13,6 +13,18 @@ import ( "gopkg.in/square/go-jose.v2/jwt" ) +var priv *rsa.PrivateKey + +func init() { + // Generate a key to sign JWTs with throughout most test cases. + // It can be slow sometimes to generate a 4096-bit RSA key, so we only do it once. + var err error + priv, err = rsa.GenerateKey(rand.Reader, 4096) + if err != nil { + panic(err) + } +} + // TestValidator_Validate_Valid_JWT tests cases where a JWT is expected to be valid. func TestValidator_Validate_Valid_JWT(t *testing.T) { tp := oidc.StartTestProvider(t) @@ -21,9 +33,6 @@ func TestValidator_Validate_Valid_JWT(t *testing.T) { keySet, err := NewOIDCDiscoveryKeySet(context.Background(), tp.Addr(), tp.CACert()) require.NoError(t, err) - // Generate a key to sign JWTs with throughout most test cases - priv, err := rsa.GenerateKey(rand.Reader, 4096) - require.NoError(t, err) tp.SetSigningKeys(priv, priv.Public(), oidc.RS256, testKeyID) // Establish past, now, and future for validation of time related claims @@ -281,6 +290,61 @@ func TestValidator_Validate_Valid_JWT(t *testing.T) { } } +func TestValidator_NoExpIatNbf(t *testing.T) { + tp := oidc.StartTestProvider(t) + + // Create the KeySet to be used to verify JWT signatures + keySet, err := NewOIDCDiscoveryKeySet(context.Background(), tp.Addr(), tp.CACert()) + require.NoError(t, err) + + tp.SetSigningKeys(priv, priv.Public(), oidc.RS256, testKeyID) + + type args struct { + claims map[string]interface{} + token func(map[string]interface{}) string + expected Expected + } + tests := []struct { + name string + args args + }{ + { + name: "valid jwt with assertion on issuer claim", + args: args{ + claims: map[string]interface{}{ + "iss": "https://example.com/", + }, + token: func(claims map[string]interface{}) string { + return oidc.TestSignJWT(t, priv, string(RS256), claims, []byte(testKeyID)) + }, + expected: Expected{ + Issuer: "https://example.com/", + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + ctx := context.Background() + + // Create the signed JWT with the given claims + token := tt.args.token(tt.args.claims) + + // Create the validator with the KeySet + validator, err := NewValidator(keySet) + require.NoError(t, err) + + // Validate the JWT claims against expected values + got, err := validator.ValidateAllowMissingIatNbfExp(ctx, token, tt.args.expected) + + // Expect to get back the same claims that were serialized in the JWT + require.NoError(t, err) + require.NotNil(t, got) + require.Equal(t, tt.args.claims, got) + }) + } +} + // TestValidator_Validate_Valid_JWT tests cases where a JWT is expected to be invalid. func TestValidator_Validate_Invalid_JWT(t *testing.T) { tp := oidc.StartTestProvider(t) @@ -289,9 +353,6 @@ func TestValidator_Validate_Invalid_JWT(t *testing.T) { keySet, err := NewOIDCDiscoveryKeySet(context.Background(), tp.Addr(), tp.CACert()) require.NoError(t, err) - // Generate a key to sign JWTs with throughout most test cases - priv, err := rsa.GenerateKey(rand.Reader, 4096) - require.NoError(t, err) tp.SetSigningKeys(priv, priv.Public(), oidc.RS256, testKeyID) // Establish past, now, and future for validation of time related claims @@ -585,9 +646,6 @@ func Test_validateAudience(t *testing.T) { } func Test_validateSigningAlgorithm(t *testing.T) { - priv, err := rsa.GenerateKey(rand.Reader, 4096) - require.NoError(t, err) - type args struct { token func() string expectedAlgorithms []Alg diff --git a/ldap/examples/cli/go.mod b/ldap/examples/cli/go.mod index 999d58c..f4ad090 100644 --- a/ldap/examples/cli/go.mod +++ b/ldap/examples/cli/go.mod @@ -3,31 +3,31 @@ module github.com/hashicorp/cap/ldap/examples/cli go 1.17 require ( - github.com/hashicorp/cap/ldap v0.0.0-20220124000331-da580acda27e + github.com/hashicorp/cap/ldap v0.0.0-20220408131637-6d654cde3216 github.com/hashicorp/go-hclog v1.1.0 github.com/hashicorp/go-secure-stdlib/password v0.1.1 - github.com/jimlambrt/gldap v0.0.0-20220125123541-c405b1d802b2 + github.com/jimlambrt/gldap v0.1.1 ) require ( - github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c // indirect + github.com/Azure/go-ntlmssp v0.0.0-20211209120228-48547f28849e // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/fatih/color v1.7.0 // indirect - github.com/go-asn1-ber/asn1-ber v1.5.1 // indirect - github.com/go-ldap/ldap/v3 v3.4.1 // indirect - github.com/hashicorp/errwrap v1.0.0 // indirect + github.com/go-asn1-ber/asn1-ber v1.5.4 // indirect + github.com/go-ldap/ldap/v3 v3.4.3 // indirect + github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect - github.com/hashicorp/go-secure-stdlib/parseutil v0.1.1 // indirect - github.com/hashicorp/go-secure-stdlib/strutil v0.1.1 // indirect + github.com/hashicorp/go-secure-stdlib/parseutil v0.1.4 // indirect + github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 // indirect github.com/hashicorp/go-secure-stdlib/tlsutil v0.1.1 // indirect github.com/hashicorp/go-sockaddr v1.0.2 // indirect github.com/mattn/go-colorable v0.1.4 // indirect github.com/mattn/go-isatty v0.0.10 // indirect - github.com/mitchellh/mapstructure v1.4.1 // indirect + github.com/mitchellh/mapstructure v1.4.3 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/ryanuber/go-glob v1.0.0 // indirect github.com/stretchr/testify v1.7.0 // indirect - golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 // indirect + golang.org/x/crypto v0.0.0-20220331220935-ae2d96664a29 // indirect golang.org/x/sys v0.0.0-20211213223007-03aa0b5f6827 // indirect golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 // indirect gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect diff --git a/ldap/examples/cli/go.sum b/ldap/examples/cli/go.sum index 9e446c7..e6c0c68 100644 --- a/ldap/examples/cli/go.sum +++ b/ldap/examples/cli/go.sum @@ -1,5 +1,5 @@ -github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c h1:/IBSNwUN8+eKzUzbJPqhK839ygXJ82sde8x3ogr6R28= -github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU= +github.com/Azure/go-ntlmssp v0.0.0-20211209120228-48547f28849e h1:ZU22z/2YRFLyf/P4ZwUYSdNCWsMEI0VeyrFoI2rAhJQ= +github.com/Azure/go-ntlmssp v0.0.0-20211209120228-48547f28849e/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -7,34 +7,34 @@ 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/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/go-asn1-ber/asn1-ber v1.5.1 h1:pDbRAunXzIUXfx4CB2QJFv5IuPiuoW+sWvr/Us009o8= -github.com/go-asn1-ber/asn1-ber v1.5.1/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= -github.com/go-ldap/ldap/v3 v3.4.1 h1:fU/0xli6HY02ocbMuozHAYsaHLcnkLjvho2r5a34BUU= -github.com/go-ldap/ldap/v3 v3.4.1/go.mod h1:iYS1MdmrmceOJ1QOTnRXrIs7i3kloqtmGQjRvjKpyMg= -github.com/hashicorp/cap/ldap v0.0.0-20220124000331-da580acda27e h1:D7Dknjs352FkoVUdT5L246rwjkd1zxZNb8BywkFpM+g= -github.com/hashicorp/cap/ldap v0.0.0-20220124000331-da580acda27e/go.mod h1:RvXjDS4JZIIOSsUOcC+bLgVXoPxWNtDCq8QFXONJicw= -github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= +github.com/go-asn1-ber/asn1-ber v1.5.4 h1:vXT6d/FNDiELJnLb6hGNa309LMsrCoYFvpwHDF0+Y1A= +github.com/go-asn1-ber/asn1-ber v1.5.4/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= +github.com/go-ldap/ldap/v3 v3.4.3 h1:JCKUtJPIcyOuG7ctGabLKMgIlKnGumD/iGjuWeEruDI= +github.com/go-ldap/ldap/v3 v3.4.3/go.mod h1:7LdHfVt6iIOESVEe3Bs4Jp2sHEKgDeduAhgM1/f9qmo= +github.com/hashicorp/cap/ldap v0.0.0-20220408131637-6d654cde3216 h1:dLuZYSsWXHumfFoVY27aEUffI7zVh4WSQSCHTTWSVNs= +github.com/hashicorp/cap/ldap v0.0.0-20220408131637-6d654cde3216/go.mod h1:raCUTLtdFrAMx/rsQNeYoWDrsfFcqQuTK1vJ5tYd3qA= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= +github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-hclog v1.1.0 h1:QsGcniKx5/LuX2eYoeL+Np3UKYPNaN7YKpTh29h8rbw= github.com/hashicorp/go-hclog v1.1.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= -github.com/hashicorp/go-secure-stdlib/parseutil v0.1.1 h1:78ki3QBevHwYrVxnyVeaEz+7WtifHhauYF23es/0KlI= github.com/hashicorp/go-secure-stdlib/parseutil v0.1.1/go.mod h1:QmrqtbKuxxSWTN3ETMPuB+VtEiBJ/A9XhoYGv8E1uD8= +github.com/hashicorp/go-secure-stdlib/parseutil v0.1.4 h1:hrIH/qrOTHfG9a1Jz6Z2jQf7Xe77AaD464W1fCFLwPQ= +github.com/hashicorp/go-secure-stdlib/parseutil v0.1.4/go.mod h1:QmrqtbKuxxSWTN3ETMPuB+VtEiBJ/A9XhoYGv8E1uD8= github.com/hashicorp/go-secure-stdlib/password v0.1.1 h1:6JzmBqXprakgFEHwBgdchsjaA9x3GyjdI568bXKxa60= github.com/hashicorp/go-secure-stdlib/password v0.1.1/go.mod h1:9hH302QllNwu1o2TGYtSk8I8kTAN0ca1EHpwhm5Mmzo= -github.com/hashicorp/go-secure-stdlib/strutil v0.1.1 h1:nd0HIW15E6FG1MsnArYaHfuw9C2zgzM8LxkG5Ty/788= github.com/hashicorp/go-secure-stdlib/strutil v0.1.1/go.mod h1:gKOamz3EwoIoJq7mlMIRBpVTAUn8qPCrEclOKKWhD3U= +github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 h1:kes8mmyCpxJsI7FTwtzRqEy9CdjCtrXrXGuOpxEA7Ts= +github.com/hashicorp/go-secure-stdlib/strutil v0.1.2/go.mod h1:Gou2R9+il93BqX25LAKCLuM+y9U2T4hlwvT1yprcna4= github.com/hashicorp/go-secure-stdlib/tlsutil v0.1.1 h1:Yc026VyMyIpq1UWRnakHRG01U8fJm+nEfEmjoAb00n8= github.com/hashicorp/go-secure-stdlib/tlsutil v0.1.1/go.mod h1:l8slYwnJA26yBz+ErHpp2IRCLr0vuOMGBORIz4rRiAs= github.com/hashicorp/go-sockaddr v1.0.2 h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0SyteCQc= github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A= -github.com/jimlambrt/gldap v0.0.0-20220123225924-e42489d01fc0/go.mod h1:4nPx4bAKKh3qMm84Z7/w7lNnuJdtp0AbAcakdh4P4Hk= -github.com/jimlambrt/gldap v0.0.0-20220124015551-82204adb5296 h1:3INpDpH0gfTBNpFLoxO3V/1IdL5O0HdhAyP1goKZ9U4= -github.com/jimlambrt/gldap v0.0.0-20220124015551-82204adb5296/go.mod h1:4nPx4bAKKh3qMm84Z7/w7lNnuJdtp0AbAcakdh4P4Hk= -github.com/jimlambrt/gldap v0.0.0-20220125123541-c405b1d802b2 h1:U3oRNKuAzjSSuqGODefVqR+Sdrp7v1Io+6iKQzBpRFo= -github.com/jimlambrt/gldap v0.0.0-20220125123541-c405b1d802b2/go.mod h1:sKo9VprcJwZRj7OoE7p8YLaPEeNxw3WIEY42NS/iV7E= +github.com/jimlambrt/gldap v0.1.1 h1:TKkPrI/32H8vIwzw29wfGpBEU1AH2W3CFxLTz58Y2oc= +github.com/jimlambrt/gldap v0.1.1/go.mod h1:sKo9VprcJwZRj7OoE7p8YLaPEeNxw3WIEY42NS/iV7E= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= @@ -44,8 +44,9 @@ github.com/mattn/go-isatty v0.0.10 h1:qxFzApOv4WsAL965uUPIsXzAKCZxN2p9UqdhFS4ZW1 github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= -github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag= github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/mapstructure v1.4.3 h1:OVowDSCllw/YjdLkam3/sm7wEtOy59d8ndGgCcyj8cs= +github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= 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/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= @@ -56,27 +57,24 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 h1:/UOmuWzQfxxo9UtlXMwuQU8CMgg1eZXqTRwkSQJWKOI= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/crypto v0.0.0-20220331220935-ae2d96664a29 h1:tkVvjkPTB7pnW3jnid7kNyAMPVWllTNOf/qKDze4p9o= +golang.org/x/crypto v0.0.0-20220331220935-ae2d96664a29/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/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-20211213223007-03aa0b5f6827 h1:A0Qkn7Z/n8zC1xd9LTw17AiKlBRK64tw3ejWQiEqca0= golang.org/x/sys v0.0.0-20211213223007-03aa0b5f6827/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.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=