Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CERTZ-1.1/1.2-gNSI Client Certificate Tests #2488

Open
wants to merge 76 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 65 commits
Commits
Show all changes
76 commits
Select commit Hold shift + click to select a range
9a24e4d
Initial Commit of CERTZ-1.1
priyacj Dec 14, 2023
10d0638
deleted ca-01 unwanted files
priyacj Dec 14, 2023
3775f6e
ca-01: added required files only.
priyacj Dec 14, 2023
02484f1
ca-01:added ecdsa files
priyacj Dec 14, 2023
3096352
ca-02:unwanted files deleted.
priyacj Dec 14, 2023
1c2a386
ca-02:keeping required files only.
priyacj Dec 14, 2023
cdf80d7
ca-10:removed unwanted files.
priyacj Dec 14, 2023
618b331
ca-10:added required files only.
priyacj Dec 14, 2023
4f5dd70
ca-1000:removed unwanted files
priyacj Dec 14, 2023
4e9382b
ca-1000:keeping required files only.
priyacj Dec 14, 2023
d4f0c55
deleting client_cert_ext.cnf
priyacj Dec 14, 2023
8e24a91
deleted wanted folder
priyacj Dec 14, 2023
cd3047d
updated file permissions.
priyacj Dec 14, 2023
4174001
updated file permission README
priyacj Dec 14, 2023
7ac8060
fixed the go script
priyacj Dec 15, 2023
c757955
Merge branch 'main' into certz1.1
priyacj Dec 15, 2023
f829a76
fixed some static commnets with test.go and setup_service.go
priyacj Dec 15, 2023
9b6c10a
fixed few more comments on the go scripts.
priyacj Dec 16, 2023
ff00db4
lint error
priyacj Dec 18, 2023
b180ac7
fixed link checks for the go scripts.
priyacj Dec 19, 2023
d373e5b
Merge branch 'main' into certz1.1
arulkumarsekar Dec 19, 2023
c30f5ec
Initial commit of certz1.2
priyacj Dec 19, 2023
8c9ea83
Merge branch 'certz1.1' of https://github.com/priyacj/featureprofiles…
priyacj Dec 19, 2023
8a4a7e8
fixed a lint error in setup_service.go file
priyacj Dec 19, 2023
10ddf80
fixed line214 return block in if loop with setup_service.go
priyacj Dec 19, 2023
9188fb3
Merge branch 'main' into certz1.1
priyacj Dec 25, 2023
5ab9c40
Merge branch 'main' into certz1.1
arulkumarsekar Jan 5, 2024
e5cc9a8
incorporated the given feedback of 1.1 and 1.2
priyacj Feb 15, 2024
9468be0
fixed the metadata file
priyacj Feb 15, 2024
882fc31
Merge branch 'main' into certz1.1
priyacj Feb 15, 2024
a15d443
Merge branch 'main' into certz1.1
priyacj Feb 15, 2024
de37578
Certz1.1/1.2
priyacj Jul 2, 2024
1020a98
Merge branch 'main' into certz1.1
priyacj Jul 2, 2024
c17065d
updated the clientscripts
priyacj Jul 3, 2024
b57c117
Merge branch 'main' into certz1.1
priyacj Jul 3, 2024
763b1d6
Merge branch 'openconfig:main' into certz1.1
priyacj Jul 10, 2024
11a7883
modified README
priyacj Jul 10, 2024
1a413b3
deprecated Dialcontext
priyacj Jul 10, 2024
e7bd71d
modified the README format
priyacj Jul 11, 2024
38e5471
Appended the tcname
priyacj Jul 11, 2024
2d9d3bc
modified metadata.textproto
priyacj Jul 11, 2024
abf8cb2
Merge branch 'main' into certz1.1
priyacj Jul 11, 2024
d6ef95e
Merge branch 'main' into certz1.1
priyacj Jul 15, 2024
2b9bb5b
Merge branch 'main' into certz1.1
priyacj Jul 16, 2024
f4d6ab2
Merge branch 'main' into certz1.1
priyacj Jul 18, 2024
566b59c
Merge branch 'openconfig:main' into certz1.1
priyacj Jul 18, 2024
629d8d1
Merge branch 'openconfig:main' into certz1.1
priyacj Jul 19, 2024
c17798f
Merge branch 'openconfig:main' into certz1.1
priyacj Jul 22, 2024
44b6209
Merge branch 'openconfig:main' into certz1.1
priyacj Jul 23, 2024
dab767f
Merge branch 'openconfig:main' into certz1.1
priyacj Jul 24, 2024
b4eeef6
Merge branch 'openconfig:main' into certz1.1
priyacj Jul 28, 2024
3b30ff8
Merge branch 'openconfig:main' into certz1.1
priyacj Jul 29, 2024
df149cb
Merge branch 'main' into certz1.1
priyacj Jul 29, 2024
5db46da
Merge branch 'openconfig:main' into certz1.1
priyacj Jul 30, 2024
4ff016d
Merge branch 'openconfig:main' into certz1.1
priyacj Aug 1, 2024
1c662f3
Merge branch 'openconfig:main' into certz1.1
priyacj Aug 2, 2024
7cd532a
Merge branch 'openconfig:main' into certz1.1
priyacj Aug 3, 2024
d3f276f
Merge branch 'openconfig:main' into certz1.1
priyacj Aug 14, 2024
9efca6d
Merge branch 'openconfig:main' into certz1.1
priyacj Aug 19, 2024
7868d3a
Merge branch 'openconfig:main' into certz1.1
priyacj Aug 20, 2024
77df411
Merge branch 'openconfig:main' into certz1.1
priyacj Aug 23, 2024
456ab50
Merge branch 'openconfig:main' into certz1.1
priyacj Aug 28, 2024
245116d
Merge branch 'openconfig:main' into certz1.1
priyacj Aug 28, 2024
c00a1ea
Merge branch 'openconfig:main' into certz1.1
priyacj Sep 10, 2024
e3042d0
Merge branch 'openconfig:main' into certz1.1
priyacj Sep 18, 2024
eb0b88a
Merge branch 'openconfig:main' into certz1.1
priyacj Sep 21, 2024
9958f39
Merge branch 'openconfig:main' into certz1.1
priyacj Oct 21, 2024
af2518e
Merge branch 'openconfig:main' into certz1.1
priyacj Oct 28, 2024
dc35a0e
Merge branch 'openconfig:main' into certz1.1
priyacj Oct 28, 2024
b1717a5
removed the README
priyacj Oct 28, 2024
7eeb621
moved README file featureprofiles/feature/security/gnsi/certz/client_…
priyacj Oct 28, 2024
54f78d8
Merge branch 'openconfig:main' into certz1.1
priyacj Nov 5, 2024
8b6b40b
fix the rundata error
priyacj Nov 5, 2024
1514361
removed the test_data under tests
priyacj Nov 5, 2024
34b6a92
Merge branch 'openconfig:main' into certz1.1
priyacj Nov 14, 2024
be654fa
Merge branch 'openconfig:main' into certz1.1
priyacj Nov 18, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
133 changes: 133 additions & 0 deletions feature/security/gnsi/certz/tests/client_certificates/README.md
priyacj marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
# CERTZ-1: gNSI Client Certificate Tests
morrowc marked this conversation as resolved.
Show resolved Hide resolved

