From 07ac30d4e1928f75ca0b866dc579ce7eec0141e9 Mon Sep 17 00:00:00 2001 From: priyacj Date: Thu, 1 Aug 2024 17:11:16 -0700 Subject: [PATCH 1/7] added certz4.1 --- .../internal/setup_service/setup_service.go | 643 ++++++++++++++++++ .../gnsi/certz/tests/trust_bundle/README.md | 88 +++ .../tests/trust_bundle/trustbundle_test.go | 235 +++++++ 3 files changed, 966 insertions(+) create mode 100644 feature/security/gnsi/certz/tests/internal/setup_service/setup_service.go create mode 100644 feature/security/gnsi/certz/tests/trust_bundle/README.md create mode 100644 feature/security/gnsi/certz/tests/trust_bundle/trustbundle_test.go diff --git a/feature/security/gnsi/certz/tests/internal/setup_service/setup_service.go b/feature/security/gnsi/certz/tests/internal/setup_service/setup_service.go new file mode 100644 index 00000000000..27aa5f3511a --- /dev/null +++ b/feature/security/gnsi/certz/tests/internal/setup_service/setup_service.go @@ -0,0 +1,643 @@ +// 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 setupservice is scoped only to be used for scripts in path +// feature/security/gnsi/certz/tests/client_certificates +// Do not use elsewhere. +package setupservice + +import ( + context "context" + "crypto/tls" + "crypto/x509" + "encoding/pem" + "fmt" + + //"io" + "os" + "os/exec" + "testing" + "time" + + gnmipb "github.com/openconfig/gnmi/proto/gnmi" + spb "github.com/openconfig/gnoi/system" + authzpb "github.com/openconfig/gnsi/authz" + certzpb "github.com/openconfig/gnsi/certz" + gribipb "github.com/openconfig/gribi/v1/proto/service" + "github.com/openconfig/ondatra" + "github.com/openconfig/ondatra/gnmi" + "github.com/openconfig/ondatra/knebind/creds" + p4rtpb "github.com/p4lang/p4runtime/go/p4/v1" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/credentials" + "google.golang.org/grpc/status" +) + +var ( + username = "certzuser" + password = "certzpasswd" + sn = "role001.pop55.net.example.com" + servers []string +) + +type rpcCredentials struct { + *creds.UserPass +} + +func (r *rpcCredentials) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) { + return map[string]string{ + "username": r.UserPass.Username, + "password": r.UserPass.Password, + }, nil +} + +func (r *rpcCredentials) RequireTransportSecurity() bool { + return true +} + +type entityType int8 + +const ( + // EntityTypeCertificateChain is type of entity of the certificate chain. + EntityTypeCertificateChain entityType = 0 + // EntityTypeTrustBundle is type of entity of the trust bundle. + EntityTypeTrustBundle entityType = 1 + // EntityTypeCRL is type of entity of the CRL. + EntityTypeCRL entityType = 2 + // EntityTypeAuthPolicy is type of entity of the auth policy. + EntityTypeAuthPolicy entityType = 3 +) + +// CertificateChainRequest is an input argument for the type definition for the CreateCertzChain. +type CertificateChainRequest struct { + RequestType entityType + ServerCertFile string + ServerKeyFile string + TrustBundleFile string +} + +// CreateCertzEntity function to create certificate entity of type certificate chain/trust bundle/CRL/Authpolicy. +func CreateCertzEntity(t *testing.T, typeOfEntity entityType, entityContent any, entityVersion string) certzpb.Entity { + + createdOnTime := time.Now() + varClock := uint64(createdOnTime.Unix()) + + switch typeOfEntity { + case EntityTypeCertificateChain: + + return certzpb.Entity{ + Version: entityVersion, + CreatedOn: varClock, + Entity: &certzpb.Entity_CertificateChain{CertificateChain: entityContent.(*certzpb.CertificateChain)}} + + case EntityTypeTrustBundle: + + return certzpb.Entity{ + Version: entityVersion, + CreatedOn: varClock, + Entity: &certzpb.Entity_TrustBundle{TrustBundle: entityContent.(*certzpb.CertificateChain)}} + + case EntityTypeCRL: + + return certzpb.Entity{ + Version: entityVersion, + CreatedOn: varClock, + Entity: &certzpb.Entity_CertificateRevocationListBundle{CertificateRevocationListBundle: entityContent.(*certzpb.CertificateRevocationListBundle)}} + + case EntityTypeAuthPolicy: + + return certzpb.Entity{ + Version: entityVersion, + CreatedOn: varClock, + Entity: &certzpb.Entity_AuthenticationPolicy{AuthenticationPolicy: entityContent.(*certzpb.AuthenticationPolicy)}} + + default: + t.Fatalf("Invalid entity type") + } + return certzpb.Entity{} +} + +// CreateCertzChain function to get the certificate chain of type certificate chain/trust bundle. +func CreateCertzChain(t *testing.T, certData CertificateChainRequest) certzpb.CertificateChain { + + switch certData.RequestType { + case EntityTypeCertificateChain: + if len(certData.ServerCertFile) == 0 { + t.Fatalf("Missing server certificate file for creating certificate chain object.") + } + serverCertContent, err := os.ReadFile(certData.ServerCertFile) + if err != nil { + t.Fatalf("Error reading Server Certificate file at: %v with error: %v", certData.ServerCertFile, err) + + } + if len(certData.ServerKeyFile) != 0 { + serverKeyContent, err := os.ReadFile(certData.ServerKeyFile) + if err != nil { + t.Fatalf("Error reading Server Key file at: %v with error: %v", certData.ServerKeyFile, err) + } + return certzpb.CertificateChain{Certificate: &certzpb.Certificate{ + Type: certzpb.CertificateType_CERTIFICATE_TYPE_X509, + Encoding: certzpb.CertificateEncoding_CERTIFICATE_ENCODING_PEM, + Certificate: serverCertContent, + PrivateKey: serverKeyContent}, Parent: nil} + } + return certzpb.CertificateChain{Certificate: &certzpb.Certificate{ + Type: certzpb.CertificateType_CERTIFICATE_TYPE_X509, + Encoding: certzpb.CertificateEncoding_CERTIFICATE_ENCODING_PEM, + Certificate: serverCertContent, + PrivateKey: nil}, Parent: nil} + + case EntityTypeTrustBundle: + if len(certData.TrustBundleFile) == 0 { + t.Fatalf("Missing trust bundle file for creating certificate chain object.") + } + trustBundleContent, err := os.ReadFile(certData.TrustBundleFile) + if err != nil { + t.Fatalf("Error reading trust bundle file at: %v with error: %v", certData.TrustBundleFile, err) + } + return certzpb.CertificateChain{Certificate: &certzpb.Certificate{ + Type: certzpb.CertificateType_CERTIFICATE_TYPE_X509, + Encoding: certzpb.CertificateEncoding_CERTIFICATE_ENCODING_PEM, + Certificate: trustBundleContent, + }, Parent: nil} + + default: + t.Fatalf("Invalid request type received.") + } + return certzpb.CertificateChain{} +} + +// CreateCertChainFromTrustBundle function to create the certificate chain from trust bundle. +func CreateCertChainFromTrustBundle(fileName string) *certzpb.CertificateChain { + pemData, err := os.ReadFile(fileName) + if err != nil { + return &certzpb.CertificateChain{} + } + var trust [][]byte + for { + var block *pem.Block + block, pemData = pem.Decode(pemData) + if block == nil { + break + } + if block.Type != "CERTIFICATE" { + continue + } + p := pem.EncodeToMemory(block) + if p == nil { + return &certzpb.CertificateChain{} + } + trust = append(trust, p) + } + //a valid check for trust not empty + if len(trust) == 0 { + return &certzpb.CertificateChain{} + } else { + var prevCert *certzpb.CertificateChain + var bundleToReturn *certzpb.CertificateChain + for i := len(trust) - 1; i >= 0; i-- { + if i == len(trust)-1 { + bundleToReturn = &certzpb.CertificateChain{Certificate: &certzpb.Certificate{ + Type: certzpb.CertificateType_CERTIFICATE_TYPE_X509, + Encoding: certzpb.CertificateEncoding_CERTIFICATE_ENCODING_PEM, + Certificate: trust[i], + }, Parent: nil} + prevCert = bundleToReturn + } else { + prevCert = bundleToReturn + bundleToReturn = &certzpb.CertificateChain{Certificate: &certzpb.Certificate{ + Type: certzpb.CertificateType_CERTIFICATE_TYPE_X509, + Encoding: certzpb.CertificateEncoding_CERTIFICATE_ENCODING_PEM, + Certificate: trust[i], + }, Parent: prevCert} + } + } + return bundleToReturn + } +} + +// CertzRotate function to request the client certificate rotation and returns true on successful rotation. +func CertzRotate(t *testing.T, caCert *x509.CertPool, certzClient certzpb.CertzClient, cert tls.Certificate, san, serverAddr, profileID string, entities ...*certzpb.Entity) bool { + ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) + defer cancel() + if len(entities) == 0 { + t.Logf("At least one entity required for Rotate request.") + return false + } + uploadRequest := &certzpb.UploadRequest{Entities: entities} + rotateRequest := &certzpb.RotateCertificateRequest_Certificates{Certificates: uploadRequest} + rotateCertRequest := &certzpb.RotateCertificateRequest{ + ForceOverwrite: false, + SslProfileId: profileID, + RotateRequest: rotateRequest} + rotateRequestClient, err := certzClient.Rotate(ctx) + defer rotateRequestClient.CloseSend() + if err != nil { + t.Fatalf("Error creating rotate request client: %v", err) + } + err = rotateRequestClient.Send(rotateCertRequest) + if err != nil { + t.Fatalf("Error sending rotate request: %v", err) + } + rotateResponse := &certzpb.RotateCertificateResponse{} + for i := 0; i < 6; i++ { + rotateResponse, err = rotateRequestClient.Recv() + if err == nil { + break + } + t.Logf("Did not receive response ~ %vs after sending rotate request. Sleeping 10s to retry...", i*10) + time.Sleep(10 * time.Second) + } + if err != nil { + t.Logf("Error fetching rotate certificate response: %v", err) + return false + } + t.Logf("Received Rotate certificate response: %v", rotateResponse) + + finalizeRequest := &certzpb.RotateCertificateRequest_FinalizeRotation{FinalizeRotation: &certzpb.FinalizeRequest{}} + rotateCertRequest = &certzpb.RotateCertificateRequest{ + ForceOverwrite: false, + SslProfileId: profileID, + RotateRequest: finalizeRequest} + + err = rotateRequestClient.Send(rotateCertRequest) + if err != nil { + t.Fatalf("Error sending rotate finalize request: %v", err) + } + err = rotateRequestClient.CloseSend() + if err != nil { + t.Fatalf("Error sending rotate close send request: %v", err) + } + return true +} + +// ServerCertzRotate function to request the server certificate rotation and returns true on successful rotation. +func ServerCertzRotate(t *testing.T, caCert *x509.CertPool, certzClient certzpb.CertzClient, cert tls.Certificate, ctx context.Context, dut *ondatra.DUTDevice, san, serverAddr, profileID string, entities ...*certzpb.Entity) bool { + if len(entities) == 0 { + t.Logf("At least one entity required for Rotate request.") + return false + } + uploadRequest := &certzpb.UploadRequest{Entities: entities} + rotateRequest := &certzpb.RotateCertificateRequest_Certificates{Certificates: uploadRequest} + rotateCertRequest := &certzpb.RotateCertificateRequest{ + ForceOverwrite: false, + SslProfileId: profileID, + RotateRequest: rotateRequest} + rotateRequestClient, err := certzClient.Rotate(context.Background()) + defer rotateRequestClient.CloseSend() + if err != nil { + t.Fatalf("Error creating rotate request client: %v", err) + } + err = rotateRequestClient.Send(rotateCertRequest) + if err != nil { + t.Fatalf("Error sending rotate request: %v", err) + } + rotateResponse := &certzpb.RotateCertificateResponse{} + for i := 0; i < 6; i++ { + rotateResponse, err = rotateRequestClient.Recv() + if err == nil { + break + } + t.Logf("Did not receive response ~ %vs after sending rotate request. Sleeping 10s to retry...", i*10) + time.Sleep(10 * time.Second) + } + if err != nil { + t.Logf("Error fetching rotate certificate response: %v", err) + return false + } + t.Logf("Received Rotate certificate response: %v", rotateResponse) + + // Replace config with newly added ssl profile after successful rotate. + servers = gnmi.GetAll(t, dut, gnmi.OC().System().GrpcServerAny().Name().State()) + batch := gnmi.SetBatch{} + for _, server := range servers { + gnmi.BatchReplace(&batch, gnmi.OC().System().GrpcServer(server).CertificateId().Config(), profileID) + } + batch.Set(t, dut) + t.Logf("gNMI config is replaced with new ssl profile successfully.") + success := false + //Trying for 60s for the connection to succeed. + for i := 0; i < 6; i++ { + success = VerifyGnsi(t, caCert, san, serverAddr, username, password, cert) + if success { + break + } + if i != 10 { + t.Logf("gNSI service RPC did not succeed ~ %vs after rotate. Sleeping 10s to retry...", i*10) + } + time.Sleep(10 * time.Second) + } + if success { + finalizeRequest := &certzpb.RotateCertificateRequest_FinalizeRotation{FinalizeRotation: &certzpb.FinalizeRequest{}} + rotateCertRequest = &certzpb.RotateCertificateRequest{ + ForceOverwrite: false, + SslProfileId: profileID, + RotateRequest: finalizeRequest} + + err = rotateRequestClient.Send(rotateCertRequest) + if err != nil { + t.Fatalf("Error sending rotate finalize request: %v", err) + } + err = rotateRequestClient.CloseSend() + if err != nil { + t.Fatalf("Error sending rotate close send request: %v", err) + } + return true + } else { + t.Logf("gNSI service RPC did not succeed ~60s after rotate. Certz/Rotate failed. FinalizeRequest will not be sent") + return false + } +} + +// CertGeneration function to create test data for use in TLS tests. +func CertGeneration(t *testing.T, dirPath string) error { + cmd := exec.Cmd{ + Path: "./mk_cas.sh", + Stdout: os.Stdout, + Stderr: os.Stderr, + } + cmd.Dir = dirPath + t.Logf("Executing cert generation command %v.", cmd) + err := cmd.Start() + if err != nil { + t.Logf("Cert generation command failed with error:%v.", err) + return err + } + err = cmd.Wait() + if err != nil { + t.Logf("Failed to run cert generation command during wait with error:%v.", err) + return err + } + return err +} + +// CertCleanup function to clean out the certificate content under test_data. +func CertCleanup(t *testing.T, dirPath string) error { + cmd := exec.Cmd{ + Path: "./cleanup.sh", + Stdout: os.Stdout, + Stderr: os.Stderr, + } + cmd.Dir = dirPath + t.Logf("Executing cleanup command") + err := cmd.Start() + if err != nil { + t.Logf("Testdata cleanup command failed with error:%v.", err) + return err + } + err = cmd.Wait() + if err != nil { + t.Logf("Testdata cleanup command failed during wait with the error:%v.", err) + return err + } + return err +} + +// ReadDecodeServerCertificate function to read and decode server certificates to extract the SubjectAltName and validate. +func ReadDecodeServerCertificate(t *testing.T, serverCertzFile string) (san string) { + sc, err := os.ReadFile(serverCertzFile) + if err != nil { + t.Fatalf("Failed to read certificate with error: %v.", err) + } + block, _ := pem.Decode(sc) + if block == nil { + t.Fatalf("Failed to parse PEM block containing the public key.") + } + sCert, err := x509.ParseCertificate(block.Bytes) + if err != nil { + t.Fatalf("Failed to parse certificate with error: %v.", err) + } + san = sCert.DNSNames[0] + t.Logf("ServerAltName:%s.", san) + if sn != san { + t.Fatalf("ServerAltName validation failed for %s.", serverCertzFile) + } + return san +} + +// VerifyGnsi function to validate the gNSI service RPC after successful rotation. +func VerifyGnsi(t *testing.T, caCert *x509.CertPool, san, serverAddr, username, password string, cert tls.Certificate) bool { + credOpts := []grpc.DialOption{grpc.WithBlock(), grpc.WithTransportCredentials(credentials.NewTLS( + &tls.Config{ + Certificates: []tls.Certificate{cert}, + RootCAs: caCert, + ServerName: san, + }))} + creds := &rpcCredentials{&creds.UserPass{Username: username, Password: password}} + credOpts = append(credOpts, grpc.WithPerRPCCredentials(creds)) + target := fmt.Sprintf("%s:%d", serverAddr, 9339) + ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) + defer cancel() + conn, err := grpc.NewClient(target, credOpts...) + if err != nil { + t.Errorf("%sVerifyGnsi:gRPC NewClient failed to %q with err %v", time.Now().String(), target, err) + return false + } + t.Logf("Connection state: %v.", conn.GetState().String()) + defer conn.Close() + authzClient := authzpb.NewAuthzClient(conn) + rsp, err := authzClient.Get(ctx, &authzpb.GetRequest{}) + if err != nil { + statusError, _ := status.FromError(err) + if statusError.Code() == codes.FailedPrecondition { + t.Logf("Expected error FAILED_PRECONDITION seen for authz Get Request with err:%v.", err) + } else { + t.Logf("Unexpected error during authz Get Request with err:%v.", err) + return false + } + } + t.Logf("gNSI authz get response is %s", rsp) + conn.Close() + return true +} + +// VerifyGnoi function to validate the gNOI service RPC after successful rotation. +func VerifyGnoi(t *testing.T, caCert *x509.CertPool, san, serverAddr, username, password string, cert tls.Certificate) bool { + credOpts := []grpc.DialOption{grpc.WithBlock(), grpc.WithTransportCredentials(credentials.NewTLS( + &tls.Config{ + Certificates: []tls.Certificate{cert}, + RootCAs: caCert, + ServerName: san, + }))} + creds := &rpcCredentials{&creds.UserPass{Username: username, Password: password}} + credOpts = append(credOpts, grpc.WithPerRPCCredentials(creds)) + target := fmt.Sprintf("%s:%d", serverAddr, 9339) + ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) + defer cancel() + conn, err := grpc.NewClient(target, credOpts...) + if err != nil { + t.Errorf("VerifyGnoi : gRPC NewClient failed to %q with err %v", target, err) + return false + } + defer conn.Close() + sysClient := spb.NewSystemClient(conn) + _, err = sysClient.Ping(ctx, &spb.PingRequest{}) + if err != nil { + t.Logf("Unable to connect gnoiClient %v", err) + return false + } + conn.Close() + return true +} + +// VerifyGnmi function to validate the gNMI service RPC after successful rotation. +func VerifyGnmi(t *testing.T, caCert *x509.CertPool, san, serverAddr, username, password string, cert tls.Certificate) bool { + credOpts := []grpc.DialOption{grpc.WithBlock(), grpc.WithTransportCredentials(credentials.NewTLS( + &tls.Config{ + Certificates: []tls.Certificate{cert}, + RootCAs: caCert, + ServerName: san, + }))} + creds := &rpcCredentials{&creds.UserPass{Username: username, Password: password}} + credOpts = append(credOpts, grpc.WithPerRPCCredentials(creds)) + target := fmt.Sprintf("%s:%d", serverAddr, 9339) + ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) + defer cancel() + conn, err := grpc.NewClient(target, credOpts...) + if err != nil { + t.Errorf("VerifyGnmi: gRPC NewClient failed to %q with err %v", target, err) + return false + } + defer conn.Close() + gnmiClient := gnmipb.NewGNMIClient(conn) + t.Logf("%s:Sending gNMI Capability request.", time.Now().String()) + response, err := gnmiClient.Capabilities(ctx, &gnmipb.CapabilityRequest{}) + if err != nil { + t.Logf("gNMI Capability request failed with err: %v", err) + return false + } + t.Logf("VerifyGnmi:gNMI response: %s", response.GNMIVersion) + conn.Close() + return true +} + +// VerifyGribi function to validate the gRIBI service RPC after successful rotation. +func VerifyGribi(t *testing.T, caCert *x509.CertPool, san, serverAddr, username, password string, cert tls.Certificate) bool { + credOpts := []grpc.DialOption{grpc.WithBlock(), grpc.WithTransportCredentials(credentials.NewTLS( + &tls.Config{ + Certificates: []tls.Certificate{cert}, + RootCAs: caCert, + ServerName: san, + }))} + creds := &rpcCredentials{&creds.UserPass{Username: username, Password: password}} + credOpts = append(credOpts, grpc.WithPerRPCCredentials(creds)) + target := fmt.Sprintf("%s:%d", serverAddr, 9340) + ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) + defer cancel() + conn, err := grpc.NewClient(target, credOpts...) + if err != nil { + t.Errorf("VerifyGribi: gRPC NewClient failed to %q with error:%v", target, err) + return false + } + defer conn.Close() + gRibiClient := gribipb.NewGRIBIClient(conn) + _, err = gRibiClient.Get(ctx, &gribipb.GetRequest{}) + if err != nil { + t.Logf("Failed to connect GribiClient with error:%v.", err) + return false + } + conn.Close() + return true +} + +// VerifyP4rt function to validate the P4rt service RPC after successful rotation. +func VerifyP4rt(t *testing.T, caCert *x509.CertPool, san, serverAddr, username, password string, cert tls.Certificate) bool { + credOpts := []grpc.DialOption{grpc.WithBlock(), grpc.WithTransportCredentials(credentials.NewTLS( + &tls.Config{ + Certificates: []tls.Certificate{cert}, + RootCAs: caCert, + ServerName: san, + }))} + creds := &rpcCredentials{&creds.UserPass{Username: username, Password: password}} + credOpts = append(credOpts, grpc.WithPerRPCCredentials(creds)) + target := fmt.Sprintf("%s:%d", serverAddr, 9559) + ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) + defer cancel() + conn, err := grpc.NewClient(target, credOpts...) + if err != nil { + t.Errorf("VerifyP4rt : gRPC NewClient failed to %q with error %v.", target, err) + } + defer conn.Close() + p4RtClient := p4rtpb.NewP4RuntimeClient(conn) + _, err = p4RtClient.Capabilities(ctx, &p4rtpb.CapabilitiesRequest{}) + if err != nil { + t.Logf("Failed to connect P4rtClient with error %v.", err) + return false + } + conn.Close() + return true +} + +// PreInitCheck function to dial gNMI/gNOI/gRIBI/p4RT services before certz rotation. +func PreInitCheck(ctx context.Context, t *testing.T, dut *ondatra.DUTDevice) bool { + + gnmiC, err := dut.RawAPIs().BindingDUT().DialGNMI(ctx) + if err != nil { + t.Fatalf("%s Failed to dial gNMI Connection with error: %v.", time.Now().String(), err) + } + t.Logf("Precheck:gNMI dial is successful %v", gnmiC) + gribiC, err := dut.RawAPIs().BindingDUT().DialGRIBI(ctx) + if err != nil { + t.Fatalf("%s Failed to dial gRIBI Connection with error: %v.", time.Now().String(), err) + } + t.Logf("Precheck:gRIBI dial is successful %v", gribiC) + gnoiC, err := dut.RawAPIs().BindingDUT().DialGNOI(ctx) + if err != nil { + t.Fatalf("%s Failed to dial gNOI Connection with error: %v.", time.Now().String(), err) + } + t.Logf("Precheck:gNOI dial is successful %v", gnoiC) + p4rtC, err := dut.RawAPIs().BindingDUT().DialP4RT(ctx) + if err != nil { + t.Fatalf("%s Failed to dial p4RT Connection with error: %v.", time.Now().String(), err) + } + t.Logf("Precheck:p4RT dial is successful %v", p4rtC) + return true +} + +// GetSslProfilelist function to fetch the existing ssl profiles on the device. +func GetSslProfilelist(ctx context.Context, t *testing.T, certzClient certzpb.CertzClient, certzGetReq *certzpb.GetProfileListRequest) { + getProfileResponse, err := certzClient.GetProfileList(ctx, certzGetReq) + if err != nil { + t.Fatalf("Get profile list request failed with %v!", err) + } + t.Logf("GetProfileResponse: %v", getProfileResponse) +} + +// PostValidationCheck function to do a validation of all services after certz rotation. +func PostValidationCheck(t *testing.T, caCert *x509.CertPool, expected_result bool, san, serverAddr, username, password string, cert tls.Certificate) bool { + t.Logf("%s:Verifying New gNSI connection.", time.Now().String()) + result := VerifyGnsi(t, caCert, san, serverAddr, username, password, cert) + if expected_result != result { + t.Fatalf("Failed with new gNSI Connection: got %v, want %v.", result, expected_result) + } + t.Logf("%s:Verifying New gNOI connection.", time.Now().String()) + result = VerifyGnoi(t, caCert, san, serverAddr, username, password, cert) + if expected_result != result { + t.Fatalf("Failed with new gNOI Connection: got false, want %v", expected_result) + } + t.Logf("%s:Verifying New gRIBI connection.", time.Now().String()) + if expected_result != VerifyGribi(t, caCert, san, serverAddr, username, password, cert) { + t.Fatalf("Failed with new gRIBI Connection: got false, want %v.", expected_result) + } + t.Logf("%s:Verifying New P4rt connection.", time.Now().String()) + if expected_result != VerifyP4rt(t, caCert, san, serverAddr, username, password, cert) { + t.Fatalf("Failed with new P4rt Connection: got false, want %v.", expected_result) + } + t.Logf("%s:Verifying New gNMI connection.", time.Now().String()) + if expected_result != VerifyGnmi(t, caCert, san, serverAddr, username, password, cert) { + t.Fatalf("Failed with new gNMI Connection: got false, want %v.", expected_result) + } + return true +} diff --git a/feature/security/gnsi/certz/tests/trust_bundle/README.md b/feature/security/gnsi/certz/tests/trust_bundle/README.md new file mode 100644 index 00000000000..1ff727de2af --- /dev/null +++ b/feature/security/gnsi/certz/tests/trust_bundle/README.md @@ -0,0 +1,88 @@ +# Trust Bundle + +## Summary + +Server and client TLS endpoints use x.509 certificates for +identification of the calling or called endpoint. Systems +could use self-signed certificates and not validate, but +this is an insecure practice. + +Servers and clients should require that the certificates +used are validated and are signed by a known Certificate +Authority(CA). + +The known CAs which can be used are contained in a +'trust bundle', which is a list of public keys of the CAs. +The list of CA public keys must be kept up to date, as +CAs will rotate their key material on a regular cadence. + +CA keys may be one of two valid (at this time) key algorithms: + + * RSA + * ECDSA + +(Note: Security of key algorithms is subject to change, the +system must be able to support more than one key type at any +point in time in order to support key algorithm change events.) + +A trust bundle may have one or more certificates contained in +it, systems should be able to support at least one thousand +CA keys in such a bundle. + + +## Baseline Setup + +### Input Args + + * the set of certificate testdata generated with the mk_cas.sh + script in the featureprofiles/feature/security/gnsi/certz/test_data + directory. + +### DUT service setup + +Configure the DUT to enable the following sevices (that are using gRPC) are +up and require using mTLS for authentication: + + * gNMI + * gNOI + * gNSI + * gRIBI + * P4RT + +For each trust_bundle created by mk_cas.sh, configure the +services to load the correct key-type certificate, key and +trust_bundle. + +## Tests + +### Test Certz-4.1 + +Load the server certificate and key from each of the following CA sets: + * ca-01 + * ca-02 + * ca-10 + * ca-1000 + +Each service must be configured to use the appropriate certificate and validate +that certificate using the included trust_bundle. + +Perform this test with both RSA dn ECDSA key-types. + +## OpenConfig Path and RPC Coverage + +The below yaml defines the OC paths intended to be covered by this test. OC paths used for test setup are not listed here. + +TODO(OCRPC): Record may not be correct or complete + +```yaml +rpcs: + gnsi: + certz.v1.Certz.GetProfileList: + certz.v1.Certz.AddProfile: + certz.v1.Certz.Rotate: +``` + + +## Minimum DUT Platform Requirement + +vRX diff --git a/feature/security/gnsi/certz/tests/trust_bundle/trustbundle_test.go b/feature/security/gnsi/certz/tests/trust_bundle/trustbundle_test.go new file mode 100644 index 00000000000..8919b5b5c42 --- /dev/null +++ b/feature/security/gnsi/certz/tests/trust_bundle/trustbundle_test.go @@ -0,0 +1,235 @@ +// 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 trustbundle_test + +import ( + context "context" + "crypto/tls" + "crypto/x509" + "os" + "testing" + "time" + + setupService "github.com/openconfig/featureprofiles/feature/security/gnsi/certz/tests/internal/setup_service" + "github.com/openconfig/featureprofiles/internal/fptest" + "github.com/openconfig/ondatra" + "github.com/openconfig/ondatra/gnmi" + "github.com/openconfig/ondatra/gnmi/oc" + "github.com/openconfig/ygot/ygot" + + certzpb "github.com/openconfig/gnsi/certz" +) + +const ( + dirPath = "../../test_data/" +) + +var ( + testProfile = "newprofile" + serverAddr string + username = "certzuser" + password = "certzpasswd" + servers []string + expected_result bool +) + +// createUser function to add an user in admin role. +func createUser(t *testing.T, dut *ondatra.DUTDevice, user, pswd string) bool { + ocUser := &oc.System_Aaa_Authentication_User{ + Username: ygot.String(user), + Role: oc.AaaTypes_SYSTEM_DEFINED_ROLES_SYSTEM_ROLE_ADMIN, + Password: ygot.String(pswd), + } + res := gnmi.Update(t, dut, gnmi.OC().System().Aaa().Authentication().User(user).Config(), ocUser) + t.Logf("Update the user configuration:%v", res) + if res == nil { + t.Fatalf("Failed to create credentials.") + } + return true +} + +func TestMain(m *testing.M) { + fptest.RunTests(m) +} + +// TestTrustBundle tests the load of server certificate and key from each of the following CA sets +// ca-01/ca-02/ca-10/ca-1000 of both rsa and ecdsa keytype +func TestServerCert(t *testing.T) { + + dut := ondatra.DUT(t, "dut") + serverAddr = dut.Name() + if !createUser(t, dut, username, password) { + t.Fatalf("%s: Failed to create certz user.", time.Now().String()) + } + t.Logf("Validation of all services that are using gRPC before certz rotation.") + if !setupService.PreInitCheck(context.Background(), t, dut) { + t.Fatalf("%s: Failed in the preInit checks.", time.Now().String()) + } + ctx := context.Background() + gnsiC, err := dut.RawAPIs().BindingDUT().DialGNSI(ctx) + if err != nil { + t.Fatalf("%s: Failed to create gNSI Connection %v", time.Now().String(), err) + } + t.Logf("%s Precheck:gNSI connection is successful %v", time.Now().String(), gnsiC) + t.Logf("%s:Creation of test data.", time.Now().String()) + if setupService.CertGeneration(t, dirPath) != nil { + t.Fatalf("%s:Failed to generate the testdata certificates.", time.Now().String()) + } + certzClient := gnsiC.Certz() + t.Logf("%s Precheck:checking baseline ssl profile list.", time.Now().String()) + setupService.GetSslProfilelist(ctx, t, certzClient, &certzpb.GetProfileListRequest{}) + t.Logf("%s:Adding new empty ssl profile ID.", time.Now().String()) + addProfileResponse, err := certzClient.AddProfile(ctx, &certzpb.AddProfileRequest{SslProfileId: testProfile}) + if err != nil { + t.Fatalf("%s:Add profile request failed with %v! ", time.Now().String(), err) + } + t.Logf("%s AddProfileResponse: %v", time.Now().String(), addProfileResponse) + t.Logf("%s: Getting the ssl profile list after new ssl profile addition.", time.Now().String()) + setupService.GetSslProfilelist(ctx, t, certzClient, &certzpb.GetProfileListRequest{}) + cases := []struct { + desc string + serverCertFile string + serverKeyFile string + trustBundleFile string + clientCertFile string + clientKeyFile string + }{ + { + desc: "Certz4.1:Load trustbundle of rsa keytype with 1CA configuration", + serverCertFile: dirPath + "ca-01/server-rsa-a-cert.pem", + serverKeyFile: dirPath + "ca-01/server-rsa-a-key.pem", + trustBundleFile: dirPath + "ca-01/trust_bundle_01_rsa.pem", + clientCertFile: dirPath + "ca-01/client-rsa-a-cert.pem", + clientKeyFile: dirPath + "ca-01/client-rsa-a-key.pem", + }, + { + desc: "Certz4.1:Load trustbundle of rsa keytype with 2CA configuration", + serverCertFile: dirPath + "ca-02/server-rsa-a-cert.pem", + serverKeyFile: dirPath + "ca-02/server-rsa-a-key.pem", + trustBundleFile: dirPath + "ca-02/trust_bundle_02_rsa.pem", + clientCertFile: dirPath + "ca-02/client-rsa-a-cert.pem", + clientKeyFile: dirPath + "ca-02/client-rsa-a-key.pem", + }, + { + desc: "Certz4.1:Load trustbundle of rsa keytype with 10CA configuration", + serverCertFile: dirPath + "ca-10/server-rsa-a-cert.pem", + serverKeyFile: dirPath + "ca-10/server-rsa-a-key.pem", + trustBundleFile: dirPath + "ca-10/trust_bundle_10_rsa.pem", + clientCertFile: dirPath + "ca-10/client-rsa-a-cert.pem", + clientKeyFile: dirPath + "ca-10/client-rsa-a-key.pem", + }, + { + desc: "Certz4.1:Load server certificate of rsa keytype with 1000CA configuration", + serverCertFile: dirPath + "ca-1000/server-rsa-a-cert.pem", + serverKeyFile: dirPath + "ca-1000/server-rsa-a-key.pem", + trustBundleFile: dirPath + "ca-1000/trust_bundle_1000_rsa.pem", + clientCertFile: dirPath + "ca-1000/client-rsa-a-cert.pem", + clientKeyFile: dirPath + "ca-1000/client-rsa-a-key.pem", + }, + { + desc: "Certz4.1:Load trustbundle of ecdsa keytype with 1CA configuration", + serverCertFile: dirPath + "ca-01/server-ecdsa-a-cert.pem", + serverKeyFile: dirPath + "ca-01/server-ecdsa-a-key.pem", + trustBundleFile: dirPath + "ca-01/trust_bundle_01_ecdsa.pem", + clientCertFile: dirPath + "ca-01/client-ecdsa-a-cert.pem", + clientKeyFile: dirPath + "ca-01/client-ecdsa-a-key.pem", + }, + { + desc: "Certz4.1:Load trustbundle of ecdsa keytype with 2CA configuration", + serverCertFile: dirPath + "ca-02/server-ecdsa-a-cert.pem", + serverKeyFile: dirPath + "ca-02/server-ecdsa-a-key.pem", + trustBundleFile: dirPath + "ca-02/trust_bundle_02_ecdsa.pem", + clientCertFile: dirPath + "ca-02/client-ecdsa-a-cert.pem", + clientKeyFile: dirPath + "ca-02/client-ecdsa-a-key.pem", + }, + { + desc: "Certz4.1:Load trustbundle of ecdsa keytype with 10CA configuration", + serverCertFile: dirPath + "ca-10/server-ecdsa-a-cert.pem", + serverKeyFile: dirPath + "ca-10/server-ecdsa-a-key.pem", + trustBundleFile: dirPath + "ca-10/trust_bundle_10_ecdsa.pem", + clientCertFile: dirPath + "ca-10/client-ecdsa-a-cert.pem", + clientKeyFile: dirPath + "ca-10/client-ecdsa-a-key.pem", + }, + { + desc: "Certz4.1:Load trustbundle of ecdsa keytype with 1000CA configuration", + serverCertFile: dirPath + "ca-1000/server-ecdsa-a-cert.pem", + serverKeyFile: dirPath + "ca-1000/server-ecdsa-a-key.pem", + trustBundleFile: dirPath + "ca-1000/trust_bundle_1000_ecdsa.pem", + clientCertFile: dirPath + "ca-1000/client-ecdsa-a-cert.pem", + clientKeyFile: dirPath + "ca-1000/client-ecdsa-a-key.pem", + }, + } + + for _, tc := range cases { + t.Run(tc.desc, func(t *testing.T) { + + san := setupService.ReadDecodeServerCertificate(t, tc.serverCertFile) + serverCert := setupService.CreateCertzChain(t, setupService.CertificateChainRequest{ + RequestType: setupService.EntityTypeCertificateChain, + ServerCertFile: tc.serverCertFile, + ServerKeyFile: tc.serverKeyFile}) + serverCertEntity := setupService.CreateCertzEntity(t, setupService.EntityTypeCertificateChain, &serverCert, "servercert") + + trustCertChain := setupService.CreateCertChainFromTrustBundle(tc.trustBundleFile) + trustBundleEntity := setupService.CreateCertzEntity(t, setupService.EntityTypeTrustBundle, trustCertChain, "cabundle") + cert, err := tls.LoadX509KeyPair(tc.clientCertFile, tc.clientKeyFile) + if err != nil { + t.Fatalf("%s Failed to load client cert: %v", time.Now().String(), err) + } + cacert := x509.NewCertPool() + cacertBytes, err := os.ReadFile(tc.trustBundleFile) + if err != nil { + t.Fatalf("%s Failed to read ca bundle :%v", time.Now().String(), err) + } + if ok := cacert.AppendCertsFromPEM(cacertBytes); !ok { + t.Fatalf("%s Failed to parse %v", time.Now().String(), tc.trustBundleFile) + } + + certzClient := gnsiC.Certz() + success := setupService.CertzRotate(t, cacert, certzClient, cert, san, serverAddr, testProfile, &serverCertEntity, &trustBundleEntity) + if !success { + t.Fatalf("%s %s:Trustbundle rotation failed.", time.Now().String(), tc.desc) + } + t.Logf("%s %s:Trustbundle rotation completed!", time.Now().String(), tc.desc) + + // Replace config with newly added ssl profile after successful rotate. + servers = gnmi.GetAll(t, dut, gnmi.OC().System().GrpcServerAny().Name().State()) + batch := gnmi.SetBatch{} + for _, server := range servers { + gnmi.BatchReplace(&batch, gnmi.OC().System().GrpcServer(server).CertificateId().Config(), testProfile) + } + batch.Set(t, dut) + t.Logf("%s %s:replaced gNMI config with new ssl profile successfully.", time.Now().String(), tc.desc) + time.Sleep(5 * time.Second) //waiting 5s for gnmi config propagation + t.Logf("Service validation begins.") + + expected_result = true + t.Run("Verification of new connection after successful server certificate rotation", func(t *testing.T) { + result := setupService.PostValidationCheck(t, cacert, expected_result, san, serverAddr, username, password, cert) + if result != expected_result { + t.Fatalf("%s postTestcase service validation failed after successful rotate -got %v, want %v .", tc.desc, result, expected_result) + } + t.Logf("%s postTestcase service validation done after trustbundle rotation!", tc.desc) + t.Logf("PASS: %s successfully completed!", tc.desc) + }) + }) + } + t.Logf("Cleanup of test data.") + if setupService.CertCleanup(t, dirPath) != nil { + t.Fatalf("Failed to execute cert cleanup.") + } else { + t.Log("Testdata cleanup is over!") + } +} From bc42b9bcc1165520dca0d41333831f80d218125c Mon Sep 17 00:00:00 2001 From: priyacj Date: Thu, 1 Aug 2024 22:23:36 -0700 Subject: [PATCH 2/7] fixed the readme under tests --- feature/security/gnsi/certz/tests/trust_bundle/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/feature/security/gnsi/certz/tests/trust_bundle/README.md b/feature/security/gnsi/certz/tests/trust_bundle/README.md index 1ff727de2af..6e69de69783 100644 --- a/feature/security/gnsi/certz/tests/trust_bundle/README.md +++ b/feature/security/gnsi/certz/tests/trust_bundle/README.md @@ -1,4 +1,4 @@ -# Trust Bundle +## CERTZ-4: gNSI Trust Bundle ## Summary From c300c3fbf6acfc65be1da6e4ce6db8922397ed7c Mon Sep 17 00:00:00 2001 From: priyacj Date: Fri, 2 Aug 2024 08:09:52 -0700 Subject: [PATCH 3/7] fixed the metadata.textproto file --- .../gnsi/certz/tests/trust_bundle/metadata.textproto | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 feature/security/gnsi/certz/tests/trust_bundle/metadata.textproto diff --git a/feature/security/gnsi/certz/tests/trust_bundle/metadata.textproto b/feature/security/gnsi/certz/tests/trust_bundle/metadata.textproto new file mode 100644 index 00000000000..d35e4dc9e6a --- /dev/null +++ b/feature/security/gnsi/certz/tests/trust_bundle/metadata.textproto @@ -0,0 +1,7 @@ +# proto-file: github.com/openconfig/featureprofiles/proto/metadata.proto +# proto-message: Metadata + +uuid: "2d5f9729-f436-4750-9140-1f0beadf6206" +plan_id: "# CERTZ-4" +description: "gNSI Trust Bundle" +testbed: TESTBED_DUT_ATE_2LINKS From 329700604cbb8c5a6a604938c50c44707014ebf3 Mon Sep 17 00:00:00 2001 From: priyacj Date: Wed, 20 Nov 2024 12:20:39 -0800 Subject: [PATCH 4/7] fixed the deprecated functions of DialOption --- .../tests/internal/setup_service/setup_service.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/feature/security/gnsi/certz/tests/internal/setup_service/setup_service.go b/feature/security/gnsi/certz/tests/internal/setup_service/setup_service.go index 27aa5f3511a..a1e53c0a5df 100644 --- a/feature/security/gnsi/certz/tests/internal/setup_service/setup_service.go +++ b/feature/security/gnsi/certz/tests/internal/setup_service/setup_service.go @@ -429,7 +429,7 @@ func ReadDecodeServerCertificate(t *testing.T, serverCertzFile string) (san stri // VerifyGnsi function to validate the gNSI service RPC after successful rotation. func VerifyGnsi(t *testing.T, caCert *x509.CertPool, san, serverAddr, username, password string, cert tls.Certificate) bool { - credOpts := []grpc.DialOption{grpc.WithBlock(), grpc.WithTransportCredentials(credentials.NewTLS( + credOpts := []grpc.DialOption{grpc.WithTransportCredentials(credentials.NewTLS( &tls.Config{ Certificates: []tls.Certificate{cert}, RootCAs: caCert, @@ -465,7 +465,7 @@ func VerifyGnsi(t *testing.T, caCert *x509.CertPool, san, serverAddr, username, // VerifyGnoi function to validate the gNOI service RPC after successful rotation. func VerifyGnoi(t *testing.T, caCert *x509.CertPool, san, serverAddr, username, password string, cert tls.Certificate) bool { - credOpts := []grpc.DialOption{grpc.WithBlock(), grpc.WithTransportCredentials(credentials.NewTLS( + credOpts := []grpc.DialOption{grpc.WithTransportCredentials(credentials.NewTLS( &tls.Config{ Certificates: []tls.Certificate{cert}, RootCAs: caCert, @@ -494,7 +494,7 @@ func VerifyGnoi(t *testing.T, caCert *x509.CertPool, san, serverAddr, username, // VerifyGnmi function to validate the gNMI service RPC after successful rotation. func VerifyGnmi(t *testing.T, caCert *x509.CertPool, san, serverAddr, username, password string, cert tls.Certificate) bool { - credOpts := []grpc.DialOption{grpc.WithBlock(), grpc.WithTransportCredentials(credentials.NewTLS( + credOpts := []grpc.DialOption{grpc.WithTransportCredentials(credentials.NewTLS( &tls.Config{ Certificates: []tls.Certificate{cert}, RootCAs: caCert, @@ -525,12 +525,13 @@ func VerifyGnmi(t *testing.T, caCert *x509.CertPool, san, serverAddr, username, // VerifyGribi function to validate the gRIBI service RPC after successful rotation. func VerifyGribi(t *testing.T, caCert *x509.CertPool, san, serverAddr, username, password string, cert tls.Certificate) bool { - credOpts := []grpc.DialOption{grpc.WithBlock(), grpc.WithTransportCredentials(credentials.NewTLS( + credOpts := []grpc.DialOption{grpc.WithTransportCredentials(credentials.NewTLS( &tls.Config{ Certificates: []tls.Certificate{cert}, RootCAs: caCert, ServerName: san, }))} + creds := &rpcCredentials{&creds.UserPass{Username: username, Password: password}} credOpts = append(credOpts, grpc.WithPerRPCCredentials(creds)) target := fmt.Sprintf("%s:%d", serverAddr, 9340) @@ -554,7 +555,7 @@ func VerifyGribi(t *testing.T, caCert *x509.CertPool, san, serverAddr, username, // VerifyP4rt function to validate the P4rt service RPC after successful rotation. func VerifyP4rt(t *testing.T, caCert *x509.CertPool, san, serverAddr, username, password string, cert tls.Certificate) bool { - credOpts := []grpc.DialOption{grpc.WithBlock(), grpc.WithTransportCredentials(credentials.NewTLS( + credOpts := []grpc.DialOption{grpc.WithTransportCredentials(credentials.NewTLS( &tls.Config{ Certificates: []tls.Certificate{cert}, RootCAs: caCert, @@ -582,7 +583,6 @@ func VerifyP4rt(t *testing.T, caCert *x509.CertPool, san, serverAddr, username, // PreInitCheck function to dial gNMI/gNOI/gRIBI/p4RT services before certz rotation. func PreInitCheck(ctx context.Context, t *testing.T, dut *ondatra.DUTDevice) bool { - gnmiC, err := dut.RawAPIs().BindingDUT().DialGNMI(ctx) if err != nil { t.Fatalf("%s Failed to dial gNMI Connection with error: %v.", time.Now().String(), err) From bd4d696e07d0160e8b14f613fa2dfcdd9427e09d Mon Sep 17 00:00:00 2001 From: priyacj Date: Thu, 21 Nov 2024 14:09:33 -0800 Subject: [PATCH 5/7] modified trustbundle_test --- .../internal/setup_service/setup_service.go | 21 +++++++----- .../tests/trust_bundle/trustbundle_test.go | 34 +++++-------------- 2 files changed, 21 insertions(+), 34 deletions(-) diff --git a/feature/security/gnsi/certz/tests/internal/setup_service/setup_service.go b/feature/security/gnsi/certz/tests/internal/setup_service/setup_service.go index a1e53c0a5df..b530d2bd2e2 100644 --- a/feature/security/gnsi/certz/tests/internal/setup_service/setup_service.go +++ b/feature/security/gnsi/certz/tests/internal/setup_service/setup_service.go @@ -1,4 +1,4 @@ -// Copyright 2023 Google LLC +// Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -23,8 +23,6 @@ import ( "crypto/x509" "encoding/pem" "fmt" - - //"io" "os" "os/exec" "testing" @@ -50,6 +48,7 @@ var ( password = "certzpasswd" sn = "role001.pop55.net.example.com" servers []string + retries int ) type rpcCredentials struct { @@ -252,7 +251,8 @@ func CertzRotate(t *testing.T, caCert *x509.CertPool, certzClient certzpb.CertzC t.Fatalf("Error sending rotate request: %v", err) } rotateResponse := &certzpb.RotateCertificateResponse{} - for i := 0; i < 6; i++ { + retries = 6 + for i := 0; i < retries; i++ { rotateResponse, err = rotateRequestClient.Recv() if err == nil { break @@ -305,7 +305,8 @@ func ServerCertzRotate(t *testing.T, caCert *x509.CertPool, certzClient certzpb. t.Fatalf("Error sending rotate request: %v", err) } rotateResponse := &certzpb.RotateCertificateResponse{} - for i := 0; i < 6; i++ { + retries = 6 + for i := 0; i < retries; i++ { rotateResponse, err = rotateRequestClient.Recv() if err == nil { break @@ -323,13 +324,15 @@ func ServerCertzRotate(t *testing.T, caCert *x509.CertPool, certzClient certzpb. servers = gnmi.GetAll(t, dut, gnmi.OC().System().GrpcServerAny().Name().State()) batch := gnmi.SetBatch{} for _, server := range servers { + t.Logf("Server:%s", server) gnmi.BatchReplace(&batch, gnmi.OC().System().GrpcServer(server).CertificateId().Config(), profileID) } batch.Set(t, dut) - t.Logf("gNMI config is replaced with new ssl profile successfully.") + t.Logf("gNMI config is replaced with new ssl profile %s successfully.", profileID) + time.Sleep(30 * time.Second) //waiting 30s for gnmi config propagation success := false //Trying for 60s for the connection to succeed. - for i := 0; i < 6; i++ { + for i := 0; i < retries; i++ { success = VerifyGnsi(t, caCert, san, serverAddr, username, password, cert) if success { break @@ -356,7 +359,7 @@ func ServerCertzRotate(t *testing.T, caCert *x509.CertPool, certzClient certzpb. } return true } else { - t.Logf("gNSI service RPC did not succeed ~60s after rotate. Certz/Rotate failed. FinalizeRequest will not be sent") + t.Logf("gNSI service RPC did not succeed ~%ds after rotate. Certz/Rotate failed. FinalizeRequest will not be sent", retries) return false } } @@ -531,7 +534,6 @@ func VerifyGribi(t *testing.T, caCert *x509.CertPool, san, serverAddr, username, RootCAs: caCert, ServerName: san, }))} - creds := &rpcCredentials{&creds.UserPass{Username: username, Password: password}} credOpts = append(credOpts, grpc.WithPerRPCCredentials(creds)) target := fmt.Sprintf("%s:%d", serverAddr, 9340) @@ -583,6 +585,7 @@ func VerifyP4rt(t *testing.T, caCert *x509.CertPool, san, serverAddr, username, // PreInitCheck function to dial gNMI/gNOI/gRIBI/p4RT services before certz rotation. func PreInitCheck(ctx context.Context, t *testing.T, dut *ondatra.DUTDevice) bool { + gnmiC, err := dut.RawAPIs().BindingDUT().DialGNMI(ctx) if err != nil { t.Fatalf("%s Failed to dial gNMI Connection with error: %v.", time.Now().String(), err) diff --git a/feature/security/gnsi/certz/tests/trust_bundle/trustbundle_test.go b/feature/security/gnsi/certz/tests/trust_bundle/trustbundle_test.go index 8919b5b5c42..d7a9aee3d1b 100644 --- a/feature/security/gnsi/certz/tests/trust_bundle/trustbundle_test.go +++ b/feature/security/gnsi/certz/tests/trust_bundle/trustbundle_test.go @@ -1,4 +1,4 @@ -// Copyright 2023 Google LLC +// Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -21,15 +21,13 @@ import ( "os" "testing" "time" - setupService "github.com/openconfig/featureprofiles/feature/security/gnsi/certz/tests/internal/setup_service" "github.com/openconfig/featureprofiles/internal/fptest" + certzpb "github.com/openconfig/gnsi/certz" "github.com/openconfig/ondatra" "github.com/openconfig/ondatra/gnmi" "github.com/openconfig/ondatra/gnmi/oc" "github.com/openconfig/ygot/ygot" - - certzpb "github.com/openconfig/gnsi/certz" ) const ( @@ -37,11 +35,10 @@ const ( ) var ( - testProfile = "newprofile" - serverAddr string - username = "certzuser" - password = "certzpasswd" - servers []string + testProfile = "newprofile" + serverAddr string + username = "certzuser" + password = "certzpasswd" expected_result bool ) @@ -174,7 +171,6 @@ func TestServerCert(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { - san := setupService.ReadDecodeServerCertificate(t, tc.serverCertFile) serverCert := setupService.CreateCertzChain(t, setupService.CertificateChainRequest{ RequestType: setupService.EntityTypeCertificateChain, @@ -196,25 +192,13 @@ func TestServerCert(t *testing.T) { if ok := cacert.AppendCertsFromPEM(cacertBytes); !ok { t.Fatalf("%s Failed to parse %v", time.Now().String(), tc.trustBundleFile) } - - certzClient := gnsiC.Certz() - success := setupService.CertzRotate(t, cacert, certzClient, cert, san, serverAddr, testProfile, &serverCertEntity, &trustBundleEntity) + certzClient := gnsiC.Certz() + success := setupService.ServerCertzRotate(t, cacert, certzClient, cert, ctx, dut, san, serverAddr, testProfile, &serverCertEntity, &trustBundleEntity) if !success { t.Fatalf("%s %s:Trustbundle rotation failed.", time.Now().String(), tc.desc) } t.Logf("%s %s:Trustbundle rotation completed!", time.Now().String(), tc.desc) - - // Replace config with newly added ssl profile after successful rotate. - servers = gnmi.GetAll(t, dut, gnmi.OC().System().GrpcServerAny().Name().State()) - batch := gnmi.SetBatch{} - for _, server := range servers { - gnmi.BatchReplace(&batch, gnmi.OC().System().GrpcServer(server).CertificateId().Config(), testProfile) - } - batch.Set(t, dut) - t.Logf("%s %s:replaced gNMI config with new ssl profile successfully.", time.Now().String(), tc.desc) - time.Sleep(5 * time.Second) //waiting 5s for gnmi config propagation - t.Logf("Service validation begins.") - + t.Logf("%s %s:Service validation begins.",time.Now().String(), tc.desc) expected_result = true t.Run("Verification of new connection after successful server certificate rotation", func(t *testing.T) { result := setupService.PostValidationCheck(t, cacert, expected_result, san, serverAddr, username, password, cert) From 878802e8089d1851e9452cc355f1704b60523a2a Mon Sep 17 00:00:00 2001 From: priyacj Date: Mon, 25 Nov 2024 15:09:06 -0800 Subject: [PATCH 6/7] fixed the static error --- .../tests/trust_bundle/trustbundle_test.go | 17 ++-- .../gnsi/certz/trust_bundle/README.md | 87 ------------------- 2 files changed, 9 insertions(+), 95 deletions(-) delete mode 100644 feature/security/gnsi/certz/trust_bundle/README.md diff --git a/feature/security/gnsi/certz/tests/trust_bundle/trustbundle_test.go b/feature/security/gnsi/certz/tests/trust_bundle/trustbundle_test.go index d7a9aee3d1b..3cbbe579bd0 100644 --- a/feature/security/gnsi/certz/tests/trust_bundle/trustbundle_test.go +++ b/feature/security/gnsi/certz/tests/trust_bundle/trustbundle_test.go @@ -21,6 +21,7 @@ import ( "os" "testing" "time" + setupService "github.com/openconfig/featureprofiles/feature/security/gnsi/certz/tests/internal/setup_service" "github.com/openconfig/featureprofiles/internal/fptest" certzpb "github.com/openconfig/gnsi/certz" @@ -35,10 +36,10 @@ const ( ) var ( - testProfile = "newprofile" - serverAddr string - username = "certzuser" - password = "certzpasswd" + testProfile = "newprofile" + serverAddr string + username = "certzuser" + password = "certzpasswd" expected_result bool ) @@ -190,20 +191,20 @@ func TestServerCert(t *testing.T) { t.Fatalf("%s Failed to read ca bundle :%v", time.Now().String(), err) } if ok := cacert.AppendCertsFromPEM(cacertBytes); !ok { - t.Fatalf("%s Failed to parse %v", time.Now().String(), tc.trustBundleFile) + t.Fatalf("%s Failed to parse %s", time.Now().String(), tc.trustBundleFile) } - certzClient := gnsiC.Certz() + certzClient := gnsiC.Certz() success := setupService.ServerCertzRotate(t, cacert, certzClient, cert, ctx, dut, san, serverAddr, testProfile, &serverCertEntity, &trustBundleEntity) if !success { t.Fatalf("%s %s:Trustbundle rotation failed.", time.Now().String(), tc.desc) } t.Logf("%s %s:Trustbundle rotation completed!", time.Now().String(), tc.desc) - t.Logf("%s %s:Service validation begins.",time.Now().String(), tc.desc) + t.Logf("%s %s:Service validation begins.", time.Now().String(), tc.desc) expected_result = true t.Run("Verification of new connection after successful server certificate rotation", func(t *testing.T) { result := setupService.PostValidationCheck(t, cacert, expected_result, san, serverAddr, username, password, cert) if result != expected_result { - t.Fatalf("%s postTestcase service validation failed after successful rotate -got %v, want %v .", tc.desc, result, expected_result) + t.Fatalf("%s postTestcase service validation failed after successful rotate -got %t, want %t .", tc.desc, result, expected_result) } t.Logf("%s postTestcase service validation done after trustbundle rotation!", tc.desc) t.Logf("PASS: %s successfully completed!", tc.desc) diff --git a/feature/security/gnsi/certz/trust_bundle/README.md b/feature/security/gnsi/certz/trust_bundle/README.md deleted file mode 100644 index fbbee7d1e6d..00000000000 --- a/feature/security/gnsi/certz/trust_bundle/README.md +++ /dev/null @@ -1,87 +0,0 @@ -# Trust Bundle - -## Summary - -Server and client TLS endpoints use x.509 certificates for -identification of the calling or called endpoint. Systems -could use self-signed certificates and not validate, but -this is an insecure practice. - -Servers and clients should require that the certificates -used are validated and are signed by a known Certificate -Authority(CA). - -The known CAs which can be used are contained in a -'trust bundle', which is a list of public keys of the CAs. -The list of CA public keys must be kept up to date, as -CAs will rotate their key material on a regular cadence. - -CA keys may be one of two valid (at this time) key algorithms: - - * RSA - * ECDSA - -(Note: Security of key algorithms is subject to change, the -system must be able to support more than one key type at any -point in time in order to support key algorithm change events.) - -A trust bundle may have one or more certificates contained in -it, systems should be able to support at least one thousand -CA keys in such a bundle. - - -## Baseline Setup - -### Input Args - - * the set of certificate testdata generated with the mk_cas.sh - script in the featureprofiles/feature/security/gnsi/certz/test_data - directory. - -### DUT service setup - -Configure the DUT to enable the following sevices (that are using gRPC) are -up and require using mTLS for authentication: - - * gNMI - * gNOI - * gNSI - * gRIBI - * P4RT - -For each trust_bundle created by mk_cas.sh, configure the -services to load the correct key-type certificate, key and -trust_bundle. - -## Tests - -### Test Certz-4.1 - -Load the server certificate and key from each of the following CA sets: - * ca-01 - * ca-02 - * ca-10 - * ca-1000 - * ca-20000 - -Each service must be configured to use the appropriate certificate and validate -that certificate using the included trust_bundle. - -Perform this test with both RSA dn ECDSA key-types. - -## OpenConfig Path and RPC Coverage - -The below yaml defines the OC paths intended to be covered by this test. OC paths used for test setup are not listed here. - -TODO(OCRPC): Record may not be correct or complete - -```yaml -rpcs: - gnsi: - certz.v1.Certz.GetProfileList: -``` - - -## Minimum DUT Platform Requirement - -vRX From a59aae84dff2410d9e6857e60823248dbbc5a661 Mon Sep 17 00:00:00 2001 From: priyacj Date: Tue, 7 Jan 2025 13:56:04 -0800 Subject: [PATCH 7/7] certz4 f:ten care of the feedback comments --- .../internal/setup_service/setup_service.go | 258 ++++++++---------- .../tests/trust_bundle/trustbundle_test.go | 2 +- 2 files changed, 110 insertions(+), 150 deletions(-) diff --git a/feature/security/gnsi/certz/tests/internal/setup_service/setup_service.go b/feature/security/gnsi/certz/tests/internal/setup_service/setup_service.go index b530d2bd2e2..1aa16594f59 100644 --- a/feature/security/gnsi/certz/tests/internal/setup_service/setup_service.go +++ b/feature/security/gnsi/certz/tests/internal/setup_service/setup_service.go @@ -48,14 +48,13 @@ var ( password = "certzpasswd" sn = "role001.pop55.net.example.com" servers []string - retries int ) type rpcCredentials struct { *creds.UserPass } -func (r *rpcCredentials) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) { +func (r *rpcCredentials) GetRequestMetadata(_ context.Context, _ ...string) (map[string]string, error) { return map[string]string{ "username": r.UserPass.Username, "password": r.UserPass.Password, @@ -203,91 +202,81 @@ func CreateCertChainFromTrustBundle(fileName string) *certzpb.CertificateChain { //a valid check for trust not empty if len(trust) == 0 { return &certzpb.CertificateChain{} - } else { - var prevCert *certzpb.CertificateChain - var bundleToReturn *certzpb.CertificateChain - for i := len(trust) - 1; i >= 0; i-- { - if i == len(trust)-1 { - bundleToReturn = &certzpb.CertificateChain{Certificate: &certzpb.Certificate{ - Type: certzpb.CertificateType_CERTIFICATE_TYPE_X509, - Encoding: certzpb.CertificateEncoding_CERTIFICATE_ENCODING_PEM, - Certificate: trust[i], - }, Parent: nil} - prevCert = bundleToReturn - } else { - prevCert = bundleToReturn - bundleToReturn = &certzpb.CertificateChain{Certificate: &certzpb.Certificate{ - Type: certzpb.CertificateType_CERTIFICATE_TYPE_X509, - Encoding: certzpb.CertificateEncoding_CERTIFICATE_ENCODING_PEM, - Certificate: trust[i], - }, Parent: prevCert} - } + } + var prevCert *certzpb.CertificateChain + var bundleToReturn *certzpb.CertificateChain + for i := len(trust) - 1; i >= 0; i-- { + if i == len(trust)-1 { + bundleToReturn = &certzpb.CertificateChain{Certificate: &certzpb.Certificate{ + Type: certzpb.CertificateType_CERTIFICATE_TYPE_X509, + Encoding: certzpb.CertificateEncoding_CERTIFICATE_ENCODING_PEM, + Certificate: trust[i], + }, Parent: nil} + prevCert = bundleToReturn + } else { + prevCert = bundleToReturn + bundleToReturn = &certzpb.CertificateChain{Certificate: &certzpb.Certificate{ + Type: certzpb.CertificateType_CERTIFICATE_TYPE_X509, + Encoding: certzpb.CertificateEncoding_CERTIFICATE_ENCODING_PEM, + Certificate: trust[i], + }, Parent: prevCert} } - return bundleToReturn } + return bundleToReturn } -// CertzRotate function to request the client certificate rotation and returns true on successful rotation. -func CertzRotate(t *testing.T, caCert *x509.CertPool, certzClient certzpb.CertzClient, cert tls.Certificate, san, serverAddr, profileID string, entities ...*certzpb.Entity) bool { - ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) - defer cancel() - if len(entities) == 0 { - t.Logf("At least one entity required for Rotate request.") - return false - } - uploadRequest := &certzpb.UploadRequest{Entities: entities} - rotateRequest := &certzpb.RotateCertificateRequest_Certificates{Certificates: uploadRequest} - rotateCertRequest := &certzpb.RotateCertificateRequest{ - ForceOverwrite: false, - SslProfileId: profileID, - RotateRequest: rotateRequest} - rotateRequestClient, err := certzClient.Rotate(ctx) - defer rotateRequestClient.CloseSend() - if err != nil { - t.Fatalf("Error creating rotate request client: %v", err) - } - err = rotateRequestClient.Send(rotateCertRequest) +// CreateCertChainFromp7bTrustBundle function to create the trust bundle encoded in pkcs7. +func CreateCertChainFromp7bTrustBundle(fileName string) *certzpb.CertificateChain { + pemData, err := os.ReadFile(fileName) if err != nil { - t.Fatalf("Error sending rotate request: %v", err) + return &certzpb.CertificateChain{} } - rotateResponse := &certzpb.RotateCertificateResponse{} - retries = 6 - for i := 0; i < retries; i++ { - rotateResponse, err = rotateRequestClient.Recv() - if err == nil { + var trust [][]byte + for { + var block *pem.Block + block, pemData = pem.Decode(pemData) + if block == nil { break } - t.Logf("Did not receive response ~ %vs after sending rotate request. Sleeping 10s to retry...", i*10) - time.Sleep(10 * time.Second) - } - if err != nil { - t.Logf("Error fetching rotate certificate response: %v", err) - return false + if block.Type != "CERTIFICATE" { + continue + } + p := pem.EncodeToMemory(block) + if p == nil { + return &certzpb.CertificateChain{} + } + trust = append(trust, p) } - t.Logf("Received Rotate certificate response: %v", rotateResponse) - - finalizeRequest := &certzpb.RotateCertificateRequest_FinalizeRotation{FinalizeRotation: &certzpb.FinalizeRequest{}} - rotateCertRequest = &certzpb.RotateCertificateRequest{ - ForceOverwrite: false, - SslProfileId: profileID, - RotateRequest: finalizeRequest} - - err = rotateRequestClient.Send(rotateCertRequest) - if err != nil { - t.Fatalf("Error sending rotate finalize request: %v", err) + //a valid check for trust not empty + if len(trust) == 0 { + return &certzpb.CertificateChain{} } - err = rotateRequestClient.CloseSend() - if err != nil { - t.Fatalf("Error sending rotate close send request: %v", err) + var prevCert *certzpb.CertificateChain + var bundleToReturn *certzpb.CertificateChain + for i := len(trust) - 1; i >= 0; i-- { + if i == len(trust)-1 { + bundleToReturn = &certzpb.CertificateChain{Certificate: &certzpb.Certificate{ + Type: certzpb.CertificateType_CERTIFICATE_TYPE_X509, + Encoding: certzpb.CertificateEncoding_CERTIFICATE_ENCODING_PEM, + Certificate: trust[i], + }, Parent: nil} + prevCert = bundleToReturn + } else { + prevCert = bundleToReturn + bundleToReturn = &certzpb.CertificateChain{Certificate: &certzpb.Certificate{ + Type: certzpb.CertificateType_CERTIFICATE_TYPE_X509, + Encoding: certzpb.CertificateEncoding_CERTIFICATE_ENCODING_PEM, + Certificate: trust[i], + }, Parent: prevCert} + } } - return true + return bundleToReturn } -// ServerCertzRotate function to request the server certificate rotation and returns true on successful rotation. -func ServerCertzRotate(t *testing.T, caCert *x509.CertPool, certzClient certzpb.CertzClient, cert tls.Certificate, ctx context.Context, dut *ondatra.DUTDevice, san, serverAddr, profileID string, entities ...*certzpb.Entity) bool { +// CertzRotate function to request the server certificate rotation and returns true on successful rotation. +func CertzRotate(_ context.Context, t *testing.T, caCert *x509.CertPool, certzClient certzpb.CertzClient, cert tls.Certificate, dut *ondatra.DUTDevice, san, serverAddr, profileID string, entities ...*certzpb.Entity) bool { if len(entities) == 0 { - t.Logf("At least one entity required for Rotate request.") - return false + t.Fatalf("At least one entity required for Rotate request.") } uploadRequest := &certzpb.UploadRequest{Entities: entities} rotateRequest := &certzpb.RotateCertificateRequest_Certificates{Certificates: uploadRequest} @@ -300,23 +289,20 @@ func ServerCertzRotate(t *testing.T, caCert *x509.CertPool, certzClient certzpb. if err != nil { t.Fatalf("Error creating rotate request client: %v", err) } - err = rotateRequestClient.Send(rotateCertRequest) - if err != nil { + if err := rotateRequestClient.Send(rotateCertRequest); err != nil { t.Fatalf("Error sending rotate request: %v", err) } rotateResponse := &certzpb.RotateCertificateResponse{} - retries = 6 - for i := 0; i < retries; i++ { + for retries, i := 6, 0; i < retries; i++ { rotateResponse, err = rotateRequestClient.Recv() if err == nil { break } t.Logf("Did not receive response ~ %vs after sending rotate request. Sleeping 10s to retry...", i*10) time.Sleep(10 * time.Second) - } - if err != nil { - t.Logf("Error fetching rotate certificate response: %v", err) - return false + if i == retries-1 { + t.Fatalf("Error fetching rotate certificate response: %v", err) + } } t.Logf("Received Rotate certificate response: %v", rotateResponse) @@ -330,38 +316,29 @@ func ServerCertzRotate(t *testing.T, caCert *x509.CertPool, certzClient certzpb. batch.Set(t, dut) t.Logf("gNMI config is replaced with new ssl profile %s successfully.", profileID) time.Sleep(30 * time.Second) //waiting 30s for gnmi config propagation - success := false - //Trying for 60s for the connection to succeed. - for i := 0; i < retries; i++ { - success = VerifyGnsi(t, caCert, san, serverAddr, username, password, cert) - if success { + // Trying for 60s for the connection to succeed. + for retries, i := 6, 0; i < retries; i++ { + if VerifyGnsi(t, caCert, san, serverAddr, username, password, cert) { break } - if i != 10 { - t.Logf("gNSI service RPC did not succeed ~ %vs after rotate. Sleeping 10s to retry...", i*10) - } time.Sleep(10 * time.Second) - } - if success { - finalizeRequest := &certzpb.RotateCertificateRequest_FinalizeRotation{FinalizeRotation: &certzpb.FinalizeRequest{}} - rotateCertRequest = &certzpb.RotateCertificateRequest{ - ForceOverwrite: false, - SslProfileId: profileID, - RotateRequest: finalizeRequest} - - err = rotateRequestClient.Send(rotateCertRequest) - if err != nil { - t.Fatalf("Error sending rotate finalize request: %v", err) - } - err = rotateRequestClient.CloseSend() - if err != nil { - t.Fatalf("Error sending rotate close send request: %v", err) + if i == retries-1 { + t.Fatalf("gNSI service RPC did not succeed ~%d*10s after rotate. Certz/Rotate failed. FinalizeRequest will not be sent", retries) } - return true - } else { - t.Logf("gNSI service RPC did not succeed ~%ds after rotate. Certz/Rotate failed. FinalizeRequest will not be sent", retries) - return false } + finalizeRequest := &certzpb.RotateCertificateRequest_FinalizeRotation{FinalizeRotation: &certzpb.FinalizeRequest{}} + rotateCertRequest = &certzpb.RotateCertificateRequest{ + ForceOverwrite: false, + SslProfileId: profileID, + RotateRequest: finalizeRequest, + } + if err := rotateRequestClient.Send(rotateCertRequest); err != nil { + t.Fatalf("Error sending rotate finalize request: %v", err) + } + if err := rotateRequestClient.CloseSend(); err != nil { + t.Fatalf("Error sending rotate close send request: %v", err) + } + return true } // CertGeneration function to create test data for use in TLS tests. @@ -375,37 +352,24 @@ func CertGeneration(t *testing.T, dirPath string) error { t.Logf("Executing cert generation command %v.", cmd) err := cmd.Start() if err != nil { - t.Logf("Cert generation command failed with error:%v.", err) - return err + t.Fatalf("Cert generation command failed with error:%v.", err) } err = cmd.Wait() if err != nil { - t.Logf("Failed to run cert generation command during wait with error:%v.", err) - return err + t.Fatalf("Failed to run cert generation command during wait with error:%v.", err) } return err } -// CertCleanup function to clean out the certificate content under test_data. +// CertCleanup function to clean out the certificate content under test_data. func CertCleanup(t *testing.T, dirPath string) error { - cmd := exec.Cmd{ - Path: "./cleanup.sh", - Stdout: os.Stdout, - Stderr: os.Stderr, - } + cmd := exec.Command("./cleanup.sh") cmd.Dir = dirPath t.Logf("Executing cleanup command") - err := cmd.Start() - if err != nil { - t.Logf("Testdata cleanup command failed with error:%v.", err) - return err - } - err = cmd.Wait() - if err != nil { - t.Logf("Testdata cleanup command failed during wait with the error:%v.", err) - return err + if err := cmd.Run(); err != nil { + t.Fatalf("Testdata cleanup command failed with error:%v.", err) } - return err + return nil } // ReadDecodeServerCertificate function to read and decode server certificates to extract the SubjectAltName and validate. @@ -457,8 +421,7 @@ func VerifyGnsi(t *testing.T, caCert *x509.CertPool, san, serverAddr, username, if statusError.Code() == codes.FailedPrecondition { t.Logf("Expected error FAILED_PRECONDITION seen for authz Get Request with err:%v.", err) } else { - t.Logf("Unexpected error during authz Get Request with err:%v.", err) - return false + t.Fatalf("Unexpected error during authz Get Request with err:%v.", err) } } t.Logf("gNSI authz get response is %s", rsp) @@ -488,8 +451,7 @@ func VerifyGnoi(t *testing.T, caCert *x509.CertPool, san, serverAddr, username, sysClient := spb.NewSystemClient(conn) _, err = sysClient.Ping(ctx, &spb.PingRequest{}) if err != nil { - t.Logf("Unable to connect gnoiClient %v", err) - return false + t.Fatalf("Unable to connect gnoiClient %v", err) } conn.Close() return true @@ -518,8 +480,7 @@ func VerifyGnmi(t *testing.T, caCert *x509.CertPool, san, serverAddr, username, t.Logf("%s:Sending gNMI Capability request.", time.Now().String()) response, err := gnmiClient.Capabilities(ctx, &gnmipb.CapabilityRequest{}) if err != nil { - t.Logf("gNMI Capability request failed with err: %v", err) - return false + t.Fatalf("gNMI Capability request failed with err: %v", err) } t.Logf("VerifyGnmi:gNMI response: %s", response.GNMIVersion) conn.Close() @@ -548,8 +509,7 @@ func VerifyGribi(t *testing.T, caCert *x509.CertPool, san, serverAddr, username, gRibiClient := gribipb.NewGRIBIClient(conn) _, err = gRibiClient.Get(ctx, &gribipb.GetRequest{}) if err != nil { - t.Logf("Failed to connect GribiClient with error:%v.", err) - return false + t.Fatalf("Failed to connect GribiClient with error:%v.", err) } conn.Close() return true @@ -576,8 +536,7 @@ func VerifyP4rt(t *testing.T, caCert *x509.CertPool, san, serverAddr, username, p4RtClient := p4rtpb.NewP4RuntimeClient(conn) _, err = p4RtClient.Capabilities(ctx, &p4rtpb.CapabilitiesRequest{}) if err != nil { - t.Logf("Failed to connect P4rtClient with error %v.", err) - return false + t.Fatalf("Failed to connect P4rtClient with error %v.", err) } conn.Close() return true @@ -619,28 +578,29 @@ func GetSslProfilelist(ctx context.Context, t *testing.T, certzClient certzpb.Ce } // PostValidationCheck function to do a validation of all services after certz rotation. -func PostValidationCheck(t *testing.T, caCert *x509.CertPool, expected_result bool, san, serverAddr, username, password string, cert tls.Certificate) bool { +func PostValidationCheck(t *testing.T, caCert *x509.CertPool, expectedResult bool, san, serverAddr, username, password string, cert tls.Certificate) bool { + t.Logf("%s:Verifying New gNSI connection.", time.Now().String()) result := VerifyGnsi(t, caCert, san, serverAddr, username, password, cert) - if expected_result != result { - t.Fatalf("Failed with new gNSI Connection: got %v, want %v.", result, expected_result) + if expectedResult != result { + t.Fatalf("Failed with new gNSI Connection: got %v, want %v.", result, expectedResult) } t.Logf("%s:Verifying New gNOI connection.", time.Now().String()) result = VerifyGnoi(t, caCert, san, serverAddr, username, password, cert) - if expected_result != result { - t.Fatalf("Failed with new gNOI Connection: got false, want %v", expected_result) + if expectedResult != result { + t.Fatalf("Failed with new gNOI Connection: got false, want %v", expectedResult) } t.Logf("%s:Verifying New gRIBI connection.", time.Now().String()) - if expected_result != VerifyGribi(t, caCert, san, serverAddr, username, password, cert) { - t.Fatalf("Failed with new gRIBI Connection: got false, want %v.", expected_result) + if expectedResult != VerifyGribi(t, caCert, san, serverAddr, username, password, cert) { + t.Fatalf("Failed with new gRIBI Connection: got false, want %v.", expectedResult) } t.Logf("%s:Verifying New P4rt connection.", time.Now().String()) - if expected_result != VerifyP4rt(t, caCert, san, serverAddr, username, password, cert) { - t.Fatalf("Failed with new P4rt Connection: got false, want %v.", expected_result) + if expectedResult != VerifyP4rt(t, caCert, san, serverAddr, username, password, cert) { + t.Fatalf("Failed with new P4rt Connection: got false, want %v.", expectedResult) } t.Logf("%s:Verifying New gNMI connection.", time.Now().String()) - if expected_result != VerifyGnmi(t, caCert, san, serverAddr, username, password, cert) { - t.Fatalf("Failed with new gNMI Connection: got false, want %v.", expected_result) + if expectedResult != VerifyGnmi(t, caCert, san, serverAddr, username, password, cert) { + t.Fatalf("Failed with new gNMI Connection: got false, want %v.", expectedResult) } return true } diff --git a/feature/security/gnsi/certz/tests/trust_bundle/trustbundle_test.go b/feature/security/gnsi/certz/tests/trust_bundle/trustbundle_test.go index 3cbbe579bd0..a6b1420b7e6 100644 --- a/feature/security/gnsi/certz/tests/trust_bundle/trustbundle_test.go +++ b/feature/security/gnsi/certz/tests/trust_bundle/trustbundle_test.go @@ -194,7 +194,7 @@ func TestServerCert(t *testing.T) { t.Fatalf("%s Failed to parse %s", time.Now().String(), tc.trustBundleFile) } certzClient := gnsiC.Certz() - success := setupService.ServerCertzRotate(t, cacert, certzClient, cert, ctx, dut, san, serverAddr, testProfile, &serverCertEntity, &trustBundleEntity) + success := setupService.CertzRotate(ctx, t, cacert, certzClient, cert, dut, san, serverAddr, testProfile, &serverCertEntity, &trustBundleEntity) if !success { t.Fatalf("%s %s:Trustbundle rotation failed.", time.Now().String(), tc.desc) }