From 74d4f084764d855c811ebd2c57193f74fe0ec7ad Mon Sep 17 00:00:00 2001 From: andy-stark-redis <164213578+andy-stark-redis@users.noreply.github.com> Date: Wed, 19 Mar 2025 15:36:58 +0000 Subject: [PATCH 1/3] DOC-4494 SADD and SMEMBERS command examples (#3242) * DOC-4494 added sadd example * DOC-4494 sadd and smembers examples * DOC-4494 better naming convention for result variables --------- Co-authored-by: Nedyalko Dyakov --- doctests/cmds_set_test.go | 102 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 doctests/cmds_set_test.go diff --git a/doctests/cmds_set_test.go b/doctests/cmds_set_test.go new file mode 100644 index 00000000..fecddbb8 --- /dev/null +++ b/doctests/cmds_set_test.go @@ -0,0 +1,102 @@ +// EXAMPLE: cmds_set +// HIDE_START +package example_commands_test + +import ( + "context" + "fmt" + + "github.com/redis/go-redis/v9" +) + +// HIDE_END + +func ExampleClient_sadd_cmd() { + ctx := context.Background() + + rdb := redis.NewClient(&redis.Options{ + Addr: "localhost:6379", + Password: "", // no password docs + DB: 0, // use default DB + }) + + // REMOVE_START + rdb.Del(ctx, "myset") + // REMOVE_END + + // STEP_START sadd + sAddResult1, err := rdb.SAdd(ctx, "myset", "Hello").Result() + + if err != nil { + panic(err) + } + + fmt.Println(sAddResult1) // >>> 1 + + sAddResult2, err := rdb.SAdd(ctx, "myset", "World").Result() + + if err != nil { + panic(err) + } + + fmt.Println(sAddResult2) // >>> 1 + + sAddResult3, err := rdb.SAdd(ctx, "myset", "World").Result() + + if err != nil { + panic(err) + } + + fmt.Println(sAddResult3) // >>> 0 + + sMembersResult, err := rdb.SMembers(ctx, "myset").Result() + + if err != nil { + panic(err) + } + + fmt.Println(sMembersResult) // >>> [Hello World] + // STEP_END + + // Output: + // 1 + // 1 + // 0 + // [Hello World] +} + +func ExampleClient_smembers_cmd() { + ctx := context.Background() + + rdb := redis.NewClient(&redis.Options{ + Addr: "localhost:6379", + Password: "", // no password docs + DB: 0, // use default DB + }) + + // REMOVE_START + rdb.Del(ctx, "myset") + // REMOVE_END + + // STEP_START smembers + sAddResult, err := rdb.SAdd(ctx, "myset", "Hello", "World").Result() + + if err != nil { + panic(err) + } + + fmt.Println(sAddResult) // >>> 2 + + sMembersResult, err := rdb.SMembers(ctx, "myset").Result() + + if err != nil { + panic(err) + } + + fmt.Println(sMembersResult) // >>> [Hello World] + // STEP_END + + // Output: + // 2 + // [Hello World] +} From d236865b0cfa1b752ea4b7da666b1fdcd0acebb6 Mon Sep 17 00:00:00 2001 From: Nedyalko Dyakov Date: Wed, 19 Mar 2025 19:02:36 +0200 Subject: [PATCH 2/3] fix: handle network error on SETINFO (#3295) (CVE-2025-29923) * fix: handle network error on SETINFO This fix addresses potential out of order responses as described in `CVE-2025-29923` * fix: deprecate DisableIndentity and introduce DisableIdentity Both options will work before V10. In v10 DisableIndentity will be dropped. The preferred flag to use is `DisableIdentity`. --- README.md | 8 +++++--- bench_decode_test.go | 4 ++-- options.go | 11 ++++++++++- osscluster.go | 18 +++++++++++++++--- redis.go | 8 ++++++-- redis_test.go | 7 +++++++ ring.go | 20 ++++++++++++++++---- sentinel.go | 31 ++++++++++++++++++++++++------- universal.go | 25 +++++++++++++++++++------ 9 files changed, 104 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index cfe97d37..335d32da 100644 --- a/README.md +++ b/README.md @@ -178,16 +178,18 @@ By default, go-redis automatically sends the client library name and version dur #### Disabling Identity Verification -When connection identity verification is not required or needs to be explicitly disabled, a `DisableIndentity` configuration option exists. In V10 of this library, `DisableIndentity` will become `DisableIdentity` in order to fix the associated typo. +When connection identity verification is not required or needs to be explicitly disabled, a `DisableIdentity` configuration option exists. +Initially there was a typo and the option was named `DisableIndentity` instead of `DisableIdentity`. The misspelled option is marked as Deprecated and will be removed in V10 of this library. +Although both options will work at the moment, the correct option is `DisableIdentity`. The deprecated option will be removed in V10 of this library, so please use the correct option name to avoid any issues. -To disable verification, set the `DisableIndentity` option to `true` in the Redis client options: +To disable verification, set the `DisableIdentity` option to `true` in the Redis client options: ```go rdb := redis.NewClient(&redis.Options{ Addr: "localhost:6379", Password: "", DB: 0, - DisableIndentity: true, // Disable set-info on connect + DisableIdentity: true, // Disable set-info on connect }) ``` diff --git a/bench_decode_test.go b/bench_decode_test.go index 16bdf2cd..d61a901a 100644 --- a/bench_decode_test.go +++ b/bench_decode_test.go @@ -30,7 +30,7 @@ func NewClientStub(resp []byte) *ClientStub { Dialer: func(ctx context.Context, network, addr string) (net.Conn, error) { return stub.stubConn(initHello), nil }, - DisableIndentity: true, + DisableIdentity: true, }) return stub } @@ -46,7 +46,7 @@ func NewClusterClientStub(resp []byte) *ClientStub { Dialer: func(ctx context.Context, network, addr string) (net.Conn, error) { return stub.stubConn(initHello), nil }, - DisableIndentity: true, + DisableIdentity: true, ClusterSlots: func(_ context.Context) ([]ClusterSlot, error) { return []ClusterSlot{ diff --git a/options.go b/options.go index a350a02f..c572bbe7 100644 --- a/options.go +++ b/options.go @@ -148,9 +148,18 @@ type Options struct { // Enables read only queries on slave/follower nodes. readOnly bool - // Disable set-lib on connect. Default is false. + // DisableIndentity - Disable set-lib on connect. + // + // default: false + // + // Deprecated: Use DisableIdentity instead. DisableIndentity bool + // DisableIdentity is used to disable CLIENT SETINFO command on connect. + // + // default: false + DisableIdentity bool + // Add suffix to client name. Default is empty. IdentitySuffix string diff --git a/osscluster.go b/osscluster.go index 1e9ee7de..b018cc9e 100644 --- a/osscluster.go +++ b/osscluster.go @@ -90,8 +90,19 @@ type ClusterOptions struct { ConnMaxIdleTime time.Duration ConnMaxLifetime time.Duration - TLSConfig *tls.Config - DisableIndentity bool // Disable set-lib on connect. Default is false. + TLSConfig *tls.Config + + // DisableIndentity - Disable set-lib on connect. + // + // default: false + // + // Deprecated: Use DisableIdentity instead. + DisableIndentity bool + + // DisableIdentity is used to disable CLIENT SETINFO command on connect. + // + // default: false + DisableIdentity bool IdentitySuffix string // Add suffix to client name. Default is empty. @@ -303,7 +314,8 @@ func (opt *ClusterOptions) clientOptions() *Options { MaxActiveConns: opt.MaxActiveConns, ConnMaxIdleTime: opt.ConnMaxIdleTime, ConnMaxLifetime: opt.ConnMaxLifetime, - DisableIndentity: opt.DisableIndentity, + DisableIdentity: opt.DisableIdentity, + DisableIndentity: opt.DisableIdentity, IdentitySuffix: opt.IdentitySuffix, TLSConfig: opt.TLSConfig, // If ClusterSlots is populated, then we probably have an artificial diff --git a/redis.go b/redis.go index 533c63c3..e0159294 100644 --- a/redis.go +++ b/redis.go @@ -350,7 +350,7 @@ func (c *baseClient) initConn(ctx context.Context, cn *pool.Conn) error { return err } - if !c.opt.DisableIndentity { + if !c.opt.DisableIdentity && !c.opt.DisableIndentity { libName := "" libVer := Version() if c.opt.IdentitySuffix != "" { @@ -359,7 +359,11 @@ func (c *baseClient) initConn(ctx context.Context, cn *pool.Conn) error { p := conn.Pipeline() p.ClientSetInfo(ctx, WithLibraryName(libName)) p.ClientSetInfo(ctx, WithLibraryVersion(libVer)) - _, _ = p.Exec(ctx) + // Handle network errors (e.g. timeouts) in CLIENT SETINFO to avoid + // out of order responses later on. + if _, err = p.Exec(ctx); err != nil && !isRedisError(err) { + return err + } } if c.opt.OnConnect != nil { diff --git a/redis_test.go b/redis_test.go index 27a24c9c..7d9bf1ce 100644 --- a/redis_test.go +++ b/redis_test.go @@ -396,6 +396,13 @@ var _ = Describe("Client timeout", func() { }) testTimeout := func() { + It("SETINFO timeouts", func() { + conn := client.Conn() + err := conn.Ping(ctx).Err() + Expect(err).To(HaveOccurred()) + Expect(err.(net.Error).Timeout()).To(BeTrue()) + }) + It("Ping timeouts", func() { err := client.Ping(ctx).Err() Expect(err).To(HaveOccurred()) diff --git a/ring.go b/ring.go index 06a26020..0ff3f75b 100644 --- a/ring.go +++ b/ring.go @@ -98,9 +98,19 @@ type RingOptions struct { TLSConfig *tls.Config Limiter Limiter + // DisableIndentity - Disable set-lib on connect. + // + // default: false + // + // Deprecated: Use DisableIdentity instead. DisableIndentity bool - IdentitySuffix string - UnstableResp3 bool + + // DisableIdentity is used to disable CLIENT SETINFO command on connect. + // + // default: false + DisableIdentity bool + IdentitySuffix string + UnstableResp3 bool } func (opt *RingOptions) init() { @@ -167,9 +177,11 @@ func (opt *RingOptions) clientOptions() *Options { TLSConfig: opt.TLSConfig, Limiter: opt.Limiter, + DisableIdentity: opt.DisableIdentity, DisableIndentity: opt.DisableIndentity, - IdentitySuffix: opt.IdentitySuffix, - UnstableResp3: opt.UnstableResp3, + + IdentitySuffix: opt.IdentitySuffix, + UnstableResp3: opt.UnstableResp3, } } diff --git a/sentinel.go b/sentinel.go index 31569554..a4c9f53c 100644 --- a/sentinel.go +++ b/sentinel.go @@ -80,9 +80,20 @@ type FailoverOptions struct { TLSConfig *tls.Config + // DisableIndentity - Disable set-lib on connect. + // + // default: false + // + // Deprecated: Use DisableIdentity instead. DisableIndentity bool - IdentitySuffix string - UnstableResp3 bool + + // DisableIdentity is used to disable CLIENT SETINFO command on connect. + // + // default: false + DisableIdentity bool + + IdentitySuffix string + UnstableResp3 bool } func (opt *FailoverOptions) clientOptions() *Options { @@ -118,9 +129,11 @@ func (opt *FailoverOptions) clientOptions() *Options { TLSConfig: opt.TLSConfig, + DisableIdentity: opt.DisableIdentity, DisableIndentity: opt.DisableIndentity, - IdentitySuffix: opt.IdentitySuffix, - UnstableResp3: opt.UnstableResp3, + + IdentitySuffix: opt.IdentitySuffix, + UnstableResp3: opt.UnstableResp3, } } @@ -156,9 +169,11 @@ func (opt *FailoverOptions) sentinelOptions(addr string) *Options { TLSConfig: opt.TLSConfig, + DisableIdentity: opt.DisableIdentity, DisableIndentity: opt.DisableIndentity, - IdentitySuffix: opt.IdentitySuffix, - UnstableResp3: opt.UnstableResp3, + + IdentitySuffix: opt.IdentitySuffix, + UnstableResp3: opt.UnstableResp3, } } @@ -197,8 +212,10 @@ func (opt *FailoverOptions) clusterOptions() *ClusterOptions { TLSConfig: opt.TLSConfig, + DisableIdentity: opt.DisableIdentity, DisableIndentity: opt.DisableIndentity, - IdentitySuffix: opt.IdentitySuffix, + + IdentitySuffix: opt.IdentitySuffix, } } diff --git a/universal.go b/universal.go index 3e3367e3..0a25bf22 100644 --- a/universal.go +++ b/universal.go @@ -61,14 +61,24 @@ type UniversalOptions struct { RouteByLatency bool RouteRandomly bool - // The sentinel master name. - // Only failover clients. - + // MasterName is the sentinel master name. + // Only for failover clients. MasterName string + // DisableIndentity - Disable set-lib on connect. + // + // default: false + // + // Deprecated: Use DisableIdentity instead. DisableIndentity bool - IdentitySuffix string - UnstableResp3 bool + + // DisableIdentity is used to disable CLIENT SETINFO command on connect. + // + // default: false + DisableIdentity bool + + IdentitySuffix string + UnstableResp3 bool // IsClusterMode can be used when only one Addrs is provided (e.g. Elasticache supports setting up cluster mode with configuration endpoint). IsClusterMode bool @@ -116,6 +126,7 @@ func (o *UniversalOptions) Cluster() *ClusterOptions { TLSConfig: o.TLSConfig, + DisableIdentity: o.DisableIdentity, DisableIndentity: o.DisableIndentity, IdentitySuffix: o.IdentitySuffix, UnstableResp3: o.UnstableResp3, @@ -163,8 +174,9 @@ func (o *UniversalOptions) Failover() *FailoverOptions { TLSConfig: o.TLSConfig, - ReplicaOnly: o.ReadOnly, + ReplicaOnly: o.ReadOnly, + DisableIdentity: o.DisableIdentity, DisableIndentity: o.DisableIndentity, IdentitySuffix: o.IdentitySuffix, UnstableResp3: o.UnstableResp3, @@ -209,6 +221,7 @@ func (o *UniversalOptions) Simple() *Options { TLSConfig: o.TLSConfig, + DisableIdentity: o.DisableIdentity, DisableIndentity: o.DisableIndentity, IdentitySuffix: o.IdentitySuffix, UnstableResp3: o.UnstableResp3, From 11efd6a01ebf1c3a0f8cc41d0a1d54c5afbae26f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 19 Mar 2025 21:11:14 +0200 Subject: [PATCH 3/3] chore(deps): bump golang.org/x/net in /example/otel (#3308) Bumps [golang.org/x/net](https://github.com/golang/net) from 0.33.0 to 0.36.0. - [Commits](https://github.com/golang/net/compare/v0.33.0...v0.36.0) --- updated-dependencies: - dependency-name: golang.org/x/net dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- example/otel/go.mod | 7 ++++--- example/otel/go.sum | 20 ++++++++++++++------ 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/example/otel/go.mod b/example/otel/go.mod index 93b5d46c..82ed7ed7 100644 --- a/example/otel/go.mod +++ b/example/otel/go.mod @@ -1,6 +1,7 @@ module github.com/redis/go-redis/example/otel go 1.19 +toolchain go1.24.1 replace github.com/redis/go-redis/v9 => ../.. @@ -34,9 +35,9 @@ require ( go.opentelemetry.io/otel/sdk/metric v1.21.0 // indirect go.opentelemetry.io/otel/trace v1.22.0 // indirect go.opentelemetry.io/proto/otlp v1.0.0 // indirect - golang.org/x/net v0.33.0 // indirect - golang.org/x/sys v0.28.0 // indirect - golang.org/x/text v0.21.0 // indirect + golang.org/x/net v0.36.0 // indirect + golang.org/x/sys v0.30.0 // indirect + golang.org/x/text v0.22.0 // indirect google.golang.org/genproto v0.0.0-20240108191215-35c7eff3a6b1 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240108191215-35c7eff3a6b1 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240108191215-35c7eff3a6b1 // indirect diff --git a/example/otel/go.sum b/example/otel/go.sum index 1a1729c6..fa94c15b 100644 --- a/example/otel/go.sum +++ b/example/otel/go.sum @@ -1,10 +1,13 @@ github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= +github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c= github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= +github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0= github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= @@ -17,10 +20,13 @@ github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 h1:Wqo399gCIufwto+VfwCSvsnfGpF/w5E9CNxSwbpD6No= github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0/go.mod h1:qmOFXW2epJhM0qSnUUYpldc7gVz2KMQwJ/QYCDIa7XU= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/uptrace/uptrace-go v1.21.0 h1:oJoUjhiVT7aiuoG6B3ClVHtJozLn3cK9hQt8U5dQO1M= github.com/uptrace/uptrace-go v1.21.0/go.mod h1:/aXAFGKOqeAFBqWa1xtzLnGX2xJm1GScqz9NJ0TJjLM= go.opentelemetry.io/contrib/instrumentation/runtime v0.46.1 h1:m9ReioVPIffxjJlGNRd0d5poy+9oTro3D+YbiEzUDOc= @@ -46,12 +52,13 @@ go.opentelemetry.io/otel/trace v1.22.0/go.mod h1:RbbHXVqKES9QhzZq/fE5UnOSILqRt40 go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= -golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= -golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= -golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= -golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= -golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +golang.org/x/net v0.36.0 h1:vWF2fRbw4qslQsQzgFqZff+BItCvGFQqKzKIzx1rmoA= +golang.org/x/net v0.36.0/go.mod h1:bFmbeoIPfrw4sMHNhb4J9f6+tPziuGjq7Jk/38fxi1I= +golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= +golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= +golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/genproto v0.0.0-20240108191215-35c7eff3a6b1 h1:/IWabOtPziuXTEtI1KYCpM6Ss7vaAkeMxk+uXV/xvZs= google.golang.org/genproto v0.0.0-20240108191215-35c7eff3a6b1/go.mod h1:+Rvu7ElI+aLzyDQhpHMFMMltsD6m7nqpuWDd2CwJw3k= @@ -66,3 +73,4 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=