-
Notifications
You must be signed in to change notification settings - Fork 148
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Credentialz-4 "This code is a Contribution to the OpenConfig Feature Profiles project ("Work") made under the Google Software Grant and Corporate Contributor License Agreement ("CLA") and governed by the Apache License 2.0. No other rights or licenses in or to any of Nokia's intellectual property are granted for any other purpose. This code is provided on an "as is" basis without any warranties of any kind." * Fix telemetry check "This code is a Contribution to the OpenConfig Feature Profiles project ("Work") made under the Google Software Grant and Corporate Contributor License Agreement ("CLA") and governed by the Apache License 2.0. No other rights or licenses in or to any of Nokia's intellectual property are granted for any other purpose. This code is provided on an "as is" basis without any warranties of any kind." * Credz library "This code is a Contribution to the OpenConfig Feature Profiles project ("Work") made under the Google Software Grant and Corporate Contributor License Agreement ("CLA") and governed by the Apache License 2.0. No other rights or licenses in or to any of Nokia's intellectual property are granted for any other purpose. This code is provided on an "as is" basis without any warranties of any kind."
- Loading branch information
Showing
3 changed files
with
191 additions
and
0 deletions.
There are no files selected for viewing
52 changes: 52 additions & 0 deletions
52
feature/security/gnsi/credentialz/tests/ssh_public_key_authentication/README.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
# Credentialz-4: SSH Public Key Authentication | ||
|
||
## Summary | ||
|
||
Test that Credentialz properly configures authorized SSH public keys for a given user, and that | ||
the DUT properly allows or disallows authentication based on the configured settings. | ||
|
||
|
||
## Procedure | ||
|
||
* Create a user ssh keypair with `ssh-keygen` | ||
* Set a username of `testuser` | ||
* Perform the following tests and assert the expected result: | ||
* Case 1: Failure | ||
* Attempt to ssh into the server with the `testuser` username, presenting the ssh key. | ||
* Assert that authentication has failed (because the key is not authorized) | ||
* Case 2: Success | ||
* Configure the previously created ssh public key as an authorized key for the | ||
`testuser` using gnsi.Credentialz/AuthorizedKeysRequest | ||
* Authenticate with the `testuser` username and the previously created public key via SSH | ||
* Assert that authentication has been successful | ||
* Ensure telemetry values for version and created-on match the values set by | ||
RotateHostParameters for | ||
`/oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:users/oc-sys:user/oc-sys:state:authorized-keys-list-version` | ||
and | ||
`/oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:users/oc-sys:user/oc-sys:state:authorized-keys-list-created-on` | ||
* Ensure that access accept telemetry counters are incremented | ||
`/oc-sys:system/oc-sys:ssh-server/oc-sys:state:counters:access-accepts` | ||
`/oc-sys:system/oc-sys:ssh-server/oc-sys:state:counters:last-access-accept` | ||
|
||
|
||
## 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. | ||
|
||
```yaml | ||
paths: | ||
## State Paths ## | ||
/system/aaa/authentication/users/user/state/authorized-keys-list-version: | ||
/system/aaa/authentication/users/user/state/authorized-keys-list-created-on: | ||
/system/ssh-server/state/counters/access-accepts: | ||
/system/ssh-server/state/counters/last-access-accept: | ||
|
||
rpcs: | ||
gnsi: | ||
credentialz.v1.Credentialz.RotateAccountCredentials: | ||
``` | ||
## Minimum DUT platform requirement | ||
N/A |
16 changes: 16 additions & 0 deletions
16
feature/security/gnsi/credentialz/tests/ssh_public_key_authentication/metadata.textproto
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
# proto-file: github.com/openconfig/featureprofiles/proto/metadata.proto | ||
# proto-message: Metadata | ||
|
||
uuid: "3e6294aa-8f9d-4c8d-9041-4a2f4cd84c36" | ||
plan_id: "Credentialz-4" | ||
description: "SSH Public Key Authentication" | ||
testbed: TESTBED_DUT | ||
|
||
platform_exceptions: { | ||
platform: { | ||
vendor: NOKIA | ||
} | ||
deviations: { | ||
ssh_server_counters_unsupported: true | ||
} | ||
} |
123 changes: 123 additions & 0 deletions
123
...nsi/credentialz/tests/ssh_public_key_authentication/ssh_public_key_authentication_test.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
// 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. | ||
// 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 sshpublickeyauthentication | ||
|
||
import ( | ||
"os" | ||
"testing" | ||
"time" | ||
|
||
"github.com/google/go-cmp/cmp" | ||
"github.com/openconfig/featureprofiles/internal/security/credz" | ||
|
||
"github.com/openconfig/featureprofiles/internal/deviations" | ||
"github.com/openconfig/featureprofiles/internal/fptest" | ||
"github.com/openconfig/ondatra" | ||
"github.com/openconfig/ondatra/gnmi" | ||
) | ||
|
||
const ( | ||
username = "testuser" | ||
authorizedKeysListVersion = "v1.0" | ||
) | ||
|
||
var ( | ||
authorizedKeysListCreatedOn = time.Now().Unix() | ||
) | ||
|
||
func TestMain(m *testing.M) { | ||
fptest.RunTests(m) | ||
} | ||
|
||
func TestCredentialz(t *testing.T) { | ||
dut := ondatra.DUT(t, "dut") | ||
target := credz.GetDutTarget(t, dut) | ||
|
||
// Create temporary directory for storing ssh keys/certificates. | ||
dir, err := os.MkdirTemp("", "") | ||
if err != nil { | ||
t.Fatalf("Creating temp dir, err: %s", err) | ||
} | ||
defer func(dir string) { | ||
err = os.RemoveAll(dir) | ||
if err != nil { | ||
t.Logf("Error removing temp directory, error: %s", err) | ||
} | ||
}(dir) | ||
|
||
credz.CreateSSHKeyPair(t, dir, username) | ||
credz.SetupUser(t, dut, username) | ||
|
||
t.Run("auth should fail ssh public key not authorized for user", func(t *testing.T) { | ||
_, err := credz.SSHWithKey(t, target, username, dir) | ||
if err == nil { | ||
t.Fatalf("Dialing ssh succeeded, but we expected to fail.") | ||
} | ||
}) | ||
|
||
t.Run("auth should succeed ssh public key authorized for user", func(t *testing.T) { | ||
// Push authorized key to the dut. | ||
credz.RotateAuthorizedKey(t, | ||
dut, | ||
dir, | ||
username, | ||
authorizedKeysListVersion, | ||
uint64(authorizedKeysListCreatedOn)) | ||
|
||
var startingAcceptCounter, startingLastAcceptTime uint64 | ||
if !deviations.SSHServerCountersUnsupported(dut) { | ||
startingAcceptCounter, startingLastAcceptTime = credz.GetAcceptTelemetry(t, dut) | ||
} | ||
|
||
// Verify ssh with key succeeds. | ||
_, err := credz.SSHWithKey(t, target, username, dir) | ||
if err != nil { | ||
t.Fatalf("Dialing ssh failed, but we expected to succeed. error: %v", err) | ||
} | ||
|
||
// Verify ssh counters. | ||
if !deviations.SSHServerCountersUnsupported(dut) { | ||
endingAcceptCounter, endingLastAcceptTime := credz.GetAcceptTelemetry(t, dut) | ||
if endingAcceptCounter <= startingAcceptCounter { | ||
t.Fatalf("SSH server accept counter did not increment after successful login. startCounter: %v, endCounter: %v", startingAcceptCounter, endingAcceptCounter) | ||
} | ||
if startingLastAcceptTime == endingLastAcceptTime { | ||
t.Fatalf("SSH server accept last timestamp did not update after successful login. Timestamp: %v", endingLastAcceptTime) | ||
} | ||
} | ||
|
||
// Verify authorized keys telemetry. | ||
userState := gnmi.Get(t, dut, gnmi.OC().System().Aaa().Authentication().User(username).State()) | ||
gotAuthorizedKeysListVersion := userState.GetAuthorizedKeysListVersion() | ||
if !cmp.Equal(gotAuthorizedKeysListVersion, authorizedKeysListVersion) { | ||
t.Fatalf( | ||
"Telemetry reports authorized keys list version is not correct\n\tgot: %s\n\twant: %s", | ||
gotAuthorizedKeysListVersion, authorizedKeysListVersion, | ||
) | ||
} | ||
gotAuthorizedKeysListCreatedOn := userState.GetAuthorizedKeysListCreatedOn() | ||
if !cmp.Equal(time.Unix(0, int64(gotAuthorizedKeysListCreatedOn)), time.Unix(authorizedKeysListCreatedOn, 0)) { | ||
t.Fatalf( | ||
"Telemetry reports authorized keys list version on is not correct\n\tgot: %d\n\twant: %d", | ||
gotAuthorizedKeysListCreatedOn, authorizedKeysListCreatedOn, | ||
) | ||
} | ||
}) | ||
|
||
t.Cleanup(func() { | ||
// Cleanup user authorized key after test. | ||
credz.RotateAuthorizedKey(t, dut, "", username, "", 0) | ||
}) | ||
} |