## Summary

Clients must be able to validate a remote server's TLS certificate
and present a valid client certificate to that server in order to provide
identification information. The client certificate should have a
SPIFFE Idenitifier embedded in it to be used as the identifier of
the client to the server.

## Baseline Setup

### Input Args

* the set of certificate testdata generated with the mk_cas.sh
script in featureprofiles/feature/security/gnsi/certz/test_data

### DUT service setup

Configure the DUT to enable the following services (that are using gRPC) are
up and using mTLS for authentication:

* gNMI
* gNOI
* gNSI
* gRIBI
* P4RT

Be prepared to load the relevant trust_bundle.pem file for each test
Certificate Authority(CA) under test on the DUT. Each CA has a RSA and ECDSA
form, both must be tested.

## Tests

### Certz-1.1

Perform these positive tests:

Test that client certificates from a set of one CA are able to be validated and
used for authentication to a device when used by a client connecting to each
gRPC service.

Perform this for both RSA and ECDSA signed CA bundles and
certificates.
Perform this for the permutations of 1, 2, 10, 1000 CA
trust_bundle configurations: (## indicates the 1, 2, 10, 1000 CA testdata)

1) Load the correct key-type trust bundle onto the device and client system:
ca-##/trust_bundle_##_rsa.pem
ca-##/trust_bundle_##_ecdsa.pem

2) Load the correct key-type client certificate into the test gRPC client:
ca-##/client-rsa-key.pem
ca-##/client-rsa-cert.pem
ca-##/client-ecdsa-key.pem
ca-##/client-ecdsa-cert.pem

