From 6b3f0ca9cb9c7d76b2aeec25d6e0aa5f8724e8cb Mon Sep 17 00:00:00 2001 From: Bruno Bressi <52347078+puffitos@users.noreply.github.com> Date: Fri, 20 Sep 2024 10:31:34 +0200 Subject: [PATCH] Refactor E2E test suite + add RSA tests (#60) * refactor: own struct for keys The tests have been refactored to use a dedicated struct for the private and public keys, which contains the key itself and the path to it. This will allow a bigger refactoring of the E2E tests, so that each test case can be run independently of what type of key is used for signing & validation Signed-off-by: Bruno Bressi * refactor: use private key variable Instead of hardcoding the path in all tests, the value is derived from the previously unused private key variable returned. This way, the tests can now be refactored to run by only passing the key creation function Signed-off-by: Bruno Bressi * refactor: [WIP] framework wraps testing.T The framework struct has been refactored to abstract the golang testing framework. This allows the E2E test cases to be written without having to create a new framework for each test. The framework functions now do not have to do a lot of micromanagement and cleanup; they just check whether an error has happened and they return. This allows for new functions to be written without having to think about whether to fail the test or not. The cleanup function takes care of the final step; cleaning up everything and then deciding whether the test failed or passed. Additionally, a new type is introduced, which will be used to wrap the tests cases, so they can be run used t.Run. * refactor: use new testing schema The test cases are now refactored to accept a signing function, so that the same test can be run regardless of RSA/ECDSA key without having to write too much duplicate code. The new fuction type is used for the signing function and each test case must now return the set of actions required for the use case to be tested, wrapped in a func which returns testing.T, so it may be run by the t.Run method. * chore: added E2E variable Added variable so that the additional E2E test is also executed. This test must be refactored in a future commit/ removed, as it depends on an image already being present on the machine running the test. * test: added rsa tests cases Each case tests for ECDSA keys is now also tested for RSA keys. The tests were also accelerated by reducing the delay between checks from 5s to 500m Signed-off-by: Bruno Bressi --------- Signed-off-by: Bruno Bressi --- Makefile | 2 +- test/framework/client.go | 196 ++++++++------ test/framework/cosign.go | 146 +++++++---- test/framework/cosign_test.go | 22 +- test/main_test.go | 31 ++- test/webhook_test.go | 471 +++++++++++----------------------- 6 files changed, 399 insertions(+), 469 deletions(-) diff --git a/Makefile b/Makefile index fc1669e..eb6a832 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ PORT := 5000 .PHONY: test-e2e test-e2e: @echo "Running e2e tests..." - @go test -v -race -count 1 ./test/ + @export COSIGN_E2E="42" && go test -v -race -count 1 ./test/ .PHONY: test-unit test-unit: diff --git a/test/framework/client.go b/test/framework/client.go index 0b2c073..301926c 100644 --- a/test/framework/client.go +++ b/test/framework/client.go @@ -18,9 +18,16 @@ import ( // the cosignwebhook in a k8s cluster type Framework struct { k8s *kubernetes.Clientset + t *testing.T + err error } -func New() (*Framework, error) { +// New creates a new Framework +func New(t *testing.T) (*Framework, error) { + if t == nil { + return nil, fmt.Errorf("test object must not be nil") + } + k8s, err := createClientSet() if err != nil { return nil, err @@ -28,6 +35,7 @@ func New() (*Framework, error) { return &Framework{ k8s: k8s, + t: t, }, nil } @@ -37,7 +45,6 @@ func createClientSet() (k8sClient *kubernetes.Clientset, err error) { kubeconfig = os.Getenv("HOME") + "/.kube/config" } - // create restconfig from kubeconfig config, err := clientcmd.BuildConfigFromFlags("", kubeconfig) if err != nil { return nil, err @@ -52,31 +59,33 @@ func createClientSet() (k8sClient *kubernetes.Clientset, err error) { // Cleanup removes all resources created by the framework // and cleans up the testing directory. -func (f *Framework) Cleanup(t testing.TB) { - cleanupKeys(t) - f.cleanupDeployments(t) - f.cleanupSecrets(t) +func (f *Framework) Cleanup() { + f.cleanupKeys() + f.cleanupDeployments() + f.cleanupSecrets() + if f.err != nil { + f.t.Fatal(f.err) + } } // cleanupDeployments removes all deployments from the testing namespace // if they exist -func (f *Framework) cleanupDeployments(t testing.TB) { +func (f *Framework) cleanupDeployments() { if f.k8s == nil { - t.Logf("k8s client is nil") return } - t.Logf("cleaning up deployments") + f.t.Logf("cleaning up deployments") deployments, err := f.k8s.AppsV1().Deployments("test-cases").List(context.Background(), metav1.ListOptions{}) if err != nil { - f.Cleanup(t) - t.Fatal(err) + f.err = err + return } for _, d := range deployments.Items { err = f.k8s.AppsV1().Deployments("test-cases").Delete(context.Background(), d.Name, metav1.DeleteOptions{}) if err != nil { - f.Cleanup(t) - t.Fatal(err) + f.err = err + return } } @@ -84,84 +93,102 @@ func (f *Framework) cleanupDeployments(t testing.TB) { for { select { case <-timeout: - f.Cleanup(t) + f.err = fmt.Errorf("timeout reached while waiting for deployments to be deleted") default: pods, err := f.k8s.CoreV1().Pods("test-cases").List(context.Background(), metav1.ListOptions{}) if err != nil { - f.Cleanup(t) - t.Fatal(err) + f.err = err + return } if len(pods.Items) == 0 { - t.Logf("All pods are deleted") + f.t.Logf("All pods are deleted") return } - time.Sleep(5 * time.Second) + time.Sleep(500 * time.Millisecond) } } } // cleanupSecrets removes all secrets from the testing namespace -func (f *Framework) cleanupSecrets(t testing.TB) { +func (f *Framework) cleanupSecrets() { if f.k8s == nil { - t.Logf("k8s client is nil") return } - t.Logf("cleaning up secrets") + f.t.Logf("cleaning up secrets") secrets, err := f.k8s.CoreV1().Secrets("test-cases").List(context.Background(), metav1.ListOptions{}) if err != nil { - f.Cleanup(t) - t.Fatal(err) + f.err = err + return } if len(secrets.Items) == 0 { + f.t.Log("no secrets to delete") return } for _, s := range secrets.Items { err = f.k8s.CoreV1().Secrets("test-cases").Delete(context.Background(), s.Name, metav1.DeleteOptions{}) if err != nil { - f.Cleanup(t) - t.Fatal(err) + f.err = err + return } } + f.t.Log("all secrets are deleted") } // GetPods returns the pod(s) of the deployment. The fetch is done by label selector (app=) // If the get request fails, the test will fail and the framework will be cleaned up -func (f *Framework) GetPods(t *testing.T, d appsv1.Deployment) *corev1.PodList { - pods, err := f.k8s.CoreV1().Pods("test-cases").List(context.Background(), metav1.ListOptions{ +func (f *Framework) GetPods(d appsv1.Deployment) *corev1.PodList { + if f.err != nil { + return nil + } + + pods, err := f.k8s.CoreV1().Pods(d.Namespace).List(context.Background(), metav1.ListOptions{ LabelSelector: fmt.Sprintf("app=%s", d.Name), }) if err != nil { - f.Cleanup(t) - t.Fatal(err) + f.err = err } return pods } // CreateDeployment creates a deployment in the testing namespace -func (f *Framework) CreateDeployment(t testing.TB, d appsv1.Deployment) { - _, err := f.k8s.AppsV1().Deployments("test-cases").Create(context.Background(), &d, metav1.CreateOptions{}) +func (f *Framework) CreateDeployment(d appsv1.Deployment) { + if f.err != nil { + return + } + + f.t.Logf("creating deployment %s", d.Name) + _, err := f.k8s.AppsV1().Deployments(d.Namespace).Create(context.Background(), &d, metav1.CreateOptions{}) if err != nil { - f.Cleanup(t) - t.Fatal(err) + f.err = err + return } + f.t.Logf("deployment %s created", d.Name) } // CreateSecret creates a secret in the testing namespace -func (f *Framework) CreateSecret(t *testing.T, secret corev1.Secret) { - t.Logf("creating secret %s", secret.Name) - s, err := f.k8s.CoreV1().Secrets("test-cases").Create(context.Background(), &secret, metav1.CreateOptions{}) +func (f *Framework) CreateSecret(s corev1.Secret) { + if f.err != nil { + return + } + + f.t.Logf("creating secret %s", s.Name) + _, err := f.k8s.CoreV1().Secrets(s.Namespace).Create(context.Background(), &s, metav1.CreateOptions{}) if err != nil { - f.Cleanup(t) - t.Fatal(err) + f.err = err + return } - t.Logf("created secret %s", s.Name) + f.t.Logf("secret %s created", s.Name) } // WaitForDeployment waits until the deployment is ready -func (f *Framework) WaitForDeployment(t *testing.T, d appsv1.Deployment) { - t.Logf("waiting for deployment %s to be ready", d.Name) +func (f *Framework) WaitForDeployment(d appsv1.Deployment) { + if f.err != nil { + return + } + + f.t.Logf("waiting for deployment %s to be ready", d.Name) // wait until the deployment is ready ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() @@ -169,39 +196,42 @@ func (f *Framework) WaitForDeployment(t *testing.T, d appsv1.Deployment) { FieldSelector: fmt.Sprintf("metadata.name=%s", d.Name), }) if err != nil { - f.Cleanup(t) - t.Fatal(err) + f.err = err + return } for { select { case <-ctx.Done(): - f.Cleanup(t) - t.Fatal("timeout reached while waiting for deployment to be ready") + f.err = fmt.Errorf("timeout reached while waiting for deployment to be ready") case event := <-w.ResultChan(): deployment, ok := event.Object.(*appsv1.Deployment) if !ok { - time.Sleep(5 * time.Second) + time.Sleep(500 * time.Millisecond) continue } if deployment.Status.ReadyReplicas == 1 { - t.Logf("deployment %s is ready", d.Name) + f.t.Logf("deployment %s is ready", d.Name) return } - time.Sleep(5 * time.Second) + time.Sleep(500 * time.Millisecond) } } } // waitForReplicaSetCreation waits for the replicaset of the given deployment to be created -func (f *Framework) waitForReplicaSetCreation(t *testing.T, d appsv1.Deployment) (string, error) { - rs, err := f.k8s.AppsV1().ReplicaSets("test-cases").Watch(context.Background(), metav1.ListOptions{ +func (f *Framework) waitForReplicaSetCreation(d appsv1.Deployment) string { + if f.err != nil { + return "" + } + + rs, err := f.k8s.AppsV1().ReplicaSets(d.Namespace).Watch(context.Background(), metav1.ListOptions{ LabelSelector: fmt.Sprintf("app=%s", d.Name), }) if err != nil { - f.Cleanup(t) - t.Fatal(err) + f.err = err + return "" } ctx, done := context.WithTimeout(context.Background(), 30*time.Second) @@ -210,37 +240,39 @@ func (f *Framework) waitForReplicaSetCreation(t *testing.T, d appsv1.Deployment) for { select { case <-ctx.Done(): - f.Cleanup(t) - t.Fatal("timeout reached while waiting for replicaset to be created") + f.err = fmt.Errorf("timeout reached while waiting for replicaset to be created") case event := <-rs.ResultChan(): rs, ok := event.Object.(*appsv1.ReplicaSet) if ok { - t.Logf("replicaset %s created", rs.Name) - return rs.Name, nil + f.t.Logf("replicaset %s created", rs.Name) + return rs.Name } - time.Sleep(5 * time.Second) + time.Sleep(500 * time.Millisecond) } } } // AssertDeploymentFailed asserts that the deployment cannot start -func (f *Framework) AssertDeploymentFailed(t *testing.T, d appsv1.Deployment) { - t.Logf("waiting for deployment %s to fail", d.Name) +func (f *Framework) AssertDeploymentFailed(d appsv1.Deployment) { + if f.err != nil { + return + } + + f.t.Logf("waiting for deployment %s to fail", d.Name) // watch for replicasets of the deployment - rsName, err := f.waitForReplicaSetCreation(t, d) - if err != nil { - f.Cleanup(t) - t.Fatal(err) + rsName := f.waitForReplicaSetCreation(d) + if rsName == "" { + return } // get warning events of deployment's namespace and check if the deployment failed - w, err := f.k8s.CoreV1().Events("test-cases").Watch(context.Background(), metav1.ListOptions{ + w, err := f.k8s.CoreV1().Events(d.Namespace).Watch(context.Background(), metav1.ListOptions{ FieldSelector: fmt.Sprintf("involvedObject.name=%s", rsName), }) if err != nil { - f.Cleanup(t) - t.Fatal(err) + f.err = err + return } ctx, done := context.WithTimeout(context.Background(), 30*time.Second) @@ -249,34 +281,37 @@ func (f *Framework) AssertDeploymentFailed(t *testing.T, d appsv1.Deployment) { for { select { case <-ctx.Done(): - f.Cleanup(t) - t.Fatal("timeout reached while waiting for deployment to fail") + f.err = fmt.Errorf("timeout reached while waiting for deployment to fail") case event := <-w.ResultChan(): e, ok := event.Object.(*corev1.Event) if !ok { - time.Sleep(5 * time.Second) + time.Sleep(500 * time.Millisecond) continue } if e.Reason == "FailedCreate" { - t.Logf("deployment %s failed: %s", d.Name, e.Message) + f.t.Logf("deployment %s failed: %s", d.Name, e.Message) return } - time.Sleep(5 * time.Second) + time.Sleep(500 * time.Millisecond) } } } // AssertEventForPod asserts that a PodVerified event is created -func (f *Framework) AssertEventForPod(t *testing.T, reason string, p corev1.Pod) { - t.Logf("waiting for %s event to be created for pod %s", reason, p.Name) +func (f *Framework) AssertEventForPod(reason string, p corev1.Pod) { + if f.err != nil { + return + } + + f.t.Logf("waiting for %s event to be created for pod %s", reason, p.Name) // watch for events of deployment's namespace and check if the podverified event is created - w, err := f.k8s.CoreV1().Events("test-cases").Watch(context.Background(), metav1.ListOptions{ + w, err := f.k8s.CoreV1().Events(p.Namespace).Watch(context.Background(), metav1.ListOptions{ FieldSelector: fmt.Sprintf("involvedObject.name=%s", p.Name), }) if err != nil { - f.Cleanup(t) - t.Fatal(err) + f.err = err + return } ctx, done := context.WithTimeout(context.Background(), 30*time.Second) @@ -285,19 +320,18 @@ func (f *Framework) AssertEventForPod(t *testing.T, reason string, p corev1.Pod) for { select { case <-ctx.Done(): - f.Cleanup(t) - t.Fatal("timeout reached while waiting for podverified event") + f.err = fmt.Errorf("timeout reached while waiting for event to be created") case event := <-w.ResultChan(): e, ok := event.Object.(*corev1.Event) if !ok { - time.Sleep(5 * time.Second) + time.Sleep(500 * time.Millisecond) continue } if e.Reason == reason { - t.Logf("%s event created for pod %s", reason, p.Name) + f.t.Logf("%s event created for pod %s", reason, p.Name) return } - time.Sleep(5 * time.Second) + time.Sleep(500 * time.Millisecond) } } } diff --git a/test/framework/cosign.go b/test/framework/cosign.go index dc05d4c..4a56beb 100644 --- a/test/framework/cosign.go +++ b/test/framework/cosign.go @@ -9,7 +9,6 @@ import ( "fmt" "os" "regexp" - "testing" "time" "github.com/sigstore/cosign/v2/cmd/cosign/cli/importkeypair" @@ -21,82 +20,123 @@ import ( const ImportKeySuffix = "imported" +// Pub contains the public key and its path +type Pub struct { + Key string + Path string +} + +// Priv contains the private key and its path +type Priv struct { + Key string + Path string +} + +// SignOptions is a struct to hold the options for signing a container +type SignOptions struct { + KeyPath string + Image string + SignatureRepo string +} + +// KeyFunc is a function that generates a keypair by using the testing framework +type KeyFunc func(f *Framework, name string) (Priv, Pub) + // cleanupKeys removes all keypair files from the testing directory -func cleanupKeys(t testing.TB) { - t.Logf("cleaning up keypair files") +func (f *Framework) cleanupKeys() { + f.t.Logf("cleaning up keypair files") files, err := os.ReadDir(".") if err != nil { - t.Fatalf("failed reading directory: %v", err) + f.err = fmt.Errorf("failed reading directory: %v", err) + return } - for _, f := range files { - if f.IsDir() { + for _, file := range files { + if file.IsDir() { continue } reKey := regexp.MustCompile(".*.key") rePub := regexp.MustCompile(".*.pub") - if reKey.MatchString(f.Name()) || rePub.MatchString(f.Name()) { - err = os.Remove(f.Name()) + if reKey.MatchString(file.Name()) || rePub.MatchString(file.Name()) { + err = os.Remove(file.Name()) if err != nil { - t.Fatalf("failed removing file %s: %v", f.Name(), err) + f.err = fmt.Errorf("failed to remove file: %v", err) + return } } } - t.Logf("cleaned up keypair files") + f.t.Logf("cleaned up keypair files") } -// CreateKeys creates a signing keypair for cosing with the provided name -func (f *Framework) CreateKeys(t testing.TB, name string) (private string, public string) { +// CreateECDSAKeyPair generates an ECDSA keypair and saves the keys to the current directory +func CreateECDSAKeyPair(f *Framework, name string) (Priv, Pub) { + if f.err != nil { + return Priv{}, Pub{} + } + args := []string{fmt.Sprintf("--output-key-prefix=%s", name)} err := os.Setenv("COSIGN_PASSWORD", "") if err != nil { - t.Fatalf("failed setting COSIGN_PASSWORD: %v", err) + f.err = err + return Priv{}, Pub{} } cmd := cli.GenerateKeyPair() cmd.SetArgs(args) err = cmd.Execute() if err != nil { - f.Cleanup(t) + f.err = err + return Priv{}, Pub{} } // read private key and public key from the current directory privateKey, err := os.ReadFile(fmt.Sprintf("%s.key", name)) if err != nil { - f.Cleanup(t) + f.err = err + return Priv{}, Pub{} } pubKey, err := os.ReadFile(fmt.Sprintf("%s.pub", name)) if err != nil { - f.Cleanup(t) + f.err = err + return Priv{}, Pub{} } - return string(privateKey), string(pubKey) + return Priv{ + Key: string(privateKey), + Path: fmt.Sprintf("%s.key", name), + }, Pub{ + Key: string(pubKey), + Path: fmt.Sprintf("%s.pub", name), + } } -// CreateRSAKeyPair creates an RSA keypair for signing with the provided name -func (f *Framework) CreateRSAKeyPair(t *testing.T, name string) (private string, public string) { - priv, err := rsa.GenerateKey(rand.Reader, 2048) - if err != nil { - f.Cleanup(t) - t.Fatal(err) +// CreateRSAKeyPair generates an RSA keypair and saves the keys to the current directory +func CreateRSAKeyPair(f *Framework, name string) (Priv, Pub) { + if f.err != nil { + return Priv{}, Pub{} } + pkey, err := rsa.GenerateKey(rand.Reader, 2048) + if err != nil { + f.err = fmt.Errorf("failed to generate RSA key: %v", err) + return Priv{}, Pub{} + } privBytes := pem.EncodeToMemory(&pem.Block{ Type: "RSA PRIVATE KEY", - Bytes: x509.MarshalPKCS1PrivateKey(priv), + Bytes: x509.MarshalPKCS1PrivateKey(pkey), }) err = os.WriteFile(fmt.Sprintf("%s.key", name), privBytes, 0o644) if err != nil { - t.Errorf("failed to write private key to file: %v", err) - return "", "" + f.err = fmt.Errorf("failed to write private key to file: %v", err) + return Priv{}, Pub{} } // Generate and save the public key to a PEM file - pub := &priv.PublicKey + pubKey := &pkey.PublicKey - pubASN1, err := x509.MarshalPKIXPublicKey(pub) + pubASN1, err := x509.MarshalPKIXPublicKey(pubKey) if err != nil { - f.Cleanup(t) - t.Fatal(err) + f.err = fmt.Errorf("failed to marshal public key: %v", err) + return Priv{}, Pub{} } pubBytes := pem.EncodeToMemory(&pem.Block{ Type: "PUBLIC KEY", @@ -104,53 +144,56 @@ func (f *Framework) CreateRSAKeyPair(t *testing.T, name string) (private string, }) err = os.WriteFile(fmt.Sprintf("%s.pub", name), pubBytes, 0o644) if err != nil { - t.Errorf("failed to write public key to file: %v", err) - return "", "" + f.err = fmt.Errorf("failed to write public key to file: %v", err) + return Priv{}, Pub{} } - t.Setenv("COSIGN_PASSWORD", "") + f.t.Setenv("COSIGN_PASSWORD", "") // import the keypair into cosign for signing err = importkeypair.ImportKeyPairCmd(context.Background(), options.ImportKeyPairOptions{ Key: fmt.Sprintf("%s.key", name), OutputKeyPrefix: fmt.Sprintf("%s-%s", name, ImportKeySuffix), }, []string{}) if err != nil { - t.Errorf("failed to import keypair to cosign: %v", err) - return "", "" + f.err = fmt.Errorf("failed to import keypair: %v", err) + return Priv{}, Pub{} } // read private key and public key from the current directory privBytes, err = os.ReadFile(fmt.Sprintf("%s-%s.key", name, ImportKeySuffix)) if err != nil { - f.Cleanup(t) - t.Fatal(err) + f.err = fmt.Errorf("failed reading private key: %v", err) + return Priv{}, Pub{} } pubBytes, err = os.ReadFile(fmt.Sprintf("%s-%s.pub", name, ImportKeySuffix)) if err != nil { - f.Cleanup(t) - t.Fatal(err) + f.err = fmt.Errorf("failed reading public key: %v", err) + return Priv{}, Pub{} } - return string(privBytes), string(pubBytes) + return Priv{ + Key: string(privBytes), + Path: fmt.Sprintf("%s-%s.key", name, ImportKeySuffix), + }, Pub{ + Key: string(pubBytes), + Path: fmt.Sprintf("%s-%s.pub", name, ImportKeySuffix), + } } -// SignOptions is a struct to hold the options for signing a container -type SignOptions struct { - KeyPath string - Image string - SignatureRepo string -} +// SignContainer signs the container using the provided SignOptions +func (f *Framework) SignContainer(opts SignOptions) { + if f.err != nil { + return + } -// SignContainer signs the container with the provided private key -func (f *Framework) SignContainer(t *testing.T, opts SignOptions) { // get SHA of the container image - t.Setenv("COSIGN_PASSWORD", "") + f.t.Setenv("COSIGN_PASSWORD", "") // if the signature repository is different from the image, set the COSIGN_REPOSITORY environment variable // to push the signature to the specified repository if opts.SignatureRepo != opts.Image { - t.Setenv("COSIGN_REPOSITORY", opts.SignatureRepo) + f.t.Setenv("COSIGN_REPOSITORY", opts.SignatureRepo) } err := sign.SignCmd( &options.RootOptions{ @@ -167,7 +210,6 @@ func (f *Framework) SignContainer(t *testing.T, opts SignOptions) { []string{opts.Image}, ) if err != nil { - f.Cleanup(t) - t.Fatal(err) + f.err = fmt.Errorf("failed to sign container: %v", err) } } diff --git a/test/framework/cosign_test.go b/test/framework/cosign_test.go index 83754fe..a156b99 100644 --- a/test/framework/cosign_test.go +++ b/test/framework/cosign_test.go @@ -16,11 +16,13 @@ func TestFramework_CreateRSAKeyPair(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - f := &Framework{} - priv, pub := f.CreateRSAKeyPair(t, tt.name) - defer f.Cleanup(t) + f := &Framework{ + t: t, + } + defer f.Cleanup() + private, public := CreateRSAKeyPair(f, tt.name) - if priv == "" || pub == "" { + if private.Key == "" || public.Key == "" { t.Fatal("failed to create RSA key pair") } @@ -67,11 +69,13 @@ func TestFramework_SignContainer_RSA(t *testing.T) { t.Skip() } - f := &Framework{} + f := &Framework{ + t: t, + } + defer f.Cleanup() name := "testkey" - priv, pub := f.CreateRSAKeyPair(t, name) - defer f.Cleanup(t) - if priv == "" || pub == "" { + private, public := CreateRSAKeyPair(f, name) + if private.Key == "" || public.Key == "" { t.Fatal("failed to create RSA key pair") } @@ -84,7 +88,7 @@ func TestFramework_SignContainer_RSA(t *testing.T) { t.Fatal("failed to create public key") } - f.SignContainer(t, SignOptions{ + f.SignContainer(SignOptions{ KeyPath: fmt.Sprintf("%s-%s.key", name, ImportKeySuffix), Image: "k3d-registry.localhost:5000/busybox:first", }) diff --git a/test/main_test.go b/test/main_test.go index 43aa93c..32fa1d0 100644 --- a/test/main_test.go +++ b/test/main_test.go @@ -1,13 +1,16 @@ package test import ( + "fmt" "testing" + + "github.com/eumel8/cosignwebhook/test/framework" ) -// TestPassingDeployments tests deployments that should pass signature verification -func TestPassingDeployments(t *testing.T) { - testFuncs := map[string]func(t *testing.T){ - "OneContainerSinglePubKeyEnvRef": testOneContainerSinglePubKeyEnvRef, +// TestPassECDSA tests deployments that should pass signature verification +func TestPassECDSA(t *testing.T) { + testFuncs := map[string]func(fw *framework.Framework, kf framework.KeyFunc, key string) func(t *testing.T){ + "OneContainerSinglePubKeyEnvRef": oneContainerSinglePubKeyEnvRef, "TwoContainersSinglePubKeyEnvRef": testTwoContainersSinglePubKeyEnvRef, "OneContainerSinglePubKeySecretRef": testOneContainerSinglePubKeySecretRef, "TwoContainersSinglePubKeyMixedRef": testTwoContainersSinglePubKeyMixedRef, @@ -16,25 +19,35 @@ func TestPassingDeployments(t *testing.T) { "EventEmittedOnSignatureVerification": testEventEmittedOnSignatureVerification, "EventEmittedOnNoSignatureVerification": testEventEmittedOnNoSignatureVerification, "OneContainerWIthCosignRepository": testOneContainerWithCosignRepository, - "OneContainerSinglePubKeyEnvRefRSA": testOneContainerSinglePubKeyEnvRefRSA, - "TwoContainersSinglePubKeyEnvRefRSA": TestTwoContainersSinglePubKeyEnvRefRSA, + } + + fw, err := framework.New(t) + if err != nil { + t.Fatal(err) } for name, tf := range testFuncs { - t.Run(name, tf) + t.Run(fmt.Sprintf("[%s] %s", "ECDSA", name), tf(fw, framework.CreateECDSAKeyPair, name)) + t.Run(fmt.Sprintf("[%s] %s", "RSA", name), tf(fw, framework.CreateRSAKeyPair, name)) } } // TestFailingDeployments tests deployments that should fail signature verification func TestFailingDeployments(t *testing.T) { - testFuncs := map[string]func(t *testing.T){ + testFuncs := map[string]func(fw *framework.Framework, kf framework.KeyFunc, key string) func(t *testing.T){ "OneContainerSinglePubKeyMalformedEnvRef": testOneContainerSinglePubKeyMalformedEnvRef, "TwoContainersSinglePubKeyMalformedEnvRef": testTwoContainersSinglePubKeyMalformedEnvRef, "OneContainerSinglePubKeyNoMatchEnvRef": testOneContainerSinglePubKeyNoMatchEnvRef, "OneContainerWithCosingRepoVariableMissing": testOneContainerWithCosingRepoVariableMissing, } + fw, err := framework.New(t) + if err != nil { + t.Fatal(err) + } + for name, tf := range testFuncs { - t.Run(name, tf) + t.Run(name, tf(fw, framework.CreateECDSAKeyPair, name)) + t.Run(name, tf(fw, framework.CreateRSAKeyPair, name)) } } diff --git a/test/webhook_test.go b/test/webhook_test.go index b2da4e7..ee4a8d7 100644 --- a/test/webhook_test.go +++ b/test/webhook_test.go @@ -1,7 +1,6 @@ package test import ( - "fmt" "testing" "github.com/eumel8/cosignwebhook/test/framework" @@ -20,17 +19,12 @@ const ( signatureRepo = "k3d-registry.localhost:5000/sigs" ) -// testOneContainerSinglePubKeyEnvRef tests that a deployment with a single signed container, +// oneContainerSinglePubKeyEnvRef tests that a deployment with a single signed container, // with a public key provided via an environment variable, succeeds. -func testOneContainerSinglePubKeyEnvRef(t *testing.T) { - fw, err := framework.New() - if err != nil { - t.Fatal(err) - } - - _, pub := fw.CreateKeys(t, "test") - fw.SignContainer(t, framework.SignOptions{ - KeyPath: "test.key", +func oneContainerSinglePubKeyEnvRef(fw *framework.Framework, keyFunc framework.KeyFunc, key string) func(t *testing.T) { + priv, pub := keyFunc(fw, key) + fw.SignContainer(framework.SignOptions{ + KeyPath: priv.Path, Image: busyboxOne, }) @@ -62,7 +56,7 @@ func testOneContainerSinglePubKeyEnvRef(t *testing.T) { Env: []corev1.EnvVar{ { Name: webhook.CosignEnvVar, - Value: pub, + Value: pub.Key, }, }, }, @@ -72,26 +66,23 @@ func testOneContainerSinglePubKeyEnvRef(t *testing.T) { }, } - fw.CreateDeployment(t, depl) - fw.WaitForDeployment(t, depl) - fw.Cleanup(t) + return func(t *testing.T) { + fw.CreateDeployment(depl) + fw.WaitForDeployment(depl) + fw.Cleanup() + } } // testTwoContainersSinglePubKeyEnvRef tests that a deployment with two signed containers, // with a public key provided via an environment variable, succeeds. -func testTwoContainersSinglePubKeyEnvRef(t *testing.T) { - fw, err := framework.New() - if err != nil { - t.Fatal(err) - } - - _, pub := fw.CreateKeys(t, "test") - fw.SignContainer(t, framework.SignOptions{ - KeyPath: "test.key", +func testTwoContainersSinglePubKeyEnvRef(fw *framework.Framework, kf framework.KeyFunc, key string) func(*testing.T) { + priv, pub := kf(fw, key) + fw.SignContainer(framework.SignOptions{ + KeyPath: priv.Path, Image: busyboxOne, }) - fw.SignContainer(t, framework.SignOptions{ - KeyPath: "test.key", + fw.SignContainer(framework.SignOptions{ + KeyPath: priv.Path, Image: busyboxTwo, }) @@ -123,7 +114,7 @@ func testTwoContainersSinglePubKeyEnvRef(t *testing.T) { Env: []corev1.EnvVar{ { Name: webhook.CosignEnvVar, - Value: pub, + Value: pub.Key, }, }, }, @@ -138,7 +129,7 @@ func testTwoContainersSinglePubKeyEnvRef(t *testing.T) { Env: []corev1.EnvVar{ { Name: webhook.CosignEnvVar, - Value: pub, + Value: pub.Key, }, }, }, @@ -148,22 +139,19 @@ func testTwoContainersSinglePubKeyEnvRef(t *testing.T) { }, } - fw.CreateDeployment(t, depl) - fw.WaitForDeployment(t, depl) - fw.Cleanup(t) + return func(*testing.T) { + fw.CreateDeployment(depl) + fw.WaitForDeployment(depl) + fw.Cleanup() + } } // testOneContainerPubKeySecret tests that a deployment with a single signed container, // with a public key provided via a secret, succeeds. -func testOneContainerSinglePubKeySecretRef(t *testing.T) { - fw, err := framework.New() - if err != nil { - t.Fatal(err) - } - - _, pub := fw.CreateKeys(t, "test") - fw.SignContainer(t, framework.SignOptions{ - KeyPath: "test.key", +func testOneContainerSinglePubKeySecretRef(fw *framework.Framework, kf framework.KeyFunc, key string) func(*testing.T) { + priv, pub := kf(fw, key) + fw.SignContainer(framework.SignOptions{ + KeyPath: priv.Path, Image: busyboxOne, }) @@ -174,7 +162,7 @@ func testOneContainerSinglePubKeySecretRef(t *testing.T) { Namespace: "test-cases", }, StringData: map[string]string{ - "cosign.pub": pub, + "cosign.pub": pub.Key, }, } @@ -223,28 +211,25 @@ func testOneContainerSinglePubKeySecretRef(t *testing.T) { }, } - fw.CreateSecret(t, secret) - fw.CreateDeployment(t, depl) - fw.WaitForDeployment(t, depl) - fw.Cleanup(t) + return func(*testing.T) { + fw.CreateSecret(secret) + fw.CreateDeployment(depl) + fw.WaitForDeployment(depl) + fw.Cleanup() + } } // testTwoContainersMixedPubKeyMixedRef tests that a deployment with two signed containers with two different public keys, // with the keys provided by a secret and an environment variable, succeeds. -func testTwoContainersMixedPubKeyMixedRef(t *testing.T) { - fw, err := framework.New() - if err != nil { - t.Fatal(err) - } - - _, pub1 := fw.CreateKeys(t, "test1") - _, pub2 := fw.CreateKeys(t, "test2") - fw.SignContainer(t, framework.SignOptions{ - KeyPath: "test1.key", +func testTwoContainersMixedPubKeyMixedRef(fw *framework.Framework, kf framework.KeyFunc, key string) func(*testing.T) { + priv1, pub1 := framework.CreateECDSAKeyPair(fw, "test1") + priv2, pub2 := framework.CreateECDSAKeyPair(fw, "test2") + fw.SignContainer(framework.SignOptions{ + KeyPath: priv1.Path, Image: busyboxOne, }) - fw.SignContainer(t, framework.SignOptions{ - KeyPath: "test2.key", + fw.SignContainer(framework.SignOptions{ + KeyPath: priv2.Path, Image: busyboxTwo, }) @@ -255,7 +240,7 @@ func testTwoContainersMixedPubKeyMixedRef(t *testing.T) { Namespace: "test-cases", }, StringData: map[string]string{ - "cosign.pub": pub1, + "cosign.pub": pub1.Key, }, } @@ -277,7 +262,7 @@ func testTwoContainersMixedPubKeyMixedRef(t *testing.T) { TerminationGracePeriodSeconds: &terminationGracePeriodSeconds, Containers: []corev1.Container{ { - Name: "two-containers-mixed-pub-keyrefs-first", + Name: "two-containers-mixed-pub-keyrefs-from-secret", Image: busyboxOne, Command: []string{ "sh", @@ -299,7 +284,7 @@ func testTwoContainersMixedPubKeyMixedRef(t *testing.T) { }, }, { - Name: "two-containers-mixed-pub-keyrefs-second", + Name: "two-containers-mixed-pub-keyrefs-second-from-env", Image: busyboxTwo, Command: []string{ "sh", @@ -309,7 +294,7 @@ func testTwoContainersMixedPubKeyMixedRef(t *testing.T) { Env: []corev1.EnvVar{ { Name: webhook.CosignEnvVar, - Value: pub2, + Value: pub2.Key, }, }, }, @@ -319,27 +304,24 @@ func testTwoContainersMixedPubKeyMixedRef(t *testing.T) { }, } - fw.CreateSecret(t, secret) - fw.CreateDeployment(t, depl) - fw.WaitForDeployment(t, depl) - fw.Cleanup(t) + return func(*testing.T) { + fw.CreateSecret(secret) + fw.CreateDeployment(depl) + fw.WaitForDeployment(depl) + fw.Cleanup() + } } // testTwoContainersSinglePubKeyMixedRef tests that a deployment with two signed containers, // with a public key provided via a secret and an environment variable, succeeds. -func testTwoContainersSinglePubKeyMixedRef(t *testing.T) { - fw, err := framework.New() - if err != nil { - t.Fatal(err) - } - - _, pub := fw.CreateKeys(t, "test") - fw.SignContainer(t, framework.SignOptions{ - KeyPath: "test.key", +func testTwoContainersSinglePubKeyMixedRef(fw *framework.Framework, kf framework.KeyFunc, key string) func(*testing.T) { + priv, pub := kf(fw, key) + fw.SignContainer(framework.SignOptions{ + KeyPath: priv.Path, Image: busyboxOne, }) - fw.SignContainer(t, framework.SignOptions{ - KeyPath: "test.key", + fw.SignContainer(framework.SignOptions{ + KeyPath: priv.Path, Image: busyboxTwo, }) @@ -350,7 +332,7 @@ func testTwoContainersSinglePubKeyMixedRef(t *testing.T) { Namespace: "test-cases", }, StringData: map[string]string{ - "cosign.pub": pub, + "cosign.pub": pub.Key, }, } @@ -404,7 +386,7 @@ func testTwoContainersSinglePubKeyMixedRef(t *testing.T) { Env: []corev1.EnvVar{ { Name: webhook.CosignEnvVar, - Value: pub, + Value: pub.Key, }, }, }, @@ -414,27 +396,24 @@ func testTwoContainersSinglePubKeyMixedRef(t *testing.T) { }, } - fw.CreateSecret(t, secret) - fw.CreateDeployment(t, depl) - fw.WaitForDeployment(t, depl) - fw.Cleanup(t) + return func(*testing.T) { + fw.CreateSecret(secret) + fw.CreateDeployment(depl) + fw.WaitForDeployment(depl) + fw.Cleanup() + } } // testTwoContainersSinglePubKeyMixedRef tests that a deployment with two signed containers, // with a public key provided via a secret and an environment variable, succeeds. -func testTwoContainersWithInitSinglePubKeyMixedRef(t *testing.T) { - fw, err := framework.New() - if err != nil { - t.Fatal(err) - } - - _, pub := fw.CreateKeys(t, "test") - fw.SignContainer(t, framework.SignOptions{ - KeyPath: "test.key", +func testTwoContainersWithInitSinglePubKeyMixedRef(fw *framework.Framework, kf framework.KeyFunc, key string) func(*testing.T) { + priv, pub := kf(fw, key) + fw.SignContainer(framework.SignOptions{ + KeyPath: priv.Path, Image: busyboxOne, }) - fw.SignContainer(t, framework.SignOptions{ - KeyPath: "test.key", + fw.SignContainer(framework.SignOptions{ + KeyPath: priv.Path, Image: busyboxTwo, }) @@ -445,7 +424,7 @@ func testTwoContainersWithInitSinglePubKeyMixedRef(t *testing.T) { Namespace: "test-cases", }, StringData: map[string]string{ - "cosign.pub": pub, + "cosign.pub": pub.Key, }, } @@ -501,7 +480,7 @@ func testTwoContainersWithInitSinglePubKeyMixedRef(t *testing.T) { Env: []corev1.EnvVar{ { Name: webhook.CosignEnvVar, - Value: pub, + Value: pub.Key, }, }, }, @@ -511,23 +490,20 @@ func testTwoContainersWithInitSinglePubKeyMixedRef(t *testing.T) { }, } - fw.CreateSecret(t, secret) - fw.CreateDeployment(t, depl) - fw.WaitForDeployment(t, depl) - fw.Cleanup(t) + return func(*testing.T) { + fw.CreateSecret(secret) + fw.CreateDeployment(depl) + fw.WaitForDeployment(depl) + fw.Cleanup() + } } // testEventEmittedOnSignatureVerification tests // that an event is emitted when a deployment passes signature verification -func testEventEmittedOnSignatureVerification(t *testing.T) { - fw, err := framework.New() - if err != nil { - t.Fatal(err) - } - - _, pub := fw.CreateKeys(t, "test") - fw.SignContainer(t, framework.SignOptions{ - KeyPath: "test.key", +func testEventEmittedOnSignatureVerification(fw *framework.Framework, kf framework.KeyFunc, key string) func(*testing.T) { + priv, pub := kf(fw, key) + fw.SignContainer(framework.SignOptions{ + KeyPath: priv.Path, Image: busyboxOne, }) @@ -559,7 +535,7 @@ func testEventEmittedOnSignatureVerification(t *testing.T) { Env: []corev1.EnvVar{ { Name: webhook.CosignEnvVar, - Value: pub, + Value: pub.Key, }, }, }, @@ -569,19 +545,16 @@ func testEventEmittedOnSignatureVerification(t *testing.T) { }, } - fw.CreateDeployment(t, depl) - fw.WaitForDeployment(t, depl) - pod := fw.GetPods(t, depl) - fw.AssertEventForPod(t, "PodVerified", pod.Items[0]) - fw.Cleanup(t) -} - -func testEventEmittedOnNoSignatureVerification(t *testing.T) { - fw, err := framework.New() - if err != nil { - t.Fatal(err) + return func(*testing.T) { + fw.CreateDeployment(depl) + fw.WaitForDeployment(depl) + pod := fw.GetPods(depl) + fw.AssertEventForPod("PodVerified", pod.Items[0]) + fw.Cleanup() } +} +func testEventEmittedOnNoSignatureVerification(fw *framework.Framework, kf framework.KeyFunc, key string) func(*testing.T) { // create a deployment with a single unsigned container depl := appsv1.Deployment{ ObjectMeta: metav1.ObjectMeta{ @@ -610,26 +583,23 @@ func testEventEmittedOnNoSignatureVerification(t *testing.T) { }, } - fw.CreateDeployment(t, depl) - fw.WaitForDeployment(t, depl) - pl := fw.GetPods(t, depl) - fw.AssertEventForPod(t, "NoVerification", pl.Items[0]) - fw.Cleanup(t) + return func(t *testing.T) { + fw.CreateDeployment(depl) + fw.WaitForDeployment(depl) + pl := fw.GetPods(depl) + fw.AssertEventForPod("NoVerification", pl.Items[0]) + fw.Cleanup() + } } // testOneContainerWithCosignRepository tests that a deployment with a single signed container, // with a public key provided via a secret succeeds. // The signature for the container is present in the repository // defined in the environment variables of the container. -func testOneContainerWithCosignRepository(t *testing.T) { - fw, err := framework.New() - if err != nil { - t.Fatal(err) - } - - _, pub := fw.CreateKeys(t, "test") - fw.SignContainer(t, framework.SignOptions{ - KeyPath: "test.key", +func testOneContainerWithCosignRepository(fw *framework.Framework, kf framework.KeyFunc, key string) func(*testing.T) { + priv, pub := kf(fw, key) + fw.SignContainer(framework.SignOptions{ + KeyPath: priv.Path, Image: busyboxOne, SignatureRepo: signatureRepo, }) @@ -641,7 +611,7 @@ func testOneContainerWithCosignRepository(t *testing.T) { Namespace: "test-cases", }, StringData: map[string]string{ - "cosign.pub": pub, + "cosign.pub": pub.Key, }, } @@ -694,153 +664,21 @@ func testOneContainerWithCosignRepository(t *testing.T) { }, } - fw.CreateSecret(t, secret) - fw.CreateDeployment(t, depl) - fw.WaitForDeployment(t, depl) - fw.Cleanup(t) -} - -// testOneContainerSinglePubKeyEnvRefRSA tests that a deployment with a single signed container, -// with a public key provided via an environment variable, succeeds. The keypair used for this test is an RSA keypair. -func testOneContainerSinglePubKeyEnvRefRSA(t *testing.T) { - fw, err := framework.New() - if err != nil { - t.Fatal(err) - } - - _, pub := fw.CreateRSAKeyPair(t, "test") - fw.SignContainer(t, framework.SignOptions{ - KeyPath: fmt.Sprintf("test-%s.key", framework.ImportKeySuffix), - Image: busyboxOne, - }) - - // create a deployment with a single signed container and a public key provided via an environment variable - depl := appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "one-container-env-ref-rsa", - Namespace: "test-cases", - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{"app": "one-container-env-ref-rsa"}, - }, - Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{"app": "one-container-env-ref-rsa"}, - }, - Spec: corev1.PodSpec{ - TerminationGracePeriodSeconds: &terminationGracePeriodSeconds, - Containers: []corev1.Container{ - { - Name: "one-container-env-ref-rsa", - Image: busyboxOne, - Command: []string{ - "sh", - "-c", - "while true; do echo 'hello world, i am tired and will sleep now'; sleep 60; done", - }, - Env: []corev1.EnvVar{ - { - Name: webhook.CosignEnvVar, - Value: pub, - }, - }, - }, - }, - }, - }, - }, - } - - fw.CreateDeployment(t, depl) - fw.WaitForDeployment(t, depl) - fw.Cleanup(t) -} - -func TestTwoContainersSinglePubKeyEnvRefRSA(t *testing.T) { - fw, err := framework.New() - if err != nil { - t.Fatal(err) - } - - // Create a deployment with two containers signed by the same RSA key - _, rsaPub := fw.CreateRSAKeyPair(t, "test") - fw.SignContainer(t, framework.SignOptions{ - KeyPath: fmt.Sprintf("test-%s.key", framework.ImportKeySuffix), - Image: busyboxOne, - }) - fw.SignContainer(t, framework.SignOptions{ - KeyPath: fmt.Sprintf("test-%s.key", framework.ImportKeySuffix), - Image: busyboxTwo, - }) - - depl := appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "two-containers-single-pubkey-envref", - Namespace: "test-cases", - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{"app": "two-containers-single-pubkey-envref"}, - }, - Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{"app": "two-containers-single-pubkey-envref"}, - }, - Spec: corev1.PodSpec{ - TerminationGracePeriodSeconds: &terminationGracePeriodSeconds, - Containers: []corev1.Container{ - { - Name: "two-containers-same-rsa-pub-key-env-ref-first", - Image: busyboxOne, - Command: []string{ - "sh", "-c", - "echo 'hello world, i am tired and will sleep now'; sleep 60", - }, - Env: []corev1.EnvVar{ - { - Name: webhook.CosignEnvVar, - Value: rsaPub, - }, - }, - }, - { - Name: "two-containers-same-rsa-pub-key-env-ref-second", - Image: busyboxTwo, - Command: []string{ - "sh", "-c", - "echo 'hello world, i am tired and will sleep now'; sleep 60", - }, - Env: []corev1.EnvVar{ - { - Name: webhook.CosignEnvVar, - Value: rsaPub, - }, - }, - }, - }, - }, - }, - }, + return func(*testing.T) { + fw.CreateSecret(secret) + fw.CreateDeployment(depl) + fw.WaitForDeployment(depl) + fw.Cleanup() } - - fw.CreateDeployment(t, depl) - fw.WaitForDeployment(t, depl) - fw.Cleanup(t) } // testOneContainerSinglePubKeyNoMatchEnvRef tests that a deployment with a single signed container, // with a public key provided via an environment variable, fails if the public key does not match the signature. -func testOneContainerSinglePubKeyNoMatchEnvRef(t *testing.T) { - fw, err := framework.New() - if err != nil { - t.Fatal(err) - } - - _, _ = fw.CreateKeys(t, "test") - _, other := fw.CreateKeys(t, "other") - fw.SignContainer(t, framework.SignOptions{ - KeyPath: "test.key", +func testOneContainerSinglePubKeyNoMatchEnvRef(fw *framework.Framework, kf framework.KeyFunc, key string) func(*testing.T) { + priv, _ := kf(fw, key) + _, otherPub := framework.CreateECDSAKeyPair(fw, "other") + fw.SignContainer(framework.SignOptions{ + KeyPath: priv.Path, Image: busyboxOne, }) @@ -872,7 +710,7 @@ func testOneContainerSinglePubKeyNoMatchEnvRef(t *testing.T) { Env: []corev1.EnvVar{ { Name: webhook.CosignEnvVar, - Value: other, + Value: otherPub.Key, }, }, }, @@ -882,22 +720,19 @@ func testOneContainerSinglePubKeyNoMatchEnvRef(t *testing.T) { }, } - fw.CreateDeployment(t, depl) - fw.AssertDeploymentFailed(t, depl) - fw.Cleanup(t) + return func(t *testing.T) { + fw.CreateDeployment(depl) + fw.AssertDeploymentFailed(depl) + fw.Cleanup() + } } // testTwoContainersSinglePubKeyNoMatchEnvRef tests that a deployment with two signed containers, -// with a public key provided via an environment variable, fails if one of the container's pub key is malformed. -func testTwoContainersSinglePubKeyMalformedEnvRef(t *testing.T) { - fw, err := framework.New() - if err != nil { - t.Fatal(err) - } - - _, pub := fw.CreateKeys(t, "test") - fw.SignContainer(t, framework.SignOptions{ - KeyPath: "test.key", +// with a public key provided via an environment variable, fails if one of the containers public key is malformed. +func testTwoContainersSinglePubKeyMalformedEnvRef(fw *framework.Framework, kf framework.KeyFunc, key string) func(*testing.T) { + priv, pub := kf(fw, key) + fw.SignContainer(framework.SignOptions{ + KeyPath: priv.Path, Image: busyboxOne, }) @@ -929,7 +764,7 @@ func testTwoContainersSinglePubKeyMalformedEnvRef(t *testing.T) { Env: []corev1.EnvVar{ { Name: webhook.CosignEnvVar, - Value: pub, + Value: pub.Key, }, }, }, @@ -954,18 +789,21 @@ func testTwoContainersSinglePubKeyMalformedEnvRef(t *testing.T) { }, } - fw.CreateDeployment(t, depl) - fw.AssertDeploymentFailed(t, depl) - fw.Cleanup(t) + return func(t *testing.T) { + fw.CreateDeployment(depl) + fw.AssertDeploymentFailed(depl) + fw.Cleanup() + } } // testOneContainerSinglePubKeyMalformedEnvRef tests that a deployment with a single signed container, -// // with a public key provided via an environment variable, fails if the public key has an incorrect format. -func testOneContainerSinglePubKeyMalformedEnvRef(t *testing.T) { - fw, err := framework.New() - if err != nil { - t.Fatal(err) - } +// with a public key provided via an environment variable, fails if the public key has an incorrect format. +func testOneContainerSinglePubKeyMalformedEnvRef(fw *framework.Framework, kf framework.KeyFunc, key string) func(*testing.T) { + priv, _ := kf(fw, key) + fw.SignContainer(framework.SignOptions{ + KeyPath: priv.Path, + Image: busyboxOne, + }) depl := appsv1.Deployment{ ObjectMeta: metav1.ObjectMeta{ @@ -1004,23 +842,20 @@ func testOneContainerSinglePubKeyMalformedEnvRef(t *testing.T) { }, } - fw.CreateDeployment(t, depl) - fw.AssertDeploymentFailed(t, depl) - fw.Cleanup(t) + return func(t *testing.T) { + fw.CreateDeployment(depl) + fw.AssertDeploymentFailed(depl) + fw.Cleanup() + } } // testOneContainerSinglePubKeyNoMatchSecretRef tests that a deployment with a single signed container, // with a public key provided via a secret, fails if the public key does not match the signature, which // is uploaded in a different repository as the image itself -func testOneContainerWithCosingRepoVariableMissing(t *testing.T) { - fw, err := framework.New() - if err != nil { - t.Fatal(err) - } - - _, pub := fw.CreateKeys(t, "test") - fw.SignContainer(t, framework.SignOptions{ - KeyPath: "test.key", +func testOneContainerWithCosingRepoVariableMissing(fw *framework.Framework, kf framework.KeyFunc, key string) func(*testing.T) { + priv, pub := kf(fw, key) + fw.SignContainer(framework.SignOptions{ + KeyPath: priv.Path, Image: busyboxOne, SignatureRepo: signatureRepo, }) @@ -1051,7 +886,7 @@ func testOneContainerWithCosingRepoVariableMissing(t *testing.T) { Env: []corev1.EnvVar{ { Name: webhook.CosignEnvVar, - Value: pub, + Value: pub.Key, }, }, }, @@ -1061,7 +896,9 @@ func testOneContainerWithCosingRepoVariableMissing(t *testing.T) { }, } - fw.CreateDeployment(t, depl) - fw.AssertDeploymentFailed(t, depl) - fw.Cleanup(t) + return func(t *testing.T) { + fw.CreateDeployment(depl) + fw.AssertDeploymentFailed(depl) + fw.Cleanup() + } }