Skip to content

Commit

Permalink
Initial Commit of CERTZ-1.1
Browse files Browse the repository at this point in the history
  • Loading branch information
priyacj committed Dec 14, 2023
1 parent 1268185 commit 9a24e4d
Show file tree
Hide file tree
Showing 24,608 changed files with 655,981 additions and 0 deletions.
The diff you're trying to view is too large. We only load the first 3000 changed files.
115 changes: 115 additions & 0 deletions feature/security/gnsi/certz/tests/client_certificates/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# CERTZ-1: gNSI Client Certificate Tests

## 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.

## Config Parameter Coverage

## Telemetry Parameter Coverage

## Protocol/RPC Parameter Coverage

None

## Minimum DUT Platform Requirement

vRX
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
// 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"
"encoding/pem"
"os"
"testing"

"github.com/openconfig/featureprofiles/feature/security/gnsi/certz/internal/setup_service"

Check failure on line 25 in feature/security/gnsi/certz/tests/client_certificates/client_certificates_test.go

View workflow job for this annotation

GitHub Actions / Static Analysis

no required module provides package github.com/openconfig/featureprofiles/feature/security/gnsi/certz/internal/setup_service; to add it:
"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"
)

var (
testProfile = "gNxI"
serverAddr string
username = "certzuser"
password = "certzpswd"
)

type EntityType int8

/*type rpcCredentials struct {
*creds.UserPass
}
func (r *rpcCredentials) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) {
return map[string]string{
"username": username,
"password": password,
}, nil
}
func (r *rpcCredentials) RequireTransportSecurity() bool {
return true
}*/

// 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),
}
gnmi.Update(t, dut, gnmi.OC().System().Aaa().Authentication().User(user).Config(), ocUser)
return true
}

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

// Certz1.1
// 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.

