Skip to content

Certz-1.1 and Certz-1.2#5653

Open
sudhirakondi wants to merge 4 commits into
openconfig:mainfrom
priyacj:certz1.1
Open

Certz-1.1 and Certz-1.2#5653
sudhirakondi wants to merge 4 commits into
openconfig:mainfrom
priyacj:certz1.1

Conversation

@sudhirakondi

Copy link
Copy Markdown
Contributor

Pushing test code for Certz1.1 and 1.2.
This code was previous merged via PR # 3684, however reverted by PR 5114 due to some issues. Raising a new pull request now with changes.

@sudhirakondi sudhirakondi requested a review from a team as a code owner July 2, 2026 04:52
@OpenConfigBot

OpenConfigBot commented Jul 2, 2026

Copy link
Copy Markdown

Pull Request Functional Test Report for #5653 / 0f75cb5

Virtual Devices

Device Test Test Documentation Job Raw Log
Arista cEOS status
Certz-1: gNSI Client Certificate Tests
Cisco 8000E status
Certz-1: gNSI Client Certificate Tests
Cisco XRd status
Certz-1: gNSI Client Certificate Tests
Juniper ncPTX status
Certz-1: gNSI Client Certificate Tests
Nokia SR Linux status
Certz-1: gNSI Client Certificate Tests
Openconfig Lemming status
Certz-1: gNSI Client Certificate Tests

Hardware Devices

Device Test Test Documentation Raw Log
Arista 7808 status
Certz-1: gNSI Client Certificate Tests
Cisco 8808 status
Certz-1: gNSI Client Certificate Tests
Juniper PTX10008 status
Certz-1: gNSI Client Certificate Tests
Nokia 7250 IXR-10e status
Certz-1: gNSI Client Certificate Tests

Help

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces comprehensive test coverage for Certz 1.1 and 1.2 functionality. It includes a new test suite that validates client certificate loading and authentication across various CA configurations, alongside minor infrastructure improvements to the test setup utilities to ensure more robust script execution and error reporting.

Highlights

  • Test Implementation: Added a new client certificate test suite for Certz 1.1 and 1.2, covering various CA configurations and key types.
  • Script Execution Fix: Updated the test data script execution to use /bin/sh -c, ensuring better compatibility and command handling.
  • Error Handling Improvements: Updated several validation functions to use t.Fatalf instead of t.Errorf to halt execution immediately upon critical test failures.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize the Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counterproductive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a new client certificates test (client_certificates_test.go) for GNSI certz rotation, updates the CA generation script to support custom directories, and improves error handling in setup_service.go by using t.Fatalf instead of t.Errorf for capability check failures. The review feedback focuses on Go best practices, recommending the removal of package-level global variables in favor of local declarations within the test function, and simplifying flag usage by dereferencing them directly instead of using redundant helper functions.

