Skip to content

Commit

Permalink
Add option to allow all of IAT, NBF, and EXP to be missing (#50)
Browse files Browse the repository at this point in the history
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)
  • Loading branch information
swenson authored May 2, 2022
1 parent 6d654cd commit 9a9f4a9
Show file tree
Hide file tree
Showing 5 changed files with 141 additions and 60 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
55 changes: 39 additions & 16 deletions jwt/jwt.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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)
}
Expand All @@ -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")
}

Expand Down Expand Up @@ -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 {
Expand Down
76 changes: 67 additions & 9 deletions jwt/jwt_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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
Expand Down Expand Up @@ -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)
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down
20 changes: 10 additions & 10 deletions ldap/examples/cli/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
48 changes: 23 additions & 25 deletions ldap/examples/cli/go.sum
Original file line number Diff line number Diff line change
@@ -1,40 +1,40 @@
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=
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=
Expand All @@ -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=
Expand All @@ -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=
Expand Down

0 comments on commit 9a9f4a9

Please sign in to comment.