forked from TrueCloudLab/certificates
Add initial tests for CreateCertificateAuthority.
This commit is contained in:
parent
062edcdfb4
commit
2611fc04d4
4 changed files with 198 additions and 53 deletions
|
@ -5,25 +5,34 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"crypto/x509/pkix"
|
|
||||||
"encoding/asn1"
|
"encoding/asn1"
|
||||||
"io"
|
"io"
|
||||||
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
lroauto "cloud.google.com/go/longrunning/autogen"
|
||||||
|
privateca "cloud.google.com/go/security/privateca/apiv1beta1"
|
||||||
|
gomock "github.com/golang/mock/gomock"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
gax "github.com/googleapis/gax-go/v2"
|
gax "github.com/googleapis/gax-go/v2"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/smallstep/certificates/cas/apiv1"
|
"github.com/smallstep/certificates/cas/apiv1"
|
||||||
|
"google.golang.org/api/option"
|
||||||
pb "google.golang.org/genproto/googleapis/cloud/security/privateca/v1beta1"
|
pb "google.golang.org/genproto/googleapis/cloud/security/privateca/v1beta1"
|
||||||
|
longrunningpb "google.golang.org/genproto/googleapis/longrunning"
|
||||||
|
"google.golang.org/grpc"
|
||||||
|
"google.golang.org/protobuf/types/known/anypb"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
errTest = errors.New("test error")
|
errTest = errors.New("test error")
|
||||||
testAuthorityName = "projects/test-project/locations/us-west1/certificateAuthorities/test-ca"
|
testAuthorityName = "projects/test-project/locations/us-west1/certificateAuthorities/test-ca"
|
||||||
testCertificateName = "projects/test-project/locations/us-west1/certificateAuthorities/test-ca/certificates/test-certificate"
|
testCertificateName = "projects/test-project/locations/us-west1/certificateAuthorities/test-ca/certificates/test-certificate"
|
||||||
|
testProject = "test-project"
|
||||||
|
testLocation = "us-west1"
|
||||||
testRootCertificate = `-----BEGIN CERTIFICATE-----
|
testRootCertificate = `-----BEGIN CERTIFICATE-----
|
||||||
MIIBhjCCAS2gAwIBAgIQLbKTuXau4+t3KFbGpJJAADAKBggqhkjOPQQDAjAiMSAw
|
MIIBhjCCAS2gAwIBAgIQLbKTuXau4+t3KFbGpJJAADAKBggqhkjOPQQDAjAiMSAw
|
||||||
HgYDVQQDExdHb29nbGUgQ0FTIFRlc3QgUm9vdCBDQTAeFw0yMDA5MTQyMjQ4NDla
|
HgYDVQQDExdHb29nbGUgQ0FTIFRlc3QgUm9vdCBDQTAeFw0yMDA5MTQyMjQ4NDla
|
||||||
|
@ -72,6 +81,21 @@ ZGNhcxMkZDhkMThhNjgtNTI5Ni00YWYzLWFlNGItMmY4NzdkYTNmYmQ5MAoGCCqG
|
||||||
SM49BAMCA0gAMEUCIGxl+pqJ50WYWUqK2l4V1FHoXSi0Nht5kwTxFxnWZu1xAiEA
|
SM49BAMCA0gAMEUCIGxl+pqJ50WYWUqK2l4V1FHoXSi0Nht5kwTxFxnWZu1xAiEA
|
||||||
zemu3bhWLFaGg3s8i+HTEhw4RqkHP74vF7AVYp88bAw=
|
zemu3bhWLFaGg3s8i+HTEhw4RqkHP74vF7AVYp88bAw=
|
||||||
-----END CERTIFICATE-----`
|
-----END CERTIFICATE-----`
|
||||||
|
testIntermediateCsr = `-----BEGIN CERTIFICATE REQUEST-----
|
||||||
|
MIIBIjCByQIBADAqMSgwJgYDVQQDEx9Hb29nbGUgQ0FTIFRlc3QgSW50ZXJtZWRp
|
||||||
|
YXRlIENBMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEqoztio0c4XuaaGxHFiU7
|
||||||
|
UBk3YRGTae9GtlKwyZJDk740hg6ZIoKcaXrzJT5taUpPiQLi7rP1eRui0dhl/bHo
|
||||||
|
o6A9MDsGCSqGSIb3DQEJDjEuMCwwKgYDVR0RBCMwIYIfR29vZ2xlIENBUyBUZXN0
|
||||||
|
IEludGVybWVkaWF0ZSBDQTAKBggqhkjOPQQDAgNIADBFAiEAvRKBPE32scAvsMe8
|
||||||
|
R7ecx91q58ZmeLaRdSzL7stsnJYCIEBu+vQUSTbUpKL2YQNclT9kbilips5pEMr3
|
||||||
|
ojxK6mk3
|
||||||
|
-----END CERTIFICATE REQUEST-----`
|
||||||
|
|
||||||
|
// testIntermediateKey = `-----BEGIN EC PRIVATE KEY-----
|
||||||
|
// MHcCAQEEIMM+DSPChJgcYyqDWs0eRA5BctIo+VSNqRzCTL2ARYAqoAoGCCqGSM49
|
||||||
|
// AwEHoUQDQgAEqoztio0c4XuaaGxHFiU7UBk3YRGTae9GtlKwyZJDk740hg6ZIoKc
|
||||||
|
// aXrzJT5taUpPiQLi7rP1eRui0dhl/bHoow==
|
||||||
|
// -----END EC PRIVATE KEY-----`
|
||||||
)
|
)
|
||||||
|
|
||||||
type testClient struct {
|
type testClient struct {
|
||||||
|
@ -146,6 +170,18 @@ func (c *testClient) GetCertificateAuthority(ctx context.Context, req *pb.GetCer
|
||||||
return c.certificateAuthority, c.err
|
return c.certificateAuthority, c.err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *testClient) CreateCertificateAuthority(ctx context.Context, req *pb.CreateCertificateAuthorityRequest, opts ...gax.CallOption) (*privateca.CreateCertificateAuthorityOperation, error) {
|
||||||
|
return nil, errors.New("use NewMockCertificateAuthorityClient")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *testClient) FetchCertificateAuthorityCsr(ctx context.Context, req *pb.FetchCertificateAuthorityCsrRequest, opts ...gax.CallOption) (*pb.FetchCertificateAuthorityCsrResponse, error) {
|
||||||
|
return nil, errors.New("use NewMockCertificateAuthorityClient")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *testClient) ActivateCertificateAuthority(ctx context.Context, req *pb.ActivateCertificateAuthorityRequest, opts ...gax.CallOption) (*privateca.ActivateCertificateAuthorityOperation, error) {
|
||||||
|
return nil, errors.New("use NewMockCertificateAuthorityClient")
|
||||||
|
}
|
||||||
|
|
||||||
func mustParseCertificate(t *testing.T, pemCert string) *x509.Certificate {
|
func mustParseCertificate(t *testing.T, pemCert string) *x509.Certificate {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
crt, err := parseCertificate(pemCert)
|
crt, err := parseCertificate(pemCert)
|
||||||
|
@ -179,17 +215,34 @@ func TestNew(t *testing.T) {
|
||||||
}}, &CloudCAS{
|
}}, &CloudCAS{
|
||||||
client: &testClient{},
|
client: &testClient{},
|
||||||
certificateAuthority: testAuthorityName,
|
certificateAuthority: testAuthorityName,
|
||||||
|
project: testProject,
|
||||||
|
location: testLocation,
|
||||||
}, false},
|
}, false},
|
||||||
{"ok with credentials", args{context.Background(), apiv1.Options{
|
{"ok with credentials", args{context.Background(), apiv1.Options{
|
||||||
CertificateAuthority: testAuthorityName, CredentialsFile: "testdata/credentials.json",
|
CertificateAuthority: testAuthorityName, CredentialsFile: "testdata/credentials.json",
|
||||||
}}, &CloudCAS{
|
}}, &CloudCAS{
|
||||||
client: &testClient{credentialsFile: "testdata/credentials.json"},
|
client: &testClient{credentialsFile: "testdata/credentials.json"},
|
||||||
certificateAuthority: testAuthorityName,
|
certificateAuthority: testAuthorityName,
|
||||||
|
project: testProject,
|
||||||
|
location: testLocation,
|
||||||
|
}, false},
|
||||||
|
{"ok creator", args{context.Background(), apiv1.Options{
|
||||||
|
IsCreator: true, Project: testProject, Location: testLocation,
|
||||||
|
}}, &CloudCAS{
|
||||||
|
client: &testClient{},
|
||||||
|
project: testProject,
|
||||||
|
location: testLocation,
|
||||||
}, false},
|
}, false},
|
||||||
{"fail certificate authority", args{context.Background(), apiv1.Options{}}, nil, true},
|
{"fail certificate authority", args{context.Background(), apiv1.Options{}}, nil, true},
|
||||||
{"fail with credentials", args{context.Background(), apiv1.Options{
|
{"fail with credentials", args{context.Background(), apiv1.Options{
|
||||||
CertificateAuthority: testAuthorityName, CredentialsFile: "testdata/error.json",
|
CertificateAuthority: testAuthorityName, CredentialsFile: "testdata/error.json",
|
||||||
}}, nil, true},
|
}}, nil, true},
|
||||||
|
{"fail creator project", args{context.Background(), apiv1.Options{
|
||||||
|
IsCreator: true, Project: "", Location: testLocation,
|
||||||
|
}}, nil, true},
|
||||||
|
{"fail creator location", args{context.Background(), apiv1.Options{
|
||||||
|
IsCreator: true, Project: testProject, Location: "",
|
||||||
|
}}, nil, true},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
@ -217,6 +270,8 @@ func TestNew_register(t *testing.T) {
|
||||||
want := &CloudCAS{
|
want := &CloudCAS{
|
||||||
client: &testClient{credentialsFile: "testdata/credentials.json"},
|
client: &testClient{credentialsFile: "testdata/credentials.json"},
|
||||||
certificateAuthority: testAuthorityName,
|
certificateAuthority: testAuthorityName,
|
||||||
|
project: testProject,
|
||||||
|
location: testLocation,
|
||||||
}
|
}
|
||||||
|
|
||||||
newFn, ok := apiv1.LoadCertificateAuthorityServiceNewFunc(apiv1.CloudCAS)
|
newFn, ok := apiv1.LoadCertificateAuthorityServiceNewFunc(apiv1.CloudCAS)
|
||||||
|
@ -675,61 +730,150 @@ func Test_getCertificateAndChain(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCloudCAS(t *testing.T) {
|
func TestCloudCAS_CreateCertificateAuthority(t *testing.T) {
|
||||||
cas, err := New(context.Background(), apiv1.Options{
|
must := func(a, b interface{}) interface{} {
|
||||||
Type: "cloudCAS",
|
return a
|
||||||
CertificateAuthority: "projects/smallstep-cas-test/locations/us-west1",
|
}
|
||||||
CredentialsFile: "/Users/mariano/smallstep-cas-test-8a068f3e4540.json",
|
|
||||||
})
|
// client, close := mockTestClient()
|
||||||
|
// defer close()
|
||||||
|
ctrl := gomock.NewController(t)
|
||||||
|
defer ctrl.Finish()
|
||||||
|
mosCtrl := gomock.NewController(t)
|
||||||
|
defer mosCtrl.Finish()
|
||||||
|
|
||||||
|
m := NewMockCertificateAuthorityClient(ctrl)
|
||||||
|
mos := NewMockOperationsServer(mosCtrl)
|
||||||
|
|
||||||
|
// Create operation server
|
||||||
|
lis, err := net.Listen("tcp", "localhost:0")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// resp, err := cas.CreateCertificateAuthority(&apiv1.CreateCertificateAuthorityRequest{
|
srv := grpc.NewServer()
|
||||||
// Type: apiv1.RootCA,
|
longrunningpb.RegisterOperationsServer(srv, mos)
|
||||||
// Template: &x509.Certificate{
|
|
||||||
// Subject: pkix.Name{
|
go srv.Serve(lis)
|
||||||
// CommonName: "Test Mariano Root CA",
|
defer srv.Stop()
|
||||||
// },
|
|
||||||
// BasicConstraintsValid: true,
|
// Create fake privateca client
|
||||||
// IsCA: true,
|
conn, err := grpc.Dial(lis.Addr().String(), grpc.WithInsecure())
|
||||||
// MaxPathLen: 1,
|
if err != nil {
|
||||||
// MaxPathLenZero: false,
|
t.Fatal(err)
|
||||||
// KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageCRLSign,
|
|
||||||
// },
|
|
||||||
// Lifetime: time.Duration(30 * 24 * time.Hour),
|
|
||||||
// Project: "smallstep-cas-test",
|
|
||||||
// Location: "us-west1",
|
|
||||||
// })
|
|
||||||
// if err != nil {
|
|
||||||
// t.Fatal(err)
|
|
||||||
// }
|
|
||||||
// debug(resp)
|
|
||||||
resp := &apiv1.CreateCertificateAuthorityResponse{
|
|
||||||
Name: "projects/smallstep-cas-test/locations/us-west1/certificateAuthorities/9a593da4-61af-4426-a2f8-0650373b9c8e",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err = cas.CreateCertificateAuthority(&apiv1.CreateCertificateAuthorityRequest{
|
client, err := lroauto.NewOperationsClient(context.Background(), option.WithGRPCConn(conn))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
fake := &privateca.CertificateAuthorityClient{
|
||||||
|
LROClient: client,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configure mocks
|
||||||
|
any := gomock.Any()
|
||||||
|
|
||||||
|
// ok root
|
||||||
|
m.EXPECT().CreateCertificateAuthority(any, any).Return(fake.CreateCertificateAuthorityOperation("CreateCertificateAuthority"), nil)
|
||||||
|
mos.EXPECT().GetOperation(any, any).Return(&longrunningpb.Operation{
|
||||||
|
Name: "CreateCertificateAuthority",
|
||||||
|
Done: true,
|
||||||
|
Result: &longrunningpb.Operation_Response{
|
||||||
|
Response: must(anypb.New(&pb.CertificateAuthority{
|
||||||
|
Name: testAuthorityName,
|
||||||
|
PemCaCertificates: []string{testRootCertificate},
|
||||||
|
})).(*anypb.Any),
|
||||||
|
},
|
||||||
|
}, nil)
|
||||||
|
|
||||||
|
// ok intermediate
|
||||||
|
m.EXPECT().CreateCertificateAuthority(any, any).Return(fake.CreateCertificateAuthorityOperation("CreateCertificateAuthority"), nil)
|
||||||
|
mos.EXPECT().GetOperation(any, any).Return(&longrunningpb.Operation{
|
||||||
|
Name: "CreateCertificateAuthority",
|
||||||
|
Done: true,
|
||||||
|
Result: &longrunningpb.Operation_Response{
|
||||||
|
Response: must(anypb.New(&pb.CertificateAuthority{
|
||||||
|
Name: testAuthorityName,
|
||||||
|
})).(*anypb.Any),
|
||||||
|
},
|
||||||
|
}, nil)
|
||||||
|
m.EXPECT().FetchCertificateAuthorityCsr(any, any).Return(&pb.FetchCertificateAuthorityCsrResponse{
|
||||||
|
PemCsr: testIntermediateCsr,
|
||||||
|
}, nil)
|
||||||
|
m.EXPECT().CreateCertificate(any, any).Return(&pb.Certificate{
|
||||||
|
PemCertificate: testIntermediateCertificate,
|
||||||
|
PemCertificateChain: []string{testRootCertificate},
|
||||||
|
}, nil)
|
||||||
|
m.EXPECT().ActivateCertificateAuthority(any, any).Return(fake.ActivateCertificateAuthorityOperation("ActivateCertificateAuthority"), nil)
|
||||||
|
mos.EXPECT().GetOperation(any, any).Return(&longrunningpb.Operation{
|
||||||
|
Name: "ActivateCertificateAuthority",
|
||||||
|
Done: true,
|
||||||
|
Result: &longrunningpb.Operation_Response{
|
||||||
|
Response: must(anypb.New(&pb.CertificateAuthority{
|
||||||
|
Name: testAuthorityName,
|
||||||
|
PemCaCertificates: []string{testIntermediateCertificate, testRootCertificate},
|
||||||
|
})).(*anypb.Any),
|
||||||
|
},
|
||||||
|
}, nil)
|
||||||
|
|
||||||
|
rootCrt := mustParseCertificate(t, testRootCertificate)
|
||||||
|
intCrt := mustParseCertificate(t, testIntermediateCertificate)
|
||||||
|
|
||||||
|
type fields struct {
|
||||||
|
client CertificateAuthorityClient
|
||||||
|
certificateAuthority string
|
||||||
|
project string
|
||||||
|
location string
|
||||||
|
}
|
||||||
|
type args struct {
|
||||||
|
req *apiv1.CreateCertificateAuthorityRequest
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
fields fields
|
||||||
|
args args
|
||||||
|
want *apiv1.CreateCertificateAuthorityResponse
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{"ok root", fields{m, "", testProject, testLocation}, args{&apiv1.CreateCertificateAuthorityRequest{
|
||||||
|
Type: apiv1.RootCA,
|
||||||
|
Template: mustParseCertificate(t, testRootCertificate),
|
||||||
|
Lifetime: 24 * time.Hour,
|
||||||
|
}}, &apiv1.CreateCertificateAuthorityResponse{
|
||||||
|
Name: testAuthorityName,
|
||||||
|
Certificate: rootCrt,
|
||||||
|
}, false},
|
||||||
|
{"ok intermediate", fields{m, "", testProject, testLocation}, args{&apiv1.CreateCertificateAuthorityRequest{
|
||||||
Type: apiv1.IntermediateCA,
|
Type: apiv1.IntermediateCA,
|
||||||
Template: &x509.Certificate{
|
Template: mustParseCertificate(t, testIntermediateCertificate),
|
||||||
Subject: pkix.Name{
|
Lifetime: 24 * time.Hour,
|
||||||
Country: []string{"US"},
|
Parent: &apiv1.CreateCertificateAuthorityResponse{
|
||||||
CommonName: "Test Mariano Intermediate CA",
|
Name: testAuthorityName,
|
||||||
|
Certificate: rootCrt,
|
||||||
},
|
},
|
||||||
BasicConstraintsValid: true,
|
}}, &apiv1.CreateCertificateAuthorityResponse{
|
||||||
IsCA: true,
|
Name: testAuthorityName,
|
||||||
MaxPathLen: 0,
|
Certificate: intCrt,
|
||||||
MaxPathLenZero: true,
|
CertificateChain: []*x509.Certificate{rootCrt},
|
||||||
KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageCRLSign,
|
}, false},
|
||||||
},
|
}
|
||||||
Lifetime: time.Duration(24 * time.Hour),
|
for _, tt := range tests {
|
||||||
Parent: resp,
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
Project: "smallstep-cas-test",
|
c := &CloudCAS{
|
||||||
Location: "us-west1",
|
client: tt.fields.client,
|
||||||
|
certificateAuthority: tt.fields.certificateAuthority,
|
||||||
|
project: tt.fields.project,
|
||||||
|
location: tt.fields.location,
|
||||||
|
}
|
||||||
|
got, err := c.CreateCertificateAuthority(tt.args.req)
|
||||||
|
if (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("CloudCAS.CreateCertificateAuthority() error = %+v, wantErr %v", err, tt.wantErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(got, tt.want) {
|
||||||
|
t.Errorf("CloudCAS.CreateCertificateAuthority() = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
}
|
||||||
// debug(resp)
|
|
||||||
t.Error("foo")
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -173,9 +173,7 @@ func (c *SoftCAS) CreateCertificateAuthority(req *apiv1.CreateCertificateAuthori
|
||||||
var chain []*x509.Certificate
|
var chain []*x509.Certificate
|
||||||
if req.Parent != nil {
|
if req.Parent != nil {
|
||||||
chain = append(chain, req.Parent.Certificate)
|
chain = append(chain, req.Parent.Certificate)
|
||||||
for _, crt := range req.Parent.CertificateChain {
|
chain = append(chain, req.Parent.CertificateChain...)
|
||||||
chain = append(chain, crt)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return &apiv1.CreateCertificateAuthorityResponse{
|
return &apiv1.CreateCertificateAuthorityResponse{
|
||||||
|
|
1
go.mod
1
go.mod
|
@ -8,6 +8,7 @@ require (
|
||||||
github.com/aws/aws-sdk-go v1.30.29
|
github.com/aws/aws-sdk-go v1.30.29
|
||||||
github.com/go-chi/chi v4.0.2+incompatible
|
github.com/go-chi/chi v4.0.2+incompatible
|
||||||
github.com/go-piv/piv-go v1.6.0
|
github.com/go-piv/piv-go v1.6.0
|
||||||
|
github.com/golang/mock v1.4.4
|
||||||
github.com/google/uuid v1.1.2
|
github.com/google/uuid v1.1.2
|
||||||
github.com/googleapis/gax-go/v2 v2.0.5
|
github.com/googleapis/gax-go/v2 v2.0.5
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect
|
github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect
|
||||||
|
|
2
go.sum
2
go.sum
|
@ -116,6 +116,7 @@ github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFU
|
||||||
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||||
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
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.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||||
|
github.com/golang/mock v1.4.4 h1:l75CXGRSwbaYNpl/Z2X1XIIAMSCquvXgpVZDhwEIJsc=
|
||||||
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
|
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
|
||||||
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
|
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
|
||||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
@ -134,6 +135,7 @@ 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.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
||||||
github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
|
github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
|
||||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||||
|
github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM=
|
||||||
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
|
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
|
||||||
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||||
|
|
Loading…
Reference in a new issue