From e2007481217c45b73b36907f25e515e4586f1fee Mon Sep 17 00:00:00 2001 From: harikri4 <144362795+harikri4@users.noreply.github.com> Date: Tue, 28 Nov 2023 11:54:15 -0800 Subject: [PATCH] Authz Feature Profile Tests (#2136) --- .../gnsi/authz/tests/{ => authz}/README.md | 69 +- .../gnsi/authz/tests/authz/authz1_4_test.go | 718 +++++++++++ .../gnsi/authz/tests/authz/metadata.textproto | 7 + .../authz/tests/authz/testdata/ca.cert.pem | 31 + .../authz/tests/authz/testdata/ca.key.pem | 51 + .../authz/tests/authz/testdata/policy.json | 228 ++++ internal/security/authz/authz.go | 279 +++++ internal/security/gen/generate.go | 294 +++++ internal/security/gnxi/gnxi.go | 45 + internal/security/gnxi/rpcexec.go | 696 +++++++++++ internal/security/gnxi/rpcs.go | 1059 +++++++++++++++++ 11 files changed, 3447 insertions(+), 30 deletions(-) rename feature/security/gnsi/authz/tests/{ => authz}/README.md (93%) create mode 100644 feature/security/gnsi/authz/tests/authz/authz1_4_test.go create mode 100644 feature/security/gnsi/authz/tests/authz/metadata.textproto create mode 100644 feature/security/gnsi/authz/tests/authz/testdata/ca.cert.pem create mode 100644 feature/security/gnsi/authz/tests/authz/testdata/ca.key.pem create mode 100644 feature/security/gnsi/authz/tests/authz/testdata/policy.json create mode 100644 internal/security/authz/authz.go create mode 100644 internal/security/gen/generate.go create mode 100644 internal/security/gnxi/gnxi.go create mode 100644 internal/security/gnxi/rpcexec.go create mode 100644 internal/security/gnxi/rpcs.go diff --git a/feature/security/gnsi/authz/tests/README.md b/feature/security/gnsi/authz/tests/authz/README.md similarity index 93% rename from feature/security/gnsi/authz/tests/README.md rename to feature/security/gnsi/authz/tests/authz/README.md index 0f9786c247b..665c66be8a2 100644 --- a/feature/security/gnsi/authz/tests/README.md +++ b/feature/security/gnsi/authz/tests/authz/README.md @@ -1,4 +1,4 @@ -# gNSI Authz Tests +# Authz: General Authz (1-4) tests ## Summary @@ -26,7 +26,7 @@ NOTE: the support of SPIFFE-ID should NOT require explicitly pre-configured loca Prepare the following certs with the specified SPIFFE ID. Cert format details can be found in [SPIFFE PR](https://github.com/openconfig/featureprofiles/pull/1563/files) * `cert_user_admin` with `spiffe://test-abc.foo.bar/xyz/admin` -* `cert_user_fake` with `spiffe://test-abc.foo.bar/xyz/fake` +* `cert_user_deny_all` with `spiffe://test-abc.foo.bar/xyz/deny-all` * `cert_gribi_modify` with `spiffe://test-abc.foo.bar/xyz/gribi-modify` * `cert_gnmi_set` with `spiffe://test-abc.foo.bar/xyz/gnmi-set` * `cert_gnoi_time` with `spiffe://test-abc.foo.bar/xyz/gnoi-time` @@ -80,30 +80,39 @@ Prepare the following gRPC authorization policies. ``` ```json -{ - "name": "policy-everyone-can-gribi-not-gnmi", - "allow_rules": [ - { - "name": "admin-can-do-everything", - "source": { - "principals": [ - "spiffe://test-abc.foo.bar/xyz/admin" - ] - }, - "request": {} - } - ], - "deny_rules": [ - { - "name": "fake-user-can-do-nothing", - "source": { - "principals": [ - "spiffe://test-abc.foo.bar/xyz/fake" - ] + { + "name": "policy-everyone-can-gribi-not-gnmi", + "allow_rules": [ + { + "name": "everyone-can-gribi", + "source": { + "principals": [ + "*" + ] + }, + "request": { + "paths": [ + "/gribi.gRIBI/*" + ] + } } - } - ] -} + ], + "deny_rules": [ + { + "name": "no-one-can-gnmi", + "source": { + "principals": [ + "*" + ] + }, + "request": { + "paths": [ + "/gribi.gNMI/*" + ] + } + } + ] + } ``` ```json @@ -114,7 +123,7 @@ Prepare the following gRPC authorization policies. "name": "no-one-can-gribi", "request": { "paths": [ - "/gribi.gRIBI/Modify" + "/gribi.gRIBI/*" ] } } @@ -165,7 +174,7 @@ The following table describes policy `policy-normal-1`: Cert | gRIBI.Modify | gRIBI.Get | gNMI.Set | gNMI.Get | gNOI.Time | gNOI.Ping | gNSI.Rotate | gNSI.Get | gNSI.Probe :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :----- | :----- cert_user_admin | allow | allow |allow |allow |allow |allow |allow |allow |allow -cert_user_fake | deny |deny |deny |deny |deny |deny |deny |deny |deny +cert_user_deny_all | deny |deny |deny |deny |deny |deny |deny |deny |deny cert_gribi_modify | allow |allow |deny |deny |deny |deny |deny |deny |deny cert_gnmi_set | deny |deny |allow |allow |deny |deny |deny |deny |deny cert_gnoi_time |deny |deny |deny |deny |allow |deny |deny |deny |deny @@ -265,10 +274,10 @@ cert_read_only |deny |allow |deny |allow |deny |deny |deny |allow |deny ], "deny_rules": [ { - "name": "fake-user-can-do-nothing", + "name": "deny-all-user-can-do-nothing", "source": { "principals": [ - "spiffe://test-abc.foo.bar/xyz/fake" + "spiffe://test-abc.foo.bar/xyz/deny_all" ] }, "request": { @@ -316,7 +325,7 @@ For each of the scenarios in this section, we need to exercise the following 3 a * Authz-1.2, "Test empty request" 1. Use `gNSI.Rotate` method to push and finalize policy `policy-everyone-can-gribi-not-gnmi`, with `create_on` = `100` and `version` = `policy-everyone-can-gribi-not-gnmi_v1`. 2. Ensure all results match per the following: - * `cert_user_fake` is denied to issue `gRIBI.Get` method. + * `cert_user_deny_all` is denied to issue `gNMI.Get` method. * `cert_user_admin` is allowed to issue `gRIBI.Get` method. * Authz-1.3, "Test that there can only be one policy" diff --git a/feature/security/gnsi/authz/tests/authz/authz1_4_test.go b/feature/security/gnsi/authz/tests/authz/authz1_4_test.go new file mode 100644 index 00000000000..579a8c7710e --- /dev/null +++ b/feature/security/gnsi/authz/tests/authz/authz1_4_test.go @@ -0,0 +1,718 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package authz_test performs functional tests for authz service +// TODO: Streaming Validation will be done in the subsequent PR +package authz_test + +import ( + "context" + "crypto/tls" + "crypto/x509" + "flag" + "fmt" + "os" + "testing" + "time" + + "github.com/google/go-cmp/cmp" + "github.com/openconfig/featureprofiles/internal/fptest" + "github.com/openconfig/featureprofiles/internal/security/authz" + "github.com/openconfig/featureprofiles/internal/security/gnxi" + "github.com/openconfig/featureprofiles/internal/security/svid" + gnps "github.com/openconfig/gnoi/system" + authzpb "github.com/openconfig/gnsi/authz" + "github.com/openconfig/ondatra" + "github.com/openconfig/ondatra/gnmi" + "github.com/openconfig/testt" +) + +const ( + maxRebootTime = 900 // Unit is Seconds + maxCompWaitTime = 600 +) + +type UsersMap map[string]authz.Spiffe + +var ( + testInfraID = flag.String("test_infra_id", "cafyauto", "SPIFFE-ID used by test Infra ID user for authz operation") + caCertPem = flag.String("ca_cert_pem", "testdata/ca.cert.pem", "a pem file for ca cert that will be used to generate svid") + caKeyPem = flag.String("ca_key_pem", "testdata/ca.key.pem", "a pem file for ca key that will be used to generate svid") + policyMap map[string]authz.AuthorizationPolicy + + usersMap = UsersMap{ + "cert_user_admin": { + ID: "spiffe://test-abc.foo.bar/xyz/admin", + }, + "cert_deny_all": { + ID: "spiffe://test-abc.foo.bar/xyz/deny-all", // a user with valid svid but no permission (has a deny rule for target *) + }, + "cert_gribi_modify": { + ID: "spiffe://test-abc.foo.bar/xyz/gribi-modify", + }, + "cert_gnmi_set": { + ID: "spiffe://test-abc.foo.bar/xyz/gnmi-set", + }, + "cert_gnoi_time": { + ID: "spiffe://test-abc.foo.bar/xyz/gnoi-time", + }, + "cert_gnoi_ping": { + ID: "spiffe://test-abc.foo.bar/xyz/gnoi-ping", + }, + "cert_gnsi_probe": { + ID: "spiffe://test-abc.foo.bar/xyz/gnsi-probe", + }, + "cert_read_only": { + ID: "spiffe://test-abc.foo.bar/xyz/read-only", + }, + } +) + +type access struct { + allowed []*gnxi.RPC + denied []*gnxi.RPC +} + +type authorizationTable map[string]access + +var authTable = authorizationTable{ + //table: map[string]access{ + "cert_user_admin": struct { + allowed []*gnxi.RPC + denied []*gnxi.RPC + }{ + allowed: []*gnxi.RPC{gnxi.RPCs.GribiGet, gnxi.RPCs.GribiModify, gnxi.RPCs.GnmiGet, + gnxi.RPCs.GnoiSystemTime, gnxi.RPCs.GnoiSystemPing, gnxi.RPCs.GnsiAuthzRotate, + gnxi.RPCs.GnsiAuthzGet, gnxi.RPCs.GnsiAuthzProbe, gnxi.RPCs.GnmiSet}, + }, + "cert_deny_all": { + denied: []*gnxi.RPC{gnxi.RPCs.GribiGet, gnxi.RPCs.GribiModify, gnxi.RPCs.GnmiSet, gnxi.RPCs.GnmiGet, + gnxi.RPCs.GnoiSystemTime, gnxi.RPCs.GnoiSystemPing, gnxi.RPCs.GnsiAuthzRotate, + gnxi.RPCs.GnsiAuthzGet, gnxi.RPCs.GnsiAuthzProbe}, + }, + "cert_gribi_modify": { + denied: []*gnxi.RPC{gnxi.RPCs.GnmiSet, gnxi.RPCs.GnmiGet, + gnxi.RPCs.GnoiSystemTime, gnxi.RPCs.GnoiSystemPing, gnxi.RPCs.GnsiAuthzRotate, + gnxi.RPCs.GnsiAuthzGet, gnxi.RPCs.GnsiAuthzProbe}, + allowed: []*gnxi.RPC{gnxi.RPCs.GribiGet, gnxi.RPCs.GribiModify}, + }, + "cert_gnmi_set": { + denied: []*gnxi.RPC{gnxi.RPCs.GribiGet, gnxi.RPCs.GribiModify, + gnxi.RPCs.GnoiSystemTime, gnxi.RPCs.GnoiSystemPing, gnxi.RPCs.GnsiAuthzRotate, + gnxi.RPCs.GnsiAuthzGet, gnxi.RPCs.GnsiAuthzProbe}, + allowed: []*gnxi.RPC{gnxi.RPCs.GnmiGet, gnxi.RPCs.GnmiSet}, + }, + "cert_gnoi_time": { + denied: []*gnxi.RPC{gnxi.RPCs.GribiGet, gnxi.RPCs.GribiModify, gnxi.RPCs.GnmiSet, + gnxi.RPCs.GnoiSystemPing, gnxi.RPCs.GnsiAuthzRotate, gnxi.RPCs.GnmiGet, + gnxi.RPCs.GnsiAuthzGet, gnxi.RPCs.GnsiAuthzProbe}, + allowed: []*gnxi.RPC{gnxi.RPCs.GnoiSystemTime}, + }, + "cert_gnoi_ping": { + denied: []*gnxi.RPC{gnxi.RPCs.GribiGet, gnxi.RPCs.GribiModify, gnxi.RPCs.GnmiSet, + gnxi.RPCs.GnsiAuthzRotate, gnxi.RPCs.GnmiGet, + gnxi.RPCs.GnsiAuthzGet, gnxi.RPCs.GnsiAuthzProbe, gnxi.RPCs.GnoiSystemTime}, + allowed: []*gnxi.RPC{gnxi.RPCs.GnoiSystemPing}, + }, + "cert_gnsi_probe": { + denied: []*gnxi.RPC{gnxi.RPCs.GribiGet, gnxi.RPCs.GribiModify, gnxi.RPCs.GnmiSet, + gnxi.RPCs.GnsiAuthzRotate, gnxi.RPCs.GnoiSystemPing, gnxi.RPCs.GnmiGet, + gnxi.RPCs.GnsiAuthzGet, gnxi.RPCs.GnoiSystemTime}, + allowed: []*gnxi.RPC{gnxi.RPCs.GnsiAuthzProbe}, + }, + "cert_read_only": { + denied: []*gnxi.RPC{gnxi.RPCs.GribiModify, gnxi.RPCs.GnmiSet, + gnxi.RPCs.GnsiAuthzRotate, gnxi.RPCs.GnoiSystemPing, gnxi.RPCs.GnoiSystemTime, + gnxi.RPCs.GnsiAuthzProbe}, + allowed: []*gnxi.RPC{gnxi.RPCs.GnsiAuthzGet, gnxi.RPCs.GribiGet, gnxi.RPCs.GnmiGet}, + }, +} + +func TestMain(m *testing.M) { + fptest.RunTests(m) +} + +func setUpBaseline(t *testing.T, dut *ondatra.DUTDevice) { + + policyMap = authz.LoadPolicyFromJSONFile(t, "testdata/policy.json") + + caKey, trustBundle, err := svid.LoadKeyPair(*caKeyPem, *caCertPem) + if err != nil { + t.Fatalf("Could not load ca key/cert: %v", err) + } + caCertBytes, err := os.ReadFile(*caCertPem) + if err != nil { + t.Fatalf("Could not load the ca cert: %v", err) + } + trusBundle := x509.NewCertPool() + if !trusBundle.AppendCertsFromPEM(caCertBytes) { + t.Fatalf("Could not create the trust bundle: %v", err) + } + for user, v := range usersMap { + userSvid, err := svid.GenSVID("", v.ID, 300, trustBundle, caKey, x509.RSA) + if err != nil { + t.Fatalf("Could not generate svid for user %s: %v", user, err) + } + tlsConf := tls.Config{ + Certificates: []tls.Certificate{*userSvid}, + RootCAs: trusBundle, + } + usersMap[user] = authz.Spiffe{ + ID: v.ID, + TLSConf: &tlsConf, + } + } +} + +// verifyPerm takes an authorization Table and verify the expected rpc/access +func verifyAuthTable(t *testing.T, dut *ondatra.DUTDevice, authTable authorizationTable) { + for certName, access := range authTable { + t.Run(fmt.Sprintf("Validating access for user %s", certName), func(t *testing.T) { + for _, allowedRPC := range access.allowed { + authz.Verify(t, dut, getSpiffe(t, dut, certName), allowedRPC, &authz.HardVerify{}) + } + for _, deniedRPC := range access.denied { + authz.Verify(t, dut, getSpiffe(t, dut, certName), deniedRPC, &authz.ExceptDeny{}, &authz.HardVerify{}) + } + }) + } +} + +func getSpiffe(t *testing.T, dut *ondatra.DUTDevice, certName string) *authz.Spiffe { + spiffe, ok := usersMap[certName] + if !ok { + t.Fatalf("Could not find Spiffe ID for user %s", certName) + } + return &spiffe +} + +// Authz-1, Test policy behaviors, and probe results matches actual client results. +func TestAuthz1(t *testing.T) { + dut := ondatra.DUT(t, "dut") + setUpBaseline(t, dut) + certAdminSpiffe := getSpiffe(t, dut, "cert_user_admin") + t.Run("Authz-1.1, - Test empty source", func(t *testing.T) { + // Pre-Test Section + _, policyBefore := authz.Get(t, dut) + t.Logf("Authz Policy of the Device %s before the Rotate Trigger is %s", dut.Name(), policyBefore.PrettyPrint(t)) + defer policyBefore.Rotate(t, dut, uint64(time.Now().UnixMilli()), fmt.Sprintf("v0.%v", (time.Now().UnixNano())), false) + + // Fetch the Desired Authorization Policy and Attach base Admin Policy Before Rotate + newpolicy, ok := policyMap["policy-everyone-can-gnmi-not-gribi"] + if !ok { + t.Fatal("Policy policy-everyone-can-gnmi-not-gribi is not loaded from policy json file") + } + newpolicy.AddAllowRules("base", []string{*testInfraID}, []*gnxi.RPC{gnxi.RPCs.AllRPC}) + // Rotate the policy. + newpolicy.Rotate(t, dut, uint64(100), "policy-everyone-can-gnmi-not-gribi_v1", false) + + // Verification of Policy for cert_user_admin is allowed gNMI Get and denied gRIBI Get + t.Run("Verification of Policy for cert_user_admin is allowed gNMI Get and denied gRIBI Get", func(t *testing.T) { + authz.Verify(t, dut, certAdminSpiffe, gnxi.RPCs.GribiGet, &authz.ExceptDeny{}, &authz.HardVerify{}) + authz.Verify(t, dut, certAdminSpiffe, gnxi.RPCs.GnmiGet, &authz.HardVerify{}) + }) + + }) + + t.Run("Authz-1.2, Test Empty Request", func(t *testing.T) { + // Pre-Test Section + _, policyBefore := authz.Get(t, dut) + t.Logf("Authz Policy of the Device %s before the Rotate Trigger is %s", dut.Name(), policyBefore.PrettyPrint(t)) + defer policyBefore.Rotate(t, dut, uint64(time.Now().UnixMilli()), fmt.Sprintf("v0.%v", (time.Now().UnixNano())), false) + + // Fetch the Desired Authorization Policy and Attach base Admin Policy Before Rotate + newpolicy, ok := policyMap["policy-everyone-can-gribi-not-gnmi"] + if !ok { + t.Fatal("policy-everyone-can-gribi-not-gnmi") + } + newpolicy.AddAllowRules("base", []string{*testInfraID}, []*gnxi.RPC{gnxi.RPCs.AllRPC}) + // Rotate the policy. + newpolicy.Rotate(t, dut, uint64(100), "policy-everyone-can-gribi-not-gnmi_v1", false) + + t.Run("Verification of cert_deny_all is denied to issue gRIBI.Get and cert_user_admin is allowed to issue `gRIBI.Get`", func(t *testing.T) { + authz.Verify(t, dut, getSpiffe(t, dut, "cert_deny_all"), gnxi.RPCs.GnmiGet, &authz.ExceptDeny{}, &authz.HardVerify{}) + authz.Verify(t, dut, certAdminSpiffe, gnxi.RPCs.GribiGet, &authz.HardVerify{}) + }) + }) + + readOnlySpiffe := getSpiffe(t, dut, "cert_read_only") + t.Run("Authz-1.3, Test that there can only be One policy", func(t *testing.T) { + // Pre-Test Section + dut := ondatra.DUT(t, "dut") + _, policyBefore := authz.Get(t, dut) + t.Logf("Authz Policy of the Device %s before the Rotate Trigger is %s", dut.Name(), policyBefore.PrettyPrint(t)) + defer policyBefore.Rotate(t, dut, uint64(time.Now().UnixMilli()), fmt.Sprintf("v0.%v", (time.Now().UnixNano())), false) + + // Fetch the Desired Authorization Policy and Attach base Admin Policy Before Rotate - 1 + newpolicy, ok := policyMap["policy-gribi-get"] + if !ok { + t.Fatal("Policy policy-gribi-get is not loaded from policy json file") + } + newpolicy.AddAllowRules("base", []string{*testInfraID}, []*gnxi.RPC{gnxi.RPCs.AllRPC}) + // Rotate the policy. + newpolicy.Rotate(t, dut, uint64(100), "policy-gribi-get_v1", false) + + // Verification of Policy for read_only to allow gRIBI Get and to deny gNMI Get + authz.Verify(t, dut, readOnlySpiffe, gnxi.RPCs.GribiGet, &authz.HardVerify{}) + authz.Verify(t, dut, readOnlySpiffe, gnxi.RPCs.GnmiGet, &authz.ExceptDeny{}, &authz.HardVerify{}) + + // Fetch the Desired Authorization Policy and Attach base Admin Policy Before Rotate - 2 + newpolicy, ok = policyMap["policy-gnmi-get"] + if !ok { + t.Fatal("Policy policy-gnmi-get is not loaded from policy json file") + } + newpolicy.AddAllowRules("base", []string{*testInfraID}, []*gnxi.RPC{gnxi.RPCs.AllRPC}) + // Rotate the policy. + newpolicy.Rotate(t, dut, uint64(time.Now().UnixMilli()), fmt.Sprintf("v0.%v", (time.Now().UnixNano())), false) + + // Verification of Policy for read-only to deny gRIBI Get and allow gNMI Get + t.Run("Verification of Policy for read-only to deny gRIBI Get and allow gNMI Get", func(t *testing.T) { + authz.Verify(t, dut, readOnlySpiffe, gnxi.RPCs.GribiGet, &authz.ExceptDeny{}, &authz.HardVerify{}) + authz.Verify(t, dut, readOnlySpiffe, gnxi.RPCs.GnmiGet, &authz.HardVerify{}) + }) + }) + + t.Run("Authz-1.4, Test Normal Policy", func(t *testing.T) { + // Pre-Test Section + _, policyBefore := authz.Get(t, dut) + t.Logf("Authz Policy of the Device %s before the Rotate Trigger is %s", dut.Name(), policyBefore.PrettyPrint(t)) + defer policyBefore.Rotate(t, dut, uint64(time.Now().UnixMilli()), fmt.Sprintf("v0.%v", (time.Now().UnixNano())), false) + + // Fetch the Desired Authorization Policy and Attach base Admin Policy Before Rotate + newpolicy, ok := policyMap["policy-normal-1"] + if !ok { + t.Fatal("Policy policy-normal-1 is not loaded from policy json file") + } + newpolicy.AddAllowRules("base", []string{*testInfraID}, []*gnxi.RPC{gnxi.RPCs.AllRPC}) + // Rotate the policy. + newpolicy.Rotate(t, dut, uint64(100), "policy-normal-1_v1", false) + + // Verify all results match per the above table for policy policy-normal-1 + verifyAuthTable(t, dut, authTable) + }) +} + +// Authz-2, Test rotation behavior +func TestAuthz2(t *testing.T) { + dut := ondatra.DUT(t, "dut") + setUpBaseline(t, dut) + spiffeUserAdmin := getSpiffe(t, dut, "cert_user_admin") + spiffeCertReadOnly := getSpiffe(t, dut, "cert_read_only") + t.Run("Authz-2.1, Test only one rotation request at a time", func(t *testing.T) { + // Pre-Test Section + _, policyBefore := authz.Get(t, dut) + t.Logf("Authz Policy of the Device %s before the Rotate Trigger is %s", dut.Name(), policyBefore.PrettyPrint(t)) + defer policyBefore.Rotate(t, dut, uint64(time.Now().UnixMilli()), fmt.Sprintf("v0.%v", (time.Now().UnixNano())), false) + + // Fetch the Desired Authorization Policy and Attach base Admin Policy Before Rotate + newpolicy, ok := policyMap["policy-everyone-can-gnmi-not-gribi"] + if !ok { + t.Fatal("Policy policy-everyone-can-gnmi-not-gribi is not loaded from policy json file") + } + newpolicy.AddAllowRules("base", []string{*testInfraID}, []*gnxi.RPC{gnxi.RPCs.AllRPC}) + jsonPolicy, err := newpolicy.Marshal() + if err != nil { + t.Fatalf("Could not marshal the policy %s", string(jsonPolicy)) + } + // Rotate Request 1 + rotateStream, err := dut.RawAPIs().GNSI(t).Authz().Rotate(context.Background()) + if err != nil { + t.Fatalf("Could not start rotate stream %v", err) + } + defer rotateStream.CloseSend() + autzRotateReq := &authzpb.RotateAuthzRequest_UploadRequest{ + UploadRequest: &authzpb.UploadRequest{ + Version: fmt.Sprintf("v0.%v", (time.Now().UnixNano())), + CreatedOn: uint64(time.Now().UnixMilli()), + Policy: string(jsonPolicy), + }, + } + t.Logf("Sending Authz.Rotate request on device (client 1): \n %v", autzRotateReq) + err = rotateStream.Send(&authzpb.RotateAuthzRequest{RotateRequest: autzRotateReq}) + if err == nil { + t.Logf("Authz.Rotate upload (client 1) was successful, receiving response ...") + } + _, err = rotateStream.Recv() + if err != nil { + t.Fatalf("Error while receiving rotate request reply (client 1) %v", err) + } + // Rotate Request 2 - Before Finalizing the Request 1 + newpolicy, ok = policyMap["policy-everyone-can-gnmi-not-gribi"] + if !ok { + t.Fatal("Policy policy-everyone-can-gnmi-not-gribi is not loaded from policy json file") + } + newpolicy.AddAllowRules("base", []string{*testInfraID}, []*gnxi.RPC{gnxi.RPCs.AllRPC}) + jsonPolicy, err = newpolicy.Marshal() + if err != nil { + t.Fatalf("Could not marshal the policy %s", string(jsonPolicy)) + } + rotateStream, err = dut.RawAPIs().GNSI(t).Authz().Rotate(context.Background()) + if err != nil { + t.Fatalf("Could not start rotate stream %v", err) + } + defer rotateStream.CloseSend() + autzRotateReq = &authzpb.RotateAuthzRequest_UploadRequest{ + UploadRequest: &authzpb.UploadRequest{ + Version: fmt.Sprintf("v0.%v", (time.Now().UnixNano())), + CreatedOn: uint64(time.Now().UnixMilli()), + Policy: string(jsonPolicy), + }, + } + t.Logf("Sending Authz.Rotate request on device (client 2): \n %v", autzRotateReq) + err = rotateStream.Send(&authzpb.RotateAuthzRequest{RotateRequest: autzRotateReq}) + if err == nil { + t.Logf("Authz.Rotate upload was successful (client 2), receiving response ...") + } + _, err = rotateStream.Recv() + if err == nil { + t.Fatalf("Second Rotate request (client 2) should be Rejected - Error while receiving rotate request reply %v", err) + } + t.Run("Verification of Policy for user_admin to deny gRIBI Get and allow gNMI Get", func(t *testing.T) { + // Verification of Policy for user_admin to deny gRIBI Get and allow gNMI Get + authz.Verify(t, dut, spiffeUserAdmin, gnxi.RPCs.GnmiGet, &authz.HardVerify{}) + authz.Verify(t, dut, spiffeUserAdmin, gnxi.RPCs.GribiGet, &authz.ExceptDeny{}, &authz.HardVerify{}) + }) + + }) + + t.Run("Authz-2.2, Test Rollback When Connection Closed", func(t *testing.T) { + // Pre-Test Section + _, policyBefore := authz.Get(t, dut) + t.Logf("Authz Policy of the Device %s before the Rotate Trigger is %s", dut.Name(), policyBefore.PrettyPrint(t)) + defer policyBefore.Rotate(t, dut, uint64(time.Now().UnixMilli()), fmt.Sprintf("v0.%v", (time.Now().UnixNano())), false) + + // Fetch the Desired Authorization Policy and Attach base Admin Policy Before Rotate + newpolicy, ok := policyMap["policy-gribi-get"] + if !ok { + t.Fatal("Policy policy-gribi-get is not loaded from policy json file") + } + newpolicy.AddAllowRules("base", []string{*testInfraID}, []*gnxi.RPC{gnxi.RPCs.AllRPC}) + // Rotate the policy. + newpolicy.Rotate(t, dut, uint64(time.Now().UnixMilli()), fmt.Sprintf("v0.%v", (time.Now().UnixNano())), false) + + // Verification of Policy for read_only to allow gRIBI Get and to deny gNMI Get + t.Run("Verification of Policy for read_only to allow gRIBI Get and to deny gNMI Get", func(t *testing.T) { + authz.Verify(t, dut, spiffeCertReadOnly, gnxi.RPCs.GribiGet, &authz.HardVerify{}) + authz.Verify(t, dut, spiffeCertReadOnly, gnxi.RPCs.GnmiGet, &authz.ExceptDeny{}, &authz.HardVerify{}) + }) + + // Fetch the Desired Authorization Policy and Attach base Admin Policy Before Rotate + newpolicy, ok = policyMap["policy-gnmi-get"] + if !ok { + t.Fatal("Policy policy-gnmi-get is not loaded from policy json file") + } + newpolicy.AddAllowRules("base", []string{*testInfraID}, []*gnxi.RPC{gnxi.RPCs.AllRPC}) + jsonPolicy, err := newpolicy.Marshal() + if err != nil { + t.Fatalf("Could not marshal the policy %s", string(jsonPolicy)) + } + rotateStream, err := dut.RawAPIs().GNSI(t).Authz().Rotate(context.Background()) + if err != nil { + t.Fatalf("Could not start rotate stream %v", err) + } + defer rotateStream.CloseSend() + autzRotateReq := &authzpb.RotateAuthzRequest_UploadRequest{ + UploadRequest: &authzpb.UploadRequest{ + Version: fmt.Sprintf("v0.%v", (time.Now().UnixNano())), + CreatedOn: uint64(time.Now().UnixMilli()), + Policy: string(jsonPolicy), + }, + } + t.Logf("Sending Authz.Rotate request on device (client 2): \n %v", autzRotateReq) + err = rotateStream.Send(&authzpb.RotateAuthzRequest{RotateRequest: autzRotateReq}) + if err == nil { + t.Logf("Authz.Rotate upload was successful, receiving response ...") + } + _, err = rotateStream.Recv() + if err != nil { + t.Fatalf("Error while receiving rotate request reply %v", err) + } + // Verification of Policy for read_only to allow gRIBI Get and to deny gNMI Get + t.Run("Verification of Policy for read_only to allow gRIBI Get and to deny gNMI Get after rotate that is not finalized", func(t *testing.T) { + authz.Verify(t, dut, spiffeCertReadOnly, gnxi.RPCs.GribiGet, &authz.ExceptDeny{}, &authz.HardVerify{}) + authz.Verify(t, dut, spiffeCertReadOnly, gnxi.RPCs.GnmiGet, &authz.HardVerify{}) + }) + + // Close the Stream + rotateStream.CloseSend() + + // Verification of Policy for read_only to allow gRIBI Get and to deny gNMI Get + t.Run("Verification of Policy for read_only to allow gRIBI Get and to deny gNMI Get after closing stream", func(t *testing.T) { + authz.Verify(t, dut, spiffeCertReadOnly, gnxi.RPCs.GribiGet, &authz.HardVerify{}) + authz.Verify(t, dut, spiffeCertReadOnly, gnxi.RPCs.GnmiGet, &authz.ExceptDeny{}, &authz.HardVerify{}) + }) + + }) + + t.Run("Authz-2.3, Test Rollback on Invalid Policy", func(t *testing.T) { + // Pre-Test Section + _, policyBefore := authz.Get(t, dut) + t.Logf("Authz Policy of the Device %s before the Rotate Trigger is %s", dut.Name(), policyBefore.PrettyPrint(t)) + defer policyBefore.Rotate(t, dut, uint64(time.Now().UnixMilli()), fmt.Sprintf("v0.%v", (time.Now().UnixNano())), false) + + // Fetch the Desired Authorization Policy and Attach base Admin Policy Before Rotate + newpolicy, ok := policyMap["policy-gribi-get"] + if !ok { + t.Fatal("Policy policy-gribi-get is not loaded from policy json file") + } + newpolicy.AddAllowRules("base", []string{*testInfraID}, []*gnxi.RPC{gnxi.RPCs.AllRPC}) + // Rotate the policy. + newpolicy.Rotate(t, dut, uint64(time.Now().UnixMilli()), fmt.Sprintf("v0.%v", (time.Now().UnixNano())), false) + + // Verification of Policy for read_only to allow gRIBI Get and to deny gNMI Get + t.Run("Verification of Policy for read_only to allow gRIBI Get and to deny gNMI Get", func(t *testing.T) { + authz.Verify(t, dut, spiffeCertReadOnly, gnxi.RPCs.GribiGet, &authz.HardVerify{}) + authz.Verify(t, dut, spiffeCertReadOnly, gnxi.RPCs.GnmiGet, &authz.ExceptDeny{}, &authz.HardVerify{}) + }) + + // Fetch the Desired Authorization Policy and Attach base Admin Policy Before Rotate + t.Run("Applying policy-invalid-no-allow-rules", func(t *testing.T) { + newpolicy, ok = policyMap["policy-invalid-no-allow-rules"] + if !ok { + t.Fatal("Policy policy-invalid-no-allow-rules is not loaded from policy json file") + } + newpolicy.AddAllowRules("base", []string{*testInfraID}, []*gnxi.RPC{gnxi.RPCs.AllRPC}) + jsonPolicy, err := newpolicy.Marshal() + if err != nil { + t.Fatalf("Could not marshal the policy %s", string(jsonPolicy)) + } + rotateStream, err := dut.RawAPIs().GNSI(t).Authz().Rotate(context.Background()) + if err != nil { + t.Fatalf("Could not start rotate stream %v", err) + } + defer rotateStream.CloseSend() + autzRotateReq := &authzpb.RotateAuthzRequest_UploadRequest{ + UploadRequest: &authzpb.UploadRequest{ + Version: fmt.Sprintf("v0.%v", (time.Now().UnixNano())), + CreatedOn: uint64(time.Now().UnixMilli()), + Policy: string(jsonPolicy), + }, + } + t.Logf("Sending Authz.Rotate request on device: \n %v", autzRotateReq) + err = rotateStream.Send(&authzpb.RotateAuthzRequest{RotateRequest: autzRotateReq}) + if err == nil { + t.Logf("Authz.Rotate upload was successful, receiving response ...") + } + _, err = rotateStream.Recv() + if err != nil { + t.Fatalf("Expected Error while receiving rotate request reply %v", err) + } + + t.Run("Verification of Policy for read_only user to deny gRIBI Get before closing stream", func(t *testing.T) { + authz.Verify(t, dut, spiffeCertReadOnly, gnxi.RPCs.GribiGet, &authz.ExceptDeny{}, &authz.HardVerify{}) + }) + + // Close the Stream + rotateStream.CloseSend() + // Verification of Policy for read_only to allow gRIBI Get and to deny gNMI Get + t.Run("Verification of Policy for read_only to allow gRIBI Get and to deny gNMI Get after closing stream", func(t *testing.T) { + authz.Verify(t, dut, spiffeCertReadOnly, gnxi.RPCs.GribiGet, &authz.HardVerify{}) + authz.Verify(t, dut, spiffeCertReadOnly, gnxi.RPCs.GnmiGet, &authz.ExceptDeny{}, &authz.HardVerify{}) + }) + }) + + }) + t.Run("Authz-2.4, Test Force_Overwrite when the Version does not change", func(t *testing.T) { + // Pre-Test Section + _, policyBefore := authz.Get(t, dut) + t.Logf("Authz Policy of the Device %s before the Rotate Trigger is %s", dut.Name(), policyBefore.PrettyPrint(t)) + defer policyBefore.Rotate(t, dut, uint64(time.Now().UnixMilli()), fmt.Sprintf("v0.%v", (time.Now().UnixNano())), false) + + // Fetch the Desired Authorization Policy and Attach base Admin Policy Before Rotate + newpolicy, ok := policyMap["policy-gribi-get"] + if !ok { + t.Fatal("Policy policy-gribi-get is not loaded from policy json file") + } + newpolicy.AddAllowRules("base", []string{*testInfraID}, []*gnxi.RPC{gnxi.RPCs.AllRPC}) + // Rotate the policy. + prevVersion := fmt.Sprintf("v0.%v", (time.Now().UnixNano())) + newpolicy.Rotate(t, dut, uint64(time.Now().UnixMilli()), prevVersion, false) + + newpolicy, ok = policyMap["policy-gnmi-get"] + if !ok { + t.Fatal("Policy policy-gnmi-get is not loaded from policy json file") + } + newpolicy.AddAllowRules("base", []string{*testInfraID}, []*gnxi.RPC{gnxi.RPCs.AllRPC}) + jsonPolicy, err := newpolicy.Marshal() + if err != nil { + t.Fatalf("Could not marshal the policy %s", string(jsonPolicy)) + } + rotateStream, err := dut.RawAPIs().GNSI(t).Authz().Rotate(context.Background()) + if err != nil { + t.Fatalf("Could not start rotate stream %v", err) + } + defer rotateStream.CloseSend() + autzRotateReq := &authzpb.RotateAuthzRequest_UploadRequest{ + UploadRequest: &authzpb.UploadRequest{ + Version: prevVersion, + CreatedOn: uint64(time.Now().UnixMilli()), + Policy: string(jsonPolicy), + }, + } + t.Logf("Sending Authz.Rotate request with the same version on device: \n %v", autzRotateReq) + err = rotateStream.Send(&authzpb.RotateAuthzRequest{RotateRequest: autzRotateReq}) + if err == nil { + t.Logf("Authz.Rotate upload was successful, receiving response ...") + } + _, err = rotateStream.Recv() + if err == nil { + t.Fatalf("Expected Error for uploading the policy with the same version as the previous one") + } + // Verification of Policy for read_only to allow gRIBI Get and to deny gNMI Get + t.Run("Verification of Policy for read_only to allow gRIBI Get and to deny gNMI Get after rotate without force overwrite", func(t *testing.T) { + authz.Verify(t, dut, spiffeCertReadOnly, gnxi.RPCs.GribiGet, &authz.HardVerify{}) + authz.Verify(t, dut, spiffeCertReadOnly, gnxi.RPCs.GnmiGet, &authz.ExceptDeny{}, &authz.HardVerify{}) + }) + + t.Logf("Preforming Rotate with the same version with force overwrite\n") + newpolicy.Rotate(t, dut, uint64(time.Now().UnixMilli()), prevVersion, true) + // Verification of Policy for read_only to allow gRIBI Get and to deny gNMI Get + t.Run("Verification of Policy for read_only to allow gRIBI Get and to deny gNMI Get after rotate wth force overwrite", func(t *testing.T) { + authz.Verify(t, dut, spiffeCertReadOnly, gnxi.RPCs.GribiGet, &authz.ExceptDeny{}, &authz.HardVerify{}) + authz.Verify(t, dut, spiffeCertReadOnly, gnxi.RPCs.GnmiGet, &authz.HardVerify{}) + }) + + }) +} + +// Authz-3 Test Get Behavior +func TestAuthz3(t *testing.T) { + // Pre-Test Section + dut := ondatra.DUT(t, "dut") + setUpBaseline(t, dut) + _, policyBefore := authz.Get(t, dut) + t.Logf("Authz Policy of the Device %s before the Rotate Trigger is %s", dut.Name(), policyBefore.PrettyPrint(t)) + defer policyBefore.Rotate(t, dut, uint64(time.Now().UnixMilli()), fmt.Sprintf("v0.%v", (time.Now().UnixNano())), false) + + // Fetch the Desired Authorization Policy object. + newpolicy, ok := policyMap["policy-gribi-get"] + if !ok { + t.Fatal("Policy policy-gribi-get is not loaded from policy json file") + } + // Attach base Admin Policy + // Rotate the policy. + newpolicy.AddAllowRules("base", []string{*testInfraID}, []*gnxi.RPC{gnxi.RPCs.AllRPC}) + expCreatedOn := uint64(time.Now().UnixMilli()) + expVersion := fmt.Sprintf("v0.%v", (time.Now().UnixNano())) + newpolicy.Rotate(t, dut, expCreatedOn, expVersion, false) + t.Logf("New Rotated Authz Policy is %s", newpolicy.PrettyPrint(t)) + // Wait for 30s, intial gNSI.Get and validate the value of version, created_on and gRPC policy content does not change. + time.Sleep(30 * time.Second) + _, finalPolicy := authz.Get(t, dut) + t.Logf("Authz Policy after waiting for 30 seconds is %s", finalPolicy.PrettyPrint(t)) + + // Version and Created On Field Verification + t.Logf("Performing Authz.Get request on device %s", dut.Name()) + gnsiC := dut.RawAPIs().GNSI(t) + resp, err := gnsiC.Authz().Get(context.Background(), &authzpb.GetRequest{}) + if err != nil { + t.Fatalf("Authz.Get request is failed on device %s", dut.Name()) + } + t.Logf("Authz.Get response is %s", resp) + if resp.GetVersion() != expVersion { + t.Errorf("Version has Changed in Authz.Get response") + } + if resp.GetCreatedOn() != expCreatedOn { + t.Errorf("CreatedOn Value has Changed in Authz.Get response") + } + if !cmp.Equal(&newpolicy, finalPolicy) { + t.Fatalf("Not Expecting Policy Mismatch before and after the Wait):\n%s", cmp.Diff(&newpolicy, finalPolicy)) + } +} + +// Authz-4 Reboot Persistent +func TestAuthz4(t *testing.T) { + // Pre-Test Section + dut := ondatra.DUT(t, "dut") + _, policyBefore := authz.Get(t, dut) + t.Logf("Authz Policy of the Device %s before the Reboot Trigger is %s", dut.Name(), policyBefore.PrettyPrint(t)) + defer policyBefore.Rotate(t, dut, uint64(time.Now().UnixMilli()), fmt.Sprintf("v0.%v", (time.Now().UnixNano())), false) + + // Fetch the Desired Authorization Policy and Attach base Admin Policy Before Rotate + newpolicy, ok := policyMap["policy-normal-1"] + if !ok { + t.Fatal("Policy policy-normal-1 is not loaded from policy json file") + } + newpolicy.AddAllowRules("base", []string{*testInfraID}, []*gnxi.RPC{gnxi.RPCs.AllRPC}) + expCreatedOn := uint64(time.Now().UnixMilli()) + expVersion := fmt.Sprintf("v0.%v", (time.Now().UnixNano())) + t.Logf("New Authz Policy is %s", newpolicy.PrettyPrint(t)) + newpolicy.Rotate(t, dut, expCreatedOn, expVersion, false) + + // Trigger Section - Reboot + gnoiClient, err := dut.RawAPIs().BindingDUT().DialGNOI(context.Background()) + if err != nil { + t.Fatalf("Failed to connect to gnoi server, err: %v", err) + } + rebootRequest := &gnps.RebootRequest{ + Method: gnps.RebootMethod_COLD, + Force: true, + } + bootTimeBeforeReboot := gnmi.Get(t, dut, gnmi.OC().System().BootTime().State()) + t.Logf("DUT boot time before reboot: %v", bootTimeBeforeReboot) + var currentTime string + currentTime = gnmi.Get(t, dut, gnmi.OC().System().CurrentDatetime().State()) + t.Logf("Time Before Reboot : %v", currentTime) + rebootResponse, err := gnoiClient.System().Reboot(context.Background(), rebootRequest) + t.Logf("Got Reboot response: %v, err: %v", rebootResponse, err) + if err != nil { + t.Fatalf("Failed to reboot chassis with unexpected err: %v", err) + } + for { + if errMsg := testt.CaptureFatal(t, func(t testing.TB) { + currentTime = gnmi.Get(t, dut, gnmi.OC().System().CurrentDatetime().State()) + }); errMsg != nil { + t.Log("Reboot is started") + break + } + t.Log("Wait for reboot to be started") + time.Sleep(30 * time.Second) + } + startReboot := time.Now() + t.Logf("Wait for DUT to boot up by polling the telemetry output.") + for { + t.Logf("Time elapsed %.2f seconds since reboot started.", time.Since(startReboot).Seconds()) + if errMsg := testt.CaptureFatal(t, func(t testing.TB) { + currentTime = gnmi.Get(t, dut, gnmi.OC().System().CurrentDatetime().State()) + }); errMsg != nil { + t.Logf("Got testt.CaptureFatal errMsg: %s, keep polling ...", *errMsg) + } else { + t.Logf("Device rebooted successfully with received time: %v", currentTime) + break + } + if uint64(time.Since(startReboot).Seconds()) > maxRebootTime { + t.Fatalf("Check boot time: got %v, want < %v", time.Since(startReboot), maxRebootTime) + } + } + // Verification Section + // Version and Created On Field Verification + t.Logf("Performing Authz.Get request on device %s", dut.Name()) + gnsiC, err := dut.RawAPIs().BindingDUT().DialGNSI(context.Background()) + if err != nil { + t.Fatalf("Could not create GNSI Connection %v", err) + } + resp, err := gnsiC.Authz().Get(context.Background(), &authzpb.GetRequest{}) + if err != nil { + t.Fatalf("Authz.Get request is failed with Error %v", err) + } + t.Logf("Authz.Get response is %s", resp) + if resp.GetVersion() != expVersion { + t.Errorf("Version has Changed to %v from Expected Version %v after Reboot Trigger", resp.GetVersion(), expVersion) + } + if resp.GetCreatedOn() != expCreatedOn { + t.Errorf("Created On has Changed to %v from Expected Created On %v after Reboot Trigger", resp.GetCreatedOn(), expCreatedOn) + } + // Verify all results match per the above table for policy policy-normal-1 + verifyAuthTable(t, dut, authTable) +} diff --git a/feature/security/gnsi/authz/tests/authz/metadata.textproto b/feature/security/gnsi/authz/tests/authz/metadata.textproto new file mode 100644 index 00000000000..8e841aa56e7 --- /dev/null +++ b/feature/security/gnsi/authz/tests/authz/metadata.textproto @@ -0,0 +1,7 @@ +# proto-file: github.com/openconfig/featureprofiles/proto/metadata.proto +# proto-message: Metadata + +uuid: "a5c2d46c-976b-41bd-9fae-3341ce5c1b29" +plan_id: "Authz" +description: "General Authz (1-4) tests" +testbed: TESTBED_DUT_ATE_2LINKS diff --git a/feature/security/gnsi/authz/tests/authz/testdata/ca.cert.pem b/feature/security/gnsi/authz/tests/authz/testdata/ca.cert.pem new file mode 100644 index 00000000000..058b7d31614 --- /dev/null +++ b/feature/security/gnsi/authz/tests/authz/testdata/ca.cert.pem @@ -0,0 +1,31 @@ +-----BEGIN CERTIFICATE----- +MIIFUDCCAzigAwIBAgIHEsH2uK4gwDANBgkqhkiG9w0BAQsFADA2MQswCQYDVQQG +EwJVUzETMBEGA1UEChMKT3BlbkNvbmZpZzESMBAGA1UEAxMJbG9jYWxob3N0MCAX +DTIzMDcxNzE4MDIwMVoYDzMwMjMwNzE3MTgwMjAxWjA2MQswCQYDVQQGEwJVUzET +MBEGA1UEChMKT3BlbkNvbmZpZzESMBAGA1UEAxMJbG9jYWxob3N0MIICIjANBgkq +hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAw+CN6Ryym3wExln3ZDGODa0REmTm6MmV +jUL8yqdm35+i5/SIV+oI8e8LkXa1ccvKSCvN3s1ESimiYyltJ+GcgiA5b+pDndd9 +e0RHhlnx2NmGau/MW+9dkwhmNniG/GBdvBxJTL43T3pR53HZafdvjNnEH6U7aBFC +4IHwXYF5Mw+B0JEldnHsYi+tGKQcBqMpCCZn5k3jyCE/dYBFmnQwr9Z6FlN53hKl +19YoT9o4NBFCZ42rf22oWieCBQMjTHSCSL+bKBxfF9abefyn+SHElgw5iJ9oiylA +Q4dpdbKHWOEFEPO5Hx4MdmUcx15o08xpg1Z2yk1dZff8GMFGO4EY2HXq0MoU4OMV +QOcl/JhGqmjxNA42hW50DY/qU2KBlS9m/AJg/e1zYXNA4MkgTTaO04m92+OnMeBO +/ZgEs8KfrmYox6TG4xAAr6WN+L4rafmo1q+Yp/dJD6kRJ32yM9b+O+ovVnFQYHDV +1Td8XDamQLRELpgsjvVLG4I4mMuCEcKrixI6PYNdslE2SES3f1xH9sv/z4YvxZ19 +cOoWT1f5/4Shzv6GuyRfa1gf7vDZVM2SZmzxNzkAQ6iRAbY0ft4t0DsxmCnNTo3W +h1zXUxIHjfDiwF9LX3JK0t+LL8PKx0V3z4alj5zDE800RXdoQo4eqvCkjmge4oRg +sR06F0VnK9ECAwEAAaNhMF8wDgYDVR0PAQH/BAQDAgKEMB0GA1UdJQQWMBQGCCsG +AQUFBwMCBggrBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBQKqJpq +IzSuypYALPMEOBTj1I13vTANBgkqhkiG9w0BAQsFAAOCAgEAY+URdI3aRzFwAvv4 +xplwRKFphzunbm/HqJT43GJV2mbXsaheEscXGyxiYtKUlBJzR9BNXbrlM4w61x0c +wR1+Yw6UfSab/64a4OGf0xoJxyG28GofIe31NtX4LK90EH6sFop1exCfQ5Edybao +ebokZAn67EJy5A1G672bnPSDpxVsfILw/83OM+T231Oz0l8nr1Zde6chiVDrOHa5 +x3ww+Ex0HjN8PDreAw2SYCO73KjjuwrjIbEAaLQ0+4Myd+Mb4UbP8biNYCfBkole +WaTNumBfYethCrSOOCYjcJv7PBujsO/qx1EJatY16V8u1jTQ29AqOW+lAkMt/igU +bV4SKZyRmMJ6dpMz9c5K6jGYySlPQeSHESi2pAO7O9NQ8smY/e+4v+puKL65jgHB +fzZfAxI8Ur7Bpf6mKJlJgnoH4phIr86l2lEXnI/Lb9CUsKTNQZ8rqlO3KJqT9H8y +7RBNfctB+McKZryKlc0+42SlnDIQdWfbb1fq6cAu+LjJGdgjeRG0/W636dFAsVQm +IghmGukwCDwFYKA5pdti251HpfltrlcbOe0L0pf4XltH1fXatqwNk2YIF8wKeNuR +QuwWEdjeXOOhqbT8uYtjbhvLCKqYN3tKUWzk53T2SF7eJuk71uEeVIeIQxu/P369 +7qD0V39Ms16pWDivpaSGn7EKFJw= +-----END CERTIFICATE----- diff --git a/feature/security/gnsi/authz/tests/authz/testdata/ca.key.pem b/feature/security/gnsi/authz/tests/authz/testdata/ca.key.pem new file mode 100644 index 00000000000..07c84bb0d3a --- /dev/null +++ b/feature/security/gnsi/authz/tests/authz/testdata/ca.key.pem @@ -0,0 +1,51 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIJKQIBAAKCAgEAw+CN6Ryym3wExln3ZDGODa0REmTm6MmVjUL8yqdm35+i5/SI +V+oI8e8LkXa1ccvKSCvN3s1ESimiYyltJ+GcgiA5b+pDndd9e0RHhlnx2NmGau/M +W+9dkwhmNniG/GBdvBxJTL43T3pR53HZafdvjNnEH6U7aBFC4IHwXYF5Mw+B0JEl +dnHsYi+tGKQcBqMpCCZn5k3jyCE/dYBFmnQwr9Z6FlN53hKl19YoT9o4NBFCZ42r +f22oWieCBQMjTHSCSL+bKBxfF9abefyn+SHElgw5iJ9oiylAQ4dpdbKHWOEFEPO5 +Hx4MdmUcx15o08xpg1Z2yk1dZff8GMFGO4EY2HXq0MoU4OMVQOcl/JhGqmjxNA42 +hW50DY/qU2KBlS9m/AJg/e1zYXNA4MkgTTaO04m92+OnMeBO/ZgEs8KfrmYox6TG +4xAAr6WN+L4rafmo1q+Yp/dJD6kRJ32yM9b+O+ovVnFQYHDV1Td8XDamQLRELpgs +jvVLG4I4mMuCEcKrixI6PYNdslE2SES3f1xH9sv/z4YvxZ19cOoWT1f5/4Shzv6G +uyRfa1gf7vDZVM2SZmzxNzkAQ6iRAbY0ft4t0DsxmCnNTo3Wh1zXUxIHjfDiwF9L +X3JK0t+LL8PKx0V3z4alj5zDE800RXdoQo4eqvCkjmge4oRgsR06F0VnK9ECAwEA +AQKCAgB3nvArV4o/6ComVBUADD9bXMDbQeG+cjUxsqIcxMTPdncPPsfxIIzb6wde +i2ddmn3rO00bbrHwtKJl+oud2msxEKrjDObEQzBvkhA4HT/UFWvAbLeZwYGc5Hk/ +dLXC9LrpwUCGbHfswp+4P0/uJdzq4KakSM0RzdDQuKnpAMPaifLWQ33kashYYhNM +xBQVfZj2UDYNcK3Vr3BIutBG9gQxrkKa1dnL5AmB2Vh/A55lNdEe2mbMiFRS0mPV +2ce5zkEuWk1P3pu4PChxA/o07AlZNRgBtpAqxENpug2Ogjuj7K+iXaVFOp2TxEYh +/yb3iZM6URh0jXCncB11pLrWZg2cOEf39oks5E8dPzQ1lS5rRf2WNHA31vQBDr3U +GOUb24bM3bV1xcFcN7Kv8fKj2iJ0j+5/MqEUK8XQ3YCNLQRdc1bEkjS/HQGlXbcp +zNirAx2gNd0VpHge0QzzUAXsRawjpt6w1DaGJ5iRu0RY+7D7YAtIv7oJ7H5H1HFT +lo5ZGIydMbd/ynJRRJlfu0FxtzkyZ7vVMLZRW9IgfEvTj/x0/synBqxqQUGuXr5+ +pGn21LVZJCCsthOgj9uI9zvF7oy/D+MQ3PGlTsLbBlwtJd0VrLAOul+BSFZT/FdE +V01iWxcDphotiifA/nzM7Gqfun5lDI4FdX/SrPXbNY1EmVRmkQKCAQEAxlQGAqyf +mKEykwoC6dEQ/jKYx1i8xX2qwPOw+lmTuWXznHn7OQkK50TMUVFnZ1fuEU4plJxD +Y0Qro57CAheJF8KPcRBWLG8GrDxb/pfufAHpx6rDUo9HjWEJ3NiPCLy+XBLu/yXo +92D1td/P4ZwC1XkagQONOuOEkVaILr0knTnYzKli0gGw325uwnD1x8X+CjuN5r1r +T2vShKKyUBm755u7rKSpbxKQypsaCPFS8NpZ8ZCDIvEz8/427oZ5Hw5pPA488Nvy +X095iRM1TQDlXEU655pGKttRrnFxOukDuVy8xcpKjC6SXXDCh5XNbhRqesciLORT +Tbztn+CzwYrNFQKCAQEA/NYRwXUxK0PMbn2+lVdMCBnzgEoxfP0dZa5BMODAlDjy +asLx7QJabdOefXwArOi0CYYR7TPqAxCCP4HvzC0SaDG7XXqiSujVSQoHGzg4dxQ1 +/Lps0vJx4nfLNj286Nyk2qQIm7oYAI4V1NB6cqR04ofpemTijI+XE7kLinT8wqX8 +6ioTLdgLgaOyDWab1/7wZBWmZ/zBg98fzC5SrLpy/UI2/XSIWWreHoY8g5uqZQK4 +ax6V8R/ScDPW/5q/0EKuNzN4Y7zC8ugJUqRpsZety4REGcx24+YDfk8XdYjm5Y/2 +GNoRzxRzRgkRn+PhUxg+VKyJHSN+QHRkMdMipw2qzQKCAQEAm8hoKDWb7vG/ngvh +GfQkWuc3Zm5naOE6/PDt9Nfj118jqaePE8/shphdvQoqJNzGnUU+GANeU1y6wnzz +e10tTEKBFZh1d9WF8kg/Io4Iv9No5HNXlUQCOiUc8CISyBQpmn0sybHneljo6AFz +co1vFGtZzDkT+Eu6V8cWlU/wsKc9ihULEFZPrlE6IvVDubXlw/ffkHz9C5dv9sst +MQnltRl4ozV7+Ukl/l8yZg/YzGNW/w46U3oPCvqF/3oVLbXOJ2Qvrim2CfONTYSO ++3tWrdGbYUynDQbU9Ccbf+CEEler19j8EXyLb2YhBws+H9ddhC9iwsxeOtPJ+ykv +STlTuQKCAQEAkB3FSSxvtmWS5XgvZhi4cfW44mtoAgKU+xx0dFPn8ZT0OP6dv6cT +vH5fXM+N4wFRfgw5s6dfwBds5p49/XfDgji2v/XjBCfrSxK4Mj+9j8Kpc0EgPq2L +VLdL0cMnJuR941KUxY8xlz9mGkQrR6WOKoGmB+nxaIWAa/GSLn24hYrvutn4zKzV +AjQ4jYLrWhcrFyFwFN3xwCUyjsPoxCQS32EazyXZgn5z1ZpWa/4TBjiivgxVE3g8 +D1C9QD0JEMCxZS2lddRmmubASacFyADZQ6RE3R+6tPSrERgsGwbJ9hg1Ar1qYUsa +2dTZgvX1vdOX09P04/MTR9IQOoZKvkYAEQKCAQBiFLqp4fZ9bQJAL5ri4BPxXotr +XHq3CdiEYuKAJuKvBFHWJGI2+7tks/3yOMJPf959HHZUVd26Po3BINSqNXJFuyc+ +yOBublRlFOLQQyR7yHe0Lt3LOdN/9Wv+0qi+Jr93JhZk/3bgDMo2aWuIaCL2CPvQ +/xRfhkF0/X6n6Og3/lAaYDRJAF7KaXWZSgj39X6cffvBL29C27Me3BWCeumYhG6Q +CD9O1nc0qsXqZ4TTESuClOxqgKs/CnoHA7VWAOKwtG21I+c/rE77J+cM6YiIn9zM +9cQxacUIZn+EBV9zh1ljvTS9CuvCgZbW5SoYgsn7QBMwOEu/8NzTDPfa6S5+ +-----END RSA PRIVATE KEY----- diff --git a/feature/security/gnsi/authz/tests/authz/testdata/policy.json b/feature/security/gnsi/authz/tests/authz/testdata/policy.json new file mode 100644 index 00000000000..be609532ab9 --- /dev/null +++ b/feature/security/gnsi/authz/tests/authz/testdata/policy.json @@ -0,0 +1,228 @@ +[{ + "name": "allow-test-infra", + "source": { + "principals": [ + "" + ] + }, + "request": {} + }, + { + "name": "policy-everyone-can-gnmi-not-gribi", + "allow_rules": [ + { + "name": "everyone-can-gnmi-get", + "source": { + "principals": [ + "*" + ] + }, + "request": { + "paths": [ + "/gnmi.gNMI/Get" + ] + } + } + ], + "deny_rules": [ + { + "name": "no-one-can-gribi-get", + "source": { + "principals": [ + "*" + ] + }, + "request": { + "paths": [ + "/gribi.gRIBI/Get" + ] + } + } + ] + }, + { + "name": "policy-everyone-can-gribi-not-gnmi", + "allow_rules": [ + { + "name": "everyone-can-gribi", + "source": { + "principals": [ + "*" + ] + }, + "request": { + "paths": [ + "/gribi.gRIBI/*" + ] + } + } + ], + "deny_rules": [ + { + "name": "no-one-can-gnmi", + "source": { + "principals": [ + "*" + ] + }, + "request": { + "paths": [ + "/gribi.gNMI/*" + ] + } + } + ] + }, + { + "name": "policy-invalid-no-allow-rules", + "deny_rules": [ + { + "name": "no-one-can-gribi", + "source": { + "principals": [ + "*" + ] + }, + "request": { + "paths": [ + "/gribi.gRIBI/*" + ] + } + } + ] + }, + { + "name": "policy-gribi-get", + "allow_rules": [ + { + "name": "gribi-get", + "source": { + "principals": [ + "spiffe://test-abc.foo.bar/xyz/read-only" + ] + }, + "request": { + "paths": ["/gribi.gRIBI/Get"] + } + } + ] + }, + { + "name": "policy-gnmi-get", + "allow_rules": [ + { + "name": "gnmi-get", + "source": { + "principals": [ + "spiffe://test-abc.foo.bar/xyz/read-only" + ] + }, + "request": { + "paths": ["/gnmi.gNMI/Get"] + } + } + ] + }, + { + "name": "policy-normal-1", + "allow_rules": [ + { + "name": "gribi-modify", + "source": { + "principals": [ + "spiffe://test-abc.foo.bar/xyz/admin", + "spiffe://test-abc.foo.bar/xyz/gribi-modify" + ] + }, + "request": { + "paths": ["/gribi.gRIBI/*"] + } + }, + { + "name": "gnmi-set", + "source": { + "principals": [ + "spiffe://test-abc.foo.bar/xyz/admin", + "spiffe://test-abc.foo.bar/xyz/gnmi-set" + ] + }, + "request": { + "paths": ["/gnmi.gNMI/*"] + } + }, + { + "name": "gnoi-time", + "source": { + "principals": [ + "spiffe://test-abc.foo.bar/xyz/admin", + "spiffe://test-abc.foo.bar/xyz/gnoi-time" + ] + }, + "request": { + "paths": ["/gnoi.system.System/Time"] + } + }, + { + "name": "gnoi-ping", + "source": { + "principals": [ + "spiffe://test-abc.foo.bar/xyz/admin", + "spiffe://test-abc.foo.bar/xyz/gnoi-ping" + ] + }, + "request": { + "paths": ["/gnoi.system.System/Ping"] + } + }, + { + "name": "gnsi-set", + "source": { + "principals": [ + "spiffe://test-abc.foo.bar/xyz/admin" + ] + }, + "request": { + "paths": ["/gnsi.authz.v1.Authz/*"] + } + }, + { + "name": "gnsi-probe", + "source": { + "principals": [ + "spiffe://test-abc.foo.bar/xyz/gnsi-probe" + ] + }, + "request": { + "paths": ["/gnsi.authz.v1.Authz/Probe"] + } + }, + { + "name": "read-only", + "source": { + "principals": [ + "spiffe://test-abc.foo.bar/xyz/read-only" + ] + }, + "request": { + "paths": [ + "/gnmi.gNMI/Get", + "/gribi.gRIBI/Get", + "/gnsi.authz.v1.Authz/Get" + ] + } + } + ], + "deny_rules": [ + { + "name": "deny-all-user-can-do-nothing", + "source": { + "principals": [ + "spiffe://test-abc.foo.bar/xyz/deny-all" + ] + }, + "request": { + "paths": ["/*"] + } + } + ] + }] \ No newline at end of file diff --git a/internal/security/authz/authz.go b/internal/security/authz/authz.go new file mode 100644 index 00000000000..5411cc241f3 --- /dev/null +++ b/internal/security/authz/authz.go @@ -0,0 +1,279 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package authz provides helper APIs to simplify writing authz test cases. +// It also packs authz rotate and get operations with the corresponding verifications to +// prevent code duplications and increase the test code readability. +package authz + +import ( + "context" + + "crypto/tls" + "encoding/json" + "os" + "testing" + "time" + + "github.com/google/go-cmp/cmp" + "github.com/openconfig/featureprofiles/internal/security/gnxi" + "github.com/openconfig/gnsi/authz" + "github.com/openconfig/ondatra" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/credentials" + "google.golang.org/grpc/status" +) + +// Spiffe is an struct to save an Spiffe id and its svid. +type Spiffe struct { + // ID store Spiffe id. + ID string + // TlsConf stores the svid of Spiffe id. + TLSConf *tls.Config +} + +// AuthorizationPolicy is an struct to save an authz policy. +type AuthorizationPolicy struct { + // name of policy. + Name string `json:"name"` + // rules that specify what are allowed by users. + AllowRules []Rule `json:"allow_rules,omitempty"` + // rules that specify what are denied for users. + DenyRules []Rule `json:"deny_rules,omitempty"` +} + +// Rule represent the structure for an authz rule. +type Rule struct { + // name of the rule. + Name string `json:"name"` + // the users that rule defined for. + Source struct { + Principals []string `json:"principals"` + } `json:"source"` + // rpc for which the rule is specified. + Request struct { + Paths []string `json:"paths"` + } `json:"request"` +} + +func createRule(name string, users []string, rpcs []*gnxi.RPC) Rule { + rule := Rule{Name: name} + for _, rpc := range rpcs { + rule.Request.Paths = append(rule.Request.Paths, rpc.Path) + } + rule.Source.Principals = users + return rule +} + +// AddAllowRules adds an allow rule for policy p. +func (p *AuthorizationPolicy) AddAllowRules(name string, users []string, rpcs []*gnxi.RPC) { + rule := createRule(name, users, rpcs) + p.AllowRules = append(p.AllowRules, rule) +} + +// AddDenyRules adds an allow rule for policy p. +func (p *AuthorizationPolicy) AddDenyRules(name string, users []string, rpcs []*gnxi.RPC) { + rule := createRule(name, users, rpcs) + p.DenyRules = append(p.DenyRules, rule) +} + +// Unmarshal unmarshal policy p to json string. +func (p *AuthorizationPolicy) Unmarshal(jsonString string) error { + return json.Unmarshal([]byte(jsonString), p) +} + +// Marshal marshal a policy from json string. +func (p *AuthorizationPolicy) Marshal() ([]byte, error) { + return json.Marshal(p) +} + +// Rotate apply policy p on device dut, this is test api for positive testing and it fails the test on failure. +func (p *AuthorizationPolicy) Rotate(t *testing.T, dut *ondatra.DUTDevice, createdOn uint64, version string, forcOverwrite bool) { + t.Logf("Performing Authz.Rotate request on device %s", dut.Name()) + gnsiC, err := dut.RawAPIs().BindingDUT().DialGNSI(context.Background()) + if err != nil { + t.Fatalf("Could not connect gnsi %v", err) + } + rotateStream, err := gnsiC.Authz().Rotate(context.Background()) + if err != nil { + t.Fatalf("Could not start a rotate stream %v", err) + } + defer rotateStream.CloseSend() + policy, err := p.Marshal() + if err != nil { + t.Fatalf("Could not marshal the policy %s", prettyPrint(policy)) + } + autzRotateReq := &authz.RotateAuthzRequest_UploadRequest{ + UploadRequest: &authz.UploadRequest{ + Version: version, + CreatedOn: createdOn, + Policy: string(policy), + }, + } + t.Logf("Sending Authz.Rotate request on device: \n %s", prettyPrint(autzRotateReq)) + err = rotateStream.Send(&authz.RotateAuthzRequest{RotateRequest: autzRotateReq, ForceOverwrite: forcOverwrite}) + if err != nil { + t.Fatalf("Error while uploading prob request reply %v", err) + } + t.Logf("Authz.Rotate upload was successful, receiving response ...") + _, err = rotateStream.Recv() + if err != nil { + t.Fatalf("Error while receiving rotate request reply %v", err) + } + // validate Result + _, tempPolicy := Get(t, dut) + if !cmp.Equal(p, tempPolicy) { + t.Fatalf("Policy after upload (temporary) is not the same as the one upload, diff is: %v", cmp.Diff(p, tempPolicy)) + } + finalizeRotateReq := &authz.RotateAuthzRequest_FinalizeRotation{FinalizeRotation: &authz.FinalizeRequest{}} + err = rotateStream.Send(&authz.RotateAuthzRequest{RotateRequest: finalizeRotateReq}) + t.Logf("Sending Authz.Rotate FinalizeRotation request: \n%s", prettyPrint(finalizeRotateReq)) + if err != nil { + t.Fatalf("Error while finalizing rotate request %v", err) + } + _, finalPolicy := Get(t, dut) + if !cmp.Equal(p, finalPolicy) { + t.Fatalf("Policy after upload (temporary) is not the same as the one upload, diff is: %v", cmp.Diff(p, finalPolicy)) + } + +} + +// NewAuthorizationPolicy creates an empty policy. +func NewAuthorizationPolicy(name string) *AuthorizationPolicy { + return &AuthorizationPolicy{ + Name: name, + } +} + +// Get read the applied policy from device dut. this is test api and fails the test when it fails. +func Get(t testing.TB, dut *ondatra.DUTDevice) (*authz.GetResponse, *AuthorizationPolicy) { + t.Logf("Performing Authz.Get request on device %s", dut.Name()) + gnsiC, err := dut.RawAPIs().BindingDUT().DialGNSI(context.Background()) + if err != nil { + t.Fatalf("Could not connect gnsi %v", err) + } + resp, err := gnsiC.Authz().Get(context.Background(), &authz.GetRequest{}) + if err != nil { + t.Fatalf("Authz.Get request is failed on device %s: %v", dut.Name(), err) + } + + t.Logf("Authz.Get response is %s", prettyPrint(resp)) + if resp.GetVersion() == "" { + t.Errorf("Version is not set in Authz.Get response") + } + if resp.GetCreatedOn() > uint64(time.Now().UnixMicro()) { + t.Errorf("CreatedOn value can not be larger than current time") + } + p := &AuthorizationPolicy{} + err = p.Unmarshal(resp.Policy) + if err != nil { + t.Fatalf("Authz.Get response contains invalid policy %s", resp.GetPolicy()) + } + return resp, p +} + +func prettyPrint(i interface{}) string { + s, _ := json.MarshalIndent(i, "", "\t") + return string(s) +} + +// PrettyPrint prints policy p in a pretty format. +func (p *AuthorizationPolicy) PrettyPrint(t *testing.T) string { + prettyTex, err := json.MarshalIndent(p, "", " ") + if err != nil { + t.Logf("PrettyPrint of an authz policy is failed due to err: %v", err) + return "" + } + return string(prettyTex) +} + +type verifyOpt interface { + isVerifyOpt() +} + +// ExceptDeny is passed to verify function when failure is expected. +type ExceptDeny struct { +} + +// HardVerify is passed to verify function when verification +// is carried out via execution on the RPC using the user svid. +type HardVerify struct { +} + +func (o *ExceptDeny) isVerifyOpt() {} +func (o *HardVerify) isVerifyOpt() {} + +// Verify uses prob to validate if the user access for a certain rpc is expected. +// It also execute the rpc when HardVerif is passed and verifies if it matches the expectation. +func Verify(t testing.TB, dut *ondatra.DUTDevice, spiffe *Spiffe, rpc *gnxi.RPC, opts ...verifyOpt) { + expectedRes := authz.ProbeResponse_ACTION_PERMIT + expectedExecErr := codes.OK + hardVerify := false + for _, opt := range opts { + switch opt.(type) { + case *ExceptDeny: + expectedRes = authz.ProbeResponse_ACTION_DENY + expectedExecErr = codes.PermissionDenied + case *HardVerify: + hardVerify = true + default: + t.Errorf("Invalid option is passed to Verify function: %T", opt) + } + } + gnsiC, err := dut.RawAPIs().BindingDUT().DialGNSI(context.Background()) + if err != nil { + t.Fatalf("Could not connect gnsi %v", err) + } + resp, err := gnsiC.Authz().Probe(context.Background(), &authz.ProbeRequest{User: spiffe.ID, Rpc: rpc.Path}) + if err != nil { + t.Fatalf("Prob Request %s failed on dut %s", prettyPrint(&authz.ProbeRequest{User: spiffe.ID, Rpc: rpc.Path}), dut.Name()) + } + + if resp.GetAction() != expectedRes { + t.Fatalf("Prob response is not expected for user %s and path %s on dut %s, want %v, got %v", spiffe.ID, rpc.Path, dut.Name(), expectedRes, resp.GetAction()) + } + if hardVerify { + opts := []grpc.DialOption{grpc.WithTransportCredentials(credentials.NewTLS(spiffe.TLSConf))} + err := rpc.Exec(context.Background(), dut, opts) + if status.Code(err) != expectedExecErr { + if status.Code(err) == codes.Unimplemented { + t.Fatalf("The execution of rpc %s is failed due to error %v, please add implementation for the rpc", rpc.Path, err) + } + t.Fatalf("The execution result of of rpc %s for user %s on dut %s is unexpected, want %v, got %v", rpc.Path, spiffe.ID, dut.Name(), expectedExecErr, err) + } + t.Logf("The execution of rpc %s for user %s on dut %v is finished as expected, want error: %v, got error: %v ", rpc.Path, spiffe.ID, dut.Name(), expectedExecErr, err) + } +} + +// LoadPolicyFromJSONFile Loads Policy from a JSON File. +func LoadPolicyFromJSONFile(t *testing.T, filePath string) map[string]AuthorizationPolicy { + file, err := os.Open(filePath) + if err != nil { + t.Fatalf("Not expecting error while opening policy file %v", err) + } + defer file.Close() + + decoder := json.NewDecoder(file) + var policies []AuthorizationPolicy + err1 := decoder.Decode(&policies) + if err1 != nil { + t.Fatalf("Not expecting error while decoding policy %v", err) + } + policyMap := map[string]AuthorizationPolicy{} + for _, policy := range policies { + policyMap[policy.Name] = policy + } + return policyMap +} diff --git a/internal/security/gen/generate.go b/internal/security/gen/generate.go new file mode 100644 index 00000000000..93e5ada0d7f --- /dev/null +++ b/internal/security/gen/generate.go @@ -0,0 +1,294 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// package main generate data structure and skeleton function for all rpc related to fp. +package main + +import ( + "bufio" + "flag" + "fmt" + "os" + "strings" + "text/template" + + "github.com/openconfig/featureprofiles/internal/security/gnxi" + "golang.org/x/text/cases" + "golang.org/x/text/language" + "google.golang.org/protobuf/reflect/protoreflect" + + gnmipb "github.com/openconfig/gnmi/proto/gnmi" + accpb "github.com/openconfig/gnsi/acctz" + authzpb "github.com/openconfig/gnsi/authz" + certzpb "github.com/openconfig/gnsi/certz" + credpb "github.com/openconfig/gnsi/credentialz" + pathzpb "github.com/openconfig/gnsi/pathz" + gribipb "github.com/openconfig/gribi/v1/proto/service" + + bpb "github.com/openconfig/gnoi/bgp" + cpb "github.com/openconfig/gnoi/cert" + dpb "github.com/openconfig/gnoi/diag" + frpb "github.com/openconfig/gnoi/factory_reset" + fpb "github.com/openconfig/gnoi/file" + hpb "github.com/openconfig/gnoi/healthz" + lpb "github.com/openconfig/gnoi/layer2" + mpb "github.com/openconfig/gnoi/mpls" + ospb "github.com/openconfig/gnoi/os" + otpb "github.com/openconfig/gnoi/otdr" + plqpb "github.com/openconfig/gnoi/packet_link_qualification" + spb "github.com/openconfig/gnoi/system" + wpb "github.com/openconfig/gnoi/wavelength_router" + p4rtpb "github.com/p4lang/p4runtime/go/p4/v1" + + log "github.com/golang/glog" +) + +var ( + srcFolder = flag.String("src_folder", ".", "The directory where the generated source code will be saved") + genExecFunc = flag.Bool("gen_exec_func", true, "if set to true, the skeleton for exec function with be generated") + pkgName = flag.String("pkg_name", "gnxi", "The name of the package for the generated source code") +) + +var ( + services = map[string]protoreflect.ServiceDescriptors{ + "gnmi": gnmipb.File_proto_gnmi_gnmi_proto.Services(), + "gribi": gribipb.File_v1_proto_service_gribi_proto.Services(), + "gnsi.authz": authzpb.File_github_com_openconfig_gnsi_authz_authz_proto.Services(), + "gnsi.certz": certzpb.File_github_com_openconfig_gnsi_certz_certz_proto.Services(), + "gnsi.pathz": pathzpb.File_github_com_openconfig_gnsi_pathz_pathz_proto.Services(), + "gnsi.cred": credpb.File_github_com_openconfig_gnsi_credentialz_credentialz_proto.Services(), + "gnsi.acc": accpb.File_github_com_openconfig_gnsi_acctz_acctz_proto.Services(), + "gnoi.bgp": bpb.File_bgp_bgp_proto.Services(), + "gnoi.cert": cpb.File_cert_cert_proto.Services(), + "gnoi.diag": dpb.File_diag_diag_proto.Services(), + "gnoi.factory_reset": frpb.File_factory_reset_factory_reset_proto.Services(), + "gnoi.file": fpb.File_file_file_proto.Services(), + "gnoi.healthz": hpb.File_healthz_healthz_proto.Services(), + "gnoi.layer2": lpb.File_layer2_layer2_proto.Services(), + "gnoi.mppls": mpb.File_mpls_mpls_proto.Services(), + "gnoi.os": ospb.File_os_os_proto.Services(), + "gnoi.otdr": otpb.File_otdr_otdr_proto.Services(), + "gnoi.link_qualification": plqpb.File_packet_link_qualification_packet_link_qualification_proto.Services(), + "gnoi.system": spb.File_system_system_proto.Services(), + "gnoi.wpb": wpb.File_wavelength_router_wavelength_router_proto.Services(), + "p4rt": p4rtpb.File_p4_v1_p4runtime_proto.Services(), + } +) + +func main() { + + rpcMap := make(map[string]*gnxi.RPC) + p4rtpb.File_p4_v1_p4data_proto.Services() + // add * that represent all grpc rpcs + rpcMap["ALL"] = &gnxi.RPC{ + Name: "*", + Service: "*", + FQN: "*", + Path: "*", + } + for serviceName, service := range services { + if service.Len() == 0 { + log.Warningf("service %s has no rpc methods\n", serviceName) + } + for i := 0; i < service.Len(); i++ { + log.Infof("Service %s RPCs are: \n", serviceName) + for j := 0; j < service.Get(i).Methods().Len(); j++ { + rpcName := fmt.Sprintf("%v", service.Get(i).Methods().Get(j).Name()) + enumName := fmt.Sprintf("%s_%s", strings.ToUpper(serviceName), strings.ToUpper(rpcName)) + rpcFQN := fmt.Sprintf("%v", service.Get(i).Methods().Get(j).FullName()) + path := "" + lastPointIdx := strings.LastIndex(rpcFQN, ".") + if lastPointIdx > 0 { + path = "/" + rpcFQN[:lastPointIdx] + "/" + rpcFQN[lastPointIdx+1:] + } + serviceName = rpcFQN[:lastPointIdx] + rpcMap[enumName] = &gnxi.RPC{ + Name: rpcName, + Service: serviceName, + FQN: rpcFQN, + Path: path, + } + log.Infof("\t RPC is %v\n", rpcMap[enumName]) + log.Infof("\t %s: %s \n", service.Get(i).Methods().Get(j).Name(), service.Get(i).Methods().Get(j).FullName()) + + } + // add service/* for each service that represents all RPC for the service + rpcMap[strings.ToUpper(serviceName)+"_ALL"] = &gnxi.RPC{ + Name: "*", + Service: serviceName, + FQN: serviceName + ".*", + Path: "/" + serviceName + "/*", + } + } + + } + + rpcsCodeFile, err := os.Create(*srcFolder + "/rpcs.go") + if err != nil { + panic(err) + } + defer rpcsCodeFile.Close() + writer := bufio.NewWriter(rpcsCodeFile) + codeGenForEnums, err := template.New("codeGenForEnums").Funcs(funcMap).Parse(authzTemplateRPCs) + if err == nil { + codeGenForEnums.Execute(writer, rpcMap) + } else { + panic(fmt.Sprintf("Code generation for RPC enums failed: %v", err)) + } + writer.Flush() + + if *genExecFunc { + rpcExecCodeFile, err := os.Create(*srcFolder + "/rpcexec.go") + if err != nil { + panic(err) + } + defer rpcExecCodeFile.Close() + writer := bufio.NewWriter(rpcExecCodeFile) + codeGenForExecFunction, err := template.New("codeGenForExecFunction").Funcs(funcMap).Parse(authzTemplateRPCExec) + if err == nil { + codeGenForExecFunction.Execute(writer, rpcMap) + } else { + panic(fmt.Sprintf("Code generation for RPC exec functions failed: %v", err)) + } + writer.Flush() + } + +} + +var ( + funcMap = template.FuncMap{ + "pkgName": func() string { + return *pkgName + }, + "varName": func(service, name string) string { + varName := "" + if service != "*" { + parts := strings.Split(service, ".") + prevPart := "" + for _, part := range parts { + if !strings.EqualFold(part, prevPart) { + varName += part + prevPart = part + } + } + } + if name != "*" { + varName += name + } else { + varName += "ALL" + } + return varName + }, + "funcName": func(service, name string) string { + if !*genExecFunc { + return "nil" + } + caser := cases.Title(language.English) + funcName := "" + if service != "*" { + parts := strings.Split(service, ".") + if len(parts) >= 1 { + funcName += caser.String(parts[0]) + if len(parts) > 2 { + funcName += caser.String(parts[len(parts)-1]) + } + } + } + if name != "*" { + funcName += name + } else { + funcName += "AllRPC" + } + return funcName + }, + "enumName": func(service, name string) string { + varName := "" + if service != "*" { + parts := strings.Split(service, ".") + prevPart := "" + for _, part := range parts { + if !strings.EqualFold(part, prevPart) { + varName += part + "_" + prevPart = part + } + } + } + if name != "*" { + varName += name + } else { + varName += "ALL" + } + return strings.ToTitle(varName) + }, + } + + authzTemplateRPCExec = `package {{pkgName}} + +import ( + "context" + + "github.com/openconfig/ondatra" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + + +{{- range .}} +// function {{funcName .Service .Name}} implements a sample request for service {{.Path}} to validate if authz works as expected. +func {{ funcName .Service .Name}}(ctx context.Context, dut *ondatra.DUTDevice, opts []grpc.DialOption, params ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC {{.Path}} is not implemented") +} +{{ end }} +` + authzTemplateRPCs = ` +// This following provide a list of all RPCs related to FP testing. +// The below code is generated using ../gen/generate.go. Please do not modify. +package {{pkgName}} + type rpcs struct{ + {{- range .}} + {{ funcName .Service .Name}} *RPC + {{- end }} + } + + + var ( + // ALL defines all FP related RPCs + + {{- range .}} + {{ varName .Service .Name}} = &RPC{ + Name: "{{.Name}}", + Service: "{{.Service}}", + FQN: "{{.FQN}}", + Path: "{{.Path}}", + Exec: {{ funcName .Service .Name}}, + } + {{- end }} + + // RPCs is a list of all FP related RPCs + RPCs=rpcs{ + {{- range .}} + {{ funcName .Service .Name}} : {{ varName .Service .Name}}, + {{- end }} + } + + // RPCMAP is a helper that maps path to RPCs data that may be needed in tests. + RPCMAP=map[string]*RPC{ + {{- range .}} + "{{.Path}}" : {{ varName .Service .Name}}, + {{- end }} + } + ) +` +) diff --git a/internal/security/gnxi/gnxi.go b/internal/security/gnxi/gnxi.go new file mode 100644 index 00000000000..df835ae1e4a --- /dev/null +++ b/internal/security/gnxi/gnxi.go @@ -0,0 +1,45 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package gnxi populates a list of all RPCs related for featuresprofile tests. It also +// add additional data (such as paths for each rpc) to simplify security testing. +// Having all rpc in a list also allow us to write tests that cover all RPCs. +// Package also contains function skeleton for all RPCs. +// By adding an implementation here, all tests can use the code. This can prevent the duplication and unify the testing. +package gnxi + +import ( + "context" + + "github.com/openconfig/ondatra" + "google.golang.org/grpc" +) + +// ExecRPCFunction is a function that is used to provide an implementation for an RPC. +// The focus here is security testing, so in most case a simple call of the RPC should suffice. +type ExecRPCFunction func(ctx context.Context, dut *ondatra.DUTDevice, opts []grpc.DialOption, params ...any) error + +// RPC is a data structure for populating information for all FP related RPCs. +type RPC struct { + // name of the grpc service that provides the RPC + Service string + // name of the RPC + Name string + // fully qualified name of the RPC + FQN string + // Path of the rpc that is used by authz to refer to the rpc + Path string + // a function that takes an grpc config (must include mtls cfg) and dut and executes the RPC against the dut. + Exec ExecRPCFunction +} diff --git a/internal/security/gnxi/rpcexec.go b/internal/security/gnxi/rpcexec.go new file mode 100644 index 00000000000..424818b246a --- /dev/null +++ b/internal/security/gnxi/rpcexec.go @@ -0,0 +1,696 @@ +package gnxi + +import ( + "context" + "io" + "strings" + "time" + + "github.com/openconfig/gnoi/system" + "github.com/openconfig/gnsi/authz" + "github.com/openconfig/ondatra" + "github.com/openconfig/ondatra/gnmi" + "github.com/openconfig/ygnmi/ygnmi" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + + gpb "github.com/openconfig/gnmi/proto/gnmi" + gribi "github.com/openconfig/gribi/v1/proto/service" +) + +// AllRPC implements a sample request for service * to validate if authz works as expected. +func AllRPC(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC * is not implemented") +} + +// GnmiAllRPC implements a sample request for service /gnmi.gNMI/* to validate if authz works as expected. +func GnmiAllRPC(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnmi.gNMI/* is not implemented") +} + +// GnmiGet implements a sample request for service /gnmi.gNMI/Get to validate if authz works as expected. +func GnmiGet(ctx context.Context, dut *ondatra.DUTDevice, opts []grpc.DialOption, _ ...any) error { + gnmiC, err := dut.RawAPIs().BindingDUT().DialGNMI(ctx, opts...) + if err != nil { + return err + } + ygnmiC, err := ygnmi.NewClient(gnmiC) + if err != nil { + return err + } + yopts := []ygnmi.Option{ + ygnmi.WithUseGet(), + ygnmi.WithEncoding(gpb.Encoding_JSON_IETF), + } + _, err = ygnmi.Get[string](ctx, ygnmiC, gnmi.OC().System().Hostname().Config(), yopts...) + if err != nil && strings.Contains(err.Error(), "value not present") { + return nil + } + return err +} + +// GnmiSet implements a sample request for service /gnmi.gNMI/Set to validate if authz works as expected. +func GnmiSet(ctx context.Context, dut *ondatra.DUTDevice, opts []grpc.DialOption, _ ...any) error { + gnmiC, err := dut.RawAPIs().BindingDUT().DialGNMI(ctx, opts...) + if err != nil { + return err + } + ygnmiC, err := ygnmi.NewClient(gnmiC) + if err != nil { + return err + } + yopts := []ygnmi.Option{ + ygnmi.WithUseGet(), + ygnmi.WithEncoding(gpb.Encoding_JSON_IETF), + } + _, err = ygnmi.Replace[string](ctx, ygnmiC, gnmi.OC().System().Hostname().Config(), "test", yopts...) + return err +} + +// GnmiSubscribe implements a sample request for service /gnmi.gNMI/Subscribe to validate if authz works as expected. +func GnmiSubscribe(ctx context.Context, dut *ondatra.DUTDevice, opts []grpc.DialOption, _ ...any) error { + gnmiC, err := dut.RawAPIs().BindingDUT().DialGNMI(ctx, opts...) + if err != nil { + return err + } + ygnmiC, err := ygnmi.NewClient(gnmiC) + if err != nil { + return err + } + _, err = ygnmi.Get(ctx, ygnmiC, gnmi.OC().System().Hostname().State()) + return err +} + +// GnmiCapabilities implements a sample request for service /gnmi.gNMI/Capabilities to validate if authz works as expected. +func GnmiCapabilities(ctx context.Context, dut *ondatra.DUTDevice, opts []grpc.DialOption, _ ...any) error { + gnmiC, err := dut.RawAPIs().BindingDUT().DialGNMI(ctx, opts...) + if err != nil { + return err + } + _, err = gnmiC.Capabilities(ctx, &gpb.CapabilityRequest{}) + return err +} + +// GnoiBgpAllRPC implements a sample request for service /gnoi.bgp.BGP/* to validate if authz works as expected. +func GnoiBgpAllRPC(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnoi.bgp.BGP/* is not implemented") +} + +// GnoiBgpClearBGPNeighbor implements a sample request for service /gnoi.bgp.BGP/ClearBGPNeighbor to validate if authz works as expected. +func GnoiBgpClearBGPNeighbor(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnoi.bgp.BGP/ClearBGPNeighbor is not implemented") +} + +// GnoiCertificatemanagementAllRPC implements a sample request for service /gnoi.certificate.CertificateManagement/* to validate if authz works as expected. +func GnoiCertificatemanagementAllRPC(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnoi.certificate.CertificateManagement/* is not implemented") +} + +// GnoiCertificatemanagementCanGenerateCSR implements a sample request for service /gnoi.certificate.CertificateManagement/CanGenerateCSR to validate if authz works as expected. +func GnoiCertificatemanagementCanGenerateCSR(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnoi.certificate.CertificateManagement/CanGenerateCSR is not implemented") +} + +// GnoiCertificatemanagementGenerateCSR implements a sample request for service /gnoi.certificate.CertificateManagement/GenerateCSR to validate if authz works as expected. +func GnoiCertificatemanagementGenerateCSR(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnoi.certificate.CertificateManagement/GenerateCSR is not implemented") +} + +// GnoiCertificatemanagementGetCertificates implements a sample request for service /gnoi.certificate.CertificateManagement/GetCertificates to validate if authz works as expected. +func GnoiCertificatemanagementGetCertificates(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnoi.certificate.CertificateManagement/GetCertificates is not implemented") +} + +// GnoiCertificatemanagementInstall implements a sample request for service /gnoi.certificate.CertificateManagement/Install to validate if authz works as expected. +func GnoiCertificatemanagementInstall(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnoi.certificate.CertificateManagement/Install is not implemented") +} + +// GnoiCertificatemanagementLoadCertificate implements a sample request for service /gnoi.certificate.CertificateManagement/LoadCertificate to validate if authz works as expected. +func GnoiCertificatemanagementLoadCertificate(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnoi.certificate.CertificateManagement/LoadCertificate is not implemented") +} + +// GnoiCertificatemanagementLoadCertificateAuthorityBundle implements a sample request for service /gnoi.certificate.CertificateManagement/LoadCertificateAuthorityBundle to validate if authz works as expected. +func GnoiCertificatemanagementLoadCertificateAuthorityBundle(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnoi.certificate.CertificateManagement/LoadCertificateAuthorityBundle is not implemented") +} + +// GnoiCertificatemanagementRevokeCertificates implements a sample request for service /gnoi.certificate.CertificateManagement/RevokeCertificates to validate if authz works as expected. +func GnoiCertificatemanagementRevokeCertificates(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnoi.certificate.CertificateManagement/RevokeCertificates is not implemented") +} + +// GnoiCertificatemanagementRotate implements a sample request for service /gnoi.certificate.CertificateManagement/Rotate to validate if authz works as expected. +func GnoiCertificatemanagementRotate(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnoi.certificate.CertificateManagement/Rotate is not implemented") +} + +// GnoiDiagAllRPC implements a sample request for service /gnoi.diag.Diag/* to validate if authz works as expected. +func GnoiDiagAllRPC(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnoi.diag.Diag/* is not implemented") +} + +// GnoiDiagGetBERTResult implements a sample request for service /gnoi.diag.Diag/GetBERTResult to validate if authz works as expected. +func GnoiDiagGetBERTResult(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnoi.diag.Diag/GetBERTResult is not implemented") +} + +// GnoiDiagStopBERT implements a sample request for service /gnoi.diag.Diag/StopBERT to validate if authz works as expected. +func GnoiDiagStopBERT(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnoi.diag.Diag/StopBERT is not implemented") +} + +// GnoiDiagStartBERT implements a sample request for service /gnoi.diag.Diag/StartBERT to validate if authz works as expected. +func GnoiDiagStartBERT(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnoi.diag.Diag/StartBERT is not implemented") +} + +// GnoiFactoryresetAllRPC implements a sample request for service /gnoi.factory_reset.FactoryReset/* to validate if authz works as expected. +func GnoiFactoryresetAllRPC(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnoi.factory_reset.FactoryReset/* is not implemented") +} + +// GnoiFactoryresetStart implements a sample request for service /gnoi.factory_reset.FactoryReset/Start to validate if authz works as expected. +func GnoiFactoryresetStart(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnoi.factory_reset.FactoryReset/Start is not implemented") +} + +// GnoiFileAllRPC implements a sample request for service /gnoi.file.File/* to validate if authz works as expected. +func GnoiFileAllRPC(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnoi.file.File/* is not implemented") +} + +// GnoiFilePut implements a sample request for service /gnoi.file.File/Put to validate if authz works as expected. +func GnoiFilePut(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnoi.file.File/Put is not implemented") +} + +// GnoiFileRemove implements a sample request for service /gnoi.file.File/Remove to validate if authz works as expected. +func GnoiFileRemove(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnoi.file.File/Remove is not implemented") +} + +// GnoiFileStat implements a sample request for service /gnoi.file.File/Stat to validate if authz works as expected. +func GnoiFileStat(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnoi.file.File/Stat is not implemented") +} + +// GnoiFileTransferToRemote implements a sample request for service /gnoi.file.File/TransferToRemote to validate if authz works as expected. +func GnoiFileTransferToRemote(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnoi.file.File/TransferToRemote is not implemented") +} + +// GnoiFileGet implements a sample request for service /gnoi.file.File/Get to validate if authz works as expected. +func GnoiFileGet(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnoi.file.File/Get is not implemented") +} + +// GnoiHealthzAcknowledge implements a sample request for service /gnoi.healthz.Healthz/Acknowledge to validate if authz works as expected. +func GnoiHealthzAcknowledge(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnoi.healthz.Healthz/Acknowledge is not implemented") +} + +// GnoiHealthzAllRPC implements a sample request for service /gnoi.healthz.Healthz/* to validate if authz works as expected. +func GnoiHealthzAllRPC(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnoi.healthz.Healthz/* is not implemented") +} + +// GnoiHealthzArtifact implements a sample request for service /gnoi.healthz.Healthz/Artifact to validate if authz works as expected. +func GnoiHealthzArtifact(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnoi.healthz.Healthz/Artifact is not implemented") +} + +// GnoiHealthzCheck implements a sample request for service /gnoi.healthz.Healthz/Check to validate if authz works as expected. +func GnoiHealthzCheck(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnoi.healthz.Healthz/Check is not implemented") +} + +// GnoiHealthzList implements a sample request for service /gnoi.healthz.Healthz/List to validate if authz works as expected. +func GnoiHealthzList(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnoi.healthz.Healthz/List is not implemented") +} + +// GnoiHealthzGet implements a sample request for service /gnoi.healthz.Healthz/Get to validate if authz works as expected. +func GnoiHealthzGet(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnoi.healthz.Healthz/Get is not implemented") +} + +// GnoiLayer2AllRPC implements a sample request for service /gnoi.layer2.Layer2/* to validate if authz works as expected. +func GnoiLayer2AllRPC(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnoi.layer2.Layer2/* is not implemented") +} + +// GnoiLayer2ClearLLDPInterface implements a sample request for service /gnoi.layer2.Layer2/ClearLLDPInterface to validate if authz works as expected. +func GnoiLayer2ClearLLDPInterface(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnoi.layer2.Layer2/ClearLLDPInterface is not implemented") +} + +// GnoiLayer2ClearSpanningTree implements a sample request for service /gnoi.layer2.Layer2/ClearSpanningTree to validate if authz works as expected. +func GnoiLayer2ClearSpanningTree(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnoi.layer2.Layer2/ClearSpanningTree is not implemented") +} + +// GnoiLayer2PerformBERT implements a sample request for service /gnoi.layer2.Layer2/PerformBERT to validate if authz works as expected. +func GnoiLayer2PerformBERT(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnoi.layer2.Layer2/PerformBERT is not implemented") +} + +// GnoiLayer2SendWakeOnLAN implements a sample request for service /gnoi.layer2.Layer2/SendWakeOnLAN to validate if authz works as expected. +func GnoiLayer2SendWakeOnLAN(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnoi.layer2.Layer2/SendWakeOnLAN is not implemented") +} + +// GnoiLayer2ClearNeighborDiscovery implements a sample request for service /gnoi.layer2.Layer2/ClearNeighborDiscovery to validate if authz works as expected. +func GnoiLayer2ClearNeighborDiscovery(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnoi.layer2.Layer2/ClearNeighborDiscovery is not implemented") +} + +// GnoiLinkqualificationCreate implements a sample request for service /gnoi.packet_link_qualification.LinkQualification/Create to validate if authz works as expected. +func GnoiLinkqualificationCreate(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnoi.packet_link_qualification.LinkQualification/Create is not implemented") +} + +// GnoiMplsAllRPC implements a sample request for service /gnoi.mpls.MPLS/* to validate if authz works as expected. +func GnoiMplsAllRPC(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnoi.mpls.MPLS/* is not implemented") +} + +// GnoiMplsClearLSPCounters implements a sample request for service /gnoi.mpls.MPLS/ClearLSPCounters to validate if authz works as expected. +func GnoiMplsClearLSPCounters(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnoi.mpls.MPLS/ClearLSPCounters is not implemented") +} + +// GnoiMplsMPLSPing implements a sample request for service /gnoi.mpls.MPLS/MPLSPing to validate if authz works as expected. +func GnoiMplsMPLSPing(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnoi.mpls.MPLS/MPLSPing is not implemented") +} + +// GnoiMplsClearLSP implements a sample request for service /gnoi.mpls.MPLS/ClearLSP to validate if authz works as expected. +func GnoiMplsClearLSP(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnoi.mpls.MPLS/ClearLSP is not implemented") +} + +// GnoiOtdrAllRPC implements a sample request for service /gnoi.optical.OTDR/* to validate if authz works as expected. +func GnoiOtdrAllRPC(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnoi.optical.OTDR/* is not implemented") +} + +// GnoiWavelengthrouterAdjustSpectrum implements a sample request for service /gnoi.optical.WavelengthRouter/AdjustSpectrum to validate if authz works as expected. +func GnoiWavelengthrouterAdjustSpectrum(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnoi.optical.WavelengthRouter/AdjustSpectrum is not implemented") +} + +// GnoiWavelengthrouterAllRPC implements a sample request for service /gnoi.optical.WavelengthRouter/* to validate if authz works as expected. +func GnoiWavelengthrouterAllRPC(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnoi.optical.WavelengthRouter/* is not implemented") +} + +// GnoiWavelengthrouterCancelAdjustPSD implements a sample request for service /gnoi.optical.WavelengthRouter/CancelAdjustPSD to validate if authz works as expected. +func GnoiWavelengthrouterCancelAdjustPSD(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnoi.optical.WavelengthRouter/CancelAdjustPSD is not implemented") +} + +// GnoiWavelengthrouterCancelAdjustSpectrum implements a sample request for service /gnoi.optical.WavelengthRouter/CancelAdjustSpectrum to validate if authz works as expected. +func GnoiWavelengthrouterCancelAdjustSpectrum(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnoi.optical.WavelengthRouter/CancelAdjustSpectrum is not implemented") +} + +// GnoiOsActivate implements a sample request for service /gnoi.os.OS/Activate to validate if authz works as expected. +func GnoiOsActivate(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnoi.os.OS/Activate is not implemented") +} + +// GnoiOsAllRPC implements a sample request for service /gnoi.os.OS/* to validate if authz works as expected. +func GnoiOsAllRPC(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnoi.os.OS/* is not implemented") +} + +// GnoiOsVerify implements a sample request for service /gnoi.os.OS/Verify to validate if authz works as expected. +func GnoiOsVerify(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnoi.os.OS/Verify is not implemented") +} + +// GnoiOsInstall implements a sample request for service /gnoi.os.OS/Install to validate if authz works as expected. +func GnoiOsInstall(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnoi.os.OS/Install is not implemented") +} + +// GnoiOtdrInitiate implements a sample request for service /gnoi.optical.OTDR/Initiate to validate if authz works as expected. +func GnoiOtdrInitiate(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnoi.optical.OTDR/Initiate is not implemented") +} + +// GnoiLinkqualificationAllRPC implements a sample request for service /gnoi.packet_link_qualification.LinkQualification/* to validate if authz works as expected. +func GnoiLinkqualificationAllRPC(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnoi.packet_link_qualification.LinkQualification/* is not implemented") +} + +// GnoiLinkqualificationCapabilities implements a sample request for service /gnoi.packet_link_qualification.LinkQualification/Capabilities to validate if authz works as expected. +func GnoiLinkqualificationCapabilities(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnoi.packet_link_qualification.LinkQualification/Capabilities is not implemented") +} + +// GnoiLinkqualificationDelete implements a sample request for service /gnoi.packet_link_qualification.LinkQualification/Delete to validate if authz works as expected. +func GnoiLinkqualificationDelete(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnoi.packet_link_qualification.LinkQualification/Delete is not implemented") +} + +// GnoiLinkqualificationGet implements a sample request for service /gnoi.packet_link_qualification.LinkQualification/Get to validate if authz works as expected. +func GnoiLinkqualificationGet(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnoi.packet_link_qualification.LinkQualification/Get is not implemented") +} + +// GnoiLinkqualificationList implements a sample request for service /gnoi.packet_link_qualification.LinkQualification/List to validate if authz works as expected. +func GnoiLinkqualificationList(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnoi.packet_link_qualification.LinkQualification/List is not implemented") +} + +// GnoiSystemAllRPC implements a sample request for service /gnoi.system.System/* to validate if authz works as expected. +func GnoiSystemAllRPC(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnoi.system.System/* is not implemented") +} + +// GnoiSystemCancelReboot implements a sample request for service /gnoi.system.System/CancelReboot to validate if authz works as expected. +func GnoiSystemCancelReboot(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnoi.system.System/CancelReboot is not implemented") +} + +// GnoiSystemKillProcess implements a sample request for service /gnoi.system.System/KillProcess to validate if authz works as expected. +func GnoiSystemKillProcess(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnoi.system.System/KillProcess is not implemented") +} + +// GnoiSystemReboot implements a sample request for service /gnoi.system.System/Reboot to validate if authz works as expected. +func GnoiSystemReboot(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnoi.system.System/Reboot is not implemented") +} + +// GnoiSystemRebootStatus implements a sample request for service /gnoi.system.System/RebootStatus to validate if authz works as expected. +func GnoiSystemRebootStatus(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnoi.system.System/RebootStatus is not implemented") +} + +// GnoiSystemSetPackage implements a sample request for service /gnoi.system.System/SetPackage to validate if authz works as expected. +func GnoiSystemSetPackage(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnoi.system.System/SetPackage is not implemented") +} + +// GnoiSystemSwitchControlProcessor implements a sample request for service /gnoi.system.System/SwitchControlProcessor to validate if authz works as expected. +func GnoiSystemSwitchControlProcessor(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnoi.system.System/SwitchControlProcessor is not implemented") +} + +// GnoiSystemTime implements a sample request for service /gnoi.system.System/Time to validate if authz works as expected. +func GnoiSystemTime(ctx context.Context, dut *ondatra.DUTDevice, opts []grpc.DialOption, _ ...any) error { + gnoiC, err := dut.RawAPIs().BindingDUT().DialGNOI(ctx, opts...) + if err != nil { + return err + } + _, err = gnoiC.System().Time(ctx, &system.TimeRequest{}) + return err +} + +// GnoiSystemTraceroute implements a sample request for service /gnoi.system.System/Traceroute to validate if authz works as expected. +func GnoiSystemTraceroute(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnoi.system.System/Traceroute is not implemented") +} + +// GnoiSystemPing implements a sample request for service /gnoi.system.System/Ping to validate if authz works as expected. +func GnoiSystemPing(ctx context.Context, dut *ondatra.DUTDevice, opts []grpc.DialOption, _ ...any) error { + gnoiC, err := dut.RawAPIs().BindingDUT().DialGNOI(ctx, opts...) + if err != nil { + return err + } + pingC, err := gnoiC.System().Ping(ctx, &system.PingRequest{Destination: "192.0.2.1"}) + if err != nil { + return err + + } + _, err = pingC.Recv() + return err +} + +// GnoiWavelengthrouterAdjustPSD implements a sample request for service /gnoi.optical.WavelengthRouter/AdjustPSD to validate if authz works as expected. +func GnoiWavelengthrouterAdjustPSD(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnoi.optical.WavelengthRouter/AdjustPSD is not implemented") +} + +// GnsiAccountingpullAllRPC implements a sample request for service /gnsi.accounting.v1.AccountingPull/* to validate if authz works as expected. +func GnsiAccountingpullAllRPC(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnsi.accounting.v1.AccountingPull/* is not implemented") +} + +// GnsiAccountingpushRecordStream implements a sample request for service /gnsi.accounting.v1.AccountingPush/RecordStream to validate if authz works as expected. +func GnsiAccountingpushRecordStream(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnsi.accounting.v1.AccountingPush/RecordStream is not implemented") +} + +// GnsiAccountingpushAllRPC implements a sample request for service /gnsi.accounting.v1.AccountingPush/* to validate if authz works as expected. +func GnsiAccountingpushAllRPC(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnsi.accounting.v1.AccountingPush/* is not implemented") +} + +// GnsiAccountingpullRecordStream implements a sample request for service /gnsi.accounting.v1.AccountingPull/RecordStream to validate if authz works as expected. +func GnsiAccountingpullRecordStream(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnsi.accounting.v1.AccountingPull/RecordStream is not implemented") +} + +// GnsiAuthzAllRPC implements a sample request for service /gnsi.authz.v1.Authz/* to validate if authz works as expected. +func GnsiAuthzAllRPC(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnsi.authz.v1.Authz/* is not implemented") +} + +// GnsiAuthzGet implements a sample request for service /gnsi.authz.v1.Authz/Get to validate if authz works as expected. +func GnsiAuthzGet(ctx context.Context, dut *ondatra.DUTDevice, opts []grpc.DialOption, _ ...any) error { + gnsiC, err := dut.RawAPIs().BindingDUT().DialGNSI(ctx, opts...) + if err != nil { + return err + } + _, err = gnsiC.Authz().Get(ctx, &authz.GetRequest{}) + return err +} + +// GnsiAuthzProbe implements a sample request for service /gnsi.authz.v1.Authz/Probe to validate if authz works as expected. +func GnsiAuthzProbe(ctx context.Context, dut *ondatra.DUTDevice, opts []grpc.DialOption, _ ...any) error { + gnsiC, err := dut.RawAPIs().BindingDUT().DialGNSI(ctx, opts...) + if err != nil { + return err + } + _, err = gnsiC.Authz().Probe(ctx, &authz.ProbeRequest{User: "dummy", Rpc: "*"}) + return err +} + +// GnsiAuthzRotate implements a sample request for service /gnsi.authz.v1.Authz/Rotate to validate if authz works as expected. +func GnsiAuthzRotate(ctx context.Context, dut *ondatra.DUTDevice, opts []grpc.DialOption, _ ...any) error { + gnsiC, err := dut.RawAPIs().BindingDUT().DialGNSI(ctx, opts...) + if err != nil { + return err + } + gnsiCStream, err := gnsiC.Authz().Rotate(ctx) + if err != nil { + return err + } + // TODO: send valid policy for postive cases + err = gnsiCStream.Send(&authz.RotateAuthzRequest{ + RotateRequest: &authz.RotateAuthzRequest_UploadRequest{ + UploadRequest: &authz.UploadRequest{ + Version: "0.0", + CreatedOn: uint64(time.Now().Nanosecond()), + Policy: "", + }, + }, + }) + if err != nil { + return err + } + _, err = gnsiCStream.Recv() + // invalid policy is expected since the empty policy is not allowed + if strings.Contains(err.Error(), "invalid policy") { + return nil + } + return err +} + +// GnsiCertzAddProfile implements a sample request for service /gnsi.certz.v1.Certz/AddProfile to validate if authz works as expected. +func GnsiCertzAddProfile(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnsi.certz.v1.Certz/AddProfile is not implemented") +} + +// GnsiCertzAllRPC implements a sample request for service /gnsi.certz.v1.Certz/* to validate if authz works as expected. +func GnsiCertzAllRPC(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnsi.certz.v1.Certz/* is not implemented") +} + +// GnsiCertzCanGenerateCSR implements a sample request for service /gnsi.certz.v1.Certz/CanGenerateCSR to validate if authz works as expected. +func GnsiCertzCanGenerateCSR(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnsi.certz.v1.Certz/CanGenerateCSR is not implemented") +} + +// GnsiCertzDeleteProfile implements a sample request for service /gnsi.certz.v1.Certz/DeleteProfile to validate if authz works as expected. +func GnsiCertzDeleteProfile(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnsi.certz.v1.Certz/DeleteProfile is not implemented") +} + +// GnsiCertzGetProfileList implements a sample request for service /gnsi.certz.v1.Certz/GetProfileList to validate if authz works as expected. +func GnsiCertzGetProfileList(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnsi.certz.v1.Certz/GetProfileList is not implemented") +} + +// GnsiCertzRotate implements a sample request for service /gnsi.certz.v1.Certz/Rotate to validate if authz works as expected. +func GnsiCertzRotate(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnsi.certz.v1.Certz/Rotate is not implemented") +} + +// GnsiCredentialzAllRPC implements a sample request for service /gnsi.credentialz.v1.Credentialz/* to validate if authz works as expected. +func GnsiCredentialzAllRPC(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnsi.credentialz.v1.Credentialz/* is not implemented") +} + +// GnsiCredentialzCanGenerateKey implements a sample request for service /gnsi.credentialz.v1.Credentialz/CanGenerateKey to validate if authz works as expected. +func GnsiCredentialzCanGenerateKey(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnsi.credentialz.v1.Credentialz/CanGenerateKey is not implemented") +} + +// GnsiCredentialzGetPublicKeys implements a sample request for service /gnsi.credentialz.v1.Credentialz/GetPublicKeys to validate if authz works as expected. +func GnsiCredentialzGetPublicKeys(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnsi.credentialz.v1.Credentialz/GetPublicKeys is not implemented") +} + +// GnsiCredentialzRotateHostCredentials implements a sample request for service /gnsi.credentialz.v1.Credentialz/RotateHostCredentials to validate if authz works as expected. +func GnsiCredentialzRotateHostCredentials(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnsi.credentialz.v1.Credentialz/RotateHostCredentials is not implemented") +} + +// GnsiCredentialzRotateAccountCredentials implements a sample request for service /gnsi.credentialz.v1.Credentialz/RotateAccountCredentials to validate if authz works as expected. +func GnsiCredentialzRotateAccountCredentials(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnsi.credentialz.v1.Credentialz/RotateAccountCredentials is not implemented") +} + +// GnsiPathzAllRPC implements a sample request for service /gnsi.pathz.v1.Pathz/* to validate if authz works as expected. +func GnsiPathzAllRPC(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnsi.pathz.v1.Pathz/* is not implemented") +} + +// GnsiPathzGet implements a sample request for service /gnsi.pathz.v1.Pathz/Get to validate if authz works as expected. +func GnsiPathzGet(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnsi.pathz.v1.Pathz/Get is not implemented") +} + +// GnsiPathzProbe implements a sample request for service /gnsi.pathz.v1.Pathz/Probe to validate if authz works as expected. +func GnsiPathzProbe(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnsi.pathz.v1.Pathz/Probe is not implemented") +} + +// GnsiPathzRotate implements a sample request for service /gnsi.pathz.v1.Pathz/Rotate to validate if authz works as expected. +func GnsiPathzRotate(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnsi.pathz.v1.Pathz/Rotate is not implemented") +} + +// GribiAllRPC implements a sample request for service /gribi.gRIBI/* to validate if authz works as expected. +func GribiAllRPC(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gribi.gRIBI/* is not implemented") +} + +// GribiFlush implements a sample request for service /gribi.gRIBI/Flush to validate if authz works as expected. +func GribiFlush(ctx context.Context, dut *ondatra.DUTDevice, opts []grpc.DialOption, _ ...any) error { + gribiC, err := dut.RawAPIs().BindingDUT().DialGRIBI(ctx, opts...) + if err != nil { + return err + } + _, err = gribiC.Flush(ctx, &gribi.FlushRequest{Election: &gribi.FlushRequest_Id{Id: &gribi.Uint128{Low: 1}}}) + return err +} + +// GribiGet implements a sample request for service /gribi.gRIBI/Get to validate if authz works as expected. +func GribiGet(ctx context.Context, dut *ondatra.DUTDevice, opts []grpc.DialOption, _ ...any) error { + gribiC, err := dut.RawAPIs().BindingDUT().DialGRIBI(ctx, opts...) + if err != nil { + return err + } + getReq := gribi.GetRequest{ + NetworkInstance: &gribi.GetRequest_All{}, + Aft: gribi.AFTType_ALL, + } + getSteram, err := gribiC.Get(ctx, &getReq) + if err != nil { + return err + } + _, err = getSteram.Recv() + if err == io.EOF { + return nil + } + return err +} + +// GribiModify implements a sample request for service /gribi.gRIBI/Modify to validate if authz works as expected. +func GribiModify(ctx context.Context, dut *ondatra.DUTDevice, opts []grpc.DialOption, _ ...any) error { + gribiC, err := dut.RawAPIs().BindingDUT().DialGRIBI(ctx, opts...) + if err != nil { + return err + } + mStream, err := gribiC.Modify(ctx) + if err != nil { + return err + } + err = mStream.Send(&gribi.ModifyRequest{ + Params: &gribi.SessionParameters{Redundancy: gribi.SessionParameters_SINGLE_PRIMARY, + Persistence: gribi.SessionParameters_PRESERVE}, + }) + if err != nil { + return err + } + _, err = mStream.Recv() + return err +} + +// P4P4runtimeAllRPC implements a sample request for service /p4.v1.P4Runtime/* to validate if authz works as expected. +func P4P4runtimeAllRPC(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /p4.v1.P4Runtime/* is not implemented") +} + +// P4P4runtimeCapabilities implements a sample request for service /p4.v1.P4Runtime/Capabilities to validate if authz works as expected. +func P4P4runtimeCapabilities(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /p4.v1.P4Runtime/Capabilities is not implemented") +} + +// P4P4runtimeGetForwardingPipelineConfig implements a sample request for service /p4.v1.P4Runtime/GetForwardingPipelineConfig to validate if authz works as expected. +func P4P4runtimeGetForwardingPipelineConfig(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /p4.v1.P4Runtime/GetForwardingPipelineConfig is not implemented") +} + +// P4P4runtimeRead implements a sample request for service /p4.v1.P4Runtime/Read to validate if authz works as expected. +func P4P4runtimeRead(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /p4.v1.P4Runtime/Read is not implemented") +} + +// P4P4runtimeSetForwardingPipelineConfig implements a sample request for service /p4.v1.P4Runtime/SetForwardingPipelineConfig to validate if authz works as expected. +func P4P4runtimeSetForwardingPipelineConfig(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /p4.v1.P4Runtime/SetForwardingPipelineConfig is not implemented") +} + +// P4P4runtimeStreamChannel implements a sample request for service /p4.v1.P4Runtime/StreamChannel to validate if authz works as expected. +func P4P4runtimeStreamChannel(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /p4.v1.P4Runtime/StreamChannel is not implemented") +} + +// P4P4runtimeWrite implements a sample request for service /p4.v1.P4Runtime/Write to validate if authz works as expected. +func P4P4runtimeWrite(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /p4.v1.P4Runtime/Write is not implemented") +} + +// GnsiAcctzAllRPC implements a sample request for service /gnsi.acctz.v1.Acctz/* to validate if authz works as expected. +func GnsiAcctzAllRPC(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnsi.acctz.v1.Acctz/* is not implemented") +} + +// GnsiAcctzRecordSubscribe implements a sample request for service /gnsi.acctz.v1.Acctz/RecordSubscribe to validate if authz works as expected. +func GnsiAcctzRecordSubscribe(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnsi.acctz.v1.Acctz/RecordSubscribe is not implemented") +} + +// GnsiCredentialzRotateHostParameters implements a sample request for service /gnsi.acctz.v1.Acctz/RecordSubscribe to validate if authz works as expected. +func GnsiCredentialzRotateHostParameters(_ context.Context, _ *ondatra.DUTDevice, _ []grpc.DialOption, _ ...any) error { + return status.Errorf(codes.Unimplemented, "exec function for RPC /gnsi.acctz.v1.Acctz/RecordSubscribe is not implemented") +} diff --git a/internal/security/gnxi/rpcs.go b/internal/security/gnxi/rpcs.go new file mode 100644 index 00000000000..71552e1b1ce --- /dev/null +++ b/internal/security/gnxi/rpcs.go @@ -0,0 +1,1059 @@ +// Package gnxi populates a list of all RPCs related for featuresprofile tests. +// The below code is generated using ../gen/generate.go. Please do not modify. +package gnxi + +type rpcs struct { + AllRPC *RPC + GnmiAllRPC *RPC + GnmiGet *RPC + GnmiSet *RPC + GnmiSubscribe *RPC + GnmiCapabilities *RPC + GnoiBgpAllRPC *RPC + GnoiBgpClearBGPNeighbor *RPC + GnoiCertificatemanagementAllRPC *RPC + GnoiCertificatemanagementCanGenerateCSR *RPC + GnoiCertificatemanagementGenerateCSR *RPC + GnoiCertificatemanagementGetCertificates *RPC + GnoiCertificatemanagementInstall *RPC + GnoiCertificatemanagementLoadCertificate *RPC + GnoiCertificatemanagementLoadCertificateAuthorityBundle *RPC + GnoiCertificatemanagementRevokeCertificates *RPC + GnoiCertificatemanagementRotate *RPC + GnoiDiagAllRPC *RPC + GnoiDiagGetBERTResult *RPC + GnoiDiagStopBERT *RPC + GnoiDiagStartBERT *RPC + GnoiFactoryresetAllRPC *RPC + GnoiFactoryresetStart *RPC + GnoiFileAllRPC *RPC + GnoiFilePut *RPC + GnoiFileRemove *RPC + GnoiFileStat *RPC + GnoiFileTransferToRemote *RPC + GnoiFileGet *RPC + GnoiHealthzAcknowledge *RPC + GnoiHealthzAllRPC *RPC + GnoiHealthzArtifact *RPC + GnoiHealthzCheck *RPC + GnoiHealthzList *RPC + GnoiHealthzGet *RPC + GnoiLayer2AllRPC *RPC + GnoiLayer2ClearLLDPInterface *RPC + GnoiLayer2ClearSpanningTree *RPC + GnoiLayer2PerformBERT *RPC + GnoiLayer2SendWakeOnLAN *RPC + GnoiLayer2ClearNeighborDiscovery *RPC + GnoiLinkqualificationCreate *RPC + GnoiMplsAllRPC *RPC + GnoiMplsClearLSPCounters *RPC + GnoiMplsMPLSPing *RPC + GnoiMplsClearLSP *RPC + GnoiOtdrAllRPC *RPC + GnoiWavelengthrouterAdjustSpectrum *RPC + GnoiWavelengthrouterAllRPC *RPC + GnoiWavelengthrouterCancelAdjustPSD *RPC + GnoiWavelengthrouterCancelAdjustSpectrum *RPC + GnoiOsActivate *RPC + GnoiOsAllRPC *RPC + GnoiOsVerify *RPC + GnoiOsInstall *RPC + GnoiOtdrInitiate *RPC + GnoiLinkqualificationAllRPC *RPC + GnoiLinkqualificationCapabilities *RPC + GnoiLinkqualificationDelete *RPC + GnoiLinkqualificationGet *RPC + GnoiLinkqualificationList *RPC + GnoiSystemAllRPC *RPC + GnoiSystemCancelReboot *RPC + GnoiSystemKillProcess *RPC + GnoiSystemReboot *RPC + GnoiSystemRebootStatus *RPC + GnoiSystemSetPackage *RPC + GnoiSystemSwitchControlProcessor *RPC + GnoiSystemTime *RPC + GnoiSystemTraceroute *RPC + GnoiSystemPing *RPC + GnoiWavelengthrouterAdjustPSD *RPC + GnsiAcctzAllRPC *RPC + GnsiAcctzRecordSubscribe *RPC + GnsiAuthzAllRPC *RPC + GnsiAuthzGet *RPC + GnsiAuthzProbe *RPC + GnsiAuthzRotate *RPC + GnsiCertzAddProfile *RPC + GnsiCertzAllRPC *RPC + GnsiCertzCanGenerateCSR *RPC + GnsiCertzDeleteProfile *RPC + GnsiCertzGetProfileList *RPC + GnsiCertzRotate *RPC + GnsiCredentialzAllRPC *RPC + GnsiCredentialzCanGenerateKey *RPC + GnsiCredentialzGetPublicKeys *RPC + GnsiCredentialzRotateHostParameters *RPC + GnsiCredentialzRotateAccountCredentials *RPC + GnsiPathzAllRPC *RPC + GnsiPathzGet *RPC + GnsiPathzProbe *RPC + GnsiPathzRotate *RPC + GribiAllRPC *RPC + GribiFlush *RPC + GribiGet *RPC + GribiModify *RPC + P4P4runtimeAllRPC *RPC + P4P4runtimeCapabilities *RPC + P4P4runtimeGetForwardingPipelineConfig *RPC + P4P4runtimeRead *RPC + P4P4runtimeSetForwardingPipelineConfig *RPC + P4P4runtimeStreamChannel *RPC + P4P4runtimeWrite *RPC +} + +var ( + // ALL defines all FP related RPCs + ALL = &RPC{ + Name: "*", + Service: "*", + FQN: "*", + Path: "*", + Exec: AllRPC, + } + gnmiALL = &RPC{ + Name: "*", + Service: "gnmi.gNMI", + FQN: "gnmi.gNMI.*", + Path: "/gnmi.gNMI/*", + Exec: GnmiAllRPC, + } + gnmiGet = &RPC{ + Name: "Get", + Service: "gnmi.gNMI", + FQN: "gnmi.gNMI.Get", + Path: "/gnmi.gNMI/Get", + Exec: GnmiGet, + } + gnmiSet = &RPC{ + Name: "Set", + Service: "gnmi.gNMI", + FQN: "gnmi.gNMI.Set", + Path: "/gnmi.gNMI/Set", + Exec: GnmiSet, + } + gnmiSubscribe = &RPC{ + Name: "Subscribe", + Service: "gnmi.gNMI", + FQN: "gnmi.gNMI.Subscribe", + Path: "/gnmi.gNMI/Subscribe", + Exec: GnmiSubscribe, + } + gnmiCapabilities = &RPC{ + Name: "Capabilities", + Service: "gnmi.gNMI", + FQN: "gnmi.gNMI.Capabilities", + Path: "/gnmi.gNMI/Capabilities", + Exec: GnmiCapabilities, + } + gnoibgpALL = &RPC{ + Name: "*", + Service: "gnoi.bgp.BGP", + FQN: "gnoi.bgp.BGP.*", + Path: "/gnoi.bgp.BGP/*", + Exec: GnoiBgpAllRPC, + } + gnoibgpClearBGPNeighbor = &RPC{ + Name: "ClearBGPNeighbor", + Service: "gnoi.bgp.BGP", + FQN: "gnoi.bgp.BGP.ClearBGPNeighbor", + Path: "/gnoi.bgp.BGP/ClearBGPNeighbor", + Exec: GnoiBgpClearBGPNeighbor, + } + gnoicertificateCertificateManagementALL = &RPC{ + Name: "*", + Service: "gnoi.certificate.CertificateManagement", + FQN: "gnoi.certificate.CertificateManagement.*", + Path: "/gnoi.certificate.CertificateManagement/*", + Exec: GnoiCertificatemanagementAllRPC, + } + gnoicertificateCertificateManagementCanGenerateCSR = &RPC{ + Name: "CanGenerateCSR", + Service: "gnoi.certificate.CertificateManagement", + FQN: "gnoi.certificate.CertificateManagement.CanGenerateCSR", + Path: "/gnoi.certificate.CertificateManagement/CanGenerateCSR", + Exec: GnoiCertificatemanagementCanGenerateCSR, + } + gnoicertificateCertificateManagementGenerateCSR = &RPC{ + Name: "GenerateCSR", + Service: "gnoi.certificate.CertificateManagement", + FQN: "gnoi.certificate.CertificateManagement.GenerateCSR", + Path: "/gnoi.certificate.CertificateManagement/GenerateCSR", + Exec: GnoiCertificatemanagementGenerateCSR, + } + gnoicertificateCertificateManagementGetCertificates = &RPC{ + Name: "GetCertificates", + Service: "gnoi.certificate.CertificateManagement", + FQN: "gnoi.certificate.CertificateManagement.GetCertificates", + Path: "/gnoi.certificate.CertificateManagement/GetCertificates", + Exec: GnoiCertificatemanagementGetCertificates, + } + gnoicertificateCertificateManagementInstall = &RPC{ + Name: "Install", + Service: "gnoi.certificate.CertificateManagement", + FQN: "gnoi.certificate.CertificateManagement.Install", + Path: "/gnoi.certificate.CertificateManagement/Install", + Exec: GnoiCertificatemanagementInstall, + } + gnoicertificateCertificateManagementLoadCertificate = &RPC{ + Name: "LoadCertificate", + Service: "gnoi.certificate.CertificateManagement", + FQN: "gnoi.certificate.CertificateManagement.LoadCertificate", + Path: "/gnoi.certificate.CertificateManagement/LoadCertificate", + Exec: GnoiCertificatemanagementLoadCertificate, + } + gnoicertificateCertificateManagementLoadCertificateAuthorityBundle = &RPC{ + Name: "LoadCertificateAuthorityBundle", + Service: "gnoi.certificate.CertificateManagement", + FQN: "gnoi.certificate.CertificateManagement.LoadCertificateAuthorityBundle", + Path: "/gnoi.certificate.CertificateManagement/LoadCertificateAuthorityBundle", + Exec: GnoiCertificatemanagementLoadCertificateAuthorityBundle, + } + gnoicertificateCertificateManagementRevokeCertificates = &RPC{ + Name: "RevokeCertificates", + Service: "gnoi.certificate.CertificateManagement", + FQN: "gnoi.certificate.CertificateManagement.RevokeCertificates", + Path: "/gnoi.certificate.CertificateManagement/RevokeCertificates", + Exec: GnoiCertificatemanagementRevokeCertificates, + } + gnoicertificateCertificateManagementRotate = &RPC{ + Name: "Rotate", + Service: "gnoi.certificate.CertificateManagement", + FQN: "gnoi.certificate.CertificateManagement.Rotate", + Path: "/gnoi.certificate.CertificateManagement/Rotate", + Exec: GnoiCertificatemanagementRotate, + } + gnoidiagALL = &RPC{ + Name: "*", + Service: "gnoi.diag.Diag", + FQN: "gnoi.diag.Diag.*", + Path: "/gnoi.diag.Diag/*", + Exec: GnoiDiagAllRPC, + } + gnoidiagGetBERTResult = &RPC{ + Name: "GetBERTResult", + Service: "gnoi.diag.Diag", + FQN: "gnoi.diag.Diag.GetBERTResult", + Path: "/gnoi.diag.Diag/GetBERTResult", + Exec: GnoiDiagGetBERTResult, + } + gnoidiagStopBERT = &RPC{ + Name: "StopBERT", + Service: "gnoi.diag.Diag", + FQN: "gnoi.diag.Diag.StopBERT", + Path: "/gnoi.diag.Diag/StopBERT", + Exec: GnoiDiagStopBERT, + } + gnoidiagStartBERT = &RPC{ + Name: "StartBERT", + Service: "gnoi.diag.Diag", + FQN: "gnoi.diag.Diag.StartBERT", + Path: "/gnoi.diag.Diag/StartBERT", + Exec: GnoiDiagStartBERT, + } + gnoifactory_resetFactoryResetALL = &RPC{ //revive:disable-line the name of the rpc includes _ + Name: "*", + Service: "gnoi.factory_reset.FactoryReset", + FQN: "gnoi.factory_reset.FactoryReset.*", + Path: "/gnoi.factory_reset.FactoryReset/*", + Exec: GnoiFactoryresetAllRPC, + } + gnoifactory_resetFactoryResetStart = &RPC{ //revive:disable-line the name of the rpc includes _ + Name: "Start", + Service: "gnoi.factory_reset.FactoryReset", + FQN: "gnoi.factory_reset.FactoryReset.Start", + Path: "/gnoi.factory_reset.FactoryReset/Start", + Exec: GnoiFactoryresetStart, + } + gnoifileALL = &RPC{ + Name: "*", + Service: "gnoi.file.File", + FQN: "gnoi.file.File.*", + Path: "/gnoi.file.File/*", + Exec: GnoiFileAllRPC, + } + gnoifilePut = &RPC{ + Name: "Put", + Service: "gnoi.file.File", + FQN: "gnoi.file.File.Put", + Path: "/gnoi.file.File/Put", + Exec: GnoiFilePut, + } + gnoifileRemove = &RPC{ + Name: "Remove", + Service: "gnoi.file.File", + FQN: "gnoi.file.File.Remove", + Path: "/gnoi.file.File/Remove", + Exec: GnoiFileRemove, + } + gnoifileStat = &RPC{ + Name: "Stat", + Service: "gnoi.file.File", + FQN: "gnoi.file.File.Stat", + Path: "/gnoi.file.File/Stat", + Exec: GnoiFileStat, + } + gnoifileTransferToRemote = &RPC{ + Name: "TransferToRemote", + Service: "gnoi.file.File", + FQN: "gnoi.file.File.TransferToRemote", + Path: "/gnoi.file.File/TransferToRemote", + Exec: GnoiFileTransferToRemote, + } + gnoifileGet = &RPC{ + Name: "Get", + Service: "gnoi.file.File", + FQN: "gnoi.file.File.Get", + Path: "/gnoi.file.File/Get", + Exec: GnoiFileGet, + } + gnoihealthzAcknowledge = &RPC{ + Name: "Acknowledge", + Service: "gnoi.healthz.Healthz", + FQN: "gnoi.healthz.Healthz.Acknowledge", + Path: "/gnoi.healthz.Healthz/Acknowledge", + Exec: GnoiHealthzAcknowledge, + } + gnoihealthzALL = &RPC{ + Name: "*", + Service: "gnoi.healthz.Healthz", + FQN: "gnoi.healthz.Healthz.*", + Path: "/gnoi.healthz.Healthz/*", + Exec: GnoiHealthzAllRPC, + } + gnoihealthzArtifact = &RPC{ + Name: "Artifact", + Service: "gnoi.healthz.Healthz", + FQN: "gnoi.healthz.Healthz.Artifact", + Path: "/gnoi.healthz.Healthz/Artifact", + Exec: GnoiHealthzArtifact, + } + gnoihealthzCheck = &RPC{ + Name: "Check", + Service: "gnoi.healthz.Healthz", + FQN: "gnoi.healthz.Healthz.Check", + Path: "/gnoi.healthz.Healthz/Check", + Exec: GnoiHealthzCheck, + } + gnoihealthzList = &RPC{ + Name: "List", + Service: "gnoi.healthz.Healthz", + FQN: "gnoi.healthz.Healthz.List", + Path: "/gnoi.healthz.Healthz/List", + Exec: GnoiHealthzList, + } + gnoihealthzGet = &RPC{ + Name: "Get", + Service: "gnoi.healthz.Healthz", + FQN: "gnoi.healthz.Healthz.Get", + Path: "/gnoi.healthz.Healthz/Get", + Exec: GnoiHealthzGet, + } + gnoilayer2ALL = &RPC{ + Name: "*", + Service: "gnoi.layer2.Layer2", + FQN: "gnoi.layer2.Layer2.*", + Path: "/gnoi.layer2.Layer2/*", + Exec: GnoiLayer2AllRPC, + } + gnoilayer2ClearLLDPInterface = &RPC{ + Name: "ClearLLDPInterface", + Service: "gnoi.layer2.Layer2", + FQN: "gnoi.layer2.Layer2.ClearLLDPInterface", + Path: "/gnoi.layer2.Layer2/ClearLLDPInterface", + Exec: GnoiLayer2ClearLLDPInterface, + } + gnoilayer2ClearSpanningTree = &RPC{ + Name: "ClearSpanningTree", + Service: "gnoi.layer2.Layer2", + FQN: "gnoi.layer2.Layer2.ClearSpanningTree", + Path: "/gnoi.layer2.Layer2/ClearSpanningTree", + Exec: GnoiLayer2ClearSpanningTree, + } + gnoilayer2PerformBERT = &RPC{ + Name: "PerformBERT", + Service: "gnoi.layer2.Layer2", + FQN: "gnoi.layer2.Layer2.PerformBERT", + Path: "/gnoi.layer2.Layer2/PerformBERT", + Exec: GnoiLayer2PerformBERT, + } + gnoilayer2SendWakeOnLAN = &RPC{ + Name: "SendWakeOnLAN", + Service: "gnoi.layer2.Layer2", + FQN: "gnoi.layer2.Layer2.SendWakeOnLAN", + Path: "/gnoi.layer2.Layer2/SendWakeOnLAN", + Exec: GnoiLayer2SendWakeOnLAN, + } + gnoilayer2ClearNeighborDiscovery = &RPC{ + Name: "ClearNeighborDiscovery", + Service: "gnoi.layer2.Layer2", + FQN: "gnoi.layer2.Layer2.ClearNeighborDiscovery", + Path: "/gnoi.layer2.Layer2/ClearNeighborDiscovery", + Exec: GnoiLayer2ClearNeighborDiscovery, + } + gnoipacket_link_qualificationLinkQualificationCreate = &RPC{ //revive:disable-line the name of the rpc includes _ + Name: "Create", + Service: "gnoi.packet_link_qualification.LinkQualification", + FQN: "gnoi.packet_link_qualification.LinkQualification.Create", + Path: "/gnoi.packet_link_qualification.LinkQualification/Create", + Exec: GnoiLinkqualificationCreate, + } + gnoimplsALL = &RPC{ + Name: "*", + Service: "gnoi.mpls.MPLS", + FQN: "gnoi.mpls.MPLS.*", + Path: "/gnoi.mpls.MPLS/*", + Exec: GnoiMplsAllRPC, + } + gnoimplsClearLSPCounters = &RPC{ + Name: "ClearLSPCounters", + Service: "gnoi.mpls.MPLS", + FQN: "gnoi.mpls.MPLS.ClearLSPCounters", + Path: "/gnoi.mpls.MPLS/ClearLSPCounters", + Exec: GnoiMplsClearLSPCounters, + } + gnoimplsMPLSPing = &RPC{ + Name: "MPLSPing", + Service: "gnoi.mpls.MPLS", + FQN: "gnoi.mpls.MPLS.MPLSPing", + Path: "/gnoi.mpls.MPLS/MPLSPing", + Exec: GnoiMplsMPLSPing, + } + gnoimplsClearLSP = &RPC{ + Name: "ClearLSP", + Service: "gnoi.mpls.MPLS", + FQN: "gnoi.mpls.MPLS.ClearLSP", + Path: "/gnoi.mpls.MPLS/ClearLSP", + Exec: GnoiMplsClearLSP, + } + gnoiopticalOTDRALL = &RPC{ + Name: "*", + Service: "gnoi.optical.OTDR", + FQN: "gnoi.optical.OTDR.*", + Path: "/gnoi.optical.OTDR/*", + Exec: GnoiOtdrAllRPC, + } + gnoiopticalWavelengthRouterAdjustSpectrum = &RPC{ + Name: "AdjustSpectrum", + Service: "gnoi.optical.WavelengthRouter", + FQN: "gnoi.optical.WavelengthRouter.AdjustSpectrum", + Path: "/gnoi.optical.WavelengthRouter/AdjustSpectrum", + Exec: GnoiWavelengthrouterAdjustSpectrum, + } + gnoiopticalWavelengthRouterALL = &RPC{ + Name: "*", + Service: "gnoi.optical.WavelengthRouter", + FQN: "gnoi.optical.WavelengthRouter.*", + Path: "/gnoi.optical.WavelengthRouter/*", + Exec: GnoiWavelengthrouterAllRPC, + } + gnoiopticalWavelengthRouterCancelAdjustPSD = &RPC{ + Name: "CancelAdjustPSD", + Service: "gnoi.optical.WavelengthRouter", + FQN: "gnoi.optical.WavelengthRouter.CancelAdjustPSD", + Path: "/gnoi.optical.WavelengthRouter/CancelAdjustPSD", + Exec: GnoiWavelengthrouterCancelAdjustPSD, + } + gnoiopticalWavelengthRouterCancelAdjustSpectrum = &RPC{ + Name: "CancelAdjustSpectrum", + Service: "gnoi.optical.WavelengthRouter", + FQN: "gnoi.optical.WavelengthRouter.CancelAdjustSpectrum", + Path: "/gnoi.optical.WavelengthRouter/CancelAdjustSpectrum", + Exec: GnoiWavelengthrouterCancelAdjustSpectrum, + } + gnoiosActivate = &RPC{ + Name: "Activate", + Service: "gnoi.os.OS", + FQN: "gnoi.os.OS.Activate", + Path: "/gnoi.os.OS/Activate", + Exec: GnoiOsActivate, + } + gnoiosALL = &RPC{ + Name: "*", + Service: "gnoi.os.OS", + FQN: "gnoi.os.OS.*", + Path: "/gnoi.os.OS/*", + Exec: GnoiOsAllRPC, + } + gnoiosVerify = &RPC{ + Name: "Verify", + Service: "gnoi.os.OS", + FQN: "gnoi.os.OS.Verify", + Path: "/gnoi.os.OS/Verify", + Exec: GnoiOsVerify, + } + gnoiosInstall = &RPC{ + Name: "Install", + Service: "gnoi.os.OS", + FQN: "gnoi.os.OS.Install", + Path: "/gnoi.os.OS/Install", + Exec: GnoiOsInstall, + } + gnoiopticalOTDRInitiate = &RPC{ + Name: "Initiate", + Service: "gnoi.optical.OTDR", + FQN: "gnoi.optical.OTDR.Initiate", + Path: "/gnoi.optical.OTDR/Initiate", + Exec: GnoiOtdrInitiate, + } + gnoipacket_link_qualificationLinkQualificationALL = &RPC{ //revive:disable-line the name of the rpc includes _ + Service: "gnoi.packet_link_qualification.LinkQualification", + FQN: "gnoi.packet_link_qualification.LinkQualification.*", + Path: "/gnoi.packet_link_qualification.LinkQualification/*", + Exec: GnoiLinkqualificationAllRPC, + } + gnoipacket_link_qualificationLinkQualificationCapabilities = &RPC{ //revive:disable-line the name of the rpc includes _ + + Name: "Capabilities", + Service: "gnoi.packet_link_qualification.LinkQualification", + FQN: "gnoi.packet_link_qualification.LinkQualification.Capabilities", + Path: "/gnoi.packet_link_qualification.LinkQualification/Capabilities", + Exec: GnoiLinkqualificationCapabilities, + } + gnoipacket_link_qualificationLinkQualificationDelete = &RPC{ //revive:disable-line the name of the rpc includes _ + + Name: "Delete", + Service: "gnoi.packet_link_qualification.LinkQualification", + FQN: "gnoi.packet_link_qualification.LinkQualification.Delete", + Path: "/gnoi.packet_link_qualification.LinkQualification/Delete", + Exec: GnoiLinkqualificationDelete, + } + gnoipacket_link_qualificationLinkQualificationGet = &RPC{ //revive:disable-line the name of the rpc includes _ + Name: "Get", + Service: "gnoi.packet_link_qualification.LinkQualification", + FQN: "gnoi.packet_link_qualification.LinkQualification.Get", + Path: "/gnoi.packet_link_qualification.LinkQualification/Get", + Exec: GnoiLinkqualificationGet, + } + gnoipacket_link_qualificationLinkQualificationList = &RPC{ //revive:disable-line the name of the rpc includes _ + Name: "List", + Service: "gnoi.packet_link_qualification.LinkQualification", + FQN: "gnoi.packet_link_qualification.LinkQualification.List", + Path: "/gnoi.packet_link_qualification.LinkQualification/List", + Exec: GnoiLinkqualificationList, + } + gnoisystemALL = &RPC{ + Name: "*", + Service: "gnoi.system.System", + FQN: "gnoi.system.System.*", + Path: "/gnoi.system.System/*", + Exec: GnoiSystemAllRPC, + } + gnoisystemCancelReboot = &RPC{ + Name: "CancelReboot", + Service: "gnoi.system.System", + FQN: "gnoi.system.System.CancelReboot", + Path: "/gnoi.system.System/CancelReboot", + Exec: GnoiSystemCancelReboot, + } + gnoisystemKillProcess = &RPC{ + Name: "KillProcess", + Service: "gnoi.system.System", + FQN: "gnoi.system.System.KillProcess", + Path: "/gnoi.system.System/KillProcess", + Exec: GnoiSystemKillProcess, + } + gnoisystemReboot = &RPC{ + Name: "Reboot", + Service: "gnoi.system.System", + FQN: "gnoi.system.System.Reboot", + Path: "/gnoi.system.System/Reboot", + Exec: GnoiSystemReboot, + } + gnoisystemRebootStatus = &RPC{ + Name: "RebootStatus", + Service: "gnoi.system.System", + FQN: "gnoi.system.System.RebootStatus", + Path: "/gnoi.system.System/RebootStatus", + Exec: GnoiSystemRebootStatus, + } + gnoisystemSetPackage = &RPC{ + Name: "SetPackage", + Service: "gnoi.system.System", + FQN: "gnoi.system.System.SetPackage", + Path: "/gnoi.system.System/SetPackage", + Exec: GnoiSystemSetPackage, + } + gnoisystemSwitchControlProcessor = &RPC{ + Name: "SwitchControlProcessor", + Service: "gnoi.system.System", + FQN: "gnoi.system.System.SwitchControlProcessor", + Path: "/gnoi.system.System/SwitchControlProcessor", + Exec: GnoiSystemSwitchControlProcessor, + } + gnoisystemTime = &RPC{ + Name: "Time", + Service: "gnoi.system.System", + FQN: "gnoi.system.System.Time", + Path: "/gnoi.system.System/Time", + Exec: GnoiSystemTime, + } + gnoisystemTraceroute = &RPC{ + Name: "Traceroute", + Service: "gnoi.system.System", + FQN: "gnoi.system.System.Traceroute", + Path: "/gnoi.system.System/Traceroute", + Exec: GnoiSystemTraceroute, + } + gnoisystemPing = &RPC{ + Name: "Ping", + Service: "gnoi.system.System", + FQN: "gnoi.system.System.Ping", + Path: "/gnoi.system.System/Ping", + Exec: GnoiSystemPing, + } + gnoiopticalWavelengthRouterAdjustPSD = &RPC{ + Name: "AdjustPSD", + Service: "gnoi.optical.WavelengthRouter", + FQN: "gnoi.optical.WavelengthRouter.AdjustPSD", + Path: "/gnoi.optical.WavelengthRouter/AdjustPSD", + Exec: GnoiWavelengthrouterAdjustPSD, + } + gnsiacctzv1AcctzALL = &RPC{ + Name: "*", + Service: "gnsi.acctz.v1.Acctz", + FQN: "gnsi.acctz.v1.Acctz.*", + Path: "/gnsi.acctz.v1.Acctz/*", + Exec: GnsiAcctzAllRPC, + } + gnsiacctzv1AcctzRecordSubscribe = &RPC{ + Name: "RecordSubscribe", + Service: "gnsi.acctz.v1.Acctz", + FQN: "gnsi.acctz.v1.Acctz.RecordSubscribe", + Path: "/gnsi.acctz.v1.Acctz/RecordSubscribe", + Exec: GnsiAcctzRecordSubscribe, + } + gnsiauthzv1AuthzALL = &RPC{ + Name: "*", + Service: "gnsi.authz.v1.Authz", + FQN: "gnsi.authz.v1.Authz.*", + Path: "/gnsi.authz.v1.Authz/*", + Exec: GnsiAuthzAllRPC, + } + gnsiauthzv1AuthzGet = &RPC{ + Name: "Get", + Service: "gnsi.authz.v1.Authz", + FQN: "gnsi.authz.v1.Authz.Get", + Path: "/gnsi.authz.v1.Authz/Get", + Exec: GnsiAuthzGet, + } + gnsiauthzv1AuthzProbe = &RPC{ + Name: "Probe", + Service: "gnsi.authz.v1.Authz", + FQN: "gnsi.authz.v1.Authz.Probe", + Path: "/gnsi.authz.v1.Authz/Probe", + Exec: GnsiAuthzProbe, + } + gnsiauthzv1AuthzRotate = &RPC{ + Name: "Rotate", + Service: "gnsi.authz.v1.Authz", + FQN: "gnsi.authz.v1.Authz.Rotate", + Path: "/gnsi.authz.v1.Authz/Rotate", + Exec: GnsiAuthzRotate, + } + gnsicertzv1CertzAddProfile = &RPC{ + Name: "AddProfile", + Service: "gnsi.certz.v1.Certz", + FQN: "gnsi.certz.v1.Certz.AddProfile", + Path: "/gnsi.certz.v1.Certz/AddProfile", + Exec: GnsiCertzAddProfile, + } + gnsicertzv1CertzALL = &RPC{ + Name: "*", + Service: "gnsi.certz.v1.Certz", + FQN: "gnsi.certz.v1.Certz.*", + Path: "/gnsi.certz.v1.Certz/*", + Exec: GnsiCertzAllRPC, + } + gnsicertzv1CertzCanGenerateCSR = &RPC{ + Name: "CanGenerateCSR", + Service: "gnsi.certz.v1.Certz", + FQN: "gnsi.certz.v1.Certz.CanGenerateCSR", + Path: "/gnsi.certz.v1.Certz/CanGenerateCSR", + Exec: GnsiCertzCanGenerateCSR, + } + gnsicertzv1CertzDeleteProfile = &RPC{ + Name: "DeleteProfile", + Service: "gnsi.certz.v1.Certz", + FQN: "gnsi.certz.v1.Certz.DeleteProfile", + Path: "/gnsi.certz.v1.Certz/DeleteProfile", + Exec: GnsiCertzDeleteProfile, + } + gnsicertzv1CertzGetProfileList = &RPC{ + Name: "GetProfileList", + Service: "gnsi.certz.v1.Certz", + FQN: "gnsi.certz.v1.Certz.GetProfileList", + Path: "/gnsi.certz.v1.Certz/GetProfileList", + Exec: GnsiCertzGetProfileList, + } + gnsicertzv1CertzRotate = &RPC{ + Name: "Rotate", + Service: "gnsi.certz.v1.Certz", + FQN: "gnsi.certz.v1.Certz.Rotate", + Path: "/gnsi.certz.v1.Certz/Rotate", + Exec: GnsiCertzRotate, + } + gnsicredentialzv1CredentialzALL = &RPC{ + Name: "*", + Service: "gnsi.credentialz.v1.Credentialz", + FQN: "gnsi.credentialz.v1.Credentialz.*", + Path: "/gnsi.credentialz.v1.Credentialz/*", + Exec: GnsiCredentialzAllRPC, + } + gnsicredentialzv1CredentialzCanGenerateKey = &RPC{ + Name: "CanGenerateKey", + Service: "gnsi.credentialz.v1.Credentialz", + FQN: "gnsi.credentialz.v1.Credentialz.CanGenerateKey", + Path: "/gnsi.credentialz.v1.Credentialz/CanGenerateKey", + Exec: GnsiCredentialzCanGenerateKey, + } + gnsicredentialzv1CredentialzGetPublicKeys = &RPC{ + Name: "GetPublicKeys", + Service: "gnsi.credentialz.v1.Credentialz", + FQN: "gnsi.credentialz.v1.Credentialz.GetPublicKeys", + Path: "/gnsi.credentialz.v1.Credentialz/GetPublicKeys", + Exec: GnsiCredentialzGetPublicKeys, + } + gnsicredentialzv1CredentialzRotateHostParameters = &RPC{ + Name: "RotateHostParameters", + Service: "gnsi.credentialz.v1.Credentialz", + FQN: "gnsi.credentialz.v1.Credentialz.RotateHostParameters", + Path: "/gnsi.credentialz.v1.Credentialz/RotateHostParameters", + Exec: GnsiCredentialzRotateHostParameters, + } + gnsicredentialzv1CredentialzRotateAccountCredentials = &RPC{ + Name: "RotateAccountCredentials", + Service: "gnsi.credentialz.v1.Credentialz", + FQN: "gnsi.credentialz.v1.Credentialz.RotateAccountCredentials", + Path: "/gnsi.credentialz.v1.Credentialz/RotateAccountCredentials", + Exec: GnsiCredentialzRotateAccountCredentials, + } + gnsipathzv1PathzALL = &RPC{ + Name: "*", + Service: "gnsi.pathz.v1.Pathz", + FQN: "gnsi.pathz.v1.Pathz.*", + Path: "/gnsi.pathz.v1.Pathz/*", + Exec: GnsiPathzAllRPC, + } + gnsipathzv1PathzGet = &RPC{ + Name: "Get", + Service: "gnsi.pathz.v1.Pathz", + FQN: "gnsi.pathz.v1.Pathz.Get", + Path: "/gnsi.pathz.v1.Pathz/Get", + Exec: GnsiPathzGet, + } + gnsipathzv1PathzProbe = &RPC{ + Name: "Probe", + Service: "gnsi.pathz.v1.Pathz", + FQN: "gnsi.pathz.v1.Pathz.Probe", + Path: "/gnsi.pathz.v1.Pathz/Probe", + Exec: GnsiPathzProbe, + } + gnsipathzv1PathzRotate = &RPC{ + Name: "Rotate", + Service: "gnsi.pathz.v1.Pathz", + FQN: "gnsi.pathz.v1.Pathz.Rotate", + Path: "/gnsi.pathz.v1.Pathz/Rotate", + Exec: GnsiPathzRotate, + } + gribiALL = &RPC{ + Name: "*", + Service: "gribi.gRIBI", + FQN: "gribi.gRIBI.*", + Path: "/gribi.gRIBI/*", + Exec: GribiAllRPC, + } + gribiFlush = &RPC{ + Name: "Flush", + Service: "gribi.gRIBI", + FQN: "gribi.gRIBI.Flush", + Path: "/gribi.gRIBI/Flush", + Exec: GribiFlush, + } + gribiGet = &RPC{ + Name: "Get", + Service: "gribi.gRIBI", + FQN: "gribi.gRIBI.Get", + Path: "/gribi.gRIBI/Get", + Exec: GribiGet, + } + gribiModify = &RPC{ + Name: "Modify", + Service: "gribi.gRIBI", + FQN: "gribi.gRIBI.Modify", + Path: "/gribi.gRIBI/Modify", + Exec: GribiModify, + } + p4v1P4RuntimeALL = &RPC{ + Name: "*", + Service: "p4.v1.P4Runtime", + FQN: "p4.v1.P4Runtime.*", + Path: "/p4.v1.P4Runtime/*", + Exec: P4P4runtimeAllRPC, + } + p4v1P4RuntimeCapabilities = &RPC{ + Name: "Capabilities", + Service: "p4.v1.P4Runtime", + FQN: "p4.v1.P4Runtime.Capabilities", + Path: "/p4.v1.P4Runtime/Capabilities", + Exec: P4P4runtimeCapabilities, + } + p4v1P4RuntimeGetForwardingPipelineConfig = &RPC{ + Name: "GetForwardingPipelineConfig", + Service: "p4.v1.P4Runtime", + FQN: "p4.v1.P4Runtime.GetForwardingPipelineConfig", + Path: "/p4.v1.P4Runtime/GetForwardingPipelineConfig", + Exec: P4P4runtimeGetForwardingPipelineConfig, + } + p4v1P4RuntimeRead = &RPC{ + Name: "Read", + Service: "p4.v1.P4Runtime", + FQN: "p4.v1.P4Runtime.Read", + Path: "/p4.v1.P4Runtime/Read", + Exec: P4P4runtimeRead, + } + p4v1P4RuntimeSetForwardingPipelineConfig = &RPC{ + Name: "SetForwardingPipelineConfig", + Service: "p4.v1.P4Runtime", + FQN: "p4.v1.P4Runtime.SetForwardingPipelineConfig", + Path: "/p4.v1.P4Runtime/SetForwardingPipelineConfig", + Exec: P4P4runtimeSetForwardingPipelineConfig, + } + p4v1P4RuntimeStreamChannel = &RPC{ + Name: "StreamChannel", + Service: "p4.v1.P4Runtime", + FQN: "p4.v1.P4Runtime.StreamChannel", + Path: "/p4.v1.P4Runtime/StreamChannel", + Exec: P4P4runtimeStreamChannel, + } + p4v1P4RuntimeWrite = &RPC{ + Name: "Write", + Service: "p4.v1.P4Runtime", + FQN: "p4.v1.P4Runtime.Write", + Path: "/p4.v1.P4Runtime/Write", + Exec: P4P4runtimeWrite, + } + + // RPCs is a list of all FP related RPCs + RPCs = rpcs{ + AllRPC: ALL, + GnmiAllRPC: gnmiALL, + GnmiGet: gnmiGet, + GnmiSet: gnmiSet, + GnmiSubscribe: gnmiSubscribe, + GnmiCapabilities: gnmiCapabilities, + GnoiBgpAllRPC: gnoibgpALL, + GnoiBgpClearBGPNeighbor: gnoibgpClearBGPNeighbor, + GnoiCertificatemanagementAllRPC: gnoicertificateCertificateManagementALL, + GnoiCertificatemanagementCanGenerateCSR: gnoicertificateCertificateManagementCanGenerateCSR, + GnoiCertificatemanagementGenerateCSR: gnoicertificateCertificateManagementGenerateCSR, + GnoiCertificatemanagementGetCertificates: gnoicertificateCertificateManagementGetCertificates, + GnoiCertificatemanagementInstall: gnoicertificateCertificateManagementInstall, + GnoiCertificatemanagementLoadCertificate: gnoicertificateCertificateManagementLoadCertificate, + GnoiCertificatemanagementLoadCertificateAuthorityBundle: gnoicertificateCertificateManagementLoadCertificateAuthorityBundle, + GnoiCertificatemanagementRevokeCertificates: gnoicertificateCertificateManagementRevokeCertificates, + GnoiCertificatemanagementRotate: gnoicertificateCertificateManagementRotate, + GnoiDiagAllRPC: gnoidiagALL, + GnoiDiagGetBERTResult: gnoidiagGetBERTResult, + GnoiDiagStopBERT: gnoidiagStopBERT, + GnoiDiagStartBERT: gnoidiagStartBERT, + GnoiFactoryresetAllRPC: gnoifactory_resetFactoryResetALL, + GnoiFactoryresetStart: gnoifactory_resetFactoryResetStart, + GnoiFileAllRPC: gnoifileALL, + GnoiFilePut: gnoifilePut, + GnoiFileRemove: gnoifileRemove, + GnoiFileStat: gnoifileStat, + GnoiFileTransferToRemote: gnoifileTransferToRemote, + GnoiFileGet: gnoifileGet, + GnoiHealthzAcknowledge: gnoihealthzAcknowledge, + GnoiHealthzAllRPC: gnoihealthzALL, + GnoiHealthzArtifact: gnoihealthzArtifact, + GnoiHealthzCheck: gnoihealthzCheck, + GnoiHealthzList: gnoihealthzList, + GnoiHealthzGet: gnoihealthzGet, + GnoiLayer2AllRPC: gnoilayer2ALL, + GnoiLayer2ClearLLDPInterface: gnoilayer2ClearLLDPInterface, + GnoiLayer2ClearSpanningTree: gnoilayer2ClearSpanningTree, + GnoiLayer2PerformBERT: gnoilayer2PerformBERT, + GnoiLayer2SendWakeOnLAN: gnoilayer2SendWakeOnLAN, + GnoiLayer2ClearNeighborDiscovery: gnoilayer2ClearNeighborDiscovery, + GnoiLinkqualificationCreate: gnoipacket_link_qualificationLinkQualificationCreate, + GnoiMplsAllRPC: gnoimplsALL, + GnoiMplsClearLSPCounters: gnoimplsClearLSPCounters, + GnoiMplsMPLSPing: gnoimplsMPLSPing, + GnoiMplsClearLSP: gnoimplsClearLSP, + GnoiOtdrAllRPC: gnoiopticalOTDRALL, + GnoiWavelengthrouterAdjustSpectrum: gnoiopticalWavelengthRouterAdjustSpectrum, + GnoiWavelengthrouterAllRPC: gnoiopticalWavelengthRouterALL, + GnoiWavelengthrouterCancelAdjustPSD: gnoiopticalWavelengthRouterCancelAdjustPSD, + GnoiWavelengthrouterCancelAdjustSpectrum: gnoiopticalWavelengthRouterCancelAdjustSpectrum, + GnoiOsActivate: gnoiosActivate, + GnoiOsAllRPC: gnoiosALL, + GnoiOsVerify: gnoiosVerify, + GnoiOsInstall: gnoiosInstall, + GnoiOtdrInitiate: gnoiopticalOTDRInitiate, + GnoiLinkqualificationAllRPC: gnoipacket_link_qualificationLinkQualificationALL, + GnoiLinkqualificationCapabilities: gnoipacket_link_qualificationLinkQualificationCapabilities, + GnoiLinkqualificationDelete: gnoipacket_link_qualificationLinkQualificationDelete, + GnoiLinkqualificationGet: gnoipacket_link_qualificationLinkQualificationGet, + GnoiLinkqualificationList: gnoipacket_link_qualificationLinkQualificationList, + GnoiSystemAllRPC: gnoisystemALL, + GnoiSystemCancelReboot: gnoisystemCancelReboot, + GnoiSystemKillProcess: gnoisystemKillProcess, + GnoiSystemReboot: gnoisystemReboot, + GnoiSystemRebootStatus: gnoisystemRebootStatus, + GnoiSystemSetPackage: gnoisystemSetPackage, + GnoiSystemSwitchControlProcessor: gnoisystemSwitchControlProcessor, + GnoiSystemTime: gnoisystemTime, + GnoiSystemTraceroute: gnoisystemTraceroute, + GnoiSystemPing: gnoisystemPing, + GnoiWavelengthrouterAdjustPSD: gnoiopticalWavelengthRouterAdjustPSD, + GnsiAcctzAllRPC: gnsiacctzv1AcctzALL, + GnsiAcctzRecordSubscribe: gnsiacctzv1AcctzRecordSubscribe, + GnsiAuthzAllRPC: gnsiauthzv1AuthzALL, + GnsiAuthzGet: gnsiauthzv1AuthzGet, + GnsiAuthzProbe: gnsiauthzv1AuthzProbe, + GnsiAuthzRotate: gnsiauthzv1AuthzRotate, + GnsiCertzAddProfile: gnsicertzv1CertzAddProfile, + GnsiCertzAllRPC: gnsicertzv1CertzALL, + GnsiCertzCanGenerateCSR: gnsicertzv1CertzCanGenerateCSR, + GnsiCertzDeleteProfile: gnsicertzv1CertzDeleteProfile, + GnsiCertzGetProfileList: gnsicertzv1CertzGetProfileList, + GnsiCertzRotate: gnsicertzv1CertzRotate, + GnsiCredentialzAllRPC: gnsicredentialzv1CredentialzALL, + GnsiCredentialzCanGenerateKey: gnsicredentialzv1CredentialzCanGenerateKey, + GnsiCredentialzGetPublicKeys: gnsicredentialzv1CredentialzGetPublicKeys, + GnsiCredentialzRotateHostParameters: gnsicredentialzv1CredentialzRotateHostParameters, + GnsiCredentialzRotateAccountCredentials: gnsicredentialzv1CredentialzRotateAccountCredentials, + GnsiPathzAllRPC: gnsipathzv1PathzALL, + GnsiPathzGet: gnsipathzv1PathzGet, + GnsiPathzProbe: gnsipathzv1PathzProbe, + GnsiPathzRotate: gnsipathzv1PathzRotate, + GribiAllRPC: gribiALL, + GribiFlush: gribiFlush, + GribiGet: gribiGet, + GribiModify: gribiModify, + P4P4runtimeAllRPC: p4v1P4RuntimeALL, + P4P4runtimeCapabilities: p4v1P4RuntimeCapabilities, + P4P4runtimeGetForwardingPipelineConfig: p4v1P4RuntimeGetForwardingPipelineConfig, + P4P4runtimeRead: p4v1P4RuntimeRead, + P4P4runtimeSetForwardingPipelineConfig: p4v1P4RuntimeSetForwardingPipelineConfig, + P4P4runtimeStreamChannel: p4v1P4RuntimeStreamChannel, + P4P4runtimeWrite: p4v1P4RuntimeWrite, + } + + // RPCMAP is a helper that maps path to RPCs data that may be needed in tests. + RPCMAP = map[string]*RPC{ + "*": ALL, + "/gnmi.gNMI/*": gnmiALL, + "/gnmi.gNMI/Get": gnmiGet, + "/gnmi.gNMI/Set": gnmiSet, + "/gnmi.gNMI/Subscribe": gnmiSubscribe, + "/gnmi.gNMI/Capabilities": gnmiCapabilities, + "/gnoi.bgp.BGP/*": gnoibgpALL, + "/gnoi.bgp.BGP/ClearBGPNeighbor": gnoibgpClearBGPNeighbor, + "/gnoi.certificate.CertificateManagement/*": gnoicertificateCertificateManagementALL, + "/gnoi.certificate.CertificateManagement/CanGenerateCSR": gnoicertificateCertificateManagementCanGenerateCSR, + "/gnoi.certificate.CertificateManagement/GenerateCSR": gnoicertificateCertificateManagementGenerateCSR, + "/gnoi.certificate.CertificateManagement/GetCertificates": gnoicertificateCertificateManagementGetCertificates, + "/gnoi.certificate.CertificateManagement/Install": gnoicertificateCertificateManagementInstall, + "/gnoi.certificate.CertificateManagement/LoadCertificate": gnoicertificateCertificateManagementLoadCertificate, + "/gnoi.certificate.CertificateManagement/LoadCertificateAuthorityBundle": gnoicertificateCertificateManagementLoadCertificateAuthorityBundle, + "/gnoi.certificate.CertificateManagement/RevokeCertificates": gnoicertificateCertificateManagementRevokeCertificates, + "/gnoi.certificate.CertificateManagement/Rotate": gnoicertificateCertificateManagementRotate, + "/gnoi.diag.Diag/*": gnoidiagALL, + "/gnoi.diag.Diag/GetBERTResult": gnoidiagGetBERTResult, + "/gnoi.diag.Diag/StopBERT": gnoidiagStopBERT, + "/gnoi.diag.Diag/StartBERT": gnoidiagStartBERT, + "/gnoi.factory_reset.FactoryReset/*": gnoifactory_resetFactoryResetALL, + "/gnoi.factory_reset.FactoryReset/Start": gnoifactory_resetFactoryResetStart, + "/gnoi.file.File/*": gnoifileALL, + "/gnoi.file.File/Put": gnoifilePut, + "/gnoi.file.File/Remove": gnoifileRemove, + "/gnoi.file.File/Stat": gnoifileStat, + "/gnoi.file.File/TransferToRemote": gnoifileTransferToRemote, + "/gnoi.file.File/Get": gnoifileGet, + "/gnoi.healthz.Healthz/Acknowledge": gnoihealthzAcknowledge, + "/gnoi.healthz.Healthz/*": gnoihealthzALL, + "/gnoi.healthz.Healthz/Artifact": gnoihealthzArtifact, + "/gnoi.healthz.Healthz/Check": gnoihealthzCheck, + "/gnoi.healthz.Healthz/List": gnoihealthzList, + "/gnoi.healthz.Healthz/Get": gnoihealthzGet, + "/gnoi.layer2.Layer2/*": gnoilayer2ALL, + "/gnoi.layer2.Layer2/ClearLLDPInterface": gnoilayer2ClearLLDPInterface, + "/gnoi.layer2.Layer2/ClearSpanningTree": gnoilayer2ClearSpanningTree, + "/gnoi.layer2.Layer2/PerformBERT": gnoilayer2PerformBERT, + "/gnoi.layer2.Layer2/SendWakeOnLAN": gnoilayer2SendWakeOnLAN, + "/gnoi.layer2.Layer2/ClearNeighborDiscovery": gnoilayer2ClearNeighborDiscovery, + "/gnoi.packet_link_qualification.LinkQualification/Create": gnoipacket_link_qualificationLinkQualificationCreate, + "/gnoi.mpls.MPLS/*": gnoimplsALL, + "/gnoi.mpls.MPLS/ClearLSPCounters": gnoimplsClearLSPCounters, + "/gnoi.mpls.MPLS/MPLSPing": gnoimplsMPLSPing, + "/gnoi.mpls.MPLS/ClearLSP": gnoimplsClearLSP, + "/gnoi.optical.OTDR/*": gnoiopticalOTDRALL, + "/gnoi.optical.WavelengthRouter/AdjustSpectrum": gnoiopticalWavelengthRouterAdjustSpectrum, + "/gnoi.optical.WavelengthRouter/*": gnoiopticalWavelengthRouterALL, + "/gnoi.optical.WavelengthRouter/CancelAdjustPSD": gnoiopticalWavelengthRouterCancelAdjustPSD, + "/gnoi.optical.WavelengthRouter/CancelAdjustSpectrum": gnoiopticalWavelengthRouterCancelAdjustSpectrum, + "/gnoi.os.OS/Activate": gnoiosActivate, + "/gnoi.os.OS/*": gnoiosALL, + "/gnoi.os.OS/Verify": gnoiosVerify, + "/gnoi.os.OS/Install": gnoiosInstall, + "/gnoi.optical.OTDR/Initiate": gnoiopticalOTDRInitiate, + "/gnoi.packet_link_qualification.LinkQualification/*": gnoipacket_link_qualificationLinkQualificationALL, + "/gnoi.packet_link_qualification.LinkQualification/Capabilities": gnoipacket_link_qualificationLinkQualificationCapabilities, + "/gnoi.packet_link_qualification.LinkQualification/Delete": gnoipacket_link_qualificationLinkQualificationDelete, + "/gnoi.packet_link_qualification.LinkQualification/Get": gnoipacket_link_qualificationLinkQualificationGet, + "/gnoi.packet_link_qualification.LinkQualification/List": gnoipacket_link_qualificationLinkQualificationList, + "/gnoi.system.System/*": gnoisystemALL, + "/gnoi.system.System/CancelReboot": gnoisystemCancelReboot, + "/gnoi.system.System/KillProcess": gnoisystemKillProcess, + "/gnoi.system.System/Reboot": gnoisystemReboot, + "/gnoi.system.System/RebootStatus": gnoisystemRebootStatus, + "/gnoi.system.System/SetPackage": gnoisystemSetPackage, + "/gnoi.system.System/SwitchControlProcessor": gnoisystemSwitchControlProcessor, + "/gnoi.system.System/Time": gnoisystemTime, + "/gnoi.system.System/Traceroute": gnoisystemTraceroute, + "/gnoi.system.System/Ping": gnoisystemPing, + "/gnoi.optical.WavelengthRouter/AdjustPSD": gnoiopticalWavelengthRouterAdjustPSD, + "/gnsi.acctz.v1.Acctz/*": gnsiacctzv1AcctzALL, + "/gnsi.acctz.v1.Acctz/RecordSubscribe": gnsiacctzv1AcctzRecordSubscribe, + "/gnsi.authz.v1.Authz/*": gnsiauthzv1AuthzALL, + "/gnsi.authz.v1.Authz/Get": gnsiauthzv1AuthzGet, + "/gnsi.authz.v1.Authz/Probe": gnsiauthzv1AuthzProbe, + "/gnsi.authz.v1.Authz/Rotate": gnsiauthzv1AuthzRotate, + "/gnsi.certz.v1.Certz/AddProfile": gnsicertzv1CertzAddProfile, + "/gnsi.certz.v1.Certz/*": gnsicertzv1CertzALL, + "/gnsi.certz.v1.Certz/CanGenerateCSR": gnsicertzv1CertzCanGenerateCSR, + "/gnsi.certz.v1.Certz/DeleteProfile": gnsicertzv1CertzDeleteProfile, + "/gnsi.certz.v1.Certz/GetProfileList": gnsicertzv1CertzGetProfileList, + "/gnsi.certz.v1.Certz/Rotate": gnsicertzv1CertzRotate, + "/gnsi.credentialz.v1.Credentialz/*": gnsicredentialzv1CredentialzALL, + "/gnsi.credentialz.v1.Credentialz/CanGenerateKey": gnsicredentialzv1CredentialzCanGenerateKey, + "/gnsi.credentialz.v1.Credentialz/GetPublicKeys": gnsicredentialzv1CredentialzGetPublicKeys, + "/gnsi.credentialz.v1.Credentialz/RotateHostParameters": gnsicredentialzv1CredentialzRotateHostParameters, + "/gnsi.credentialz.v1.Credentialz/RotateAccountCredentials": gnsicredentialzv1CredentialzRotateAccountCredentials, + "/gnsi.pathz.v1.Pathz/*": gnsipathzv1PathzALL, + "/gnsi.pathz.v1.Pathz/Get": gnsipathzv1PathzGet, + "/gnsi.pathz.v1.Pathz/Probe": gnsipathzv1PathzProbe, + "/gnsi.pathz.v1.Pathz/Rotate": gnsipathzv1PathzRotate, + "/gribi.gRIBI/*": gribiALL, + "/gribi.gRIBI/Flush": gribiFlush, + "/gribi.gRIBI/Get": gribiGet, + "/gribi.gRIBI/Modify": gribiModify, + "/p4.v1.P4Runtime/*": p4v1P4RuntimeALL, + "/p4.v1.P4Runtime/Capabilities": p4v1P4RuntimeCapabilities, + "/p4.v1.P4Runtime/GetForwardingPipelineConfig": p4v1P4RuntimeGetForwardingPipelineConfig, + "/p4.v1.P4Runtime/Read": p4v1P4RuntimeRead, + "/p4.v1.P4Runtime/SetForwardingPipelineConfig": p4v1P4RuntimeSetForwardingPipelineConfig, + "/p4.v1.P4Runtime/StreamChannel": p4v1P4RuntimeStreamChannel, + "/p4.v1.P4Runtime/Write": p4v1P4RuntimeWrite, + } +)