3) Load the correct key-type server certificate into the services on the DUT:
ca-##/server-rsa-key.pem
ca-##/server-rsa-cert.pem
ca-##/server-ecdsa-key.pem
ca-##/server-ecdsa-cert.pem

4) Validate that the certificate is loaded and useful for outbound
client connections.

5) Connect to the service on the DUT.

6) Validate that the connection is established and that the client's
provided certificate is validated by the service on the DUT.

7) Validate that the connection's provided certificate is used for
authentication of the connection to the service on the DUT.

### Certz-1.2

Perform these negative tests:

This test should show that the trust-bundle/CA-set being mis-matched
between client and server results in failed connections.

Perform these tests with both RSA and ECDSA trust_bundles and
certificates:

1) Load the correct key type trust_bundle from ca-02 on to the DUT:
ca-02/trust_bundle_02_rsa.pem
ca-02/trust_bundle_02_ecsda.pem

2) Load the correct key type client certificate from the ca-01 set into
the test gRPC client:
ca-01/client-rsa-key.pem
ca-01/client-rsa-cert.pem
ca-01/client-ecdsa-key.pem
ca-01/client-ecdsa-cert.pem

3) Validate that the certificate is loaded and useful for outbound
client connections. Connect to the service on the DUT.

4) Validate that the connection to the remote device is established,
validate the client certificate can not be used (is untrusted) by
service on the DUT.

5) Validate that the connection is properly torn down by the DUT.

## Protocol/RPC Parameter coverage

Copy link
Contributor

Choose a reason for hiding this comment

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

this and the next 3 section headers are new, that appears to be basically the only changes to this file?

## Config parameter coverage

## Telemetry parameter coverage

## 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
paths:
# config paths

# state paths

rpcs:
gnsi:
certz.v1.Certz.GetProfileList:
certz.v1.Certz.AddProfile:
Copy link
Contributor

Choose a reason for hiding this comment

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

apologies, this line and the next are 'new'.

I don't understand why this diff is 'whole file is new'.

