forked from TrueCloudLab/certificates
Merge branch 'master' into herman/remote-management-helm
This commit is contained in:
commit
da5d2b405c
10 changed files with 194 additions and 78 deletions
|
@ -2774,3 +2774,97 @@ func Test_doStepAttestationFormat(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_doStepAttestationFormat_noCAIntermediate(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
// This CA simulates a YubiKey v5.2.4, where the attestation intermediate in
|
||||
// the CA does not have the basic constraint extension. With the current
|
||||
// validation of the certificate the test case below returns an error. If
|
||||
// we change the validation to support this use case, the test case below
|
||||
// should change.
|
||||
//
|
||||
// See https://github.com/Yubico/yubikey-manager/issues/522
|
||||
ca, err := minica.New(minica.WithIntermediateTemplate(`{"subject": {{ toJson .Subject }}}`))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
caRoot := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: ca.Root.Raw})
|
||||
|
||||
makeLeaf := func(signer crypto.Signer, serialNumber []byte) *x509.Certificate {
|
||||
leaf, err := ca.Sign(&x509.Certificate{
|
||||
Subject: pkix.Name{CommonName: "attestation cert"},
|
||||
PublicKey: signer.Public(),
|
||||
ExtraExtensions: []pkix.Extension{
|
||||
{Id: oidYubicoSerialNumber, Value: serialNumber},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return leaf
|
||||
}
|
||||
|
||||
signer, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
serialNumber, err := asn1.Marshal(1234)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
leaf := makeLeaf(signer, serialNumber)
|
||||
|
||||
jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
keyAuth, err := KeyAuthorization("token", jwk)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
keyAuthSum := sha256.Sum256([]byte(keyAuth))
|
||||
sig, err := signer.Sign(rand.Reader, keyAuthSum[:], crypto.SHA256)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
cborSig, err := cbor.Marshal(sig)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
prov Provisioner
|
||||
ch *Challenge
|
||||
jwk *jose.JSONWebKey
|
||||
att *AttestationObject
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want *stepAttestationData
|
||||
wantErr bool
|
||||
}{
|
||||
{"fail no intermediate", args{ctx, mustAttestationProvisioner(t, caRoot), &Challenge{Token: "token"}, jwk, &AttestationObject{
|
||||
Format: "step",
|
||||
AttStatement: map[string]interface{}{
|
||||
"x5c": []interface{}{leaf.Raw, ca.Intermediate.Raw},
|
||||
"alg": -7,
|
||||
"sig": cborSig,
|
||||
},
|
||||
}}, nil, true},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := doStepAttestationFormat(tt.args.ctx, tt.args.prov, tt.args.ch, tt.args.jwk, tt.args.att)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("doStepAttestationFormat() error = %#v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("doStepAttestationFormat() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -241,9 +241,10 @@ func TestUnimplementedMethods(t *testing.T) {
|
|||
default:
|
||||
t.Errorf("unexpected method %s", tt.method)
|
||||
}
|
||||
sc, ok := err.(render.StatusCodedError)
|
||||
assert.Fatal(t, ok, "error does not implement StatusCodedError interface")
|
||||
var sc render.StatusCodedError
|
||||
if assert.True(t, errors.As(err, &sc), "error does not implement StatusCodedError interface") {
|
||||
assert.Equals(t, sc.StatusCode(), http.StatusUnauthorized)
|
||||
}
|
||||
assert.Equals(t, err.Error(), msg)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -218,9 +218,10 @@ func TestSSHPOP_authorizeToken(t *testing.T) {
|
|||
t.Run(name, func(t *testing.T) {
|
||||
tc := tt(t)
|
||||
if claims, err := tc.p.authorizeToken(tc.token, testAudiences.Sign, true); err != nil {
|
||||
sc, ok := err.(render.StatusCodedError)
|
||||
assert.Fatal(t, ok, "error does not implement StatusCodedError interface")
|
||||
var sc render.StatusCodedError
|
||||
if assert.True(t, errors.As(err, &sc), "error does not implement StatusCodedError interface") {
|
||||
assert.Equals(t, sc.StatusCode(), tc.code)
|
||||
}
|
||||
if assert.NotNil(t, tc.err) {
|
||||
assert.HasPrefix(t, err.Error(), tc.err.Error())
|
||||
}
|
||||
|
@ -289,9 +290,10 @@ func TestSSHPOP_AuthorizeSSHRevoke(t *testing.T) {
|
|||
t.Run(name, func(t *testing.T) {
|
||||
tc := tt(t)
|
||||
if err := tc.p.AuthorizeSSHRevoke(context.Background(), tc.token); err != nil {
|
||||
sc, ok := err.(render.StatusCodedError)
|
||||
assert.Fatal(t, ok, "error does not implement StatusCodedError interface")
|
||||
var sc render.StatusCodedError
|
||||
if assert.True(t, errors.As(err, &sc), "error does not implement StatusCodedError interface") {
|
||||
assert.Equals(t, sc.StatusCode(), tc.code)
|
||||
}
|
||||
if assert.NotNil(t, tc.err) {
|
||||
assert.HasPrefix(t, err.Error(), tc.err.Error())
|
||||
}
|
||||
|
@ -370,9 +372,10 @@ func TestSSHPOP_AuthorizeSSHRenew(t *testing.T) {
|
|||
tc := tt(t)
|
||||
if cert, err := tc.p.AuthorizeSSHRenew(context.Background(), tc.token); err != nil {
|
||||
if assert.NotNil(t, tc.err) {
|
||||
sc, ok := err.(render.StatusCodedError)
|
||||
assert.Fatal(t, ok, "error does not implement StatusCodedError interface")
|
||||
var sc render.StatusCodedError
|
||||
if assert.True(t, errors.As(err, &sc), "error does not implement StatusCodedError interface") {
|
||||
assert.Equals(t, sc.StatusCode(), tc.code)
|
||||
}
|
||||
assert.HasPrefix(t, err.Error(), tc.err.Error())
|
||||
}
|
||||
} else {
|
||||
|
@ -452,9 +455,10 @@ func TestSSHPOP_AuthorizeSSHRekey(t *testing.T) {
|
|||
tc := tt(t)
|
||||
if cert, opts, err := tc.p.AuthorizeSSHRekey(context.Background(), tc.token); err != nil {
|
||||
if assert.NotNil(t, tc.err) {
|
||||
sc, ok := err.(render.StatusCodedError)
|
||||
assert.Fatal(t, ok, "error does not implement StatusCodedError interface")
|
||||
var sc render.StatusCodedError
|
||||
if assert.True(t, errors.As(err, &sc), "error does not implement StatusCodedError interface") {
|
||||
assert.Equals(t, sc.StatusCode(), tc.code)
|
||||
}
|
||||
assert.HasPrefix(t, err.Error(), tc.err.Error())
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -389,9 +389,10 @@ lgsqsR63is+0YQ==
|
|||
tc := tt(t)
|
||||
if claims, err := tc.p.authorizeToken(tc.token, testAudiences.Sign); err != nil {
|
||||
if assert.NotNil(t, tc.err) {
|
||||
sc, ok := err.(render.StatusCodedError)
|
||||
assert.Fatal(t, ok, "error does not implement StatusCodedError interface")
|
||||
var sc render.StatusCodedError
|
||||
if assert.True(t, errors.As(err, &sc), "error does not implement StatusCodedError interface") {
|
||||
assert.Equals(t, sc.StatusCode(), tc.code)
|
||||
}
|
||||
assert.HasPrefix(t, err.Error(), tc.err.Error())
|
||||
}
|
||||
} else {
|
||||
|
@ -460,9 +461,10 @@ func TestX5C_AuthorizeSign(t *testing.T) {
|
|||
tc := tt(t)
|
||||
if opts, err := tc.p.AuthorizeSign(context.Background(), tc.token); err != nil {
|
||||
if assert.NotNil(t, tc.err) {
|
||||
sc, ok := err.(render.StatusCodedError)
|
||||
assert.Fatal(t, ok, "error does not implement StatusCoder interface")
|
||||
var sc render.StatusCodedError
|
||||
if assert.True(t, errors.As(err, &sc), "error does not implement StatusCodedError interface") {
|
||||
assert.Equals(t, sc.StatusCode(), tc.code)
|
||||
}
|
||||
assert.HasPrefix(t, err.Error(), tc.err.Error())
|
||||
}
|
||||
} else {
|
||||
|
@ -547,9 +549,10 @@ func TestX5C_AuthorizeRevoke(t *testing.T) {
|
|||
tc := tt(t)
|
||||
if err := tc.p.AuthorizeRevoke(context.Background(), tc.token); err != nil {
|
||||
if assert.NotNil(t, tc.err) {
|
||||
sc, ok := err.(render.StatusCodedError)
|
||||
assert.Fatal(t, ok, "error does not implement StatusCodedError interface")
|
||||
var sc render.StatusCodedError
|
||||
if assert.True(t, errors.As(err, &sc), "error does not implement StatusCodedError interface") {
|
||||
assert.Equals(t, sc.StatusCode(), tc.code)
|
||||
}
|
||||
assert.HasPrefix(t, err.Error(), tc.err.Error())
|
||||
}
|
||||
} else {
|
||||
|
@ -597,9 +600,10 @@ func TestX5C_AuthorizeRenew(t *testing.T) {
|
|||
NotAfter: now.Add(time.Hour),
|
||||
}); err != nil {
|
||||
if assert.NotNil(t, tc.err) {
|
||||
sc, ok := err.(render.StatusCodedError)
|
||||
assert.Fatal(t, ok, "error does not implement StatusCodedError interface")
|
||||
var sc render.StatusCodedError
|
||||
if assert.True(t, errors.As(err, &sc), "error does not implement StatusCodedError interface") {
|
||||
assert.Equals(t, sc.StatusCode(), tc.code)
|
||||
}
|
||||
assert.HasPrefix(t, err.Error(), tc.err.Error())
|
||||
}
|
||||
} else {
|
||||
|
@ -758,9 +762,10 @@ func TestX5C_AuthorizeSSHSign(t *testing.T) {
|
|||
tc := tt(t)
|
||||
if opts, err := tc.p.AuthorizeSSHSign(context.Background(), tc.token); err != nil {
|
||||
if assert.NotNil(t, tc.err) {
|
||||
sc, ok := err.(render.StatusCodedError)
|
||||
assert.Fatal(t, ok, "error does not implement StatusCoder interface")
|
||||
var sc render.StatusCodedError
|
||||
if assert.True(t, errors.As(err, &sc), "error does not implement StatusCodedError interface") {
|
||||
assert.Equals(t, sc.StatusCode(), tc.code)
|
||||
}
|
||||
assert.HasPrefix(t, err.Error(), tc.err.Error())
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -58,9 +58,10 @@ func TestGetEncryptedKey(t *testing.T) {
|
|||
ek, err := tc.a.GetEncryptedKey(tc.kid)
|
||||
if err != nil {
|
||||
if assert.NotNil(t, tc.err) {
|
||||
sc, ok := err.(render.StatusCodedError)
|
||||
assert.Fatal(t, ok, "error does not implement StatusCodedError interface")
|
||||
var sc render.StatusCodedError
|
||||
if assert.True(t, errors.As(err, &sc), "error does not implement StatusCodedError interface") {
|
||||
assert.Equals(t, sc.StatusCode(), tc.code)
|
||||
}
|
||||
assert.HasPrefix(t, err.Error(), tc.err.Error())
|
||||
}
|
||||
} else {
|
||||
|
@ -108,9 +109,10 @@ func TestGetProvisioners(t *testing.T) {
|
|||
ps, next, err := tc.a.GetProvisioners("", 0)
|
||||
if err != nil {
|
||||
if assert.NotNil(t, tc.err) {
|
||||
sc, ok := err.(render.StatusCodedError)
|
||||
assert.Fatal(t, ok, "error does not implement StatusCodedError interface")
|
||||
var sc render.StatusCodedError
|
||||
if assert.True(t, errors.As(err, &sc), "error does not implement StatusCodedError interface") {
|
||||
assert.Equals(t, sc.StatusCode(), tc.code)
|
||||
}
|
||||
assert.HasPrefix(t, err.Error(), tc.err.Error())
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -774,8 +774,8 @@ func TestAuthority_GetSSHBastion(t *testing.T) {
|
|||
t.Errorf("Authority.GetSSHBastion() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
} else if err != nil {
|
||||
_, ok := err.(render.StatusCodedError)
|
||||
assert.Fatal(t, ok, "error does not implement StatusCodedError interface")
|
||||
var sc render.StatusCodedError
|
||||
assert.True(t, errors.As(err, &sc), "error does not implement StatusCodedError interface")
|
||||
}
|
||||
if !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("Authority.GetSSHBastion() = %v, want %v", got, tt.want)
|
||||
|
@ -865,8 +865,9 @@ func TestAuthority_GetSSHHosts(t *testing.T) {
|
|||
if err != nil {
|
||||
if assert.NotNil(t, tc.err) {
|
||||
var sc render.StatusCodedError
|
||||
assert.Fatal(t, errors.As(err, &sc), "error does not implement StatusCodedError interface")
|
||||
if assert.True(t, errors.As(err, &sc), "error does not implement StatusCodedError interface") {
|
||||
assert.Equals(t, sc.StatusCode(), tc.code)
|
||||
}
|
||||
assert.HasPrefix(t, err.Error(), tc.err.Error())
|
||||
}
|
||||
} else {
|
||||
|
@ -1092,8 +1093,9 @@ func TestAuthority_RekeySSH(t *testing.T) {
|
|||
if err != nil {
|
||||
if assert.NotNil(t, tc.err) {
|
||||
var sc render.StatusCodedError
|
||||
assert.Fatal(t, errors.As(err, &sc), "error does not implement StatusCodedError interface")
|
||||
if assert.True(t, errors.As(err, &sc), "error does not implement StatusCodedError interface") {
|
||||
assert.Equals(t, sc.StatusCode(), tc.code)
|
||||
}
|
||||
assert.HasPrefix(t, err.Error(), tc.err.Error())
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -519,9 +519,10 @@ func TestClient_Renew(t *testing.T) {
|
|||
t.Errorf("Client.Renew() = %v, want nil", got)
|
||||
}
|
||||
|
||||
sc, ok := err.(render.StatusCodedError)
|
||||
assert.Fatal(t, ok, "error does not implement StatusCodedError interface")
|
||||
var sc render.StatusCodedError
|
||||
if assert.True(t, errors.As(err, &sc), "error does not implement StatusCodedError interface") {
|
||||
assert.Equals(t, sc.StatusCode(), tt.responseCode)
|
||||
}
|
||||
assert.HasPrefix(t, err.Error(), tt.err.Error())
|
||||
default:
|
||||
if !reflect.DeepEqual(got, tt.response) {
|
||||
|
@ -587,9 +588,10 @@ func TestClient_RenewWithToken(t *testing.T) {
|
|||
t.Errorf("Client.RenewWithToken() = %v, want nil", got)
|
||||
}
|
||||
|
||||
sc, ok := err.(render.StatusCodedError)
|
||||
assert.Fatal(t, ok, "error does not implement StatusCodedError interface")
|
||||
var sc render.StatusCodedError
|
||||
if assert.True(t, errors.As(err, &sc), "error does not implement StatusCodedError interface") {
|
||||
assert.Equals(t, sc.StatusCode(), tt.responseCode)
|
||||
}
|
||||
assert.HasPrefix(t, err.Error(), tt.err.Error())
|
||||
default:
|
||||
if !reflect.DeepEqual(got, tt.response) {
|
||||
|
@ -656,9 +658,10 @@ func TestClient_Rekey(t *testing.T) {
|
|||
t.Errorf("Client.Renew() = %v, want nil", got)
|
||||
}
|
||||
|
||||
sc, ok := err.(render.StatusCodedError)
|
||||
assert.Fatal(t, ok, "error does not implement StatusCodedError interface")
|
||||
var sc render.StatusCodedError
|
||||
if assert.True(t, errors.As(err, &sc), "error does not implement StatusCodedError interface") {
|
||||
assert.Equals(t, sc.StatusCode(), tt.responseCode)
|
||||
}
|
||||
assert.HasPrefix(t, err.Error(), tt.err.Error())
|
||||
default:
|
||||
if !reflect.DeepEqual(got, tt.response) {
|
||||
|
@ -777,9 +780,10 @@ func TestClient_ProvisionerKey(t *testing.T) {
|
|||
t.Errorf("Client.ProvisionerKey() = %v, want nil", got)
|
||||
}
|
||||
|
||||
sc, ok := err.(render.StatusCodedError)
|
||||
assert.Fatal(t, ok, "error does not implement StatusCodedError interface")
|
||||
var sc render.StatusCodedError
|
||||
if assert.True(t, errors.As(err, &sc), "error does not implement StatusCodedError interface") {
|
||||
assert.Equals(t, sc.StatusCode(), tt.responseCode)
|
||||
}
|
||||
assert.HasPrefix(t, tt.err.Error(), err.Error())
|
||||
default:
|
||||
if !reflect.DeepEqual(got, tt.response) {
|
||||
|
@ -836,9 +840,10 @@ func TestClient_Roots(t *testing.T) {
|
|||
if got != nil {
|
||||
t.Errorf("Client.Roots() = %v, want nil", got)
|
||||
}
|
||||
sc, ok := err.(render.StatusCodedError)
|
||||
assert.Fatal(t, ok, "error does not implement StatusCodedError interface")
|
||||
var sc render.StatusCodedError
|
||||
if assert.True(t, errors.As(err, &sc), "error does not implement StatusCodedError interface") {
|
||||
assert.Equals(t, sc.StatusCode(), tt.responseCode)
|
||||
}
|
||||
assert.HasPrefix(t, err.Error(), tt.err.Error())
|
||||
default:
|
||||
if !reflect.DeepEqual(got, tt.response) {
|
||||
|
@ -894,9 +899,10 @@ func TestClient_Federation(t *testing.T) {
|
|||
if got != nil {
|
||||
t.Errorf("Client.Federation() = %v, want nil", got)
|
||||
}
|
||||
sc, ok := err.(render.StatusCodedError)
|
||||
assert.Fatal(t, ok, "error does not implement StatusCodedError interface")
|
||||
var sc render.StatusCodedError
|
||||
if assert.True(t, errors.As(err, &sc), "error does not implement StatusCodedError interface") {
|
||||
assert.Equals(t, sc.StatusCode(), tt.responseCode)
|
||||
}
|
||||
assert.HasPrefix(t, tt.err.Error(), err.Error())
|
||||
default:
|
||||
if !reflect.DeepEqual(got, tt.response) {
|
||||
|
@ -956,9 +962,10 @@ func TestClient_SSHRoots(t *testing.T) {
|
|||
if got != nil {
|
||||
t.Errorf("Client.SSHKeys() = %v, want nil", got)
|
||||
}
|
||||
sc, ok := err.(render.StatusCodedError)
|
||||
assert.Fatal(t, ok, "error does not implement StatusCodedError interface")
|
||||
var sc render.StatusCodedError
|
||||
if assert.True(t, errors.As(err, &sc), "error does not implement StatusCodedError interface") {
|
||||
assert.Equals(t, sc.StatusCode(), tt.responseCode)
|
||||
}
|
||||
assert.HasPrefix(t, tt.err.Error(), err.Error())
|
||||
default:
|
||||
if !reflect.DeepEqual(got, tt.response) {
|
||||
|
@ -1118,9 +1125,10 @@ func TestClient_SSHBastion(t *testing.T) {
|
|||
t.Errorf("Client.SSHBastion() = %v, want nil", got)
|
||||
}
|
||||
if tt.responseCode != 200 {
|
||||
sc, ok := err.(render.StatusCodedError)
|
||||
assert.Fatal(t, ok, "error does not implement StatusCodedError interface")
|
||||
var sc render.StatusCodedError
|
||||
if assert.True(t, errors.As(err, &sc), "error does not implement StatusCodedError interface") {
|
||||
assert.Equals(t, sc.StatusCode(), tt.responseCode)
|
||||
}
|
||||
assert.HasPrefix(t, err.Error(), tt.err.Error())
|
||||
}
|
||||
default:
|
||||
|
|
|
@ -143,8 +143,9 @@ func (e *Error) UnmarshalJSON(data []byte) error {
|
|||
|
||||
// Format implements the fmt.Formatter interface.
|
||||
func (e *Error) Format(f fmt.State, c rune) {
|
||||
if err, ok := e.Err.(fmt.Formatter); ok {
|
||||
err.Format(f, c)
|
||||
var fe fmt.Formatter
|
||||
if errors.As(e.Err, &fe) {
|
||||
fe.Format(f, c)
|
||||
return
|
||||
}
|
||||
fmt.Fprint(f, e.Err.Error())
|
||||
|
@ -253,7 +254,8 @@ func NewError(status int, err error, format string, args ...interface{}) error {
|
|||
return err
|
||||
}
|
||||
msg := fmt.Sprintf(format, args...)
|
||||
if _, ok := err.(log.StackTracedError); !ok {
|
||||
var ste log.StackTracedError
|
||||
if !errors.As(err, &ste) {
|
||||
err = errors.Wrap(err, msg)
|
||||
}
|
||||
return &Error{
|
||||
|
@ -268,17 +270,13 @@ func NewError(status int, err error, format string, args ...interface{}) error {
|
|||
func NewErr(status int, err error, opts ...Option) error {
|
||||
var e *Error
|
||||
if !errors.As(err, &e) {
|
||||
if sc, ok := err.(render.StatusCodedError); ok {
|
||||
e = &Error{Status: sc.StatusCode(), Err: err}
|
||||
} else {
|
||||
cause := errors.Cause(err)
|
||||
if sc, ok := cause.(render.StatusCodedError); ok {
|
||||
e = &Error{Status: sc.StatusCode(), Err: err}
|
||||
var ste render.StatusCodedError
|
||||
if errors.As(err, &ste) {
|
||||
e = &Error{Status: ste.StatusCode(), Err: err}
|
||||
} else {
|
||||
e = &Error{Status: status, Err: err}
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, o := range opts {
|
||||
o(e)
|
||||
}
|
||||
|
|
2
go.mod
2
go.mod
|
@ -142,7 +142,7 @@ require (
|
|||
go.opencensus.io v0.23.0 // indirect
|
||||
go.uber.org/atomic v1.9.0 // indirect
|
||||
golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1 // indirect
|
||||
golang.org/x/text v0.3.8-0.20211105212822-18b340fc7af2 // indirect
|
||||
golang.org/x/text v0.3.8 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
|
|
2
go.sum
2
go.sum
|
@ -1060,6 +1060,8 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
|||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.3.8-0.20211105212822-18b340fc7af2 h1:GLw7MR8AfAG2GmGcmVgObFOHXYypgGjnGno25RDwn3Y=
|
||||
golang.org/x/text v0.3.8-0.20211105212822-18b340fc7af2/go.mod h1:EFNZuWvGYxIRUEX+K8UmCFwYmZjqcrnq15ZuVldZkZ0=
|
||||
golang.org/x/text v0.3.8 h1:nAL+RVCQ9uMn3vJZbV+MRnydTJFPf8qqY42YiA6MrqY=
|
||||
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
||||
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=
|
||||
|
|
Loading…
Reference in a new issue