Add srcprefix command arg to restrice src copyin

This commit is contained in:
criyle 2020-07-04 21:08:23 -07:00
parent 9448892f61
commit 7535e5862f
10 changed files with 95 additions and 38 deletions

View File

@ -58,6 +58,7 @@ The `executorserver` need root privilege to create `cgroup`. Either creates sub-
- The default file store is in memory, local cache can be specified with `-dir` flag.
- The default log level is debug, use `-silent` to disable logs.
- `-token` to add token-based authentication to REST / gRPC
- `-srcprefix` to restrict `src` copyIn path (need to be absolute path)
#### Environment Variables

View File

@ -19,10 +19,10 @@ func handleRun(c *gin.Context) {
c.AbortWithStatusJSON(http.StatusBadRequest, "no cmd provided")
return
}
r, err := model.ConvertRequest(&req)
r, err := model.ConvertRequest(&req, *srcPrefix)
if err != nil {
c.Error(err)
c.AbortWithStatusJSON(http.StatusBadRequest, err.Error)
c.AbortWithStatusJSON(http.StatusBadRequest, err.Error())
return
}
rt := <-work.Submit(c.Request.Context(), r)

View File

@ -4,6 +4,8 @@ import (
"context"
"fmt"
"os"
"path/filepath"
"strings"
"sync"
"github.com/creack/pty"
@ -22,11 +24,12 @@ var buffPool = sync.Pool{
type execServer struct {
pb.UnimplementedExecutorServer
fs filestore.FileStore
fs filestore.FileStore
srcPrefix string
}
func (e *execServer) Exec(ctx context.Context, req *pb.Request) (*pb.Response, error) {
r, si, so, err := convertPBRequest(req)
r, si, so, err := convertPBRequest(req, e.srcPrefix)
if err != nil {
return nil, err
}
@ -104,7 +107,7 @@ func convertPBResult(r worker.Result) *pb.Response_Result {
}
}
func convertPBRequest(r *pb.Request) (req *worker.Request, streamIn []*fileStreamIn, streamOut []*fileStreamOut, err error) {
func convertPBRequest(r *pb.Request, srcPrefix string) (req *worker.Request, streamIn []*fileStreamIn, streamOut []*fileStreamOut, err error) {
defer func() {
if err != nil {
for _, fi := range streamIn {
@ -123,7 +126,7 @@ func convertPBRequest(r *pb.Request) (req *worker.Request, streamIn []*fileStrea
PipeMapping: make([]worker.PipeMap, 0, len(r.PipeMapping)),
}
for _, c := range r.Cmd {
cm, si, so, err := convertPBCmd(c)
cm, si, so, err := convertPBCmd(c, srcPrefix)
streamIn = append(streamIn, si...)
streamOut = append(streamOut, so...)
if err != nil {
@ -151,7 +154,7 @@ func convertPBPipeMap(p *pb.Request_PipeMap) worker.PipeMap {
}
}
func convertPBCmd(c *pb.Request_CmdType) (cm worker.Cmd, streamIn []*fileStreamIn, streamOut []*fileStreamOut, err error) {
func convertPBCmd(c *pb.Request_CmdType, srcPrefix string) (cm worker.Cmd, streamIn []*fileStreamIn, streamOut []*fileStreamOut, err error) {
defer func() {
if err != nil {
for _, fi := range streamIn {
@ -227,7 +230,7 @@ func convertPBCmd(c *pb.Request_CmdType) (cm worker.Cmd, streamIn []*fileStreamI
cf = so
default:
cf, err = convertPBFile(f)
cf, err = convertPBFile(f, srcPrefix)
}
if err != nil {
return cm, streamIn, streamOut, err
@ -237,7 +240,7 @@ func convertPBCmd(c *pb.Request_CmdType) (cm worker.Cmd, streamIn []*fileStreamI
if copyIn := c.GetCopyIn(); copyIn != nil {
cm.CopyIn = make(map[string]worker.CmdFile)
for k, f := range copyIn {
cf, err := convertPBFile(f)
cf, err := convertPBFile(f, srcPrefix)
if err != nil {
return cm, streamIn, streamOut, err
}
@ -247,11 +250,20 @@ func convertPBCmd(c *pb.Request_CmdType) (cm worker.Cmd, streamIn []*fileStreamI
return cm, streamIn, streamOut, nil
}
func convertPBFile(c *pb.Request_File) (worker.CmdFile, error) {
func convertPBFile(c *pb.Request_File, srcPrefix string) (worker.CmdFile, error) {
switch c := c.File.(type) {
case nil:
return nil, nil
case *pb.Request_File_Local:
if srcPrefix != "" {
ok, err := checkPathPrefix(c.Local.GetSrc(), srcPrefix)
if err != nil {
return nil, err
}
if !ok {
return nil, fmt.Errorf("file (%s) does not under (%s)", c.Local.GetSrc(), srcPrefix)
}
}
return &worker.LocalFile{Src: c.Local.GetSrc()}, nil
case *pb.Request_File_Memory:
return &worker.MemoryFile{Content: c.Memory.GetContent()}, nil
@ -262,3 +274,14 @@ func convertPBFile(c *pb.Request_File) (worker.CmdFile, error) {
}
return nil, fmt.Errorf("request file type not supported yet %v", c)
}
func checkPathPrefix(path, prefix string) (bool, error) {
if filepath.IsAbs(path) {
return strings.HasPrefix(filepath.Clean(path), prefix), nil
}
wd, err := os.Getwd()
if err != nil {
return false, err
}
return strings.HasPrefix(filepath.Join(wd, path), prefix), nil
}

View File

@ -17,7 +17,7 @@ func (e *execServer) ExecStream(es pb.Executor_ExecStreamServer) error {
if req == nil {
return fmt.Errorf("The first stream request must be exec request")
}
rq, streamIn, streamOut, err := convertPBRequest(req)
rq, streamIn, streamOut, err := convertPBRequest(req, e.srcPrefix)
if err != nil {
return err
}

View File

@ -60,6 +60,7 @@ var (
cinitPath = flag.String("cinit", "", "container init absolute path")
token = flag.String("token", "", "bearer token auth for REST / gRPC")
release = flag.Bool("release", false, "use release mode for log")
srcPrefix = flag.String("srcprefix", "", "specifies directory prefix for source type copyin")
printLog = func(v ...interface{}) {}
@ -217,7 +218,7 @@ func main() {
grpc.StreamInterceptor(grpc_middleware.ChainStreamServer(streamMiddleware...)),
grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer(unaryMiddleware...)),
)
pb.RegisterExecutorServer(grpcServer, &execServer{fs: fs})
pb.RegisterExecutorServer(grpcServer, &execServer{fs: fs, srcPrefix: *srcPrefix})
grpc_prometheus.Register(grpcServer)
grpc_prometheus.EnableHandlingTimeHistogram()

View File

@ -2,6 +2,9 @@ package model
import (
"fmt"
"os"
"path/filepath"
"strings"
"github.com/criyle/go-judge/pkg/envexec"
"github.com/criyle/go-judge/worker"
@ -99,14 +102,14 @@ func ConvertResponse(r worker.Response) Response {
}
// ConvertRequest converts json request into worker request
func ConvertRequest(r *Request) (*worker.Request, error) {
func ConvertRequest(r *Request, srcPrefix string) (*worker.Request, error) {
req := &worker.Request{
RequestID: r.RequestID,
Cmd: make([]worker.Cmd, 0, len(r.Cmd)),
PipeMapping: make([]worker.PipeMap, 0, len(r.PipeMapping)),
}
for _, c := range r.Cmd {
wc, err := convertCmd(c)
wc, err := convertCmd(c, srcPrefix)
if err != nil {
return nil, err
}
@ -150,7 +153,7 @@ func convertPipe(p PipeMap) worker.PipeMap {
}
}
func convertCmd(c Cmd) (worker.Cmd, error) {
func convertCmd(c Cmd, srcPrefix string) (worker.Cmd, error) {
w := worker.Cmd{
Args: c.Args,
Env: c.Env,
@ -167,7 +170,7 @@ func convertCmd(c Cmd) (worker.Cmd, error) {
CopyOutDir: c.CopyOutDir,
}
for _, f := range c.Files {
cf, err := convertCmdFile(f)
cf, err := convertCmdFile(f, srcPrefix)
if err != nil {
return w, err
}
@ -176,7 +179,7 @@ func convertCmd(c Cmd) (worker.Cmd, error) {
if c.CopyIn != nil {
w.CopyIn = make(map[string]worker.CmdFile)
for k, f := range c.CopyIn {
cf, err := convertCmdFile(&f)
cf, err := convertCmdFile(&f, srcPrefix)
if err != nil {
return w, err
}
@ -186,11 +189,20 @@ func convertCmd(c Cmd) (worker.Cmd, error) {
return w, nil
}
func convertCmdFile(f *CmdFile) (worker.CmdFile, error) {
func convertCmdFile(f *CmdFile, srcPrefix string) (worker.CmdFile, error) {
switch {
case f == nil:
return nil, nil
case f.Src != nil:
if srcPrefix != "" {
ok, err := checkPathPrefix(*f.Src, srcPrefix)
if err != nil {
return nil, err
}
if !ok {
return nil, fmt.Errorf("file (%s) does not under (%s)", *f.Src, srcPrefix)
}
}
return &worker.LocalFile{Src: *f.Src}, nil
case f.Content != nil:
return &worker.MemoryFile{Content: []byte(*f.Content)}, nil
@ -202,3 +214,14 @@ func convertCmdFile(f *CmdFile) (worker.CmdFile, error) {
return nil, fmt.Errorf("file is not valid for cmd")
}
}
func checkPathPrefix(path, prefix string) (bool, error) {
if filepath.IsAbs(path) {
return strings.HasPrefix(filepath.Clean(path), prefix), nil
}
wd, err := os.Getwd()
if err != nil {
return false, err
}
return strings.HasPrefix(filepath.Join(wd, path), prefix), nil
}

View File

@ -48,7 +48,7 @@ func handleWS(c *gin.Context) {
printLog("ws read:", err)
return
}
r, err := model.ConvertRequest(req)
r, err := model.ConvertRequest(req, *srcPrefix)
if err != nil {
printLog("convert", err)
return

View File

@ -23,11 +23,14 @@ type initParameter struct {
Dir string `json:"dir"`
NetShare bool `json:"netShare"`
MountConf string `json:"mountConf"`
SrcPrefix string `json:"srcPrefix"`
}
var (
fs filestore.FileStore
work *worker.Worker
srcPrefix string
)
func newFilsStore(dir string) filestore.FileStore {
@ -62,6 +65,8 @@ func Init(i *C.char) C.int {
ip.MountConf = "mount.yaml"
}
srcPrefix = ip.SrcPrefix
fs = newFilsStore(ip.Dir)
printLog := func(v ...interface{}) {}
@ -84,7 +89,7 @@ func Exec(e *C.char) *C.char {
if err := json.NewDecoder(bytes.NewBufferString(es)).Decode(&req); err != nil {
return nil
}
r, err := model.ConvertRequest(&req)
r, err := model.ConvertRequest(&req, srcPrefix)
if err != nil {
return nil
}

10
go.mod
View File

@ -12,13 +12,13 @@ require (
github.com/gorilla/websocket v1.4.2
github.com/grpc-ecosystem/go-grpc-middleware v1.2.0
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0
github.com/prometheus/client_golang v1.6.0
github.com/prometheus/client_golang v1.7.1
github.com/zsais/go-gin-prometheus v0.1.0
go.uber.org/zap v1.15.0
golang.org/x/crypto v0.0.0-20200602180216-279210d13fed
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a
golang.org/x/sys v0.0.0-20200602100848-8d3cce7afc34
google.golang.org/grpc v1.29.1
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae
google.golang.org/grpc v1.30.0
google.golang.org/protobuf v1.23.0
gopkg.in/yaml.v2 v2.3.0
)

30
go.sum
View File

@ -85,6 +85,8 @@ github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCV
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68=
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
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=
@ -123,20 +125,20 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.6.0 h1:YVPodQOcK15POxhgARIvnDRVpLcuK8mglnMrWfyrw6A=
github.com/prometheus/client_golang v1.6.0/go.mod h1:ZLOG9ck3JLRdB5MgO8f+lLTe83AXG6ro35rLTxvnIl4=
github.com/prometheus/client_golang v1.7.1 h1:NTGy1Ja9pByO+xAeH/qiWnLrKtr3hJPNjaVUwnjpdpA=
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/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.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M=
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.9.1 h1:KOMtN28tlbam3/7ZKEYKHhKoJZYYj3gMH4uc62x7X7U=
github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4=
github.com/prometheus/common v0.10.0 h1:RyRA7RzGXQZiW+tGMr7sxa85G1z0yOpM1qq5c8lNawc=
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.11 h1:DhHlBtkHWPYi8O2y31JkK0TF+DGM+51OopZjH/Ia5qI=
github.com/prometheus/procfs v0.0.11/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/prometheus/procfs v0.1.3 h1:F0+tqvhOksq22sc6iCHF5WGlWjdwj92p0udFh1VFBS8=
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
@ -173,8 +175,8 @@ golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnf
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200602180216-279210d13fed h1:g4KENRiCMEx58Q7/ecwfT0N2o8z35Fnbsjig/Alf2T4=
golang.org/x/crypto v0.0.0-20200602180216-279210d13fed/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
@ -199,8 +201,8 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a h1:WXEvlFVvvGxCJLG6REjsT03iWnKLEWinaScsxF2Vm2o=
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208 h1:qwRHBd0NqMbJxfbotnDhm2ByMI1Shq4Y6oRJo21SGJA=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@ -212,9 +214,11 @@ golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200602100848-8d3cce7afc34 h1:u6CI7A++8r4SItZHYe2cWeAEndN4p1p+3Oum/Ft2EzM=
golang.org/x/sys v0.0.0-20200602100848-8d3cce7afc34/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae h1:Ih9Yo4hSPImZOpfGuA4bR/ORKTAbhZo2AbWNRCnevdo=
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
@ -240,8 +244,8 @@ google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.29.1 h1:EC2SB8S04d2r73uptxphDSUG+kTKVgjRPF+N3xpxRB4=
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
google.golang.org/grpc v1.30.0 h1:M5a8xTlYTxwMn5ZFkwhRabsygDY5G8TYLyQDBxJNAxE=
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
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=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=