Make Hardware Key unit test interactive (#32235)

* Make yubikey unit test interactive and add to test plan.

* Move yubikey hardware signer method tests to interactive yubikey test.

* Remove hardware key interactive unit test from testplan
This commit is contained in:
Brian Joerger 2023-09-27 11:55:47 -07:00 committed by GitHub
parent eb82a9b5db
commit f87c46ad73
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 43 additions and 44 deletions

View file

@ -1,5 +1,3 @@
//go:build piv
/*
Copyright 2022 Gravitational, Inc.
@ -19,11 +17,9 @@ limitations under the License.
package keys_test
import (
"context"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"os"
"testing"
"github.com/stretchr/testify/require"
@ -31,30 +27,10 @@ import (
"github.com/gravitational/teleport/api/utils/keys"
)
// TestHardwareSigner tests the HardwareSigner interface with hardware keys.
func TestHardwareSigner(t *testing.T) {
// The rest of the test expects a yubiKey to be connected with default PIV settings
// and will overwrite any PIV data on the yubiKey.
if os.Getenv("TELEPORT_TEST_YUBIKEY_PIV") == "" {
t.Skipf("Skipping TestGenerateYubiKeyPrivateKey because TELEPORT_TEST_YUBIKEY_PIV is not set")
}
ctx := context.Background()
resetYubikey(ctx, t)
// Generate a new YubiKeyPrivateKey. It should return a valid attestation statement and key policy.
priv, err := keys.GetOrGenerateYubiKeyPrivateKey(false)
require.NoError(t, err)
att, err := keys.GetAttestationStatement(priv)
require.NoError(t, err)
require.NotNil(t, att)
policy := keys.GetPrivateKeyPolicy(priv)
require.Equal(t, keys.PrivateKeyPolicyHardwareKey, policy)
}
// TestNonHardwareSigner tests the HardwareSigner interface with non-hardware keys.
//
// HardwareSigners require the piv go tag and should be tested individually in tests
// like `TestGetYubiKeyPrivateKey_Interactive`.
func TestNonHardwareSigner(t *testing.T) {
priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
require.NoError(t, err)

View file

@ -19,6 +19,7 @@ import (
"context"
"crypto/rand"
"crypto/x509/pkix"
"fmt"
"os"
"testing"
@ -28,35 +29,57 @@ import (
"github.com/gravitational/teleport/api/utils/prompt"
)
// TestGetOrGenerateYubiKeyPrivateKey tests GetOrGenerateYubiKeyPrivateKey.
func TestGetOrGenerateYubiKeyPrivateKey(t *testing.T) {
// TestGetYubiKeyPrivateKey_Interactive tests generation and retrieval of YubiKey private keys.
func TestGetYubiKeyPrivateKey_Interactive(t *testing.T) {
// This test expects a yubiKey to be connected with default PIV
// settings and will overwrite any PIV data on the yubiKey.
if os.Getenv("TELEPORT_TEST_YUBIKEY_PIV") == "" {
t.Skipf("Skipping TestGenerateYubiKeyPrivateKey because TELEPORT_TEST_YUBIKEY_PIV is not set")
}
if !testing.Verbose() {
t.Fatal("This test is interactive and must be called with the -v verbose flag to see touch prompts.")
}
fmt.Println("This test is interactive, tap your YubiKey when prompted.")
ctx := context.Background()
resetYubikey(ctx, t)
// Generate a new YubiKeyPrivateKey.
priv, err := keys.GetOrGenerateYubiKeyPrivateKey(false)
require.NoError(t, err)
for _, policy := range []keys.PrivateKeyPolicy{
keys.PrivateKeyPolicyHardwareKey,
keys.PrivateKeyPolicyHardwareKeyTouch,
} {
t.Run(fmt.Sprintf("policy:%q", policy), func(t *testing.T) {
t.Cleanup(func() { resetYubikey(ctx, t) })
// Test creating a self signed certificate with the key.
digest := make([]byte, 32)
_, err = priv.Sign(rand.Reader, digest, nil)
require.NoError(t, err)
// GetYubiKeyPrivateKey should generate a new YubiKeyPrivateKey.
priv, err := keys.GetOrGenerateYubiKeyPrivateKey(policy == keys.PrivateKeyPolicyHardwareKeyTouch)
require.NoError(t, err)
// Another call to GetOrGenerateYubiKeyPrivateKey should retrieve the previously generated key.
retrievePriv, err := keys.GetOrGenerateYubiKeyPrivateKey(false)
require.NoError(t, err)
require.Equal(t, priv, retrievePriv)
// test HardwareSigner methods
getPolicy := keys.GetPrivateKeyPolicy(priv)
require.Equal(t, policy, getPolicy)
// parsing the key's private key PEM should produce the same key as well.
retrieveKey, err := keys.ParsePrivateKey(priv.PrivateKeyPEM())
require.NoError(t, err)
require.Equal(t, priv, retrieveKey)
att, err := keys.GetAttestationStatement(priv)
require.NoError(t, err)
require.NotNil(t, att)
// Test Sign.
digest := make([]byte, 32)
_, err = priv.Sign(rand.Reader, digest, nil)
require.NoError(t, err)
// Another call to GetYubiKeyPrivateKey should retrieve the previously generated key.
retrievePriv, err := keys.GetOrGenerateYubiKeyPrivateKey(policy == keys.PrivateKeyPolicyHardwareKeyTouch)
require.NoError(t, err)
require.Equal(t, priv.Public(), retrievePriv.Public())
// parsing the key's private key PEM should produce the same key as well.
retrievePriv, err = keys.ParsePrivateKey(priv.PrivateKeyPEM())
require.NoError(t, err)
require.Equal(t, priv.Public(), retrievePriv.Public())
})
}
}
func TestOverwriteSlot(t *testing.T) {