├── .gitignore ├── gcsproxy.service ├── Makefile ├── .github └── workflows │ └── release.yaml ├── Dockerfile ├── .goreleaser.yml ├── LICENSE ├── go.mod ├── README.md ├── main.go └── go.sum /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor/ 2 | /bin/ 3 | /dist/ 4 | -------------------------------------------------------------------------------- /gcsproxy.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=gcsproxy 3 | 4 | [Service] 5 | Type=simple 6 | ExecStart=/opt/gcsproxy/gcsproxy -v 7 | ExecStop=/bin/kill -SIGTERM $MAINPID 8 | 9 | [Install] 10 | WantedBy = multi-user.target -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | BIN_NAME := gcsproxy 2 | GOFILES := $(shell find . -type f -name '*.go') 3 | 4 | build: bin/$(BIN_NAME) 5 | 6 | bin/$(BIN_NAME): $(GOFILES) 7 | go build -o $@ . 8 | 9 | build-cross: clean 10 | GOOS=linux GOARCH=amd64 go build -o dist/$(BIN_NAME)_amd64_linux 11 | GOOS=darwin GOARCH=amd64 go build -o dist/$(BIN_NAME)_amd64_darwin 12 | GOOS=linux GOARCH=arm go build -o dist/$(BIN_NAME)_arm_linux 13 | GOOS=darwin GOARCH=arm go build -o dist/$(BIN_NAME)_arm_darwin 14 | 15 | clean: 16 | rm -rf bin dist 17 | 18 | deps: 19 | go get -t ./... 20 | go mod tidy 21 | 22 | test: 23 | go test -race -v ./... 24 | -------------------------------------------------------------------------------- /.github/workflows/release.yaml: -------------------------------------------------------------------------------- 1 | name: Release 2 | on: 3 | push: 4 | tags: 5 | - v* 6 | jobs: 7 | goreleaser: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - name: Checkout 11 | uses: actions/checkout@v4 12 | with: 13 | fetch-depth: 0 14 | - name: Set up Go 15 | uses: actions/setup-go@v5 16 | with: 17 | go-version: '1.23' 18 | - name: Run GoReleaser 19 | uses: goreleaser/goreleaser-action@v4 20 | with: 21 | version: latest 22 | args: release --clean 23 | env: 24 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 25 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM debian:buster-slim AS build 2 | 3 | WORKDIR /tmp 4 | ARG GCSPROXY_VERSION=0.4.2 5 | 6 | RUN apt-get update \ 7 | && apt-get install --no-install-suggests --no-install-recommends --yes ca-certificates wget \ 8 | && wget https://github.com/daichirata/gcsproxy/releases/download/v${GCSPROXY_VERSION}/gcsproxy-${GCSPROXY_VERSION}-linux-amd64.tar.gz \ 9 | && tar zxf gcsproxy-${GCSPROXY_VERSION}-linux-amd64.tar.gz \ 10 | && cp ./gcsproxy-${GCSPROXY_VERSION}-linux-amd64/gcsproxy . 11 | 12 | FROM gcr.io/distroless/base 13 | COPY --from=build /tmp/gcsproxy /gcsproxy 14 | ENTRYPOINT ["/gcsproxy"] 15 | CMD [ "-b", "0.0.0.0:80" ] 16 | -------------------------------------------------------------------------------- /.goreleaser.yml: -------------------------------------------------------------------------------- 1 | before: 2 | hooks: 3 | - go mod download 4 | builds: 5 | - main: . 6 | binary: gcsproxy 7 | env: 8 | - CGO_ENABLED=0 9 | goos: 10 | - darwin 11 | - linux 12 | - windows 13 | goarch: 14 | - amd64 15 | - arm64 16 | - arm 17 | - 386 18 | ignore: 19 | - goos: darwin 20 | goarch: 386 21 | 22 | archives: 23 | - format: tar.gz 24 | wrap_in_directory: true 25 | format_overrides: 26 | - goos: windows 27 | format: zip 28 | name_template: '{{ .ProjectName }}-{{ .Version }}-{{ .Os }}-{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}' 29 | files: 30 | - LICENSE 31 | - README.md 32 | 33 | checksum: 34 | name_template: 'checksums.txt' 35 | 36 | snapshot: 37 | name_template: "SNAPSHOT-{{ .Tag }}" 38 | 39 | changelog: 40 | sort: asc 41 | filters: 42 | exclude: 43 | - '^test:' 44 | - 'README' 45 | - Merge pull request 46 | - Merge branch 47 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Daichi Hirata 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/daichirata/gcsproxy 2 | 3 | go 1.23 4 | 5 | require ( 6 | cloud.google.com/go/storage v1.43.0 7 | github.com/gorilla/mux v1.8.1 8 | google.golang.org/api v0.197.0 9 | ) 10 | 11 | require ( 12 | cloud.google.com/go v0.115.1 // indirect 13 | cloud.google.com/go/auth v0.9.3 // indirect 14 | cloud.google.com/go/auth/oauth2adapt v0.2.4 // indirect 15 | cloud.google.com/go/compute/metadata v0.5.0 // indirect 16 | cloud.google.com/go/iam v1.2.0 // indirect 17 | github.com/felixge/httpsnoop v1.0.4 // indirect 18 | github.com/go-logr/logr v1.4.2 // indirect 19 | github.com/go-logr/stdr v1.2.2 // indirect 20 | github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect 21 | github.com/google/s2a-go v0.1.8 // indirect 22 | github.com/google/uuid v1.6.0 // indirect 23 | github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect 24 | github.com/googleapis/gax-go/v2 v2.13.0 // indirect 25 | go.opencensus.io v0.24.0 // indirect 26 | go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.54.0 // indirect 27 | go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 // indirect 28 | go.opentelemetry.io/otel v1.29.0 // indirect 29 | go.opentelemetry.io/otel/metric v1.29.0 // indirect 30 | go.opentelemetry.io/otel/trace v1.29.0 // indirect 31 | golang.org/x/crypto v0.27.0 // indirect 32 | golang.org/x/net v0.29.0 // indirect 33 | golang.org/x/oauth2 v0.23.0 // indirect 34 | golang.org/x/sync v0.8.0 // indirect 35 | golang.org/x/sys v0.25.0 // indirect 36 | golang.org/x/text v0.18.0 // indirect 37 | golang.org/x/time v0.6.0 // indirect 38 | google.golang.org/genproto v0.0.0-20240903143218-8af14fe29dc1 // indirect 39 | google.golang.org/genproto/googleapis/api v0.0.0-20240827150818-7e3bb234dfed // indirect 40 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect 41 | google.golang.org/grpc v1.66.1 // indirect 42 | google.golang.org/protobuf v1.34.2 // indirect 43 | ) 44 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # gcsproxy 2 | 3 | Reverse proxy for Google Cloud Storage. 4 | 5 | ## Description 6 | 7 | This is a reverse proxy for Google Cloud Storage for performing limited disclosure (IP address restriction etc...). Gets the URL of the GCS object through its internal API. Therefore, it is possible to make GCS objects private and deliver limited content. 8 | 9 | ``` 10 | +---------------------------------------+ 11 | | Nginx | 12 | | access control (basic auth/ip) | 13 | +-----+---------------------------------+ 14 | | 15 | -----------------------------------------+ 16 | | 17 | | 18 | +------v-----+ +---------------+ 19 | | | | | 20 | | gcsproxy | +------> | Google Cloud | 21 | | | | Storage | 22 | +------------+ +---------------+ 23 | ``` 24 | 25 | ## Usage 26 | 27 | ``` 28 | Usage of gcsproxy: 29 | -b string 30 | Bind address (default "127.0.0.1:8080") 31 | -c string 32 | The path to the keyfile. If not present, client will use your default application credentials. 33 | -i string 34 | The default index file to serve. 35 | -v Show access log 36 | 37 | ``` 38 | 39 | The gcsproxy routing configuration is shown below. 40 | 41 | `"/{bucket:[0-9a-zA-Z-_.] +}/{object:. *}"` 42 | 43 | If you are running gcsproxy on localhost:8080 and you want to access the file `gs://test-bucket/your/file/path.txt` in GCS via gcsproxy, 44 | you can use the URL You can access the file via gcsproxy at the URL `http://localhost:8080/test-bucket/your/file/path.txt`. 45 | 46 | If a default index file is specified and the target object does not exist, an attempt is made to retrieve the object specified in the default index file. 47 | 48 | ``` 49 | gcsproxy -i index.html 50 | 51 | http://localhost:8080/test-bucket/foo/bar 52 | #=> gs://test-bucket/foo/bar/index.html 53 | ``` 54 | 55 | ## Configurations 56 | 57 | **Dockerfile example** 58 | 59 | ``` dockerfile 60 | FROM debian:buster-slim AS build 61 | 62 | WORKDIR /tmp 63 | ENV GCSPROXY_VERSION=0.3.1 64 | 65 | RUN apt-get update \ 66 | && apt-get install --no-install-suggests --no-install-recommends --yes ca-certificates wget \ 67 | && wget https://github.com/daichirata/gcsproxy/releases/download/v${GCSPROXY_VERSION}/gcsproxy-${GCSPROXY_VERSION}-linux-amd64.tar.gz \ 68 | && tar zxf gcsproxy-${GCSPROXY_VERSION}-linux-amd64.tar.gz \ 69 | && cp ./gcsproxy-${GCSPROXY_VERSION}-linux-amd64/gcsproxy . 70 | 71 | FROM gcr.io/distroless/base 72 | COPY --from=build /tmp/gcsproxy /gcsproxy 73 | CMD ["/gcsproxy"] 74 | ``` 75 | 76 | ### Docker image build example 77 | 78 | ```bash 79 | docker build --build-arg GCSPROXY_VERSION=0.4.0 -t gcsproxy . 80 | ``` 81 | 82 | Example how to run the image 83 | 84 | The **d53ee11da87c.json** JSON files contains the Google Cloud Service Account credentials. 85 | 86 | ```bash 87 | docker run \ 88 | -it --rm \ 89 | -p 8080:80 \ 90 | -e GOOGLE_APPLICATION_CREDENTIALS=/cred.json \ 91 | -v $(pwd)/../d53ee11da87c.json:/cred.json gcsproxy 92 | ``` 93 | 94 | ### Docker Compose example 95 | 96 | ```dockerfile 97 | version: '3.3' 98 | 99 | networks: 100 | web: 101 | 102 | services: 103 | gcsproxy: 104 | build: 105 | context: . 106 | dockerfile: Dockerfile 107 | args: 108 | GCSPROXY_VERSION: 0.4.0 109 | #HTTPS_PROXY: http://192.168.1.1:8080/ 110 | #HTTP_PROXY: http://192.168.1.1:8080/ 111 | restart: unless-stopped 112 | networks: 113 | - "web" 114 | ports: 115 | - 8080:80 116 | command: -b 0.0.0.0:80 -c /cred.json 117 | #environment: 118 | #HTTPS_PROXY: http://192.168.1.1:8080/ 119 | #HTTP_PROXY: http://192.168.1.1:8080/ 120 | volumes: 121 | - ./d53ee11da87c.json:/cred.json 122 | ``` 123 | 124 | 125 | **systemd example** 126 | 127 | ``` 128 | [Unit] 129 | Description=gcsproxy 130 | 131 | [Service] 132 | Type=simple 133 | ExecStart=/opt/gcsproxy/gcsproxy -v 134 | ExecStop=/bin/kill -SIGTERM $MAINPID 135 | 136 | [Install] 137 | WantedBy = multi-user.target 138 | ``` 139 | 140 | **nginx.conf** 141 | 142 | ``` 143 | upstream gcsproxy { 144 | server '127.0.0.1:8080'; 145 | } 146 | 147 | server { 148 | listen 8081; 149 | server_name _; 150 | 151 | # Logs 152 | access_log off; 153 | error_log /var/log/nginx/gcsproxy.error.log error; 154 | 155 | if ($request_method !~ "GET|HEAD|PURGE") { 156 | return 405; 157 | } 158 | 159 | location / { 160 | proxy_pass http://gcsproxy$uri; 161 | } 162 | } 163 | ``` 164 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "errors" 6 | "flag" 7 | "io" 8 | "log" 9 | "net/http" 10 | "net/url" 11 | "strconv" 12 | "strings" 13 | "time" 14 | 15 | "cloud.google.com/go/storage" 16 | "github.com/gorilla/mux" 17 | "google.golang.org/api/option" 18 | ) 19 | 20 | var ( 21 | bind = flag.String("b", "127.0.0.1:8080", "Bind address") 22 | verbose = flag.Bool("v", false, "Show access log") 23 | credentials = flag.String("c", "", "The path to the keyfile. If not present, client will use your default application credentials.") 24 | defaultIndex = flag.String("i", "", "The default index file to serve.") 25 | ) 26 | 27 | var client *storage.Client 28 | 29 | func handleError(w http.ResponseWriter, err error) { 30 | if errors.Is(err, storage.ErrObjectNotExist) { 31 | http.Error(w, err.Error(), http.StatusNotFound) 32 | } else { 33 | http.Error(w, err.Error(), http.StatusInternalServerError) 34 | } 35 | } 36 | 37 | func header(r *http.Request, key string) (string, bool) { 38 | if r.Header == nil { 39 | return "", false 40 | } 41 | if candidate := r.Header[key]; len(candidate) > 0 { 42 | return candidate[0], true 43 | } 44 | return "", false 45 | } 46 | 47 | func setStrHeader(w http.ResponseWriter, key string, value string) { 48 | if value != "" { 49 | w.Header().Add(key, value) 50 | } 51 | } 52 | 53 | func setIntHeader(w http.ResponseWriter, key string, value int64) { 54 | if value > 0 { 55 | w.Header().Add(key, strconv.FormatInt(value, 10)) 56 | } 57 | } 58 | 59 | func setTimeHeader(w http.ResponseWriter, key string, value time.Time) { 60 | if !value.IsZero() { 61 | w.Header().Add(key, value.UTC().Format(http.TimeFormat)) 62 | } 63 | } 64 | 65 | type wrapResponseWriter struct { 66 | http.ResponseWriter 67 | status int 68 | } 69 | 70 | func (w *wrapResponseWriter) WriteHeader(status int) { 71 | w.ResponseWriter.WriteHeader(status) 72 | w.status = status 73 | } 74 | 75 | func wrapper(fn func(w http.ResponseWriter, r *http.Request)) http.HandlerFunc { 76 | return func(w http.ResponseWriter, r *http.Request) { 77 | proc := time.Now() 78 | writer := &wrapResponseWriter{ 79 | ResponseWriter: w, 80 | status: http.StatusOK, 81 | } 82 | fn(writer, r) 83 | addr := r.RemoteAddr 84 | if ip, found := header(r, "X-Forwarded-For"); found { 85 | addr = ip 86 | } 87 | if *verbose { 88 | log.Printf("[%s] %.3f %d %s %s", 89 | addr, 90 | time.Now().Sub(proc).Seconds(), 91 | writer.status, 92 | r.Method, 93 | r.URL, 94 | ) 95 | } 96 | } 97 | } 98 | 99 | func fetchObjectAttrs(ctx context.Context, bucket, object string) (*storage.ObjectAttrs, error) { 100 | var err error 101 | var indexAppended bool 102 | if object == "" && *defaultIndex != "" { 103 | object, err = url.JoinPath(object, *defaultIndex) 104 | if err != nil { 105 | return nil, err 106 | } 107 | indexAppended = true 108 | } 109 | 110 | attrs, err := client.Bucket(bucket).Object(strings.TrimSuffix(object, "/")).Attrs(ctx) 111 | if err != nil { 112 | if errors.Is(err, storage.ErrObjectNotExist) { 113 | if *defaultIndex == "" || indexAppended { 114 | return nil, err 115 | } 116 | object, err = url.JoinPath(object, *defaultIndex) 117 | if err != nil { 118 | return nil, err 119 | } 120 | return client.Bucket(bucket).Object(object).Attrs(ctx) 121 | } 122 | return nil, err 123 | } 124 | return attrs, nil 125 | } 126 | 127 | func proxy(w http.ResponseWriter, r *http.Request) { 128 | params := mux.Vars(r) 129 | 130 | attrs, err := fetchObjectAttrs(r.Context(), params["bucket"], params["object"]) 131 | if err != nil { 132 | handleError(w, err) 133 | return 134 | } 135 | if lastStrs, ok := r.Header["If-Modified-Since"]; ok && len(lastStrs) > 0 { 136 | last, err := http.ParseTime(lastStrs[0]) 137 | if *verbose && err != nil { 138 | log.Printf("could not parse If-Modified-Since: %v", err) 139 | } 140 | if !attrs.Updated.Truncate(time.Second).After(last) { 141 | w.WriteHeader(304) 142 | return 143 | } 144 | } 145 | 146 | gzipAcceptable := strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") 147 | objr, err := client.Bucket(attrs.Bucket).Object(attrs.Name).ReadCompressed(gzipAcceptable).NewReader(r.Context()) 148 | if err != nil { 149 | handleError(w, err) 150 | return 151 | } 152 | setTimeHeader(w, "Last-Modified", attrs.Updated) 153 | setStrHeader(w, "Content-Type", attrs.ContentType) 154 | setStrHeader(w, "Content-Language", attrs.ContentLanguage) 155 | setStrHeader(w, "Cache-Control", attrs.CacheControl) 156 | setStrHeader(w, "Content-Encoding", objr.Attrs.ContentEncoding) 157 | setStrHeader(w, "Content-Disposition", attrs.ContentDisposition) 158 | setIntHeader(w, "Content-Length", objr.Attrs.Size) 159 | io.Copy(w, objr) 160 | } 161 | 162 | func healthCheck(w http.ResponseWriter, r *http.Request) { 163 | setStrHeader(w, "Content-Type", "text/plain") 164 | io.WriteString(w, "OK\n") 165 | } 166 | 167 | func main() { 168 | flag.Parse() 169 | 170 | var err error 171 | if *credentials != "" { 172 | client, err = storage.NewClient(context.Background(), option.WithCredentialsFile(*credentials)) 173 | } else { 174 | client, err = storage.NewClient(context.Background()) 175 | } 176 | if err != nil { 177 | log.Fatalf("Failed to create client: %v", err) 178 | } 179 | 180 | r := mux.NewRouter() 181 | r.HandleFunc("/_health", wrapper(healthCheck)).Methods("GET", "HEAD") 182 | r.HandleFunc("/{bucket:[0-9a-zA-Z-_.]+}/{object:.*}", wrapper(proxy)).Methods("GET", "HEAD") 183 | 184 | log.Printf("[service] listening on %s", *bind) 185 | if err := http.ListenAndServe(*bind, r); err != nil { 186 | log.Fatal(err) 187 | } 188 | } 189 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 2 | cloud.google.com/go v0.115.1 h1:Jo0SM9cQnSkYfp44+v+NQXHpcHqlnRJk2qxh6yvxxxQ= 3 | cloud.google.com/go v0.115.1/go.mod h1:DuujITeaufu3gL68/lOFIirVNJwQeyf5UXyi+Wbgknc= 4 | cloud.google.com/go/auth v0.9.3 h1:VOEUIAADkkLtyfr3BLa3R8Ed/j6w1jTBmARx+wb5w5U= 5 | cloud.google.com/go/auth v0.9.3/go.mod h1:7z6VY+7h3KUdRov5F1i8NDP5ZzWKYmEPO842BgCsmTk= 6 | cloud.google.com/go/auth/oauth2adapt v0.2.4 h1:0GWE/FUsXhf6C+jAkWgYm7X9tK8cuEIfy19DBn6B6bY= 7 | cloud.google.com/go/auth/oauth2adapt v0.2.4/go.mod h1:jC/jOpwFP6JBxhB3P5Rr0a9HLMC/Pe3eaL4NmdvqPtc= 8 | cloud.google.com/go/compute/metadata v0.5.0 h1:Zr0eK8JbFv6+Wi4ilXAR8FJ3wyNdpxHKJNPos6LTZOY= 9 | cloud.google.com/go/compute/metadata v0.5.0/go.mod h1:aHnloV2TPI38yx4s9+wAZhHykWvVCfu7hQbF+9CWoiY= 10 | cloud.google.com/go/iam v1.2.0 h1:kZKMKVNk/IsSSc/udOb83K0hL/Yh/Gcqpz+oAkoIFN8= 11 | cloud.google.com/go/iam v1.2.0/go.mod h1:zITGuWgsLZxd8OwAlX+eMFgZDXzBm7icj1PVTYG766Q= 12 | cloud.google.com/go/longrunning v0.6.0 h1:mM1ZmaNsQsnb+5n1DNPeL0KwQd9jQRqSqSDEkBZr+aI= 13 | cloud.google.com/go/longrunning v0.6.0/go.mod h1:uHzSZqW89h7/pasCWNYdUpwGz3PcVWhrWupreVPYLts= 14 | cloud.google.com/go/storage v1.43.0 h1:CcxnSohZwizt4LCzQHWvBf1/kvtHUn7gk9QERXPyXFs= 15 | cloud.google.com/go/storage v1.43.0/go.mod h1:ajvxEa7WmZS1PxvKRq4bq0tFT3vMd502JwstCcYv0Q0= 16 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 17 | github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= 18 | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 19 | github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= 20 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 21 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 22 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 23 | github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 24 | github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 25 | github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= 26 | github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= 27 | github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= 28 | github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= 29 | github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= 30 | github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= 31 | github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= 32 | github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= 33 | github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= 34 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 35 | github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 36 | github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= 37 | github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 38 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 39 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 40 | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 41 | github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= 42 | github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= 43 | github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= 44 | github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= 45 | github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= 46 | github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= 47 | github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 48 | github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= 49 | github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= 50 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= 51 | github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 52 | github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 53 | github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 54 | github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 55 | github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 56 | github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= 57 | github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 58 | github.com/google/martian/v3 v3.3.3 h1:DIhPTQrbPkgs2yJYdXU/eNACCG5DVQjySNRNlflZ9Fc= 59 | github.com/google/martian/v3 v3.3.3/go.mod h1:iEPrYcgCF7jA9OtScMFQyAlZZ4YXTKEtJ1E6RWzmBA0= 60 | github.com/google/s2a-go v0.1.8 h1:zZDs9gcbt9ZPLV0ndSyQk6Kacx2g/X+SKYovpnz3SMM= 61 | github.com/google/s2a-go v0.1.8/go.mod h1:6iNWHTpQ+nfNRN5E00MSdfDwVesa8hhS32PhPO8deJA= 62 | github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 63 | github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= 64 | github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 65 | github.com/googleapis/enterprise-certificate-proxy v0.3.4 h1:XYIDZApgAnrN1c855gTgghdIA6Stxb52D5RnLI1SLyw= 66 | github.com/googleapis/enterprise-certificate-proxy v0.3.4/go.mod h1:YKe7cfqYXjKGpGvmSg28/fFvhNzinZQm8DGnaburhGA= 67 | github.com/googleapis/gax-go/v2 v2.13.0 h1:yitjD5f7jQHhyDsnhKEBU52NdvvdSeGzlAnDPT0hH1s= 68 | github.com/googleapis/gax-go/v2 v2.13.0/go.mod h1:Z/fvTZXF8/uw7Xu5GuslPw+bplx6SS338j1Is2S+B7A= 69 | github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= 70 | github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= 71 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 72 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 73 | github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 74 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 75 | github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= 76 | github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= 77 | github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 78 | github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= 79 | github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= 80 | github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= 81 | github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= 82 | go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= 83 | go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= 84 | go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.54.0 h1:r6I7RJCN86bpD/FQwedZ0vSixDpwuWREjW9oRMsmqDc= 85 | go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.54.0/go.mod h1:B9yO6b04uB80CzjedvewuqDhxJxi11s7/GtiGa8bAjI= 86 | go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 h1:TT4fX+nBOA/+LUkobKGW1ydGcn+G3vRw9+g5HwCphpk= 87 | go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0/go.mod h1:L7UH0GbB0p47T4Rri3uHjbpCFYrVrwc1I25QhNPiGK8= 88 | go.opentelemetry.io/otel v1.29.0 h1:PdomN/Al4q/lN6iBJEN3AwPvUiHPMlt93c8bqTG5Llw= 89 | go.opentelemetry.io/otel v1.29.0/go.mod h1:N/WtXPs1CNCUEx+Agz5uouwCba+i+bJGFicT8SR4NP8= 90 | go.opentelemetry.io/otel/metric v1.29.0 h1:vPf/HFWTNkPu1aYeIsc98l4ktOQaL6LeSoeV2g+8YLc= 91 | go.opentelemetry.io/otel/metric v1.29.0/go.mod h1:auu/QWieFVWx+DmQOUMgj0F8LHWdgalxXqvp7BII/W8= 92 | go.opentelemetry.io/otel/sdk v1.28.0 h1:b9d7hIry8yZsgtbmM0DKyPWMMUMlK9NEKuIG4aBqWyE= 93 | go.opentelemetry.io/otel/sdk v1.28.0/go.mod h1:oYj7ClPUA7Iw3m+r7GeEjz0qckQRJK2B8zjcZEfu7Pg= 94 | go.opentelemetry.io/otel/trace v1.29.0 h1:J/8ZNK4XgR7a21DZUAsbF8pZ5Jcw1VhACmnYt39JTi4= 95 | go.opentelemetry.io/otel/trace v1.29.0/go.mod h1:eHl3w0sp3paPkYstJOmAimxhiFXPg+MMTlEh3nsQgWQ= 96 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 97 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 98 | golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= 99 | golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= 100 | golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 101 | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 102 | golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= 103 | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 104 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 105 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 106 | golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 107 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 108 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 109 | golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= 110 | golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= 111 | golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= 112 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 113 | golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs= 114 | golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= 115 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 116 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 117 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 118 | golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= 119 | golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= 120 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 121 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 122 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 123 | golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 124 | golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= 125 | golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 126 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 127 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 128 | golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= 129 | golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= 130 | golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U= 131 | golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= 132 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 133 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 134 | golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= 135 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 136 | golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 137 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 138 | google.golang.org/api v0.197.0 h1:x6CwqQLsFiA5JKAiGyGBjc2bNtHtLddhJCE2IKuhhcQ= 139 | google.golang.org/api v0.197.0/go.mod h1:AuOuo20GoQ331nq7DquGHlU6d+2wN2fZ8O0ta60nRNw= 140 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 141 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 142 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 143 | google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= 144 | google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= 145 | google.golang.org/genproto v0.0.0-20240903143218-8af14fe29dc1 h1:BulPr26Jqjnd4eYDVe+YvyR7Yc2vJGkO5/0UxD0/jZU= 146 | google.golang.org/genproto v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:hL97c3SYopEHblzpxRL4lSs523++l8DYxGM1FQiYmb4= 147 | google.golang.org/genproto/googleapis/api v0.0.0-20240827150818-7e3bb234dfed h1:3RgNmBoI9MZhsj3QxC+AP/qQhNwpCLOvYDYYsFrhFt0= 148 | google.golang.org/genproto/googleapis/api v0.0.0-20240827150818-7e3bb234dfed/go.mod h1:OCdP9MfskevB/rbYvHTsXTtKC+3bHWajPdoKgjcYkfo= 149 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= 150 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= 151 | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= 152 | google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= 153 | google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= 154 | google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= 155 | google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= 156 | google.golang.org/grpc v1.66.1 h1:hO5qAXR19+/Z44hmvIM4dQFMSYX9XcWsByfoxutBpAM= 157 | google.golang.org/grpc v1.66.1/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= 158 | google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= 159 | google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= 160 | google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= 161 | google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= 162 | google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= 163 | google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 164 | google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 165 | google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 166 | google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= 167 | google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= 168 | google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= 169 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 170 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 171 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 172 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 173 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 174 | honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 175 | --------------------------------------------------------------------------------