certz.v1.Certz.Rotate:
```


## Minimum DUT Platform Requirement

vRX
Original file line number Diff line number Diff line change
@@ -0,0 +1,257 @@
// 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 client_certificates_test

import (
context "context"
"crypto/tls"
"crypto/x509"
"os"
"testing"

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"
)

const (
dirPath = "../../test_data/"
)

var (
testProfile = "newprofile"
serverAddr string
username = "certzuser"
password = "certzpasswd"
servers []string
)

// createUser function to add an user in admin role.
priyacj marked this conversation as resolved.
Show resolved Hide resolved
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: got %v ,want notnil ", res)
}

return true
}

func TestMain(m *testing.M) {
fptest.RunTests(m)
}

// TestClientCert Test validates that client certificates from a set of one CA are able to be loaded successfully
// and used for authentication to a device when used by a client connecting to each
// gRPC service.
func TestClientCert(t *testing.T) {
dut := ondatra.DUT(t, "dut")
serverAddr = dut.Name()
if !createUser(t, dut, username, password) {
t.Fatalf("Failed to create certz user.")
}
t.Logf("Validation of all services that are using gRPC before certz rotation.")
ctx := context.Background()
if !setupService.PreInitCheck(ctx, t, dut) {
t.Fatalf("Failed in the preInit checks.")
}
gnsiC, err := dut.RawAPIs().BindingDUT().DialGNSI(ctx)
if err != nil {
t.Fatalf("Failed to create gNSI Connection with error: %v", err)
}
t.Logf("Precheck:gNSI connection is successful %v", gnsiC)
t.Logf("Creation of test data.")
if setupService.CertGeneration(dirPath) != nil {
t.Fatalf("Failed to generate the testdata certificates with the error: %v", setupService.CertGeneration(dirPath))
}
certzClient := gnsiC.Certz()
t.Logf("Precheck:baseline ssl profile list")
setupService.GetSslProfilelist(ctx, t, certzClient, &certzpb.GetProfileListRequest{})
t.Logf("Adding new empty ssl profile ID.")
addProfileResponse, err := certzClient.AddProfile(ctx, &certzpb.AddProfileRequest{SslProfileId: testProfile})
if err != nil {
t.Fatalf("Add profile request failed with %v!", err)
}
t.Logf("AddProfileResponse: %v", addProfileResponse)
t.Logf("Getting the ssl profile list after new ssl profile addition.")
setupService.GetSslProfilelist(ctx, t, certzClient, &certzpb.GetProfileListRequest{})

cases := []struct {
desc string
clientCertFile string
clientKeyFile string
sequence uint32
serverCertFile string
serverKeyFile string
trustBundleFile string
mismatch bool
}{
{
desc: "Certz1.1:Load the key-type rsa trustbundle with 1 CA 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: "Certz1.1:Load the key-type ecdsa trustbundle with 1 CA 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: "Certz1.1:Load the key-type rsa trustbundle with 2 CA 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: "Certz1.1:Load the key-type ecdsa trustbundle with 2 CA 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: "Certz1.1:Load the key-type rsa trustbundle 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: "Certz1.1:Load the key-type ecdsa trustbundle 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: "Certz1.1:Load the key-type rsa trustbundle 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: "Certz1.1:Load the key-type ecdsa trustbundle 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",
},
{
desc: "Certz1.2:Load the rsa trust_bundle from ca-02 with mismatching key type rsa client certificate from ca-01",
serverCertFile: dirPath + "ca-01/server-rsa-a-cert.pem",
serverKeyFile: dirPath + "ca-01/server-rsa-a-key.pem",
trustBundleFile: dirPath + "ca-02/trust_bundle_02_rsa.pem",
clientCertFile: dirPath + "ca-01/client-rsa-a-cert.pem",
clientKeyFile: dirPath + "ca-01/client-rsa-a-key.pem",
mismatch: true,
},
{
desc: "Certz1.2:Load the ecdsa trust_bundle from ca-02 with mismatching key type ecdsa client certificate from ca-01",
serverCertFile: dirPath + "ca-01/server-ecdsa-a-cert.pem",
serverKeyFile: dirPath + "ca-01/server-ecdsa-a-key.pem",
trustBundleFile: dirPath + "ca-02/trust_bundle_02_ecdsa.pem",
clientCertFile: dirPath + "ca-01/client-ecdsa-a-cert.pem",
clientKeyFile: dirPath + "ca-01/client-ecdsa-a-key.pem",
mismatch: true,
},
}
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, "cert1")
trustCertChain := setupService.CreateCertChainFromTrustBundle(tc.trustBundleFile)
trustBundleEntity := setupService.CreateCertzEntity(t, setupService.EntityTypeTrustBundle, trustCertChain, "bundle1")
cert, err := tls.LoadX509KeyPair(tc.clientCertFile, tc.clientKeyFile)
if err != nil {
t.Fatalf("Failed to load client cert: %v", err)
}
cacert := x509.NewCertPool()
cacertBytes, err := os.ReadFile(tc.trustBundleFile)
if err != nil {
t.Fatalf("Failed to read ca bundle :%v", err)
}
if ok := cacert.AppendCertsFromPEM(cacertBytes); !ok {
t.Fatalf("Failed to parse %v", tc.trustBundleFile)
}

success := setupService.CertzRotate(t, cacert, certzClient, cert, san, serverAddr, testProfile, &serverCertEntity, &trustBundleEntity)
if !success {
t.Fatalf("%s:Certz rotation failed.", tc.desc)
}
t.Logf("%s:successfully completed certz rotation!", 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:replaced gNMI config with new ssl profile successfully.", tc.desc)

// Verification check of the new connection post rotation.
switch tc.mismatch {
case true:
t.Run("Verification of new connection with mismatch rotate of trustbundle.", func(t *testing.T) {
result := setupService.TestNewConnection(t, cacert, san, serverAddr, username, password, cert)
if result {
t.Fatalf("%s :postTestcase service validation failed with mismatch rotate of trustbundle- got %v,want %v ", tc.desc, result, !result)
}
})
case false:
t.Run("Verification of new connection after rotate ", func(t *testing.T) {
result := setupService.PostValidationCheck(t, cacert, san, serverAddr, username, password, cert)
priyacj marked this conversation as resolved.
Show resolved Hide resolved
if !result {
t.Fatalf("%s :postTestcase service validation failed after rotate- got %v, want %v", tc.desc, !result, result)
}
t.Logf("%s postTestcase service validation done!", tc.desc)
})
}
})
t.Logf("PASS: %s successfully completed!", tc.desc)
}

t.Logf("Cleanup of test data.")
if setupService.CertCleanup(dirPath) != nil {
t.Fatalf("could not run testdata cleanup command.")
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# proto-file: github.com/openconfig/featureprofiles/proto/metadata.proto
# proto-message: Metadata

uuid: "f7bcfa59-dd84-4998-aa54-243dde4a99db"
plan_id: "CERTZ-1"
description: "gNSI Client Certificate Tests"
testbed: TESTBED_DUT_ATE_2LINKS
Loading
Loading