func TestClientCertTcOne(t *testing.T) {

dut := ondatra.DUT(t, "dut")
serverAddr = dut.Name()

checkUser := createUser(t, dut, username, password)
if !checkUser {
t.Fatalf("Failed to create certz user.")
}

t.Logf("Validation of all services that are using gRPC before certz rotation.")
initCheck := setup_service.PreInitCheck(t, dut, context.Background())
if !initCheck {
t.Fatalf("Failed in the preInit checks.")
}

ctx := context.Background()
gnsiC, err := dut.RawAPIs().BindingDUT().DialGNSI(ctx)
if err != nil {
t.Fatalf("Could not create gNSI Connection %v", err)
}
t.Logf("Precheck:gNSI connection is successful%v", gnsiC)

cases := []struct {
desc string
serverCertzFile string
serverKeyzFile string
trustBundlezFile string
clientCertzFile string
clientKeyzFile string
}{
{
desc: "Load the correct key-type rsa trustbundle with 1 CA configuration",
serverCertzFile: "test_data/ca-01/server-rsa-a-cert.pem",
serverKeyzFile: "test_data/ca-01/server-rsa-a-key.pem",
trustBundlezFile: "test_data/ca-01/trust_bundle_01_rsa_a.pem",
clientCertzFile: "test_data/ca-01/client-rsa-a-cert.pem",
clientKeyzFile: "test_data/ca-01/client-rsa-a-key.pem",
},
{
desc: "Load the correct key-type ecdsa trustbundle with 1 CA configuration",
serverCertzFile: "test_data/ca-01/server-ecdsa-a-cert.pem",
serverKeyzFile: "test_data/ca-01/server-ecdsa-a-key.pem",
trustBundlezFile: "test_data/ca-01/trust_bundle_01_ecdsa_a.pem",
clientCertzFile: "test_data/ca-01/client-ecdsa-a-cert.pem",
clientKeyzFile: "test_data/ca-01/client-ecdsa-a-key.pem",
},
{
desc: "Load the correct key-type rsa trustbundle with 2 CA configuration",
serverCertzFile: "test_data/ca-02/server-rsa-a-cert.pem",
serverKeyzFile: "test_data/ca-02/server-rsa-a-key.pem",
trustBundlezFile: "test_data/ca-02/trust_bundle_02_rsa_a.pem",
clientCertzFile: "test_data/ca-02/client-rsa-a-cert.pem",
clientKeyzFile: "test_data/ca-02/client-rsa-a-key.pem",
},
{
desc: "Load the correct key-type ecdsa trustbundle with 2 CA configuration",
serverCertzFile: "test_data/ca-02/server-ecdsa-a-cert.pem",
serverKeyzFile: "test_data/ca-02/server-ecdsa-a-key.pem",
trustBundlezFile: "test_data/ca-02/trust_bundle_02_ecdsa_a.pem",
clientCertzFile: "test_data/ca-02/client-ecdsa-a-cert.pem",
clientKeyzFile: "test_data/ca-02/client-ecdsa-a-key.pem",
},
{
desc: "Load the correct key-type rsa trustbundle with 10CA configuration",
serverCertzFile: "test_data/ca-10/server-rsa-a-cert.pem",
serverKeyzFile: "test_data/ca-10/server-rsa-a-key.pem",
trustBundlezFile: "test_data/ca-10/trust_bundle_10_rsa_a.pem",
clientCertzFile: "test_data/ca-10/client-rsa-a-cert.pem",
clientKeyzFile: "test_data/ca-10/client-rsa-a-key.pem",
},
{
desc: "Load the correct key-type ecdsa trustbundle with 10CA configuration",
serverCertzFile: "test_data/ca-10/server-ecdsa-a-cert.pem",
serverKeyzFile: "test_data/ca-10/server-ecdsa-a-key.pem",
trustBundlezFile: "test_data/ca-10/trust_bundle_10_ecdsa_a.pem",
clientCertzFile: "test_data/ca-10/client-ecdsa-a-cert.pem",
clientKeyzFile: "test_data/ca-10/client-ecdsa-a-key.pem",
},
{
desc: "Load the correct key-type rsa trustbundle with 1000CA configuration",
serverCertzFile: "test_data/ca-1000/server-rsa-a-cert.pem",
serverKeyzFile: "test_data/ca-1000/server-rsa-a-key.pem",
trustBundlezFile: "test_data/ca-1000/trust_bundle_1000_rsa_a.pem",
clientCertzFile: "test_data/ca-1000/client-rsa-a-cert.pem",
clientKeyzFile: "test_data/ca-1000/client-rsa-a-key.pem",
},
{
desc: "Load the correct key-type ecdsa trustbundle with 1000CA configuration",
serverCertzFile: "test_data/ca-1000/server-ecdsa-a-cert.pem",
serverKeyzFile: "test_data/ca-1000/server-ecdsa-a-key.pem",
trustBundlezFile: "test_data/ca-1000/trust_bundle_1000_ecdsa_a.pem",
clientCertzFile: "test_data/ca-1000/client-ecdsa-a-cert.pem",
clientKeyzFile: "test_data/ca-1000/client-ecdsa-a-key.pem",
},
}

for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {

sc1, err := os.ReadFile(tc.serverCertzFile)
if err != nil {
t.Fatalf("Failed to read certificate: %v", err)
}
block, _ := pem.Decode(sc1)
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: %v", err)
}

san := sCert.DNSNames[0]

serverCert := setup_service.CreateCertzChain(t, setup_service.CertificateChainRequest{
RequestType: setup_service.EntityTypeCertificateChain,
ServerCertFile: tc.serverCertzFile,
ServerKeyFile: tc.serverKeyzFile})

serverCertEntity := setup_service.CreateCertzEntity(t, setup_service.EntityTypeCertificateChain, &serverCert)

trustCertChain := setup_service.CreateCertChainFromTrustBundle(tc.trustBundlezFile)
trustBundleEntity := setup_service.CreateCertzEntity(t, setup_service.EntityTypeTrustBundle, trustCertChain)

cert, err := tls.LoadX509KeyPair(tc.clientCertzFile, tc.clientKeyzFile)
if err != nil {
t.Fatalf("Failed to load client cert: %v", err)
}

cacert := x509.NewCertPool()
cacertBytes, err := os.ReadFile(tc.trustBundlezFile)
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.trustBundlezFile)
}