Comment on lines +45 to +61
var (
serverAddr string
creds DUTCredentialer //an interface for getting credentials from a DUT binding
testProfile string = "newprofile" //sslProfileId name
prevClientCertFile string = ""
prevClientKeyFile string = ""
prevTrustBundleFile string = ""
expectedResult bool = true
certsList = flag.String("certsList", "01,02,10,1000", "Number of Certificate Sets to generate for this test. Comma separated string")
certsTimeout = flag.Duration("certsTimeout", 10*time.Minute, "Time duration for cert generation and cleanup. Increase if more certs are to be generated")
certsString = func() string {
return *certsList
}
certsTimeOutVar = func() time.Duration {
return *certsTimeout
}
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Declaring test-specific variables (such as serverAddr, creds, testProfile, prevClientCertFile, prevClientKeyFile, prevTrustBundleFile, and expectedResult) as package-level global variables is an anti-pattern in Go. It pollutes the global namespace and can lead to shared state issues or race conditions if tests are run concurrently or multiple times in the same process. These variables should be declared locally within the TestClientCert function. Additionally, the helper functions certsString and certsTimeOutVar are redundant; the flag pointers certsList and certsTimeout can be dereferenced directly.

var (
	certsList    = flag.String("certsList", "01,02,10,1000", "Number of Certificate Sets to generate for this test. Comma separated string")
	certsTimeout = flag.Duration("certsTimeout", 10*time.Minute, "Time duration for cert generation and cleanup. Increase if more certs are to be generated")
)
References
  1. Follow Go Code Review Comments and Effective Go for writing readable, idiomatic Go code. Avoid package-level global variables for test-specific state to prevent shared state issues and namespace pollution. (link)

Comment on lines +70 to +107
func TestClientCert(t *testing.T) {

dut := ondatra.DUT(t, "dut")
serverAddr = dut.Name() //returns the device name.
if err := binding.DUTAs(dut.RawAPIs().BindingDUT(), &creds); err != nil {
t.Fatalf("%sSTATUS:Failed to get DUT credentials using binding.DUTAs: %v. The binding for %s must implement the DUTCredentialer interface.", time.Now().String(), err, dut.Name())
}
username := creds.RPCUsername()
password := creds.RPCPassword()
t.Logf("Validation of all services that are using gRPC before certz rotation.")
gnmiClient, gnsiC := setup_service.PreInitCheck(context.Background(), t, dut)
//Generate testdata certificates
t.Logf("%sSTATUS:Generation of test data certificates.", time.Now().String())
command := fmt.Sprintf("./mk_cas.sh %v", certsString())
if err := setup_service.TestdataMakeCleanup(t, dirPath, certsTimeOutVar(), command); err != nil {
t.Fatalf("%sSTATUS:Generation of testdata certificates failed!: %v", time.Now().String(), err)
}
//Create a certz client
ctx := context.Background()
certzClient := gnsiC.Certz()
t.Logf("%sSTATUS:Precheck:checking baseline ssl profile list.", time.Now().String())
//Get ssl profile list.
if getResp := setup_service.GetSslProfilelist(ctx, t, certzClient, &certzpb.GetProfileListRequest{}); slices.Contains(getResp.SslProfileIds, testProfile) {
t.Fatalf("%sSTATUS:profileID %s already exists.", time.Now().String(), testProfile)
}
//Add a new ssl profileID
t.Logf("%sSTATUS:Adding new empty ssl profile ID %s.", time.Now().String(), testProfile)
if addProfileResponse, err := certzClient.AddProfile(ctx, &certzpb.AddProfileRequest{SslProfileId: testProfile}); err != nil {
t.Fatalf("%sSTATUS:Add profile request failed with %v!", time.Now().String(), err)
} else {
t.Logf("%sSTATUS:Received the AddProfileResponse %v.", time.Now().String(), addProfileResponse)
}
//Get ssl profile list after new ssl profile addition.
if getResp := setup_service.GetSslProfilelist(ctx, t, certzClient, &certzpb.GetProfileListRequest{}); !slices.Contains(getResp.SslProfileIds, testProfile) {
t.Fatalf("%sSTATUS:newly added profileID is not seen.", time.Now().String())
} else {
t.Logf("%sSTATUS: new profileID %s is seen in ssl profile list.", time.Now().String(), testProfile)
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Refactor TestClientCert to declare test-specific variables locally and dereference the flags directly instead of using the redundant package-level helper functions. This improves maintainability, encapsulation, and adheres to Go best practices.

func TestClientCert(t *testing.T) {
	dut := ondatra.DUT(t, "dut")
	serverAddr := dut.Name() //returns the device name.
	var creds DUTCredentialer
	if err := binding.DUTAs(dut.RawAPIs().BindingDUT(), &creds); err != nil {
		t.Fatalf("Failed to get DUT credentials using binding.DUTAs: %v. The binding for %s must implement the DUTCredentialer interface.", err, dut.Name())
	}
	username := creds.RPCUsername()
	password := creds.RPCPassword()
	t.Logf("Validation of all services that are using gRPC before certz rotation.")
	gnmiClient, gnsiC := setup_service.PreInitCheck(context.Background(), t, dut)
	//Generate testdata certificates
	t.Logf("Generation of test data certificates.")
	command := fmt.Sprintf("./mk_cas.sh %v", *certsList)
	if err := setup_service.TestdataMakeCleanup(t, dirPath, *certsTimeout, command); err != nil {
		t.Fatalf("Generation of testdata certificates failed!: %v", err)
	}
	//Create a certz client
	ctx := context.Background()
	certzClient := gnsiC.Certz()
	t.Logf("Precheck:checking baseline ssl profile list.")
	//Get ssl profile list.
	testProfile := "newprofile"
	if getResp := setup_service.GetSslProfilelist(ctx, t, certzClient, &certzpb.GetProfileListRequest{}); slices.Contains(getResp.SslProfileIds, testProfile) {
		t.Fatalf("profileID %s already exists.", testProfile)
	}
	//Add a new ssl profileID
	t.Logf("Adding new empty ssl profile ID %s.", testProfile)
	if addProfileResponse, err := certzClient.AddProfile(ctx, &certzpb.AddProfileRequest{SslProfileId: testProfile}); err != nil {
		t.Fatalf("Add profile request failed with %v!", err)
	} else {
		t.Logf("Received the AddProfileResponse %v.", addProfileResponse)
	}
	//Get ssl profile list after new ssl profile addition.
	if getResp := setup_service.GetSslProfilelist(ctx, t, certzClient, &certzpb.GetProfileListRequest{}); !slices.Contains(getResp.SslProfileIds, testProfile) {
		t.Fatalf("newly added profileID is not seen.")
	} else {
		t.Logf("new profileID %s is seen in ssl profile list.", testProfile)
	}

	var prevClientCertFile string
	var prevClientKeyFile string
	var prevTrustBundleFile string
	expectedResult := true

Comment on lines +309 to +314
t.Logf("%s:STATUS:Cleanup of test data.", time.Now().String())
//Cleanup of test data.
if err := setup_service.TestdataMakeCleanup(t, dirPath, certsTimeOutVar(), "./cleanup.sh"); err != nil {
t.Errorf("%s:STATUS:Cleanup of testdata certificates failed!: %v", time.Now().String(), err)
}
t.Logf("%s:STATUS:Test completed!", time.Now().String())

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Clean up the test data cleanup block to use the dereferenced *certsTimeout flag directly and remove the redundant time.Now().String() and STATUS: prefixes from the logs.

Suggested change
t.Logf("%s:STATUS:Cleanup of test data.", time.Now().String())
//Cleanup of test data.
if err := setup_service.TestdataMakeCleanup(t, dirPath, certsTimeOutVar(), "./cleanup.sh"); err != nil {
t.Errorf("%s:STATUS:Cleanup of testdata certificates failed!: %v", time.Now().String(), err)
}
t.Logf("%s:STATUS:Test completed!", time.Now().String())
t.Logf("Cleanup of test data.")
//Cleanup of test data.
if err := setup_service.TestdataMakeCleanup(t, dirPath, *certsTimeout, "./cleanup.sh"); err != nil {
t.Errorf("Cleanup of testdata certificates failed!: %v", err)
}
t.Logf("Test completed!")

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants