From 687c621d4a6d4292c2aeb7ac224d593047058eed Mon Sep 17 00:00:00 2001 From: Qi Wang Date: Thu, 6 Feb 2025 18:32:15 -0500 Subject: [PATCH] Add SigstoreImageVerification e2e tests Signed-off-by: Qi Wang --- test/extended/imagepolicy/imagepolicy.go | 238 ++++++++++++++++++ test/extended/include.go | 1 + test/extended/machine_config/helpers.go | 79 ++++++ test/extended/testdata/bindata.go | 132 ++++++++++ ...valid-public-key-cluster-image-policy.yaml | 12 + .../invalid-public-key-image-policy.yaml | 12 + ...public-key-rekor-cluster-image-policy.yaml | 13 + .../public-key-rekor-image-policy.yaml | 13 + .../generated/zz_generated.annotations.go | 10 + zz_generated.manifests/test-reporting.yaml | 15 ++ 10 files changed, 525 insertions(+) create mode 100644 test/extended/imagepolicy/imagepolicy.go create mode 100644 test/extended/testdata/imagepolicy/invalid-public-key-cluster-image-policy.yaml create mode 100644 test/extended/testdata/imagepolicy/invalid-public-key-image-policy.yaml create mode 100644 test/extended/testdata/imagepolicy/public-key-rekor-cluster-image-policy.yaml create mode 100644 test/extended/testdata/imagepolicy/public-key-rekor-image-policy.yaml diff --git a/test/extended/imagepolicy/imagepolicy.go b/test/extended/imagepolicy/imagepolicy.go new file mode 100644 index 000000000000..bc478058d64c --- /dev/null +++ b/test/extended/imagepolicy/imagepolicy.go @@ -0,0 +1,238 @@ +package imagepolicy + +import ( + "context" + "fmt" + "path/filepath" + "time" + + g "github.com/onsi/ginkgo/v2" + o "github.com/onsi/gomega" + machineconfighelper "github.com/openshift/origin/test/extended/machine_config" + exutil "github.com/openshift/origin/test/extended/util" + kapiv1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/util/retry" + e2e "k8s.io/kubernetes/test/e2e/framework" + e2epod "k8s.io/kubernetes/test/e2e/framework/pod" + e2eskipper "k8s.io/kubernetes/test/e2e/framework/skipper" + admissionapi "k8s.io/pod-security-admission/api" +) + +const ( + testReleaseImageScope = "quay.io/openshift-release-dev/ocp-release@sha256:fbad931c725b2e5b937b295b58345334322bdabb0b67da1c800a53686d7397da" + testReferenceImageScope = "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:4db234f37ae6712e2f7ed8d13f7fb49971c173d0e4f74613d0121672fa2e01f5" + registriesWorkerPoolMachineConfig = "99-worker-generated-registries" + registriesMasterPoolMachineConfig = "99-master-generated-registries" + testPodName = "signature-validation-test-pod" + workerPool = "worker" + masterPool = "master" + SignatureValidationFaildReason = "SignatureValidationFailed" +) + +var _ = g.Describe("[sig-imagepolicy][OCPFeatureGate:SigstoreImageVerification][Serial]", g.Ordered, func() { + defer g.GinkgoRecover() + var ( + oc = exutil.NewCLIWithoutNamespace("cluster-image-policy") + tctx = context.Background() + cli = exutil.NewCLIWithPodSecurityLevel("verifysigstore-e2e", admissionapi.LevelBaseline) + clif = cli.KubeFramework() + imgpolicyCli = exutil.NewCLIWithPodSecurityLevel("verifysigstore-imagepolicy-e2e", admissionapi.LevelBaseline) + imgpolicyClif = imgpolicyCli.KubeFramework() + imagePolicyBaseDir = exutil.FixturePath("testdata", "imagepolicy") + invalidPublicKeyClusterImagePolicyFixture = filepath.Join(imagePolicyBaseDir, "invalid-public-key-cluster-image-policy.yaml") + publiKeyRekorClusterImagePolicyFixture = filepath.Join(imagePolicyBaseDir, "public-key-rekor-cluster-image-policy.yaml") + invalidPublicKeyImagePolicyFixture = filepath.Join(imagePolicyBaseDir, "invalid-public-key-image-policy.yaml") + publiKeyRekorImagePolicyFixture = filepath.Join(imagePolicyBaseDir, "public-key-rekor-image-policy.yaml") + ) + + g.BeforeAll(func() { + if !exutil.IsTechPreviewNoUpgrade(tctx, oc.AdminConfigClient()) { + g.Skip("skipping, this feature is only supported on TechPreviewNoUpgrade clusters") + } + + outStr, err := oc.Run("adm", "release", "info", testReleaseImageScope).Args("-o=go-template", "--template={{.digest}}").Output() + if err != nil || outStr == "" { + o.Expect(err).ToNot(o.HaveOccurred()) + e2eskipper.Skipf("can't validate %s release image for testing, consider updating the test", testReleaseImageScope) + } + }) + + g.It("Should fail clusterimagepolicy signature validation root of trust does not match the identity in the signature", func() { + createClusterImagePolicy(oc, invalidPublicKeyClusterImagePolicyFixture) + g.DeferCleanup(deleteClusterImagePolicy, oc, invalidPublicKeyClusterImagePolicyFixture) + + pod, err := launchTestPod(tctx, clif, testPodName, testReleaseImageScope) + o.Expect(err).NotTo(o.HaveOccurred()) + g.DeferCleanup(deleteTestPod, tctx, clif, testPodName) + + err = waitForTestPodContainerToFailSignatureValidation(tctx, clif, pod) + o.Expect(err).NotTo(o.HaveOccurred()) + }) + + g.It("Should fail clusterimagepolicy signature validation when scope in allowedRegistries list does not skip signature verification", func() { + // Ensure allowedRegistries do not skip signature verification by adding testReleaseImageScope to the list + allowedRegistries := []string{"quay.io", "registry.redhat.io", "image-registry.openshift-image-registry.svc:5000", testReleaseImageScope} + updateImageConfig(oc, allowedRegistries) + g.DeferCleanup(cleanupImageConfig, oc) + + createClusterImagePolicy(oc, invalidPublicKeyClusterImagePolicyFixture) + g.DeferCleanup(deleteClusterImagePolicy, oc, invalidPublicKeyClusterImagePolicyFixture) + + pod, err := launchTestPod(tctx, clif, testPodName, testReleaseImageScope) + o.Expect(err).NotTo(o.HaveOccurred()) + g.DeferCleanup(deleteTestPod, tctx, clif, testPodName) + + err = waitForTestPodContainerToFailSignatureValidation(tctx, clif, pod) + o.Expect(err).NotTo(o.HaveOccurred()) + }) + + g.It("Should pass clusterimagepolicy signature validation with signed image", func() { + createClusterImagePolicy(oc, publiKeyRekorClusterImagePolicyFixture) + g.DeferCleanup(deleteClusterImagePolicy, oc, publiKeyRekorClusterImagePolicyFixture) + + pod, err := launchTestPod(tctx, clif, testPodName, testReleaseImageScope) + o.Expect(err).NotTo(o.HaveOccurred()) + g.DeferCleanup(deleteTestPod, tctx, clif, testPodName) + + err = e2epod.WaitForPodSuccessInNamespace(tctx, clif.ClientSet, pod.Name, pod.Namespace) + o.Expect(err).NotTo(o.HaveOccurred()) + }) + + g.It("Should fail imagepolicy signature validation in different namespaces root of trust does not match the identity in the signature", func() { + createImagePolicy(imgpolicyCli, invalidPublicKeyImagePolicyFixture, imgpolicyClif.Namespace.Name) + g.DeferCleanup(deleteImagePolicy, imgpolicyCli, invalidPublicKeyImagePolicyFixture, imgpolicyClif.Namespace.Name) + + createImagePolicy(cli, invalidPublicKeyImagePolicyFixture, clif.Namespace.Name) + g.DeferCleanup(deleteImagePolicy, cli, invalidPublicKeyImagePolicyFixture, clif.Namespace.Name) + + pod, err := launchTestPod(tctx, imgpolicyClif, testPodName, testReferenceImageScope) + o.Expect(err).NotTo(o.HaveOccurred()) + g.DeferCleanup(deleteTestPod, tctx, imgpolicyClif, testPodName) + + err = waitForTestPodContainerToFailSignatureValidation(tctx, imgpolicyClif, pod) + o.Expect(err).NotTo(o.HaveOccurred()) + + pod, err = launchTestPod(tctx, clif, testPodName, testReferenceImageScope) + o.Expect(err).NotTo(o.HaveOccurred()) + g.DeferCleanup(deleteTestPod, tctx, clif, testPodName) + + err = waitForTestPodContainerToFailSignatureValidation(tctx, clif, pod) + o.Expect(err).NotTo(o.HaveOccurred()) + }) + + g.It("Should pass imagepolicy signature validation with signed image in namespaces", func() { + createImagePolicy(oc, publiKeyRekorImagePolicyFixture, clif.Namespace.Name) + g.DeferCleanup(deleteImagePolicy, oc, publiKeyRekorImagePolicyFixture, clif.Namespace.Name) + + createImagePolicy(oc, publiKeyRekorImagePolicyFixture, imgpolicyClif.Namespace.Name) + g.DeferCleanup(deleteImagePolicy, oc, publiKeyRekorImagePolicyFixture, imgpolicyClif.Namespace.Name) + + pod, err := launchTestPod(tctx, clif, testPodName, testReferenceImageScope) + o.Expect(err).NotTo(o.HaveOccurred()) + g.DeferCleanup(deleteTestPod, tctx, clif, testPodName) + + err = e2epod.WaitForPodSuccessInNamespace(tctx, clif.ClientSet, pod.Name, pod.Namespace) + o.Expect(err).NotTo(o.HaveOccurred()) + + pod, err = launchTestPod(tctx, imgpolicyClif, testPodName, testReferenceImageScope) + o.Expect(err).NotTo(o.HaveOccurred()) + g.DeferCleanup(deleteTestPod, tctx, imgpolicyClif, testPodName) + + err = e2epod.WaitForPodSuccessInNamespace(tctx, imgpolicyClif.ClientSet, pod.Name, pod.Namespace) + o.Expect(err).NotTo(o.HaveOccurred()) + }) +}) + +func createClusterImagePolicy(oc *exutil.CLI, fixture string) { + err := oc.Run("apply").Args("-f", fixture).Execute() + o.Expect(err).NotTo(o.HaveOccurred()) + time.Sleep(10 * time.Second) + machineconfighelper.WaitForConfigAndPoolComplete(oc, workerPool, registriesWorkerPoolMachineConfig) + machineconfighelper.WaitForConfigAndPoolComplete(oc, masterPool, registriesMasterPoolMachineConfig) +} + +func deleteClusterImagePolicy(oc *exutil.CLI, fixture string) error { + return oc.Run("delete").Args("-f", fixture).Execute() +} + +func createImagePolicy(oc *exutil.CLI, fixture string, namespace string) { + err := oc.Run("apply").Args("-f", fixture, "-n", namespace).Execute() + o.Expect(err).NotTo(o.HaveOccurred()) + time.Sleep(10 * time.Second) + machineconfighelper.WaitForConfigAndPoolComplete(oc, workerPool, registriesWorkerPoolMachineConfig) + machineconfighelper.WaitForConfigAndPoolComplete(oc, masterPool, registriesMasterPoolMachineConfig) +} + +func deleteImagePolicy(oc *exutil.CLI, fixture string, namespace string) error { + return oc.Run("delete").Args("-f", fixture, "-n", namespace).Execute() +} + +func updateImageConfig(oc *exutil.CLI, allowedRegistries []string) { + err := retry.RetryOnConflict(retry.DefaultBackoff, func() error { + imageConfig, err := oc.AdminConfigClient().ConfigV1().Images().Get( + context.Background(), "cluster", metav1.GetOptions{}, + ) + if err != nil { + return err + } + imageConfig.Spec.RegistrySources.AllowedRegistries = allowedRegistries + _, err = oc.AdminConfigClient().ConfigV1().Images().Update( + context.Background(), imageConfig, metav1.UpdateOptions{}, + ) + return err + }) + o.Expect(err).NotTo(o.HaveOccurred(), "error updating image config") + time.Sleep(10 * time.Second) + machineconfighelper.WaitForConfigAndPoolComplete(oc, workerPool, registriesWorkerPoolMachineConfig) + machineconfighelper.WaitForConfigAndPoolComplete(oc, masterPool, registriesMasterPoolMachineConfig) +} + +func cleanupImageConfig(oc *exutil.CLI) error { + return retry.RetryOnConflict(retry.DefaultBackoff, func() error { + imageConfig, err := oc.AdminConfigClient().ConfigV1().Images().Get( + context.Background(), "cluster", metav1.GetOptions{}, + ) + if err != nil { + return err + } + imageConfig.Spec.RegistrySources.AllowedRegistries = []string{} + _, err = oc.AdminConfigClient().ConfigV1().Images().Update( + context.Background(), imageConfig, metav1.UpdateOptions{}, + ) + return err + }) +} + +func launchTestPod(ctx context.Context, f *e2e.Framework, podName, image string) (*kapiv1.Pod, error) { + g.By(fmt.Sprintf("launching the pod: %s", podName)) + contName := fmt.Sprintf("%s-container", podName) + pod := &kapiv1.Pod{ + TypeMeta: metav1.TypeMeta{ + Kind: "Pod", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: podName, + }, + Spec: kapiv1.PodSpec{ + Containers: []kapiv1.Container{ + { + Name: contName, + Image: image, + ImagePullPolicy: kapiv1.PullAlways, + }, + }, + RestartPolicy: kapiv1.RestartPolicyNever, + }, + } + pod, err := f.ClientSet.CoreV1().Pods(f.Namespace.Name).Create(ctx, pod, metav1.CreateOptions{}) + return pod, err +} + +func deleteTestPod(ctx context.Context, f *e2e.Framework, podName string) error { + return f.ClientSet.CoreV1().Pods(f.Namespace.Name).Delete(ctx, podName, *metav1.NewDeleteOptions(0)) +} + +func waitForTestPodContainerToFailSignatureValidation(ctx context.Context, f *e2e.Framework, pod *kapiv1.Pod) error { + return e2epod.WaitForPodContainerToFail(ctx, f.ClientSet, pod.Namespace, pod.Name, 0, SignatureValidationFaildReason, e2e.PodStartShortTimeout) +} diff --git a/test/extended/include.go b/test/extended/include.go index fd750e5288c0..673ef371154a 100644 --- a/test/extended/include.go +++ b/test/extended/include.go @@ -32,6 +32,7 @@ import ( _ "github.com/openshift/origin/test/extended/idling" _ "github.com/openshift/origin/test/extended/image_ecosystem" _ "github.com/openshift/origin/test/extended/imageapis" + _ "github.com/openshift/origin/test/extended/imagepolicy" _ "github.com/openshift/origin/test/extended/images" _ "github.com/openshift/origin/test/extended/images/trigger" _ "github.com/openshift/origin/test/extended/kernel" diff --git a/test/extended/machine_config/helpers.go b/test/extended/machine_config/helpers.go index 961c105dc80d..4a75020b1eb7 100644 --- a/test/extended/machine_config/helpers.go +++ b/test/extended/machine_config/helpers.go @@ -292,3 +292,82 @@ func WaitForOneMasterNodeToBeReady(oc *exutil.CLI) error { }, 5*time.Minute, 10*time.Second).Should(o.BeTrue()) return nil } + +// WaitForConfigAndPoolComplete is a helper function that gets a renderedConfig and waits for its pool to complete. +// The return value is the final rendered config. +func WaitForConfigAndPoolComplete(oc *exutil.CLI, pool, mcName string) string { + config, err := WaitForRenderedConfig(oc, pool, mcName) + o.Expect(err).NotTo(o.HaveOccurred(), fmt.Sprintf("%v: failed to render machine config %s from pool %s", err, mcName, pool)) + + err = WaitForPoolComplete(oc, pool, config) + o.Expect(err).NotTo(o.HaveOccurred(), fmt.Sprintf("%v: pool %s did not update to config %s", err, pool, config)) + return config +} + +// WaitForRenderedConfig polls a MachineConfigPool until it has +// included the given mcName in its config, and returns the new +// rendered config name. +func WaitForRenderedConfig(oc *exutil.CLI, pool, mcName string) (string, error) { + return WaitForRenderedConfigs(oc, pool, mcName) +} + +// WaitForRenderedConfigs polls a MachineConfigPool until it has +// included the given mcNames in its config, and returns the new +// rendered config name. +func WaitForRenderedConfigs(oc *exutil.CLI, pool string, mcNames ...string) (string, error) { + var renderedConfig string + machineConfigClient, err := machineconfigclient.NewForConfig(oc.KubeFramework().ClientConfig()) + o.Expect(err).NotTo(o.HaveOccurred()) + found := make(map[string]bool) + o.Eventually(func() bool { + // Set up the list + for _, name := range mcNames { + found[name] = false + } + + // Update found based on the MCP + mcp, err := machineConfigClient.MachineconfigurationV1().MachineConfigPools().Get(context.TODO(), pool, metav1.GetOptions{}) + if err != nil { + return false + } + for _, mc := range mcp.Spec.Configuration.Source { + if _, ok := found[mc.Name]; ok { + found[mc.Name] = true + } + } + + // If any are still false, then they weren't included in the MCP + for _, nameFound := range found { + if !nameFound { + return false + } + } + + // All the required names were found + renderedConfig = mcp.Spec.Configuration.Name + return true + }, 5*time.Minute, 10*time.Second).Should(o.BeTrue()) + return renderedConfig, nil +} + +// WaitForPoolComplete polls a pool until it has completed an update to target +func WaitForPoolComplete(oc *exutil.CLI, pool, target string) error { + machineConfigClient, err := machineconfigclient.NewForConfig(oc.KubeFramework().ClientConfig()) + o.Expect(err).NotTo(o.HaveOccurred()) + framework.Logf("Waiting for pool %s to complete %s", pool, target) + o.Eventually(func() bool { + mcp, err := machineConfigClient.MachineconfigurationV1().MachineConfigPools().Get(context.TODO(), pool, metav1.GetOptions{}) + if err != nil { + framework.Logf("Failed to grab machineconfigpools, error :%v", err) + return false + } + if mcp.Status.Configuration.Name != target { + return false + } + if IsMachineConfigPoolConditionTrue(mcp.Status.Conditions, mcfgv1.MachineConfigPoolUpdated) { + return true + } + return false + }, 20*time.Minute, 10*time.Second).Should(o.BeTrue()) + return nil +} diff --git a/test/extended/testdata/bindata.go b/test/extended/testdata/bindata.go index 642ccbc52644..1e09cc67e340 100644 --- a/test/extended/testdata/bindata.go +++ b/test/extended/testdata/bindata.go @@ -345,6 +345,10 @@ // test/extended/testdata/image_ecosystem/perl-hotdeploy/index.pl // test/extended/testdata/image_ecosystem/perl-hotdeploy/lib/My/Test.pm // test/extended/testdata/image_ecosystem/perl-hotdeploy/perl.json +// test/extended/testdata/imagepolicy/invalid-public-key-cluster-image-policy.yaml +// test/extended/testdata/imagepolicy/invalid-public-key-image-policy.yaml +// test/extended/testdata/imagepolicy/public-key-rekor-cluster-image-policy.yaml +// test/extended/testdata/imagepolicy/public-key-rekor-image-policy.yaml // test/extended/testdata/ipsec/ipsec-nsconfig-machine-config.yaml // test/extended/testdata/ipsec/nmstate.yaml // test/extended/testdata/kernel/rt-tests-environment.yaml @@ -45721,6 +45725,124 @@ func testExtendedTestdataImage_ecosystemPerlHotdeployPerlJson() (*asset, error) return a, nil } +var _testExtendedTestdataImagepolicyInvalidPublicKeyClusterImagePolicyYaml = []byte(`apiVersion: config.openshift.io/v1alpha1 +kind: ClusterImagePolicy +metadata: + name: invalid-public-key-cluster-image-policy +spec: + scopes: + - quay.io/openshift-release-dev/ocp-release@sha256:fbad931c725b2e5b937b295b58345334322bdabb0b67da1c800a53686d7397da + policy: + rootOfTrust: + policyType: PublicKey + publicKey: + keyData: LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFVW9GVW9ZQVJlS1hHeTU5eGU1U1FPazJhSjhvKwoyL1l6NVk4R2NOM3pGRTZWaUl2a0duSGhNbEFoWGFYL2JvME05UjYyczAvNnErK1Q3dXdORnVPZzhBPT0KLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tCgo= +`) + +func testExtendedTestdataImagepolicyInvalidPublicKeyClusterImagePolicyYamlBytes() ([]byte, error) { + return _testExtendedTestdataImagepolicyInvalidPublicKeyClusterImagePolicyYaml, nil +} + +func testExtendedTestdataImagepolicyInvalidPublicKeyClusterImagePolicyYaml() (*asset, error) { + bytes, err := testExtendedTestdataImagepolicyInvalidPublicKeyClusterImagePolicyYamlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "test/extended/testdata/imagepolicy/invalid-public-key-cluster-image-policy.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _testExtendedTestdataImagepolicyInvalidPublicKeyImagePolicyYaml = []byte(`apiVersion: config.openshift.io/v1alpha1 +kind: ImagePolicy +metadata: + name: invalid-public-key-image-policy +spec: + scopes: + - quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:4db234f37ae6712e2f7ed8d13f7fb49971c173d0e4f74613d0121672fa2e01f5 + policy: + rootOfTrust: + policyType: PublicKey + publicKey: + keyData: LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFVW9GVW9ZQVJlS1hHeTU5eGU1U1FPazJhSjhvKwoyL1l6NVk4R2NOM3pGRTZWaUl2a0duSGhNbEFoWGFYL2JvME05UjYyczAvNnErK1Q3dXdORnVPZzhBPT0KLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tCgo= +`) + +func testExtendedTestdataImagepolicyInvalidPublicKeyImagePolicyYamlBytes() ([]byte, error) { + return _testExtendedTestdataImagepolicyInvalidPublicKeyImagePolicyYaml, nil +} + +func testExtendedTestdataImagepolicyInvalidPublicKeyImagePolicyYaml() (*asset, error) { + bytes, err := testExtendedTestdataImagepolicyInvalidPublicKeyImagePolicyYamlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "test/extended/testdata/imagepolicy/invalid-public-key-image-policy.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _testExtendedTestdataImagepolicyPublicKeyRekorClusterImagePolicyYaml = []byte(`apiVersion: config.openshift.io/v1alpha1 +kind: ClusterImagePolicy +metadata: + name: public-key-rekor-cluster-image-policy +spec: + scopes: + - quay.io/openshift-release-dev/ocp-release@sha256:fbad931c725b2e5b937b295b58345334322bdabb0b67da1c800a53686d7397da + policy: + rootOfTrust: + policyType: PublicKey + publicKey: + keyData: LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQ0lqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FnOEFNSUlDQ2dLQ0FnRUEzQzJlVGdJQUo3aGxveDdDSCtIcE1qdDEvbW5lYXcyejlHdE9NUmlSaEgya09ZalRadGVLSEtnWUJHcGViajRBcUpWYnVRaWJYZTZKYVFHQUFER0VOZXozTldsVXpCby9FUUEwaXJDRnN6dlhVbTE2cWFZMG8zOUZpbWpsVVovaG1VNVljSHhxMzR2OTh4bGtRbUVxekowR0VJMzNtWTFMbWFEM3ZhYmd3WWcwb3lzSTk1Z1V1Tk81TmdZUHA4WDREaFNoSmtyVEl5dDJLTEhYWW5BMExzOEJlbG9PWVJlTnJhZmxKRHNzaE5VRFh4MDJhQVZSd2RjMXhJUDArRTlZaTY1ZE4zKzlReVhEOUZ6K3MrTDNjZzh3bDdZd3ZZb1Z2NDhndklmTHlJbjJUaHY2Uzk2R0V6bXBoazRjWDBIeitnUkdocWpyajU4U2hSZzlteitrcnVhR0VuVGcyS3BWR0gzd3I4Z09UdUFZMmtqMnY1YWhnZWt4V1pFN05vazNiNTBKNEpnYXlpSnVSL2R0cmFQMWVMMjlFMG52akdsMXptUXlGNlZnNGdIVXYwaktrcnJ2QUQ4c1dNY2NBS00zbXNXU01uRVpOTnljTTRITlNobGNReG5xU1lFSXR6MGZjajdYamtKbnAxME51Z2lVWlNLeVNXOHc0R3hTaFNraGRGbzByRDlkVElRZkJoeS91ZHRQWUkrK2VoK243QTV2UVV4Wk5BTmZqOUhRbC81Z3lFbFV6TTJOekJ2RHpHellSNVdVZEVEaDlJQ1I4ZlFpMVIxNUtZU0h2Tlc3RW5ucDdZT2d5dmtoSkdwRU5PQkF3c1pLMUhhMkJZYXZMMk05NDJzSkhxOUQ1eEsrZyszQU81eXp6V2NqaUFDMWU4RURPcUVpY01Ud05LOENBd0VBQVE9PQotLS0tLUVORCBQVUJMSUMgS0VZLS0tLS0K + rekorKeyData: LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUhZd0VBWUhLb1pJemowQ0FRWUZLNEVFQUNJRFlnQUVEazBFbGdHdk1yc0pVTGtnL2ppMVhYN0VuZ0RsMldZNwpjNzVrS0t5L1N3V1E4bjNaeW1vbXk0RHRrWHpqc2p1MjA0TWdqdGRjN2RWU1BHU0JuN1ZMTGRESXpxU2QxbUxFCjJ5YlBSelk4Zzc0Mk1uLzVoZ0g0ZUJ6TktCalozd3YxCi0tLS0tRU5EIFBVQkxJQyBLRVktLS0tLQ== +`) + +func testExtendedTestdataImagepolicyPublicKeyRekorClusterImagePolicyYamlBytes() ([]byte, error) { + return _testExtendedTestdataImagepolicyPublicKeyRekorClusterImagePolicyYaml, nil +} + +func testExtendedTestdataImagepolicyPublicKeyRekorClusterImagePolicyYaml() (*asset, error) { + bytes, err := testExtendedTestdataImagepolicyPublicKeyRekorClusterImagePolicyYamlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "test/extended/testdata/imagepolicy/public-key-rekor-cluster-image-policy.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _testExtendedTestdataImagepolicyPublicKeyRekorImagePolicyYaml = []byte(`apiVersion: config.openshift.io/v1alpha1 +kind: ImagePolicy +metadata: + name: public-key-rekor-image-policy +spec: + scopes: + - quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:4db234f37ae6712e2f7ed8d13f7fb49971c173d0e4f74613d0121672fa2e01f5 + policy: + rootOfTrust: + policyType: PublicKey + publicKey: + keyData: LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQ0lqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FnOEFNSUlDQ2dLQ0FnRUEzQzJlVGdJQUo3aGxveDdDSCtIcE1qdDEvbW5lYXcyejlHdE9NUmlSaEgya09ZalRadGVLSEtnWUJHcGViajRBcUpWYnVRaWJYZTZKYVFHQUFER0VOZXozTldsVXpCby9FUUEwaXJDRnN6dlhVbTE2cWFZMG8zOUZpbWpsVVovaG1VNVljSHhxMzR2OTh4bGtRbUVxekowR0VJMzNtWTFMbWFEM3ZhYmd3WWcwb3lzSTk1Z1V1Tk81TmdZUHA4WDREaFNoSmtyVEl5dDJLTEhYWW5BMExzOEJlbG9PWVJlTnJhZmxKRHNzaE5VRFh4MDJhQVZSd2RjMXhJUDArRTlZaTY1ZE4zKzlReVhEOUZ6K3MrTDNjZzh3bDdZd3ZZb1Z2NDhndklmTHlJbjJUaHY2Uzk2R0V6bXBoazRjWDBIeitnUkdocWpyajU4U2hSZzlteitrcnVhR0VuVGcyS3BWR0gzd3I4Z09UdUFZMmtqMnY1YWhnZWt4V1pFN05vazNiNTBKNEpnYXlpSnVSL2R0cmFQMWVMMjlFMG52akdsMXptUXlGNlZnNGdIVXYwaktrcnJ2QUQ4c1dNY2NBS00zbXNXU01uRVpOTnljTTRITlNobGNReG5xU1lFSXR6MGZjajdYamtKbnAxME51Z2lVWlNLeVNXOHc0R3hTaFNraGRGbzByRDlkVElRZkJoeS91ZHRQWUkrK2VoK243QTV2UVV4Wk5BTmZqOUhRbC81Z3lFbFV6TTJOekJ2RHpHellSNVdVZEVEaDlJQ1I4ZlFpMVIxNUtZU0h2Tlc3RW5ucDdZT2d5dmtoSkdwRU5PQkF3c1pLMUhhMkJZYXZMMk05NDJzSkhxOUQ1eEsrZyszQU81eXp6V2NqaUFDMWU4RURPcUVpY01Ud05LOENBd0VBQVE9PQotLS0tLUVORCBQVUJMSUMgS0VZLS0tLS0K + rekorKeyData: LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUhZd0VBWUhLb1pJemowQ0FRWUZLNEVFQUNJRFlnQUVEazBFbGdHdk1yc0pVTGtnL2ppMVhYN0VuZ0RsMldZNwpjNzVrS0t5L1N3V1E4bjNaeW1vbXk0RHRrWHpqc2p1MjA0TWdqdGRjN2RWU1BHU0JuN1ZMTGRESXpxU2QxbUxFCjJ5YlBSelk4Zzc0Mk1uLzVoZ0g0ZUJ6TktCalozd3YxCi0tLS0tRU5EIFBVQkxJQyBLRVktLS0tLQ== +`) + +func testExtendedTestdataImagepolicyPublicKeyRekorImagePolicyYamlBytes() ([]byte, error) { + return _testExtendedTestdataImagepolicyPublicKeyRekorImagePolicyYaml, nil +} + +func testExtendedTestdataImagepolicyPublicKeyRekorImagePolicyYaml() (*asset, error) { + bytes, err := testExtendedTestdataImagepolicyPublicKeyRekorImagePolicyYamlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "test/extended/testdata/imagepolicy/public-key-rekor-image-policy.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + var _testExtendedTestdataIpsecIpsecNsconfigMachineConfigYaml = []byte(`# Generated by Butane; do not edit apiVersion: machineconfiguration.openshift.io/v1 kind: MachineConfig @@ -55598,6 +55720,10 @@ var _bindata = map[string]func() (*asset, error){ "test/extended/testdata/image_ecosystem/perl-hotdeploy/index.pl": testExtendedTestdataImage_ecosystemPerlHotdeployIndexPl, "test/extended/testdata/image_ecosystem/perl-hotdeploy/lib/My/Test.pm": testExtendedTestdataImage_ecosystemPerlHotdeployLibMyTestPm, "test/extended/testdata/image_ecosystem/perl-hotdeploy/perl.json": testExtendedTestdataImage_ecosystemPerlHotdeployPerlJson, + "test/extended/testdata/imagepolicy/invalid-public-key-cluster-image-policy.yaml": testExtendedTestdataImagepolicyInvalidPublicKeyClusterImagePolicyYaml, + "test/extended/testdata/imagepolicy/invalid-public-key-image-policy.yaml": testExtendedTestdataImagepolicyInvalidPublicKeyImagePolicyYaml, + "test/extended/testdata/imagepolicy/public-key-rekor-cluster-image-policy.yaml": testExtendedTestdataImagepolicyPublicKeyRekorClusterImagePolicyYaml, + "test/extended/testdata/imagepolicy/public-key-rekor-image-policy.yaml": testExtendedTestdataImagepolicyPublicKeyRekorImagePolicyYaml, "test/extended/testdata/ipsec/ipsec-nsconfig-machine-config.yaml": testExtendedTestdataIpsecIpsecNsconfigMachineConfigYaml, "test/extended/testdata/ipsec/nmstate.yaml": testExtendedTestdataIpsecNmstateYaml, "test/extended/testdata/kernel/rt-tests-environment.yaml": testExtendedTestdataKernelRtTestsEnvironmentYaml, @@ -56325,6 +56451,12 @@ var _bintree = &bintree{nil, map[string]*bintree{ "perl.json": {testExtendedTestdataImage_ecosystemPerlHotdeployPerlJson, map[string]*bintree{}}, }}, }}, + "imagepolicy": {nil, map[string]*bintree{ + "invalid-public-key-cluster-image-policy.yaml": {testExtendedTestdataImagepolicyInvalidPublicKeyClusterImagePolicyYaml, map[string]*bintree{}}, + "invalid-public-key-image-policy.yaml": {testExtendedTestdataImagepolicyInvalidPublicKeyImagePolicyYaml, map[string]*bintree{}}, + "public-key-rekor-cluster-image-policy.yaml": {testExtendedTestdataImagepolicyPublicKeyRekorClusterImagePolicyYaml, map[string]*bintree{}}, + "public-key-rekor-image-policy.yaml": {testExtendedTestdataImagepolicyPublicKeyRekorImagePolicyYaml, map[string]*bintree{}}, + }}, "ipsec": {nil, map[string]*bintree{ "ipsec-nsconfig-machine-config.yaml": {testExtendedTestdataIpsecIpsecNsconfigMachineConfigYaml, map[string]*bintree{}}, "nmstate.yaml": {testExtendedTestdataIpsecNmstateYaml, map[string]*bintree{}}, diff --git a/test/extended/testdata/imagepolicy/invalid-public-key-cluster-image-policy.yaml b/test/extended/testdata/imagepolicy/invalid-public-key-cluster-image-policy.yaml new file mode 100644 index 000000000000..86f98a10652b --- /dev/null +++ b/test/extended/testdata/imagepolicy/invalid-public-key-cluster-image-policy.yaml @@ -0,0 +1,12 @@ +apiVersion: config.openshift.io/v1alpha1 +kind: ClusterImagePolicy +metadata: + name: invalid-public-key-cluster-image-policy +spec: + scopes: + - quay.io/openshift-release-dev/ocp-release@sha256:fbad931c725b2e5b937b295b58345334322bdabb0b67da1c800a53686d7397da + policy: + rootOfTrust: + policyType: PublicKey + publicKey: + keyData: LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFVW9GVW9ZQVJlS1hHeTU5eGU1U1FPazJhSjhvKwoyL1l6NVk4R2NOM3pGRTZWaUl2a0duSGhNbEFoWGFYL2JvME05UjYyczAvNnErK1Q3dXdORnVPZzhBPT0KLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tCgo= diff --git a/test/extended/testdata/imagepolicy/invalid-public-key-image-policy.yaml b/test/extended/testdata/imagepolicy/invalid-public-key-image-policy.yaml new file mode 100644 index 000000000000..01788db7ff82 --- /dev/null +++ b/test/extended/testdata/imagepolicy/invalid-public-key-image-policy.yaml @@ -0,0 +1,12 @@ +apiVersion: config.openshift.io/v1alpha1 +kind: ImagePolicy +metadata: + name: invalid-public-key-image-policy +spec: + scopes: + - quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:4db234f37ae6712e2f7ed8d13f7fb49971c173d0e4f74613d0121672fa2e01f5 + policy: + rootOfTrust: + policyType: PublicKey + publicKey: + keyData: LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFVW9GVW9ZQVJlS1hHeTU5eGU1U1FPazJhSjhvKwoyL1l6NVk4R2NOM3pGRTZWaUl2a0duSGhNbEFoWGFYL2JvME05UjYyczAvNnErK1Q3dXdORnVPZzhBPT0KLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tCgo= diff --git a/test/extended/testdata/imagepolicy/public-key-rekor-cluster-image-policy.yaml b/test/extended/testdata/imagepolicy/public-key-rekor-cluster-image-policy.yaml new file mode 100644 index 000000000000..5ed340750437 --- /dev/null +++ b/test/extended/testdata/imagepolicy/public-key-rekor-cluster-image-policy.yaml @@ -0,0 +1,13 @@ +apiVersion: config.openshift.io/v1alpha1 +kind: ClusterImagePolicy +metadata: + name: public-key-rekor-cluster-image-policy +spec: + scopes: + - quay.io/openshift-release-dev/ocp-release@sha256:fbad931c725b2e5b937b295b58345334322bdabb0b67da1c800a53686d7397da + policy: + rootOfTrust: + policyType: PublicKey + publicKey: + keyData: LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQ0lqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FnOEFNSUlDQ2dLQ0FnRUEzQzJlVGdJQUo3aGxveDdDSCtIcE1qdDEvbW5lYXcyejlHdE9NUmlSaEgya09ZalRadGVLSEtnWUJHcGViajRBcUpWYnVRaWJYZTZKYVFHQUFER0VOZXozTldsVXpCby9FUUEwaXJDRnN6dlhVbTE2cWFZMG8zOUZpbWpsVVovaG1VNVljSHhxMzR2OTh4bGtRbUVxekowR0VJMzNtWTFMbWFEM3ZhYmd3WWcwb3lzSTk1Z1V1Tk81TmdZUHA4WDREaFNoSmtyVEl5dDJLTEhYWW5BMExzOEJlbG9PWVJlTnJhZmxKRHNzaE5VRFh4MDJhQVZSd2RjMXhJUDArRTlZaTY1ZE4zKzlReVhEOUZ6K3MrTDNjZzh3bDdZd3ZZb1Z2NDhndklmTHlJbjJUaHY2Uzk2R0V6bXBoazRjWDBIeitnUkdocWpyajU4U2hSZzlteitrcnVhR0VuVGcyS3BWR0gzd3I4Z09UdUFZMmtqMnY1YWhnZWt4V1pFN05vazNiNTBKNEpnYXlpSnVSL2R0cmFQMWVMMjlFMG52akdsMXptUXlGNlZnNGdIVXYwaktrcnJ2QUQ4c1dNY2NBS00zbXNXU01uRVpOTnljTTRITlNobGNReG5xU1lFSXR6MGZjajdYamtKbnAxME51Z2lVWlNLeVNXOHc0R3hTaFNraGRGbzByRDlkVElRZkJoeS91ZHRQWUkrK2VoK243QTV2UVV4Wk5BTmZqOUhRbC81Z3lFbFV6TTJOekJ2RHpHellSNVdVZEVEaDlJQ1I4ZlFpMVIxNUtZU0h2Tlc3RW5ucDdZT2d5dmtoSkdwRU5PQkF3c1pLMUhhMkJZYXZMMk05NDJzSkhxOUQ1eEsrZyszQU81eXp6V2NqaUFDMWU4RURPcUVpY01Ud05LOENBd0VBQVE9PQotLS0tLUVORCBQVUJMSUMgS0VZLS0tLS0K + rekorKeyData: LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUhZd0VBWUhLb1pJemowQ0FRWUZLNEVFQUNJRFlnQUVEazBFbGdHdk1yc0pVTGtnL2ppMVhYN0VuZ0RsMldZNwpjNzVrS0t5L1N3V1E4bjNaeW1vbXk0RHRrWHpqc2p1MjA0TWdqdGRjN2RWU1BHU0JuN1ZMTGRESXpxU2QxbUxFCjJ5YlBSelk4Zzc0Mk1uLzVoZ0g0ZUJ6TktCalozd3YxCi0tLS0tRU5EIFBVQkxJQyBLRVktLS0tLQ== diff --git a/test/extended/testdata/imagepolicy/public-key-rekor-image-policy.yaml b/test/extended/testdata/imagepolicy/public-key-rekor-image-policy.yaml new file mode 100644 index 000000000000..900adfc8a633 --- /dev/null +++ b/test/extended/testdata/imagepolicy/public-key-rekor-image-policy.yaml @@ -0,0 +1,13 @@ +apiVersion: config.openshift.io/v1alpha1 +kind: ImagePolicy +metadata: + name: public-key-rekor-image-policy +spec: + scopes: + - quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:4db234f37ae6712e2f7ed8d13f7fb49971c173d0e4f74613d0121672fa2e01f5 + policy: + rootOfTrust: + policyType: PublicKey + publicKey: + keyData: LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQ0lqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FnOEFNSUlDQ2dLQ0FnRUEzQzJlVGdJQUo3aGxveDdDSCtIcE1qdDEvbW5lYXcyejlHdE9NUmlSaEgya09ZalRadGVLSEtnWUJHcGViajRBcUpWYnVRaWJYZTZKYVFHQUFER0VOZXozTldsVXpCby9FUUEwaXJDRnN6dlhVbTE2cWFZMG8zOUZpbWpsVVovaG1VNVljSHhxMzR2OTh4bGtRbUVxekowR0VJMzNtWTFMbWFEM3ZhYmd3WWcwb3lzSTk1Z1V1Tk81TmdZUHA4WDREaFNoSmtyVEl5dDJLTEhYWW5BMExzOEJlbG9PWVJlTnJhZmxKRHNzaE5VRFh4MDJhQVZSd2RjMXhJUDArRTlZaTY1ZE4zKzlReVhEOUZ6K3MrTDNjZzh3bDdZd3ZZb1Z2NDhndklmTHlJbjJUaHY2Uzk2R0V6bXBoazRjWDBIeitnUkdocWpyajU4U2hSZzlteitrcnVhR0VuVGcyS3BWR0gzd3I4Z09UdUFZMmtqMnY1YWhnZWt4V1pFN05vazNiNTBKNEpnYXlpSnVSL2R0cmFQMWVMMjlFMG52akdsMXptUXlGNlZnNGdIVXYwaktrcnJ2QUQ4c1dNY2NBS00zbXNXU01uRVpOTnljTTRITlNobGNReG5xU1lFSXR6MGZjajdYamtKbnAxME51Z2lVWlNLeVNXOHc0R3hTaFNraGRGbzByRDlkVElRZkJoeS91ZHRQWUkrK2VoK243QTV2UVV4Wk5BTmZqOUhRbC81Z3lFbFV6TTJOekJ2RHpHellSNVdVZEVEaDlJQ1I4ZlFpMVIxNUtZU0h2Tlc3RW5ucDdZT2d5dmtoSkdwRU5PQkF3c1pLMUhhMkJZYXZMMk05NDJzSkhxOUQ1eEsrZyszQU81eXp6V2NqaUFDMWU4RURPcUVpY01Ud05LOENBd0VBQVE9PQotLS0tLUVORCBQVUJMSUMgS0VZLS0tLS0K + rekorKeyData: LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUhZd0VBWUhLb1pJemowQ0FRWUZLNEVFQUNJRFlnQUVEazBFbGdHdk1yc0pVTGtnL2ppMVhYN0VuZ0RsMldZNwpjNzVrS0t5L1N3V1E4bjNaeW1vbXk0RHRrWHpqc2p1MjA0TWdqdGRjN2RWU1BHU0JuN1ZMTGRESXpxU2QxbUxFCjJ5YlBSelk4Zzc0Mk1uLzVoZ0g0ZUJ6TktCalozd3YxCi0tLS0tRU5EIFBVQkxJQyBLRVktLS0tLQ== diff --git a/test/extended/util/annotate/generated/zz_generated.annotations.go b/test/extended/util/annotate/generated/zz_generated.annotations.go index 62783d100634..331a4b275e71 100644 --- a/test/extended/util/annotate/generated/zz_generated.annotations.go +++ b/test/extended/util/annotate/generated/zz_generated.annotations.go @@ -1159,6 +1159,16 @@ var Annotations = map[string]string{ "[sig-etcd][OCPFeatureGate:HardwareSpeed][Serial] etcd is able to set the hardware speed to \"\" [Timeout:30m][apigroup:machine.openshift.io]": " [Suite:openshift/conformance/serial]", + "[sig-imagepolicy][OCPFeatureGate:SigstoreImageVerification][Serial] Should fail clusterimagepolicy signature validation root of trust does not match the identity in the signature": " [Suite:openshift/conformance/serial]", + + "[sig-imagepolicy][OCPFeatureGate:SigstoreImageVerification][Serial] Should fail clusterimagepolicy signature validation when scope in allowedRegistries list does not skip signature verification": " [Suite:openshift/conformance/serial]", + + "[sig-imagepolicy][OCPFeatureGate:SigstoreImageVerification][Serial] Should fail imagepolicy signature validation in different namespaces root of trust does not match the identity in the signature": " [Suite:openshift/conformance/serial]", + + "[sig-imagepolicy][OCPFeatureGate:SigstoreImageVerification][Serial] Should pass clusterimagepolicy signature validation with signed image": " [Suite:openshift/conformance/serial]", + + "[sig-imagepolicy][OCPFeatureGate:SigstoreImageVerification][Serial] Should pass imagepolicy signature validation with signed image in namespaces": " [Suite:openshift/conformance/serial]", + "[sig-imageregistry] Image registry [apigroup:route.openshift.io] should redirect on blob pull [apigroup:image.openshift.io]": " [Skipped:NoOptionalCapabilities] [Suite:openshift/conformance/parallel]", "[sig-imageregistry][Feature:ImageAppend] Image append should create images by appending them [apigroup:image.openshift.io]": " [Skipped:Disconnected] [Skipped:NoOptionalCapabilities] [Suite:openshift/conformance/parallel]", diff --git a/zz_generated.manifests/test-reporting.yaml b/zz_generated.manifests/test-reporting.yaml index 73e043995eaa..4a3ca6fd568b 100644 --- a/zz_generated.manifests/test-reporting.yaml +++ b/zz_generated.manifests/test-reporting.yaml @@ -520,6 +520,21 @@ spec: [LinuxOnly] [Feature:SELinux] [Serial] warning is not bumped on two Pods with the same context on RWO volume [FeatureGate:SELinuxMountReadWriteOncePod] [Beta] [Feature:SELinuxMountReadWriteOncePodOnly]' + - featureGate: SigstoreImageVerification + tests: + - testName: '[sig-imagepolicy][OCPFeatureGate:SigstoreImageVerification][Serial] + Should fail clusterimagepolicy signature validation root of trust does not + match the identity in the signature' + - testName: '[sig-imagepolicy][OCPFeatureGate:SigstoreImageVerification][Serial] + Should fail clusterimagepolicy signature validation when scope in allowedRegistries + list does not skip signature verification' + - testName: '[sig-imagepolicy][OCPFeatureGate:SigstoreImageVerification][Serial] + Should fail imagepolicy signature validation in different namespaces root + of trust does not match the identity in the signature' + - testName: '[sig-imagepolicy][OCPFeatureGate:SigstoreImageVerification][Serial] + Should pass clusterimagepolicy signature validation with signed image' + - testName: '[sig-imagepolicy][OCPFeatureGate:SigstoreImageVerification][Serial] + Should pass imagepolicy signature validation with signed image in namespaces' - featureGate: VSphereDriverConfiguration tests: - testName: '[sig-storage][FeatureGate:VSphereDriverConfiguration][Serial][apigroup:operator.openshift.io]