From 80067ec2623e0d6b18006bb3fad554a3526a9d48 Mon Sep 17 00:00:00 2001 From: wumiao Date: Thu, 17 Oct 2024 16:14:12 -0400 Subject: [PATCH 1/6] Fix a panic by gnmi subscribe with invalid xpath --- gnmi_server/client_subscribe.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gnmi_server/client_subscribe.go b/gnmi_server/client_subscribe.go index bf791e79..2207bd30 100644 --- a/gnmi_server/client_subscribe.go +++ b/gnmi_server/client_subscribe.go @@ -179,12 +179,13 @@ func (c *Client) Run(stream gnmipb.GNMI_SubscribeServer) (err error) { /* For any other target or no target create new Transl Client. */ dc, err = sdc.NewTranslClient(prefix, paths, ctx, extensions, sdc.TranslWildcardOption{}) } - defer dc.Close() if err != nil { return grpc.Errorf(codes.NotFound, "%v", err) } + defer dc.Close() + switch mode { case gnmipb.SubscriptionList_STREAM: c.stop = make(chan struct{}, 1) From e784b6f2c67e9464c865311439dfe03a89ee4b9b Mon Sep 17 00:00:00 2001 From: Zain Budhwani <99770260+zbud-msft@users.noreply.github.com> Date: Mon, 11 Nov 2024 13:35:12 -0800 Subject: [PATCH 2/6] Fix Wildcard entries to return empty data instead of invalid path (#299) * Fix Wildcard entries to return empty data instead of invalid path * Add existing table test * Add check for empty json in test --- gnmi_server/server_test.go | 193 ++++++++++++++++++++++++++++++++- sonic_data_client/db_client.go | 10 +- testdata/EMPTY_JSON.txt | 1 + 3 files changed, 196 insertions(+), 8 deletions(-) create mode 100644 testdata/EMPTY_JSON.txt diff --git a/gnmi_server/server_test.go b/gnmi_server/server_test.go index bee65d08..b97e2f63 100644 --- a/gnmi_server/server_test.go +++ b/gnmi_server/server_test.go @@ -1297,11 +1297,11 @@ func runGnmiTestGet(t *testing.T, namespace string) { }, { desc: "Get valid but non-existing node", - pathTarget: "COUNTERS_DB", + pathTarget: stateDBPath, textPbPath: ` - elem: - `, - wantRetCode: codes.NotFound, + elem: + `, + wantRetCode: codes.OK, }, { desc: "Get COUNTERS_PORT_NAME_MAP", pathTarget: "COUNTERS_DB", @@ -3487,6 +3487,191 @@ func TestClientConnections(t *testing.T) { } } +func TestWildcardTableNoError(t *testing.T) { + s := createServer(t, 8081) + go runServer(t, s) + defer s.ForceStop() + + fileName := "../testdata/NEIGH_STATE_TABLE_MAP.txt" + neighStateTableByte, err := ioutil.ReadFile(fileName) + if err != nil { + t.Fatalf("read file %v err: %v", fileName, err) + } + + var neighStateTableJson interface{} + json.Unmarshal(neighStateTableByte, &neighStateTableJson) + + tests := []struct { + desc string + q client.Query + wantNoti []client.Notification + poll int + }{ + { + desc: "poll query for NEIGH_STATE_TABLE", + poll: 1, + q: client.Query{ + Target: "STATE_DB", + Type: client.Poll, + Queries: []client.Path{{"NEIGH_STATE_TABLE"}}, + TLS: &tls.Config{InsecureSkipVerify: true}, + }, + wantNoti: []client.Notification{ + client.Update{Path: []string{"NEIGH_STATE_TABLE"}, TS: time.Unix(0, 200), Val: neighStateTableJson}, + client.Update{Path: []string{"NEIGH_STATE_TABLE"}, TS: time.Unix(0, 200), Val: neighStateTableJson}, + }, + }, + } + namespace, _ := sdcfg.GetDbDefaultNamespace() + prepareStateDb(t, namespace) + var mutexNoti sync.Mutex + for _, tt := range tests { + + t.Run(tt.desc, func(t *testing.T) { + q := tt.q + q.Addrs = []string{"127.0.0.1:8081"} + c := client.New() + var gotNoti []client.Notification + q.NotificationHandler = func(n client.Notification) error { + mutexNoti.Lock() + if nn, ok := n.(client.Update); ok { + nn.TS = time.Unix(0, 200) + gotNoti = append(gotNoti, nn) + } + mutexNoti.Unlock() + return nil + } + + wg := new(sync.WaitGroup) + wg.Add(1) + + go func() { + defer wg.Done() + if err := c.Subscribe(context.Background(), q); err != nil { + t.Errorf("c.Subscribe(): got error %v, expected nil", err) + } + }() + + wg.Wait() + + for i := 0; i < tt.poll; i++ { + if err := c.Poll(); err != nil { + t.Errorf("c.Poll(): got error %v, expected nil", err) + } + } + + mutexNoti.Lock() + + if len(gotNoti) == 0 { + t.Errorf("expected non zero notifications") + } + + if diff := pretty.Compare(tt.wantNoti, gotNoti); diff != "" { + t.Log("\n Want: \n", tt.wantNoti) + t.Log("\n Got: \n", gotNoti) + t.Errorf("unexpected updates: \n%s", diff) + } + + mutexNoti.Unlock() + + c.Close() + }) + } +} + +func TestNonExistentTableNoError(t *testing.T) { + s := createServer(t, 8081) + go runServer(t, s) + defer s.ForceStop() + + fileName := "../testdata/EMPTY_JSON.txt" + transceiverDomSensorTableByte, err := ioutil.ReadFile(fileName) + if err != nil { + t.Fatalf("read file %v err: %v", fileName, err) + } + + var transceiverDomSensorTableJson interface{} + json.Unmarshal(transceiverDomSensorTableByte, &transceiverDomSensorTableJson) + + tests := []struct { + desc string + q client.Query + wantNoti []client.Notification + poll int + }{ + { + desc: "poll query for TRANSCEIVER_DOM_SENSOR", + poll: 1, + q: client.Query{ + Target: "STATE_DB", + Type: client.Poll, + Queries: []client.Path{{"TRANSCEIVER_DOM_SENSOR"}}, + TLS: &tls.Config{InsecureSkipVerify: true}, + }, + wantNoti: []client.Notification{ + client.Update{Path: []string{"TRANSCEIVER_DOM_SENSOR"}, TS: time.Unix(0, 200), Val: transceiverDomSensorTableJson}, + client.Update{Path: []string{"TRANSCEIVER_DOM_SENSOR"}, TS: time.Unix(0, 200), Val: transceiverDomSensorTableJson}, + }, + }, + } + namespace, _ := sdcfg.GetDbDefaultNamespace() + prepareStateDb(t, namespace) + var mutexNoti sync.Mutex + + for _, tt := range tests { + prepareStateDb(t, namespace) + t.Run(tt.desc, func(t *testing.T) { + q := tt.q + q.Addrs = []string{"127.0.0.1:8081"} + c := client.New() + var gotNoti []client.Notification + q.NotificationHandler = func(n client.Notification) error { + mutexNoti.Lock() + if nn, ok := n.(client.Update); ok { + nn.TS = time.Unix(0, 200) + gotNoti = append(gotNoti, nn) + } + mutexNoti.Unlock() + return nil + } + + wg := new(sync.WaitGroup) + wg.Add(1) + + go func() { + defer wg.Done() + if err := c.Subscribe(context.Background(), q); err != nil { + t.Errorf("c.Subscribe(): got error %v, expected nil", err) + } + }() + + wg.Wait() + + for i := 0; i < tt.poll; i++ { + if err := c.Poll(); err != nil { + t.Errorf("c.Poll(): got error %v, expected nil", err) + } + } + + mutexNoti.Lock() + + if len(gotNoti) == 0 { + t.Errorf("expected non zero notifications") + } + + if diff := pretty.Compare(tt.wantNoti, gotNoti); diff != "" { + t.Log("\n Want: \n", tt.wantNoti) + t.Log("\n Got: \n", gotNoti) + t.Errorf("unexpected updates: \n%s", diff) + } + + mutexNoti.Unlock() + + c.Close() + }) + } +} + func TestConnectionDataSet(t *testing.T) { s := createServer(t, 8081) go runServer(t, s) diff --git a/sonic_data_client/db_client.go b/sonic_data_client/db_client.go index 99f58a8a..cb94d1b0 100644 --- a/sonic_data_client/db_client.go +++ b/sonic_data_client/db_client.go @@ -670,11 +670,13 @@ func populateDbtablePath(prefix, path *gnmipb.Path, pathG2S *map[*gnmipb.Path][] // <5> DB Table Key Key Field switch len(stringSlice) { case 2: // only table name provided - res, err := redisDb.Keys(tblPath.tableName + "*").Result() - if err != nil || len(res) < 1 { - log.V(2).Infof("Invalid db table Path %v %v", target, dbPath) - return fmt.Errorf("Failed to find %v %v %v %v", target, dbPath, err, res) + wildcardTableName := tblPath.tableName + "*" + log.V(6).Infof("Fetching all keys for %v with table name %s", target, wildcardTableName) + res, err := redisDb.Keys(wildcardTableName).Result() + if err != nil { + return fmt.Errorf("redis Keys op failed for %v %v, got err %v %v", target, dbPath, err, res) } + log.V(6).Infof("Result of keys operation for %v %v, got %v", target, dbPath, res) tblPath.tableKey = "" case 3: // Third element could be table key; or field name in which case table name itself is the key too n, err := redisDb.Exists(tblPath.tableName + tblPath.delimitor + mappedKey).Result() diff --git a/testdata/EMPTY_JSON.txt b/testdata/EMPTY_JSON.txt new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/testdata/EMPTY_JSON.txt @@ -0,0 +1 @@ +{} From 883d617a9338fb10210990682116be13e96407c0 Mon Sep 17 00:00:00 2001 From: ganglv <88995770+ganglyu@users.noreply.github.com> Date: Tue, 12 Nov 2024 16:00:07 +0800 Subject: [PATCH 3/6] Update dbus timeout to 10 minutes (#326) Why I did it We found that GCU takes about 10 minutes to update ACL rules How I did it Update dbus timeout to 10 minutes so that we can use GNMI to update ACL rules. How to verify it Run GNMI unit test and end to end test --- sonic_service_client/dbus_client.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sonic_service_client/dbus_client.go b/sonic_service_client/dbus_client.go index 51777099..d54dda13 100644 --- a/sonic_service_client/dbus_client.go +++ b/sonic_service_client/dbus_client.go @@ -125,7 +125,7 @@ func (c *DbusClient) ApplyPatchYang(patch string) error { busName := c.busNamePrefix + modName busPath := c.busPathPrefix + modName intName := c.intNamePrefix + modName + ".apply_patch_yang" - _, err := DbusApi(busName, busPath, intName, 240, patch) + _, err := DbusApi(busName, busPath, intName, 600, patch) return err } @@ -135,7 +135,7 @@ func (c *DbusClient) ApplyPatchDb(patch string) error { busName := c.busNamePrefix + modName busPath := c.busPathPrefix + modName intName := c.intNamePrefix + modName + ".apply_patch_db" - _, err := DbusApi(busName, busPath, intName, 240, patch) + _, err := DbusApi(busName, busPath, intName, 600, patch) return err } From e0f09241f7ac15135cdc3ea0f16e7f217d1dd4b7 Mon Sep 17 00:00:00 2001 From: Hua Liu <58683130+liuh-80@users.noreply.github.com> Date: Tue, 19 Nov 2024 10:30:20 +0800 Subject: [PATCH 4/6] Install advancetls package to support crl. (#318) Install advancetls package to support crl. #### Why I did it Support certificate revocation list. #### How I did it Install advancetls package to support crl. Improve make file. #### How to verify it Manually test. Add new UT. #### Work item tracking Microsoft ADO (number only): 27146924 #### Which release branch to backport (provide reason below if selected) - [ ] 201811 - [ ] 201911 - [ ] 202006 - [ ] 202012 - [ ] 202106 - [ ] 202111 #### Description for the changelog Upgrade crypto package to v0.24.0 to support crl #### Link to config_db schema for YANG module changes #### A picture of a cute animal (not mandatory but encouraged) --- Makefile | 47 ++++++--- go.mod | 24 +++-- go.sum | 97 ++++++++++++------- ...02-Fix-advance-tls-build-with-go-119.patch | 33 +++++++ 4 files changed, 145 insertions(+), 56 deletions(-) create mode 100644 patches/0002-Fix-advance-tls-build-with-go-119.patch diff --git a/Makefile b/Makefile index c711ee05..039fed73 100644 --- a/Makefile +++ b/Makefile @@ -49,18 +49,18 @@ go.mod: $(GO_DEPS): go.mod $(PATCHES) swsscommon_wrap $(GO) mod vendor - $(GO) mod download golang.org/x/crypto@v0.0.0-20191206172530-e9b2fee46413 $(GO) mod download github.com/jipanyang/gnxi@v0.0.0-20181221084354-f0a90cca6fd0 - cp -r $(GOPATH)/pkg/mod/golang.org/x/crypto@v0.0.0-20191206172530-e9b2fee46413/* vendor/golang.org/x/crypto/ cp -r $(GOPATH)/pkg/mod/github.com/jipanyang/gnxi@v0.0.0-20181221084354-f0a90cca6fd0/* vendor/github.com/jipanyang/gnxi/ + +# Apply patch from sonic-mgmt-common, ignore glog.patch because glog version changed + sed -i 's/patch -d $${DEST_DIR}\/github.com\/golang\/glog/\#patch -d $${DEST_DIR}\/github.com\/golang\/glog/g' $(MGMT_COMMON_DIR)/patches/apply.sh $(MGMT_COMMON_DIR)/patches/apply.sh vendor + sed -i 's/#patch -d $${DEST_DIR}\/github.com\/golang\/glog/patch -d $${DEST_DIR}\/github.com\/golang\/glog/g' $(MGMT_COMMON_DIR)/patches/apply.sh + chmod -R u+w vendor - patch -d vendor -p0 < patches/gnmi_cli.all.patch - patch -d vendor -p0 < patches/gnmi_set.patch - patch -d vendor -p0 < patches/gnmi_get.patch patch -d vendor -p0 < patches/gnmi_path.patch patch -d vendor -p0 < patches/gnmi_xpath.patch - git apply patches/0001-Updated-to-filter-and-write-to-file.patch + touch $@ go-deps: $(GO_DEPS) @@ -69,14 +69,14 @@ go-deps-clean: $(RM) -r vendor sonic-gnmi: $(GO_DEPS) +# advancetls 1.0.0 release need following patch to build by go-1.19 +# patch -d vendor -p0 < patches/0002-Fix-advance-tls-build-with-go-119.patch +# build service first which depends on advancetls ifeq ($(CROSS_BUILD_ENVIRON),y) $(GO) build -o ${GOBIN}/telemetry -mod=vendor $(BLD_FLAGS) github.com/sonic-net/sonic-gnmi/telemetry ifneq ($(ENABLE_DIALOUT_VALUE),0) $(GO) build -o ${GOBIN}/dialout_client_cli -mod=vendor $(BLD_FLAGS) github.com/sonic-net/sonic-gnmi/dialout/dialout_client_cli endif - $(GO) build -o ${GOBIN}/gnmi_get -mod=vendor github.com/jipanyang/gnxi/gnmi_get - $(GO) build -o ${GOBIN}/gnmi_set -mod=vendor github.com/jipanyang/gnxi/gnmi_set - $(GO) build -o ${GOBIN}/gnmi_cli -mod=vendor github.com/openconfig/gnmi/cmd/gnmi_cli $(GO) build -o ${GOBIN}/gnoi_client -mod=vendor github.com/sonic-net/sonic-gnmi/gnoi_client $(GO) build -o ${GOBIN}/gnmi_dump -mod=vendor github.com/sonic-net/sonic-gnmi/gnmi_dump else @@ -84,13 +84,38 @@ else ifneq ($(ENABLE_DIALOUT_VALUE),0) $(GO) install -mod=vendor $(BLD_FLAGS) github.com/sonic-net/sonic-gnmi/dialout/dialout_client_cli endif + $(GO) install -mod=vendor github.com/sonic-net/sonic-gnmi/gnoi_client + $(GO) install -mod=vendor github.com/sonic-net/sonic-gnmi/gnmi_dump +endif + +# download and apply patch for gnmi client, which will break advancetls +# backup crypto and gnxi + mkdir backup_crypto + cp -r vendor/golang.org/x/crypto/* backup_crypto/ + +# download and patch crypto and gnxi + $(GO) mod download golang.org/x/crypto@v0.0.0-20191206172530-e9b2fee46413 + cp -r $(GOPATH)/pkg/mod/golang.org/x/crypto@v0.0.0-20191206172530-e9b2fee46413/* vendor/golang.org/x/crypto/ + chmod -R u+w vendor + patch -d vendor -p0 < patches/gnmi_cli.all.patch + patch -d vendor -p0 < patches/gnmi_set.patch + patch -d vendor -p0 < patches/gnmi_get.patch + git apply patches/0001-Updated-to-filter-and-write-to-file.patch + +ifeq ($(CROSS_BUILD_ENVIRON),y) + $(GO) build -o ${GOBIN}/gnmi_get -mod=vendor github.com/jipanyang/gnxi/gnmi_get + $(GO) build -o ${GOBIN}/gnmi_set -mod=vendor github.com/jipanyang/gnxi/gnmi_set + $(GO) build -o ${GOBIN}/gnmi_cli -mod=vendor github.com/openconfig/gnmi/cmd/gnmi_cli +else $(GO) install -mod=vendor github.com/jipanyang/gnxi/gnmi_get $(GO) install -mod=vendor github.com/jipanyang/gnxi/gnmi_set $(GO) install -mod=vendor github.com/openconfig/gnmi/cmd/gnmi_cli - $(GO) install -mod=vendor github.com/sonic-net/sonic-gnmi/gnoi_client - $(GO) install -mod=vendor github.com/sonic-net/sonic-gnmi/gnmi_dump endif +# restore old version + rm -rf vendor/golang.org/x/crypto/ + mv backup_crypto/ vendor/golang.org/x/crypto/ + swsscommon_wrap: make -C swsscommon diff --git a/go.mod b/go.mod index 2f783515..1607686a 100644 --- a/go.mod +++ b/go.mod @@ -12,8 +12,8 @@ require ( github.com/go-redis/redis v6.15.6+incompatible github.com/godbus/dbus/v5 v5.1.0 github.com/gogo/protobuf v1.3.2 - github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b - github.com/golang/protobuf v1.5.0 + github.com/golang/glog v1.2.0 + github.com/golang/protobuf v1.5.4 github.com/google/gnxi v0.0.0-20191016182648-6697a080bc2d github.com/jipanyang/gnmi v0.0.0-20180820232453-cb4d464fa018 github.com/jipanyang/gnxi v0.0.0-20181221084354-f0a90cca6fd0 @@ -22,10 +22,11 @@ require ( github.com/openconfig/gnmi v0.0.0-20200617225440-d2b4e6a45802 github.com/openconfig/gnoi v0.0.0-20211029052138-349b3dcd04ec github.com/openconfig/ygot v0.7.1 - golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 - golang.org/x/net v0.0.0-20201110031124-69a78807bb2b - google.golang.org/grpc v1.33.2 - google.golang.org/protobuf v1.26.0 + golang.org/x/crypto v0.24.0 + golang.org/x/net v0.26.0 + google.golang.org/grpc v1.64.1 + google.golang.org/grpc/security/advancedtls v1.0.0 + google.golang.org/protobuf v1.34.1 gopkg.in/yaml.v2 v2.2.8 ) @@ -37,7 +38,7 @@ require ( github.com/cenkalti/backoff/v4 v4.0.0 // indirect github.com/go-redis/redis/v7 v7.0.0-beta.3.0.20190824101152-d19aba07b476 // indirect github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect - github.com/google/go-cmp v0.5.5 // indirect + github.com/google/go-cmp v0.6.0 // indirect github.com/maruel/natural v1.1.1 // indirect github.com/onsi/ginkgo v1.10.3 // indirect github.com/onsi/gomega v1.7.1 // indirect @@ -46,10 +47,13 @@ require ( github.com/stretchr/testify v1.9.0 // indirect go4.org/intern v0.0.0-20211027215823-ae77deb06f29 // indirect go4.org/unsafe/assume-no-moving-gc v0.0.0-20230525183740-e7c30c78aeb2 // indirect - golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac // indirect - golang.org/x/text v0.3.3 // indirect + golang.org/x/sys v0.26.0 // indirect + golang.org/x/text v0.16.0 // indirect google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 // indirect inet.af/netaddr v0.0.0-20230525184311-b8eac61e914a // indirect ) -replace github.com/Azure/sonic-mgmt-common => ../sonic-mgmt-common +replace ( + github.com/Azure/sonic-mgmt-common => ../sonic-mgmt-common + golang.org/x/crypto => golang.org/x/crypto v0.24.0 +) diff --git a/go.sum b/go.sum index 7946b4e3..38b55147 100644 --- a/go.sum +++ b/go.sum @@ -18,14 +18,9 @@ github.com/c9s/goprocinfo v0.0.0-20191125144613-4acdd056c72d/go.mod h1:uEyr4WpAH github.com/cenkalti/backoff/v4 v4.0.0 h1:6VeaLF9aI+MAUQ95106HwWzYZgJJpZ4stumjj6RFYAU= github.com/cenkalti/backoff/v4 v4.0.0/go.mod h1:eEew/i+1Q6OrCDZh3WiXYv3+nJwBASZ8Bog/87DQnVg= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 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/dgrijalva/jwt-go v3.2.1-0.20210802184156-9742bd7fca1c+incompatible h1:kFnl8B5YgOXou7f+dsklKcGSXph/nubNx7I6d6RoFuE= github.com/dgrijalva/jwt-go v3.2.1-0.20210802184156-9742bd7fca1c+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dvyukov/go-fuzz v0.0.0-20210103155950-6a8e9d1f2415/go.mod h1:11Gm+ccJnvAhCNLlf5+cS9KjtbaD5I5zaZpFMsTHWTw= @@ -33,7 +28,6 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/felixge/fgprof v0.9.3/go.mod h1:RdbpDgzqYVh/T9fPELJyV7EYJuHB55UTEULNun8eiPw= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/go-redis/redis v6.15.6+incompatible h1:H9evprGPLI8+ci7fxQx6WNZHJSb7be8FqJQRhdQZ5Sg= @@ -44,8 +38,9 @@ github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/glog v1.2.0 h1:uCdmnmatrKCgMBlM4rMuJZWOkPDqdbZPnrMXDY4gI68= +github.com/golang/glog v1.2.0/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= @@ -60,8 +55,9 @@ github.com/golang/protobuf v1.4.0-rc.4/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9c github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.5.0 h1:LUVKkCeviFUMKqHa4tXIIij/lbhnMbP7Fn5wKdKkRh4= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/gnxi v0.0.0-20191016182648-6697a080bc2d h1:OtErLAncPdsEEhOI4ueR48dr6uThRIPkwWcOAdQ4LyI= github.com/google/gnxi v0.0.0-20191016182648-6697a080bc2d/go.mod h1:6kkMbKS62iZMyk1q0zukcqkEJwnIhcbgg/hmoFmRDZk= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -69,15 +65,14 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/pprof v0.0.0-20211214055906-6f57359322fd/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg= +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/google/protobuf v3.11.4+incompatible/go.mod h1:lUQ9D1ePzbH2PrIS7ob/bjm9HXyH5WHB0Akwh7URreM= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= github.com/jipanyang/gnmi v0.0.0-20180820232453-cb4d464fa018 h1:M++7b2XCTGqQwqu+AB0B3XzXiV+vVawnXJ4tvxUMrTU= github.com/jipanyang/gnmi v0.0.0-20180820232453-cb4d464fa018/go.mod h1:+aiusdWGFuKzi7B8/Y75kTlIA3UDF+sUBfY5+1e2NLs= github.com/jipanyang/gnxi v0.0.0-20181221084354-f0a90cca6fd0 h1:Dr/hrfbZxVlT/VvLfv8glHZAf9dLfuTSCJQq7cRGydo= @@ -111,70 +106,96 @@ github.com/openconfig/ygot v0.7.1 h1:kqDRYQpowXTr7EhGwr2BBDKJzqs+H8aFYjffYQ8lBsw github.com/openconfig/ygot v0.7.1/go.mod h1:5MwNX6DMP1QMf2eQjW+aJN/KNslVqRJtbfSL3SO6Urk= github.com/philopon/go-toposort v0.0.0-20170620085441-9be86dbd762f h1:WyCn68lTiytVSkk7W1K9nBiSGTSRlUOdyTnSjwrIlok= github.com/philopon/go-toposort v0.0.0-20170620085441-9be86dbd762f/go.mod h1:/iRjX3DdSK956SzsUdV55J+wIsQ+2IBWmBrB4RvZfk4= -github.com/pkg/profile v1.7.0/go.mod h1:8Uer0jas47ZQMJ7VD+OHknK4YDY07LPUC6dEvqDjvNo= 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/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go4.org/intern v0.0.0-20211027215823-ae77deb06f29 h1:UXLjNohABv4S58tHmeuIZDO6e3mHpW2Dx33gaNt03LE= go4.org/intern v0.0.0-20211027215823-ae77deb06f29/go.mod h1:cS2ma+47FKrLPdXFpr7CuxiTW3eyJbWew4qx0qtQWDA= go4.org/unsafe/assume-no-moving-gc v0.0.0-20211027215541-db492cf91b37/go.mod h1:FftLjUGFEDu5k8lt0ddY+HcrH/qU/0qk+H8j9/nTl3E= go4.org/unsafe/assume-no-moving-gc v0.0.0-20230525183740-e7c30c78aeb2 h1:WJhcL4p+YeDxmZWg141nRm7XC8IDmhz7lk5GpadO1Sg= go4.org/unsafe/assume-no-moving-gc v0.0.0-20230525183740-e7c30c78aeb2/go.mod h1:FftLjUGFEDu5k8lt0ddY+HcrH/qU/0qk+H8j9/nTl3E= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/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/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= +golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= 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= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201110031124-69a78807bb2b h1:uwuIcX0g4Yl1NC5XAz37xsr2lTtcqevgzYNVt49waME= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= +golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= +golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/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-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac h1:oN6lz7iLW/YC7un8pq+9bOLyXrprv2+DKfkJY+2LJJw= -golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= +golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= +golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= +golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= +golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -185,10 +206,13 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -203,8 +227,12 @@ google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQ google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.33.2 h1:EQyQC3sa8M+p6Ulc8yy9SWSS2GVwyRc83gAbG8lrl4o= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.64.1 h1:LKtvyfbX3UGVPFcGqJ9ItpVWW6oN/2XqTxfAnwRRXiA= +google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvyjeP0= +google.golang.org/grpc/examples v0.0.0-20201112215255-90f1b3ee835b h1:NuxyvVZoDfHZwYW9LD4GJiF5/nhiSyP4/InTrvw9Ibk= +google.golang.org/grpc/security/advancedtls v1.0.0 h1:/KQ7VP/1bs53/aopk9QhuPyFAp9Dm9Ejix3lzYkCrDA= +google.golang.org/grpc/security/advancedtls v1.0.0/go.mod h1:o+s4go+e1PJ2AjuQMY5hU82W7lDlefjJA6FqEHRVHWk= 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= @@ -215,8 +243,9 @@ google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= +google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= @@ -227,9 +256,7 @@ gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= inet.af/netaddr v0.0.0-20230525184311-b8eac61e914a h1:1XCVEdxrvL6c0TGOhecLuB7U9zYNdxZEjvOqJreKZiM= diff --git a/patches/0002-Fix-advance-tls-build-with-go-119.patch b/patches/0002-Fix-advance-tls-build-with-go-119.patch new file mode 100644 index 00000000..4f2dd481 --- /dev/null +++ b/patches/0002-Fix-advance-tls-build-with-go-119.patch @@ -0,0 +1,33 @@ +--- ./google.golang.org/grpc/security/advancedtls/advancedtls.go ++++ ./google.golang.org/grpc/security/advancedtls/advancedtls.go +@@ -576,7 +576,7 @@ func buildVerifyFunc(c *advancedTLSCreds, + if verifiedChains == nil { + verifiedChains = CertificateChains{rawCertList} + } +- if err := checkChainRevocation(verifiedChains, *c.revocationOptions); err != nil { ++ if err := CheckChainRevocation(verifiedChains, *c.revocationOptions); err != nil { + return err + } + } + +--- ./google.golang.org/grpc/security/advancedtls/crl.go ++++ ./google.golang.org/grpc/security/advancedtls/crl.go +@@ -119,7 +119,7 @@ var ( + + // checkChainRevocation checks the verified certificate chain + // for revoked certificates based on RFC5280. +-func checkChainRevocation(verifiedChains [][]*x509.Certificate, cfg RevocationOptions) error { ++func CheckChainRevocation(verifiedChains [][]*x509.Certificate, cfg RevocationOptions) error { + // Iterate the verified chains looking for one that is RevocationUnrevoked. + // A single RevocationUnrevoked chain is enough to allow the connection, and a single RevocationRevoked + // chain does not mean the connection should fail. +@@ -224,7 +224,7 @@ func checkCertRevocation(c *x509.Certificate, crl *CRL) (revocationStatus, error + rawEntryIssuer := crl.rawIssuer + + // Loop through all the revoked certificates. +- for _, revCert := range crl.certList.RevokedCertificateEntries { ++ for _, revCert := range crl.certList.RevokedCertificates { + // 5.3 Loop through CRL entry extensions for needed information. + for _, ext := range revCert.Extensions { + if oidCertificateIssuer.Equal(ext.Id) { +-- From e6bc0e72083eb88a6fac83ab02da2e4f2189d3c9 Mon Sep 17 00:00:00 2001 From: Hua Liu <58683130+liuh-80@users.noreply.github.com> Date: Wed, 20 Nov 2024 09:01:53 +0800 Subject: [PATCH 5/6] Add cert CRL support. (#269) Add cert CRL support. #### Why I did it Support certificate revocation list. #### How I did it Download CRL and verify cert with CRL. #### How to verify it Manually test: I1119 06:45:56.678454 139 server.go:201] Created Server on localhost:50052, read-only: true I1119 06:45:56.678478 139 telemetry.go:465] Auth Modes: cert I1119 06:45:56.678495 139 telemetry.go:466] Starting RPC server on address: localhost:50052 I1119 06:45:56.678532 139 telemetry.go:469] GNMI Server started serving I1119 06:46:14.936024 139 clientCertAuth.go:183] Get Crl Urls for cert: [] I1119 06:46:14.936363 139 clientCertAuth.go:224] Cert does not contains and CRL distribution points I1119 06:46:14.936375 139 server.go:278] authenticate user , roles [role1] I1119 06:46:21.524943 139 clientCertAuth.go:183] Get Crl Urls for cert: [http://10.250.0.102:1234/crl] I1119 06:46:21.526022 139 clientCertAuth.go:93] SearchCrlCache not found cache for url: http://10.250.0.102:1234/crl I1119 06:46:21.526138 139 clientCertAuth.go:158] Download CRL start: http://10.250.0.102:1234/crl I1119 06:46:21.533821 139 clientCertAuth.go:176] Download CRL: http://10.250.0.102:1234/crl successed I1119 06:46:21.534318 139 clientCertAuth.go:66] CrlExpired expireTime: Wed Nov 20 06:46:21 2024, now: Tue Nov 19 06:46:21 2024 I1119 06:46:21.534337 139 clientCertAuth.go:211] CreateStaticCRLProvider add crl: http://10.250.0.102:1234/crl content: [...] I1119 06:46:21.535269 139 clientCertAuth.go:244] VerifyCertCrl peer certificate revoked: no unrevoked chains found: map[2:1] I1119 06:46:21.535289 139 clientCertAuth.go:149] [TELEMETRY-2] Failed to verify cert with CRL; rpc error: code = Unauthenticated desc = Peer certificate revoked Add new UT. #### Work item tracking Microsoft ADO (number only): 27146924 #### Which release branch to backport (provide reason below if selected) - [ ] 201811 - [ ] 201911 - [ ] 202006 - [ ] 202012 - [ ] 202106 - [ ] 202111 #### Description for the changelog Add cert CRL support. #### Link to config_db schema for YANG module changes #### A picture of a cute animal (not mandatory but encouraged) --- Makefile | 2 +- gnmi_server/clientCertAuth.go | 204 ++++++++++++++++++++++++++- gnmi_server/crl_test.go | 251 ++++++++++++++++++++++++++++++++++ gnmi_server/server.go | 3 +- gnmi_server/server_test.go | 10 +- telemetry/telemetry.go | 7 + testdata/crl/revokedInt.pem | 58 ++++++++ testdata/crl/test.crl | 11 ++ testdata/crl/unrevoked.pem | 58 ++++++++ 9 files changed, 596 insertions(+), 8 deletions(-) create mode 100644 gnmi_server/crl_test.go create mode 100644 testdata/crl/revokedInt.pem create mode 100644 testdata/crl/test.crl create mode 100644 testdata/crl/unrevoked.pem diff --git a/Makefile b/Makefile index 039fed73..817d853f 100644 --- a/Makefile +++ b/Makefile @@ -70,7 +70,7 @@ go-deps-clean: sonic-gnmi: $(GO_DEPS) # advancetls 1.0.0 release need following patch to build by go-1.19 -# patch -d vendor -p0 < patches/0002-Fix-advance-tls-build-with-go-119.patch + patch -d vendor -p0 < patches/0002-Fix-advance-tls-build-with-go-119.patch # build service first which depends on advancetls ifeq ($(CROSS_BUILD_ENVIRON),y) $(GO) build -o ${GOBIN}/telemetry -mod=vendor $(BLD_FLAGS) github.com/sonic-net/sonic-gnmi/telemetry diff --git a/gnmi_server/clientCertAuth.go b/gnmi_server/clientCertAuth.go index 9a4a9a4f..48fecf3c 100644 --- a/gnmi_server/clientCertAuth.go +++ b/gnmi_server/clientCertAuth.go @@ -1,6 +1,11 @@ package gnmi import ( + "crypto/tls" + "crypto/x509" + "io" + "net/http" + "time" "github.com/sonic-net/sonic-gnmi/common_utils" "github.com/sonic-net/sonic-gnmi/swsscommon" "github.com/golang/glog" @@ -9,9 +14,103 @@ import ( "google.golang.org/grpc/credentials" "google.golang.org/grpc/peer" "google.golang.org/grpc/status" + "google.golang.org/grpc/security/advancedtls" ) -func ClientCertAuthenAndAuthor(ctx context.Context, serviceConfigTableName string) (context.Context, error) { +const DEFAULT_CRL_EXPIRE_DURATION time.Duration = 24 * 60* 60 * time.Second + +type Crl struct { + thisUpdate time.Time + nextUpdate time.Time + crl []byte +} + +// CRL content cache +var CrlCache map[string]*Crl = nil + +// CRL content cache +var CrlDxpireDuration time.Duration = DEFAULT_CRL_EXPIRE_DURATION + +func InitCrlCache() { + if CrlCache == nil { + CrlCache = make(map[string]*Crl) + } +} + +func ReleaseCrlCache() { + for mapkey, _ := range(CrlCache) { + delete(CrlCache, mapkey) + } +} + +func AppendCrlToCache(url string, rawCRL []byte) { + crl := new(Crl) + crl.thisUpdate = time.Now() + crl.nextUpdate = time.Now() + crl.crl = rawCRL + + CrlCache[url] = crl +} + +func GetCrlExpireDuration() time.Duration { + return CrlDxpireDuration +} + +func SetCrlExpireDuration(duration time.Duration) { + CrlDxpireDuration = duration +} + +func CrlExpired(crl *Crl) bool { + now := time.Now() + expireTime := crl.thisUpdate.Add(GetCrlExpireDuration()) + glog.Infof("CrlExpired expireTime: %s, now: %s", expireTime.Format(time.ANSIC), now.Format(time.ANSIC)) + // CRL expiresion policy follow the policy of Get-CRLFreshness command in following doc: + // https://learn.microsoft.com/en-us/archive/blogs/russellt/get-crlfreshness + // The policy are: + // 1. CRL expired when current time is after CRL expiresion time, which defined in "Next CRL Publish" extension. + // Because CRL cached in memory, GNMI support OnDemand CRL referesh by restart GNMI service. + return now.After(expireTime) +} + +func CrlNeedUpdate(crl *Crl) bool { + now := time.Now() + glog.Infof("CrlNeedUpdate nextUpdate: %s, now: %s", crl.nextUpdate.Format(time.ANSIC), now.Format(time.ANSIC)) + return now.After(crl.nextUpdate) +} + +func RemoveExpiredCrl() { + for mapkey, crl := range(CrlCache) { + if CrlExpired(crl) { + glog.Infof("RemoveExpiredCrl key: %s", mapkey) + delete(CrlCache, mapkey) + } + } +} + +func SearchCrlCache(url string) (bool, *Crl) { + crl, exist := CrlCache[url] + if !exist { + glog.Infof("SearchCrlCache not found cache for url: %s", url) + return false, nil + } + + if CrlExpired(crl) { + glog.Infof("SearchCrlCache crl expired: %s", url) + delete(CrlCache, url) + return false, nil + } + + if CrlNeedUpdate(crl) { + glog.Infof("SearchCrlCache crl need update: %s", url) + delete(CrlCache, url) + return false, nil + } + + glog.Infof("SearchCrlCache found cache for url: %s", url) + return true, crl +} + +func ClientCertAuthenAndAuthor(ctx context.Context, serviceConfigTableName string, enableCrl bool) (context.Context, error) { rc, ctx := common_utils.GetContext(ctx) p, ok := peer.FromContext(ctx) if !ok { @@ -44,9 +143,112 @@ func ClientCertAuthenAndAuthor(ctx context.Context, serviceConfigTableName strin } } + if enableCrl { + err := VerifyCertCrl(tlsAuth.State) + if err != nil { + glog.Infof("[%s] Failed to verify cert with CRL; %v", rc.ID, err) + return ctx, err + } + } + return ctx, nil } +func TryDownload(url string) bool { + glog.Infof("Download CRL start: %s", url) + resp, err := http.Get(url) + + if resp != nil { + defer resp.Body.Close() + } + + if err != nil || resp.StatusCode != http.StatusOK { + glog.Infof("Download CRL: %s failed: %v", url, err) + return false + } + + crlContent, err := io.ReadAll(resp.Body) + if err != nil { + glog.Infof("Download CRL: %s failed: %v", url, err) + return false + } + + glog.Infof("Download CRL: %s successed", url) + AppendCrlToCache(url, crlContent) + + return true +} + +func GetCrlUrls(cert x509.Certificate) []string { + glog.Infof("Get Crl Urls for cert: %v", cert.CRLDistributionPoints) + return cert.CRLDistributionPoints +} + +func DownloadNotCachedCrl(crlUrlArray []string) bool { + crlAvaliable := false + for _, crlUrl := range crlUrlArray{ + exist, _ := SearchCrlCache(crlUrl) + if exist { + crlAvaliable = true + } else { + downloaded := TryDownload(crlUrl) + if downloaded { + crlAvaliable = true + } + } + } + + return crlAvaliable +} + +func CreateStaticCRLProvider() *advancedtls.StaticCRLProvider { + crlArray := make([][]byte, 1) + for mapkey, item := range(CrlCache) { + if CrlExpired(item) { + glog.Infof("CreateStaticCRLProvider remove expired crl: %s", mapkey) + delete(CrlCache, mapkey) + } else { + glog.Infof("CreateStaticCRLProvider add crl: %s content: %v", mapkey, item.crl) + crlArray = append(crlArray, item.crl) + } + } + + return advancedtls.NewStaticCRLProvider(crlArray) +} + +func VerifyCertCrl(tlsConnState tls.ConnectionState) error { + InitCrlCache() + // Check if any CRL already exist in local + crlUriArray := GetCrlUrls(*tlsConnState.VerifiedChains[0][0]) + if len(crlUriArray) == 0 { + glog.Infof("Cert does not contains and CRL distribution points") + return nil + } + + crlAvaliable := DownloadNotCachedCrl(crlUriArray) + if !crlAvaliable { + // Every certificate will contain multiple CRL distribution points. + // If all CRLs are not available, the certificate validation should be blocked. + glog.Infof("VerifyCertCrl can't download CRL and verify cert: %v", crlUriArray) + return status.Errorf(codes.Unauthenticated, "Can't download CRL and verify cert") + } + + // Build CRL provider from cache and verify cert + crlProvider := CreateStaticCRLProvider() + err := advancedtls.CheckChainRevocation(tlsConnState.VerifiedChains, advancedtls.RevocationOptions{ + DenyUndetermined: false, + CRLProvider: crlProvider, + }) + + if err != nil { + glog.Infof("VerifyCertCrl peer certificate revoked: %v", err.Error()) + return status.Error(codes.Unauthenticated, "Peer certificate revoked") + } + + glog.Infof("VerifyCertCrl verify cert passed: %v", crlUriArray) + return nil +} + func PopulateAuthStructByCommonName(certCommonName string, auth *common_utils.AuthInfo, serviceConfigTableName string) error { if serviceConfigTableName == "" { return status.Errorf(codes.Unauthenticated, "Service config table name should not be empty") diff --git a/gnmi_server/crl_test.go b/gnmi_server/crl_test.go new file mode 100644 index 00000000..c4c53b19 --- /dev/null +++ b/gnmi_server/crl_test.go @@ -0,0 +1,251 @@ +package gnmi + +// server_test covers gNMI get, subscribe (stream and poll) test +// Prerequisite: redis-server should be running. +import ( + "crypto/tls" + "crypto/x509" + "crypto/x509/pkix" + "encoding/pem" + "fmt" + "os" + "testing" + "time" + "github.com/agiledragon/gomonkey/v2" + "github.com/sonic-net/sonic-gnmi/common_utils" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +func TestCrlExpireDuration(t *testing.T) { + duration := GetCrlExpireDuration() + if duration != DEFAULT_CRL_EXPIRE_DURATION { + t.Errorf("TestCrlExpireDuration test failed, default expire duration incorrect.") + } + + newDuration := 60 * time.Second + SetCrlExpireDuration(newDuration) + duration = GetCrlExpireDuration() + if duration != newDuration { + t.Errorf("TestCrlExpireDuration test failed, change expire duration failed.") + } +} + +func TestCrlCache(t *testing.T) { + InitCrlCache() + defer ReleaseCrlCache() + + rawCRL, _ := os.ReadFile("../testdata/crl/test.crl") + if rawCRL == nil { + t.Errorf("TestCrlCache test failed, crl file missing.") + } + AppendCrlToCache("http://test.crl.com/test.crl", rawCRL) + + // mock to make test CRL valied + mockCrlExpired := gomonkey.ApplyFunc(CrlExpired, func(crl *Crl) bool { + return true + }) + + // test CRL expired + exist, cacheItem := SearchCrlCache("http://test.crl.com/test.crl") + if exist { + t.Errorf("TestCrlCache test failed, crl should expired.") + } + + if cacheItem != nil { + t.Errorf("TestCrlCache test failed, crl content incorrect.") + } + + // test CRL expired and remove + AppendCrlToCache("http://test.crl.com/test.crl", rawCRL) + RemoveExpiredCrl() + _, exist = CrlCache["http://test.crl.com/test.crl"] + if exist { + t.Errorf("TestCrlCache test failed, expired crl should removed.") + } + + // test CRL does not exist + exist, cacheItem = SearchCrlCache("http://test.crl.com/notexist.crl") + if exist { + t.Errorf("TestCrlCache test failed, crl should not exist.") + } + + if cacheItem != nil { + t.Errorf("TestCrlCache test failed, crl content incorrect.") + } + + // mock to make test CRL valied + mockCrlExpired.Reset() + mockCrlNeedUpdate := gomonkey.ApplyFunc(CrlNeedUpdate, func(crl *Crl) bool { + return false + }) + defer mockCrlNeedUpdate.Reset() + + AppendCrlToCache("http://test.crl.com/test.crl", rawCRL) + exist, cacheItem = SearchCrlCache("http://test.crl.com/test.crl") + if !exist { + t.Errorf("TestCrlCache test failed, crl should exist.") + } + + if len(cacheItem.crl) != len(rawCRL) { + t.Errorf("TestCrlCache test failed, crl content incorrect.") + } +} + +func TestGetCrlUrls(t *testing.T) { + cert := x509.Certificate{ + Subject: pkix.Name{ + CommonName: "certname1", + }, + CRLDistributionPoints: []string{ + "http://test.crl.com/test.crl", + }, + } + + crlUrlArray := GetCrlUrls(cert) + + if len(crlUrlArray) != 1 { + t.Errorf("TestGetCrlUrls get incorrect CRLDistributionPoints.") + } + + if crlUrlArray[0] != "http://test.crl.com/test.crl" { + t.Errorf("TestGetCrlUrls get incorrect CRL.") + } +} + +func makeChain(name string) []*x509.Certificate { + certChain := make([]*x509.Certificate, 0) + + rest, err := os.ReadFile(name) + if err != nil { + fmt.Printf("makeChain ReadFile err: %s\n", err.Error()) + } + + for len(rest) > 0 { + var block *pem.Block + block, rest = pem.Decode(rest) + c, err := x509.ParseCertificate(block.Bytes) + if err != nil { + fmt.Printf("makeChain ParseCertificate err: %s\n", err.Error()) + } + certChain = append(certChain, c) + } + return certChain +} + +func CreateConnectionState(certPath string) tls.ConnectionState { + certChain := makeChain(certPath) + return tls.ConnectionState { + VerifiedChains: [][]*x509.Certificate { + certChain, + }, + } +} + +func TestVerifyCertCrl(t *testing.T) { + InitCrlCache() + defer ReleaseCrlCache() + + mockGetCrlUrls := gomonkey.ApplyFunc(GetCrlUrls, func(cert x509.Certificate) []string { + return []string{ "http://test.crl.com/test.crl" } + }) + defer mockGetCrlUrls.Reset() + + mockCrlExpired := gomonkey.ApplyFunc(CrlExpired, func(crl *Crl) bool { + return false + }) + defer mockCrlExpired.Reset() + + mockTryDownload := gomonkey.ApplyFunc(TryDownload, func(url string) bool { + rawCRL, _ := os.ReadFile("../testdata/crl/test.crl") + AppendCrlToCache("http://test.crl.com/test.crl", rawCRL) + return true + }) + defer mockTryDownload.Reset() + + // test revoked cert + tlsConnState := CreateConnectionState("../testdata/crl/revokedInt.pem") + err := VerifyCertCrl(tlsConnState) + if err == nil { + t.Errorf("TestVerifyCertCrl verify revoked cert failed.") + } + + // test valid cert + tlsConnState = CreateConnectionState("../testdata/crl/unrevoked.pem") + err = VerifyCertCrl(tlsConnState) + if err != nil { + t.Errorf("TestVerifyCertCrl verify unrevoked cert failed.") + } +} + + +func TestVerifyCertCrlWithDownloadFailed(t *testing.T) { + InitCrlCache() + defer ReleaseCrlCache() + + mockGetCrlUrls := gomonkey.ApplyFunc(GetCrlUrls, func(cert x509.Certificate) []string { + return []string{ "http://test.crl.com/test.crl" } + }) + defer mockGetCrlUrls.Reset() + + mockTryDownload := gomonkey.ApplyFunc(TryDownload, func(url string) bool { + return false + }) + defer mockTryDownload.Reset() + + // test valid cert,should failed because download CRL failed + tlsConnState := CreateConnectionState("../testdata/crl/unrevoked.pem") + err := VerifyCertCrl(tlsConnState) + if err == nil { + t.Errorf("TestVerifyCertCrl verify unrevoked cert should failed when CRL can't download.") + } +} + +func TestClientCertAuthenAndAuthorWithCrl(t *testing.T) { + // initialize err variable + err := status.Error(codes.Unauthenticated, "") + + // when config table is empty, will authorize with PopulateAuthStruct + mockpopulate := gomonkey.ApplyFunc(PopulateAuthStruct, func(username string, auth *common_utils.AuthInfo, r []string) error { + return nil + }) + defer mockpopulate.Reset() + + // mock for revoked cert + mockVerifyCertCrl := gomonkey.ApplyFunc(VerifyCertCrl, func(tlsConnState tls.ConnectionState) error { + return status.Error(codes.Unauthenticated, "Peer certificate revoked") + }) + + // check auth with nil cert name + ctx, cancel := CreateAuthorizationCtx() + ctx, err = ClientCertAuthenAndAuthor(ctx, "", true) + if err == nil { + t.Errorf("Auth with revoked cert should failed.") + } + + cancel() + mockVerifyCertCrl.Reset() + + // mock for unrevoked cert + mockVerifyCertCrl = gomonkey.ApplyFunc(VerifyCertCrl, func(tlsConnState tls.ConnectionState) error { + return nil + }) + + // check auth with nil cert name + ctx, cancel = CreateAuthorizationCtx() + ctx, err = ClientCertAuthenAndAuthor(ctx, "", true) + if err != nil { + t.Errorf("Auth with revoked cert should failed: %v", err) + } + + cancel() + mockVerifyCertCrl.Reset() +} + +func TestTryDownload(t *testing.T) { + // Use this test case for improve coverage + downloaded := TryDownload("http://127.0.0.1:1234/") + if downloaded != false { + t.Errorf("Download should failed: %v", downloaded) + } +} \ No newline at end of file diff --git a/gnmi_server/server.go b/gnmi_server/server.go index f3ec24ce..23dd817c 100644 --- a/gnmi_server/server.go +++ b/gnmi_server/server.go @@ -86,6 +86,7 @@ type Config struct { IdleConnDuration int ConfigTableName string Vrf string + EnableCrl bool } var AuthLock sync.Mutex @@ -263,7 +264,7 @@ func authenticate(config *Config, ctx context.Context) (context.Context, error) } } if !success && config.UserAuth.Enabled("cert") { - ctx, err = ClientCertAuthenAndAuthor(ctx, config.ConfigTableName) + ctx, err = ClientCertAuthenAndAuthor(ctx, config.ConfigTableName, config.EnableCrl) if err == nil { success = true } diff --git a/gnmi_server/server_test.go b/gnmi_server/server_test.go index b97e2f63..40a90abc 100644 --- a/gnmi_server/server_test.go +++ b/gnmi_server/server_test.go @@ -4490,7 +4490,7 @@ func CreateAuthorizationCtx() (context.Context, context.CancelFunc) { return ctx, cancel } - func TestClientCertAuthenAndAuthor(t *testing.T) { +func TestClientCertAuthenAndAuthor(t *testing.T) { if !swsscommon.SonicDBConfigIsInit() { swsscommon.SonicDBConfigInitialize() } @@ -4510,7 +4510,7 @@ func CreateAuthorizationCtx() (context.Context, context.CancelFunc) { // check auth with nil cert name ctx, cancel := CreateAuthorizationCtx() - ctx, err = ClientCertAuthenAndAuthor(ctx, "") + ctx, err = ClientCertAuthenAndAuthor(ctx, "", false) if err != nil { t.Errorf("CommonNameMatch with empty config table should success: %v", err) } @@ -4521,7 +4521,7 @@ func CreateAuthorizationCtx() (context.Context, context.CancelFunc) { ctx, cancel = CreateAuthorizationCtx() configDb.Flushdb() gnmiTable.Hset("certname1", "role", "role1") - ctx, err = ClientCertAuthenAndAuthor(ctx, "GNMI_CLIENT_CERT") + ctx, err = ClientCertAuthenAndAuthor(ctx, "GNMI_CLIENT_CERT", false) if err != nil { t.Errorf("CommonNameMatch with correct cert name should success: %v", err) } @@ -4533,7 +4533,7 @@ func CreateAuthorizationCtx() (context.Context, context.CancelFunc) { configDb.Flushdb() gnmiTable.Hset("certname1", "role", "role1") gnmiTable.Hset("certname2", "role", "role2") - ctx, err = ClientCertAuthenAndAuthor(ctx, "GNMI_CLIENT_CERT") + ctx, err = ClientCertAuthenAndAuthor(ctx, "GNMI_CLIENT_CERT", false) if err != nil { t.Errorf("CommonNameMatch with correct cert name should success: %v", err) } @@ -4544,7 +4544,7 @@ func CreateAuthorizationCtx() (context.Context, context.CancelFunc) { ctx, cancel = CreateAuthorizationCtx() configDb.Flushdb() gnmiTable.Hset("certname2", "role", "role2") - ctx, err = ClientCertAuthenAndAuthor(ctx, "GNMI_CLIENT_CERT") + ctx, err = ClientCertAuthenAndAuthor(ctx, "GNMI_CLIENT_CERT", false) if err == nil { t.Errorf("CommonNameMatch with invalid cert name should fail: %v", err) } diff --git a/telemetry/telemetry.go b/telemetry/telemetry.go index cb56e10c..f310a4d7 100644 --- a/telemetry/telemetry.go +++ b/telemetry/telemetry.go @@ -58,6 +58,8 @@ type TelemetryConfig struct { WithSaveOnSet *bool IdleConnDuration *int Vrf *string + EnableCrl *bool + CrlExpireDuration *int } func main() { @@ -167,6 +169,8 @@ func setupFlags(fs *flag.FlagSet) (*TelemetryConfig, *gnmi.Config, error) { WithSaveOnSet: fs.Bool("with-save-on-set", false, "Enables save-on-set."), IdleConnDuration: fs.Int("idle_conn_duration", 5, "Seconds before server closes idle connections"), Vrf: fs.String("vrf", "", "VRF name, when zmq_address belong on a VRF, need VRF name to bind ZMQ."), + EnableCrl: fs.Bool("enable_crl", false, "Enable certificate revocation list"), + CrlExpireDuration: fs.Int("crl_expire_duration", 86400, "Certificate revocation list cache expire duration"), } fs.Var(&telemetryCfg.UserAuth, "client_auth", "Client auth mode(s) - none,cert,password") @@ -230,6 +234,9 @@ func setupFlags(fs *flag.FlagSet) (*TelemetryConfig, *gnmi.Config, error) { cfg.IdleConnDuration = int(*telemetryCfg.IdleConnDuration) cfg.ConfigTableName = *telemetryCfg.ConfigTableName cfg.Vrf = *telemetryCfg.Vrf + cfg.EnableCrl = *telemetryCfg.EnableCrl + + gnmi.SetCrlExpireDuration(time.Duration(*telemetryCfg.CrlExpireDuration) * time.Second) // TODO: After other dependent projects are migrated to ZmqPort, remove ZmqAddress zmqAddress := *telemetryCfg.ZmqAddress diff --git a/testdata/crl/revokedInt.pem b/testdata/crl/revokedInt.pem new file mode 100644 index 00000000..8b7282ff --- /dev/null +++ b/testdata/crl/revokedInt.pem @@ -0,0 +1,58 @@ +-----BEGIN CERTIFICATE----- +MIIDAzCCAqmgAwIBAgITAWjKwm2dNQvkO62Jgyr5rAvVQzAKBggqhkjOPQQDAjCB +pTELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDU1v +dW50YWluIFZpZXcxEzARBgNVBAoTCkdvb2dsZSBMTEMxJjARBgNVBAsTClByb2R1 +Y3Rpb24wEQYDVQQLEwpjYW1wdXMtc2xuMSwwKgYDVQQDEyNSb290IENBICgyMDIx +LTAyLTAyVDA3OjMxOjU0LTA4OjAwKTAgFw0yMTAyMDIxNTMxNTRaGA85OTk5MTIz +MTIzNTk1OVowgaUxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYw +FAYDVQQHEw1Nb3VudGFpbiBWaWV3MRMwEQYDVQQKEwpHb29nbGUgTExDMSYwEQYD +VQQLEwpQcm9kdWN0aW9uMBEGA1UECxMKY2FtcHVzLXNsbjEsMCoGA1UEAxMjUm9v +dCBDQSAoMjAyMS0wMi0wMlQwNzozMTo1NC0wODowMCkwWTATBgcqhkjOPQIBBggq +hkjOPQMBBwNCAAQhA0/puhTtSxbVVHseVhL2z7QhpPyJs5Q4beKi7tpaYRDmVn6p +Phh+jbRzg8Qj4gKI/Q1rrdm4rKer63LHpdWdo4GzMIGwMA4GA1UdDwEB/wQEAwIB +BjAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDwYDVR0TAQH/BAUwAwEB +/zAdBgNVHQ4EFgQUeq/TQ959KbWk/um08jSTXogXpWUwHwYDVR0jBBgwFoAUeq/T +Q959KbWk/um08jSTXogXpWUwLgYDVR0RBCcwJYYjc3BpZmZlOi8vY2FtcHVzLXNs +bi5wcm9kLmdvb2dsZS5jb20wCgYIKoZIzj0EAwIDSAAwRQIgOSQZvyDPQwVOWnpF +zWvI+DS2yXIj/2T2EOvJz2XgcK4CIQCL0mh/+DxLiO4zzbInKr0mxpGSxSeZCUk7 +1ZF7AeLlbw== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDizCCAzKgAwIBAgIUAK6BGFvOeQUak65aL+XAQhr5LrcwCgYIKoZIzj0EAwIw +gaUxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1N +b3VudGFpbiBWaWV3MRMwEQYDVQQKEwpHb29nbGUgTExDMSYwEQYDVQQLEwpQcm9k +dWN0aW9uMBEGA1UECxMKY2FtcHVzLXNsbjEsMCoGA1UEAxMjUm9vdCBDQSAoMjAy +MS0wMi0wMlQwNzozMTo1NC0wODowMCkwIBcNMjEwMjAyMTUzMTU0WhgPOTk5OTEy +MzEyMzU5NTlaMIGlMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEW +MBQGA1UEBxMNTW91bnRhaW4gVmlldzETMBEGA1UEChMKR29vZ2xlIExMQzEmMBEG +A1UECxMKUHJvZHVjdGlvbjARBgNVBAsTCmNhbXB1cy1zbG4xLDAqBgNVBAMTI25v +ZGUgQ0EgKDIwMjEtMDItMDJUMDc6MzE6NTQtMDg6MDApMFkwEwYHKoZIzj0CAQYI +KoZIzj0DAQcDQgAEye6UOlBos8Q3FFBiLahD9BaLTA18bO4MTPyv35T3lppvxD5X +U/AnEllOnx5OMtMjMBbIQjSkMbiQ9xNXoSqB6aOCATowggE2MA4GA1UdDwEB/wQE +AwIBBjAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDwYDVR0TAQH/BAUw +AwEB/zAdBgNVHQ4EFgQUhWfy0gWBmkh2GiaBgnZzlQsvOlIwHwYDVR0jBBgwFoAU +eq/TQ959KbWk/um08jSTXogXpWUwMwYDVR0RBCwwKoYoc3BpZmZlOi8vbm9kZS5j +YW1wdXMtc2xuLnByb2QuZ29vZ2xlLmNvbTA7BgNVHR4BAf8EMTAvoC0wK4YpY3Nj +cy10ZWFtLm5vZGUuY2FtcHVzLXNsbi5wcm9kLmdvb2dsZS5jb20wQgYDVR0fBDsw +OTA3oDWgM4YxaHR0cDovL3N0YXRpYy5jb3JwLmdvb2dsZS5jb20vY3JsL2NhbXB1 +cy1zbG4vbm9kZTAKBggqhkjOPQQDAgNHADBEAiA79rPu6ZO1/0qB6RxL7jVz1200 +UTo8ioB4itbTzMnJqAIgJqp/Rc8OhpsfzQX8XnIIkl+SewT+tOxJT1MHVNMlVhc= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIC0DCCAnWgAwIBAgITXQ2c/C27OGqk4Pbu+MNJlOtpYTAKBggqhkjOPQQDAjCB +pTELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDU1v +dW50YWluIFZpZXcxEzARBgNVBAoTCkdvb2dsZSBMTEMxJjARBgNVBAsTClByb2R1 +Y3Rpb24wEQYDVQQLEwpjYW1wdXMtc2xuMSwwKgYDVQQDEyNub2RlIENBICgyMDIx +LTAyLTAyVDA3OjMxOjU0LTA4OjAwKTAgFw0yMTAyMDIxNTMxNTRaGA85OTk5MTIz +MTIzNTk1OVowADBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABN2/1le5d3hS/piw +hrNMHjd7gPEjzXwtuXQTzdV+aaeOf3ldnC6OnEF/bggym9MldQSJZLXPYSaoj430 +Vu5PRNejggEkMIIBIDAOBgNVHQ8BAf8EBAMCB4AwHQYDVR0lBBYwFAYIKwYBBQUH +AwIGCCsGAQUFBwMBMB0GA1UdDgQWBBTEewP3JgrJPekWWGGjChVqaMhaqTAfBgNV +HSMEGDAWgBSFZ/LSBYGaSHYaJoGCdnOVCy86UjBrBgNVHREBAf8EYTBfghZqemFi +MTIucHJvZC5nb29nbGUuY29thkVzcGlmZmU6Ly9jc2NzLXRlYW0ubm9kZS5jYW1w +dXMtc2xuLnByb2QuZ29vZ2xlLmNvbS9yb2xlL2JvcmctYWRtaW4tY28wQgYDVR0f +BDswOTA3oDWgM4YxaHR0cDovL3N0YXRpYy5jb3JwLmdvb2dsZS5jb20vY3JsL2Nh +bXB1cy1zbG4vbm9kZTAKBggqhkjOPQQDAgNJADBGAiEA9w4qp3nHpXo+6d7mZc69 +QoALfP5ynfBCArt8bAlToo8CIQCgc/lTfl2BtBko+7h/w6pKxLeuoQkvCL5gHFyK +LXE6vA== +-----END CERTIFICATE----- diff --git a/testdata/crl/test.crl b/testdata/crl/test.crl new file mode 100644 index 00000000..d37ad224 --- /dev/null +++ b/testdata/crl/test.crl @@ -0,0 +1,11 @@ +-----BEGIN X509 CRL----- +MIIBiDCCAS8CAQEwCgYIKoZIzj0EAwIwgaUxCzAJBgNVBAYTAlVTMRMwEQYDVQQI +EwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRMwEQYDVQQKEwpH +b29nbGUgTExDMSYwEQYDVQQLEwpQcm9kdWN0aW9uMBEGA1UECxMKY2FtcHVzLXNs +bjEsMCoGA1UEAxMjUm9vdCBDQSAoMjAyMS0wMi0wMlQwNzozMTo1NC0wODowMCkX +DTIxMDIwMjE1MzE1NFoXDTIxMDIwOTE1MzE1NFowJzAlAhQAroEYW855BRqTrlov +5cBCGvkutxcNMjEwMjAyMTUzMTU0WqAvMC0wHwYDVR0jBBgwFoAUeq/TQ959KbWk +/um08jSTXogXpWUwCgYDVR0UBAMCAQEwCgYIKoZIzj0EAwIDRwAwRAIgaSOIhJDg +wOLYlbXkmxW0cqy/AfOUNYbz5D/8/FfvhosCICftg7Vzlu0Nh83jikyjy+wtkiJt +ZYNvGFQ3Sp2L3A9e +-----END X509 CRL----- diff --git a/testdata/crl/unrevoked.pem b/testdata/crl/unrevoked.pem new file mode 100644 index 00000000..5c5fc58a --- /dev/null +++ b/testdata/crl/unrevoked.pem @@ -0,0 +1,58 @@ +-----BEGIN CERTIFICATE----- +MIIDBDCCAqqgAwIBAgIUALy864QhnkTdceLH52k2XVOe8IQwCgYIKoZIzj0EAwIw +gaUxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1N +b3VudGFpbiBWaWV3MRMwEQYDVQQKEwpHb29nbGUgTExDMSYwEQYDVQQLEwpQcm9k +dWN0aW9uMBEGA1UECxMKY2FtcHVzLXNsbjEsMCoGA1UEAxMjUm9vdCBDQSAoMjAy +MS0wMi0wMlQwNzozMDozNi0wODowMCkwIBcNMjEwMjAyMTUzMDM2WhgPOTk5OTEy +MzEyMzU5NTlaMIGlMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEW +MBQGA1UEBxMNTW91bnRhaW4gVmlldzETMBEGA1UEChMKR29vZ2xlIExMQzEmMBEG +A1UECxMKUHJvZHVjdGlvbjARBgNVBAsTCmNhbXB1cy1zbG4xLDAqBgNVBAMTI1Jv +b3QgQ0EgKDIwMjEtMDItMDJUMDc6MzA6MzYtMDg6MDApMFkwEwYHKoZIzj0CAQYI +KoZIzj0DAQcDQgAEYv/JS5hQ5kIgdKqYZWTKCO/6gloHAmIb1G8lmY0oXLXYNHQ4 +qHN7/pPtlcHQp0WK/hM8IGvgOUDoynA8mj0H9KOBszCBsDAOBgNVHQ8BAf8EBAMC +AQYwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMA8GA1UdEwEB/wQFMAMB +Af8wHQYDVR0OBBYEFPQNtnCIBcG4ReQgoVi0kPgTROseMB8GA1UdIwQYMBaAFPQN +tnCIBcG4ReQgoVi0kPgTROseMC4GA1UdEQQnMCWGI3NwaWZmZTovL2NhbXB1cy1z +bG4ucHJvZC5nb29nbGUuY29tMAoGCCqGSM49BAMCA0gAMEUCIQDwBn20DB4X/7Uk +Q5BR8JxQYUPxOfvuedjfeA8bPvQ2FwIgOEWa0cXJs1JxarILJeCXtdXvBgu6LEGQ +3Pk/bgz8Gek= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDizCCAzKgAwIBAgIUAM/6RKQ7Vke0i4xp5LaAqV73cmIwCgYIKoZIzj0EAwIw +gaUxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1N +b3VudGFpbiBWaWV3MRMwEQYDVQQKEwpHb29nbGUgTExDMSYwEQYDVQQLEwpQcm9k +dWN0aW9uMBEGA1UECxMKY2FtcHVzLXNsbjEsMCoGA1UEAxMjUm9vdCBDQSAoMjAy +MS0wMi0wMlQwNzozMDozNi0wODowMCkwIBcNMjEwMjAyMTUzMDM2WhgPOTk5OTEy +MzEyMzU5NTlaMIGlMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEW +MBQGA1UEBxMNTW91bnRhaW4gVmlldzETMBEGA1UEChMKR29vZ2xlIExMQzEmMBEG +A1UECxMKUHJvZHVjdGlvbjARBgNVBAsTCmNhbXB1cy1zbG4xLDAqBgNVBAMTI25v +ZGUgQ0EgKDIwMjEtMDItMDJUMDc6MzA6MzYtMDg6MDApMFkwEwYHKoZIzj0CAQYI +KoZIzj0DAQcDQgAEllnhxmMYiUPUgRGmenbnm10gXpM94zHx3D1/HumPs6arjYuT +Zlhx81XL+g4bu4HII2qcGdP+Hqj/MMFNDI9z4aOCATowggE2MA4GA1UdDwEB/wQE +AwIBBjAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDwYDVR0TAQH/BAUw +AwEB/zAdBgNVHQ4EFgQUGOhXkmeT+CnWTt+ZbCS9OT9wX8gwHwYDVR0jBBgwFoAU +9A22cIgFwbhF5CChWLSQ+BNE6x4wMwYDVR0RBCwwKoYoc3BpZmZlOi8vbm9kZS5j +YW1wdXMtc2xuLnByb2QuZ29vZ2xlLmNvbTA7BgNVHR4BAf8EMTAvoC0wK4YpY3Nj +cy10ZWFtLm5vZGUuY2FtcHVzLXNsbi5wcm9kLmdvb2dsZS5jb20wQgYDVR0fBDsw +OTA3oDWgM4YxaHR0cDovL3N0YXRpYy5jb3JwLmdvb2dsZS5jb20vY3JsL2NhbXB1 +cy1zbG4vbm9kZTAKBggqhkjOPQQDAgNHADBEAiA86egqPw0qyapAeMGbHxrmYZYa +i5ARQsSKRmQixgYizQIgW+2iRWN6Kbqt4WcwpmGv/xDckdRXakF5Ign/WUDO5u4= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICzzCCAnWgAwIBAgITYjjKfYZUKQNUjNyF+hLDGpHJKTAKBggqhkjOPQQDAjCB +pTELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDU1v +dW50YWluIFZpZXcxEzARBgNVBAoTCkdvb2dsZSBMTEMxJjARBgNVBAsTClByb2R1 +Y3Rpb24wEQYDVQQLEwpjYW1wdXMtc2xuMSwwKgYDVQQDEyNub2RlIENBICgyMDIx +LTAyLTAyVDA3OjMwOjM2LTA4OjAwKTAgFw0yMTAyMDIxNTMwMzZaGA85OTk5MTIz +MTIzNTk1OVowADBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABD4r4+nCgZExYF8v +CLvGn0lY/cmam8mAkJDXRN2Ja2t+JwaTOptPmbbXft+1NTk5gCg5wB+FJCnaV3I/ +HaxEhBWjggEkMIIBIDAOBgNVHQ8BAf8EBAMCB4AwHQYDVR0lBBYwFAYIKwYBBQUH +AwIGCCsGAQUFBwMBMB0GA1UdDgQWBBTTCjXX1Txjc00tBg/5cFzpeCSKuDAfBgNV +HSMEGDAWgBQY6FeSZ5P4KdZO35lsJL05P3BfyDBrBgNVHREBAf8EYTBfghZqemFi +MTIucHJvZC5nb29nbGUuY29thkVzcGlmZmU6Ly9jc2NzLXRlYW0ubm9kZS5jYW1w +dXMtc2xuLnByb2QuZ29vZ2xlLmNvbS9yb2xlL2JvcmctYWRtaW4tY28wQgYDVR0f +BDswOTA3oDWgM4YxaHR0cDovL3N0YXRpYy5jb3JwLmdvb2dsZS5jb20vY3JsL2Nh +bXB1cy1zbG4vbm9kZTAKBggqhkjOPQQDAgNIADBFAiBq3URViNyMLpvzZHC1Y+4L ++35guyIJfjHu08P3S8/xswIhAJtWSQ1ZtozdOzGxg7GfUo4hR+5SP6rBTgIqXEfq +48fW +-----END CERTIFICATE----- From 2c4b9c85833b4b71b35fd1099271bd67aaa3b3b3 Mon Sep 17 00:00:00 2001 From: Hua Liu <58683130+liuh-80@users.noreply.github.com> Date: Fri, 22 Nov 2024 14:32:32 +0800 Subject: [PATCH 6/6] Add swss-common log level support to gnmi (#330) --- telemetry/telemetry.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/telemetry/telemetry.go b/telemetry/telemetry.go index f310a4d7..4ebf6857 100644 --- a/telemetry/telemetry.go +++ b/telemetry/telemetry.go @@ -26,6 +26,7 @@ import ( "google.golang.org/grpc" "google.golang.org/grpc/credentials" "google.golang.org/grpc/keepalive" + "github.com/sonic-net/sonic-gnmi/swsscommon" ) type ServerControlValue int @@ -88,6 +89,9 @@ func runTelemetry(args []string) error { return err } + // enable swss-common debug level + swsscommon.LoggerLinkToDbNative("telemetry") + var wg sync.WaitGroup // serverControlSignal channel is a channel that will be used to notify gnmi server to start, stop, restart, depending of syscall or cert updates var serverControlSignal = make(chan ServerControlValue, 1)