certzClient := gnsiC.Certz()
success := setup_service.CertzRotate(t, dut, cacert, cert, certzClient, testProfile, san, &serverCertEntity, &trustBundleEntity)
if !success {
t.Fatalf("%s:Certz/Rotate failed.", tc.desc)
}

t.Logf("%s:successfully completed second certz/Rotate!", tc.desc)
// Verification check of the new connection with the new rotated certificates.
t.Run("Verification of fresh new connection after successful rotate ", func(t *testing.T) {
result := setup_service.PostValidationCheck(t, dut, cacert, san, serverAddr, username, password, cert)
if !result {
t.Fatalf("%s postTestcase validation failed.", tc.desc)
}

t.Logf("PASS: %s successfully completed!", tc.desc)
})
})
}
}
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Certificate Authority Test Data

Creation of test data for use in TLS tests.

## Content

* mk_cas.sh - create sets of Certificate Authority(CA) content for tests.
* cleanup.sh - clean out the CA content for recreation efforts.
* ca-01 - a single CA set where signatures are RSA or ECDSA.
* ca-02 - a set of two CAs where signatures are RSA or ECDSA.
* ca-10 - a set of ten CAs where signatures are RSA or ECDSA.
* ca-1000 - a set of one thousand CAs where signatures are RSA or ECDSA.
* server_cert.cnf/server_cert_ext.cnf - server openssl profile configuration
* client_cert.cnf/client_cert_ext.cnf - client openssl profile configuration

Each CA set includes, for both RSA and ECDSA signature types:
* CA key
* CA public certificate
* client key, certificate request, certificate
* server key, certificate request, certificate
* CA trust bundle

NOTE: Creation of bad data has not been completed yet.
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
-----BEGIN CERTIFICATE-----
MIICDjCCAbWgAwIBAgIUQ0mp9CWtL+EAzM3D7U9osgz9PJkwCgYIKoZIzj0EAwIw
XTEQMA4GA1UEAwwHQ0EgMDAwMTELMAkGA1UEBhMCQVExCzAJBgNVBAgMAk5aMQsw
CQYDVQQHDAJOWjEiMCAGA1UECgwZT3BlbkNvbmZpZ0ZlYXR1cmVQcm9maWxlczAe
Fw0yMzEyMDYyMTMxMzVaFw0zMzEyMDMyMTMxMzVaMF0xEDAOBgNVBAMMB0NBIDAw
MDExCzAJBgNVBAYTAkFRMQswCQYDVQQIDAJOWjELMAkGA1UEBwwCTloxIjAgBgNV
BAoMGU9wZW5Db25maWdGZWF0dXJlUHJvZmlsZXMwWTATBgcqhkjOPQIBBggqhkjO
PQMBBwNCAATPv9MxFOtzl/+8U3icjigGjnXE/GMmdjvsWiJiveND6HRmM6et3/Dq
523Zoxf1RyV8GE0WaKVmXl1WJ91oXokjo1MwUTAdBgNVHQ4EFgQUTB7IGZ88Z6di
1565GJyPTd+zs00wHwYDVR0jBBgwFoAUTB7IGZ88Z6di1565GJyPTd+zs00wDwYD
VR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNHADBEAiBq5+eAO4gF0wS0Op4hm3XY
SkhQkS+qfrvePTlnf9WmJgIgQqpMPrHxcskJVpveKytyiNOdkATLTxE68snQ/9tj
NC4=
-----END CERTIFICATE-----
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
383487DEE25BE2D50AF2D97A34BAC1026979DAFC
Loading

0 comments on commit 9a24e4d

Please sign in to comment.