github.com/redhat-appstudio/e2e-tests@v0.0.0-20240520140907-9709f6f59323/tests/enterprise-contract/contract.go (about)

     1  package enterprisecontract
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"time"
     7  
     8  	"github.com/devfile/library/v2/pkg/util"
     9  	ecp "github.com/enterprise-contract/enterprise-contract-controller/api/v1alpha1"
    10  	. "github.com/onsi/ginkgo/v2"
    11  	. "github.com/onsi/gomega"
    12  	"github.com/redhat-appstudio/e2e-tests/pkg/clients/common"
    13  	kubeapi "github.com/redhat-appstudio/e2e-tests/pkg/clients/kubernetes"
    14  	"github.com/redhat-appstudio/e2e-tests/pkg/constants"
    15  	"github.com/redhat-appstudio/e2e-tests/pkg/framework"
    16  	"github.com/redhat-appstudio/e2e-tests/pkg/utils"
    17  	"github.com/redhat-appstudio/e2e-tests/pkg/utils/contract"
    18  	"github.com/redhat-appstudio/e2e-tests/pkg/utils/tekton"
    19  	pipeline "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1"
    20  	corev1 "k8s.io/api/core/v1"
    21  	k8sErrors "k8s.io/apimachinery/pkg/api/errors"
    22  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    23  	"sigs.k8s.io/yaml"
    24  )
    25  
    26  var _ = framework.EnterpriseContractSuiteDescribe("Enterprise Contract E2E tests", Label("ec", "HACBS"), func() {
    27  
    28  	defer GinkgoRecover()
    29  
    30  	var namespace string
    31  	var kubeClient *framework.ControllerHub
    32  	var fwk *framework.Framework
    33  
    34  	AfterEach(framework.ReportFailure(&fwk))
    35  
    36  	BeforeAll(func() {
    37  		// Allow the use of a custom namespace for testing.
    38  		namespace = os.Getenv(constants.E2E_APPLICATIONS_NAMESPACE_ENV)
    39  		if len(namespace) > 0 {
    40  			adminClient, err := kubeapi.NewAdminKubernetesClient()
    41  			Expect(err).ShouldNot(HaveOccurred())
    42  			kubeClient, err = framework.InitControllerHub(adminClient)
    43  			Expect(err).ShouldNot(HaveOccurred())
    44  			_, err = kubeClient.CommonController.CreateTestNamespace(namespace)
    45  			Expect(err).ShouldNot(HaveOccurred())
    46  		} else {
    47  			var err error
    48  			fwk, err = framework.NewFramework(utils.GetGeneratedNamespace(constants.TEKTON_CHAINS_E2E_USER))
    49  			Expect(err).NotTo(HaveOccurred())
    50  			Expect(fwk.UserNamespace).NotTo(BeNil(), "failed to create sandbox user")
    51  			namespace = fwk.UserNamespace
    52  			kubeClient = fwk.AsKubeAdmin
    53  		}
    54  	})
    55  
    56  	Context("infrastructure is running", Label("pipeline"), func() {
    57  		It("verifies if the chains controller is running", func() {
    58  			err := kubeClient.CommonController.WaitForPodSelector(kubeClient.CommonController.IsPodRunning, constants.TEKTON_CHAINS_NS, "app", "tekton-chains-controller", 60, 100)
    59  			Expect(err).NotTo(HaveOccurred())
    60  		})
    61  
    62  		It("verifies the signing secret is present", func() {
    63  			timeout := time.Minute * 5
    64  			interval := time.Second * 1
    65  
    66  			Eventually(func() bool {
    67  				config, err := kubeClient.CommonController.GetSecret(constants.TEKTON_CHAINS_NS, constants.TEKTON_CHAINS_SIGNING_SECRETS_NAME)
    68  				Expect(err).NotTo(HaveOccurred())
    69  
    70  				_, private := config.Data["cosign.key"]
    71  				_, public := config.Data["cosign.pub"]
    72  				_, password := config.Data["cosign.password"]
    73  
    74  				return private && public && password
    75  			}, timeout, interval).Should(BeTrue(), fmt.Sprintf("timed out when waiting for Tekton Chains signing secret %q to be present in %q namespace", constants.TEKTON_CHAINS_SIGNING_SECRETS_NAME, constants.TEKTON_CHAINS_NS))
    76  		})
    77  	})
    78  
    79  	Context("test creating and signing an image and task", Label("pipeline"), func() {
    80  		// Make the PipelineRun name and namespace predictable. For convenience, the name of the
    81  		// PipelineRun that builds an image, is the same as the repository where the image is
    82  		// pushed to.
    83  		var buildPipelineRunName, image, imageWithDigest string
    84  		var pipelineRunTimeout int
    85  		var defaultECP *ecp.EnterpriseContractPolicy
    86  
    87  		BeforeAll(func() {
    88  			buildPipelineRunName = fmt.Sprintf("buildah-demo-%s", util.GenerateRandomString(10))
    89  			image = fmt.Sprintf("quay.io/%s/test-images:%s", utils.GetQuayIOOrganization(), buildPipelineRunName)
    90  			sharedSecret, err := fwk.AsKubeAdmin.CommonController.GetSecret(constants.QuayRepositorySecretNamespace, constants.QuayRepositorySecretName)
    91  			Expect(err).ShouldNot(HaveOccurred(), fmt.Sprintf("error when getting shared secret - make sure the secret %s in %s namespace is created", constants.QuayRepositorySecretName, constants.QuayRepositorySecretNamespace))
    92  
    93  			_, err = fwk.AsKubeAdmin.CommonController.GetSecret(namespace, constants.QuayRepositorySecretName)
    94  			if err == nil {
    95  				err = fwk.AsKubeAdmin.CommonController.DeleteSecret(namespace, constants.QuayRepositorySecretName)
    96  				Expect(err).ToNot(HaveOccurred())
    97  			} else if !k8sErrors.IsNotFound(err) {
    98  				Expect(err).ToNot(HaveOccurred())
    99  			}
   100  
   101  			repositorySecret := &corev1.Secret{ObjectMeta: metav1.ObjectMeta{Name: constants.QuayRepositorySecretName, Namespace: namespace},
   102  				Type: corev1.SecretTypeDockerConfigJson,
   103  				Data: map[string][]byte{corev1.DockerConfigJsonKey: sharedSecret.Data[".dockerconfigjson"]}}
   104  			_, err = fwk.AsKubeAdmin.CommonController.CreateSecret(namespace, repositorySecret)
   105  			Expect(err).ShouldNot(HaveOccurred())
   106  			err = fwk.AsKubeAdmin.CommonController.LinkSecretToServiceAccount(namespace, constants.QuayRepositorySecretName, constants.DefaultPipelineServiceAccount, true)
   107  			Expect(err).ToNot(HaveOccurred())
   108  
   109  			pipelineRunTimeout = int(time.Duration(20) * time.Minute)
   110  
   111  			defaultECP, err = fwk.AsKubeAdmin.TektonController.GetEnterpriseContractPolicy("default", "enterprise-contract-service")
   112  			Expect(err).NotTo(HaveOccurred())
   113  
   114  			// Trigger a demo task to generate an image that has been signed by Tekton Chains within the context for each spec
   115  			bundles, err := kubeClient.TektonController.NewBundles()
   116  			Expect(err).ShouldNot(HaveOccurred())
   117  			dockerBuildBundle := bundles.DockerBuildBundle
   118  			Expect(dockerBuildBundle).NotTo(Equal(""), "Can't continue without a docker-build pipeline got from selector config")
   119  			pr, err := fwk.AsKubeAdmin.TektonController.RunPipeline(tekton.BuildahDemo{Image: image, Bundle: dockerBuildBundle, Namespace: namespace, Name: buildPipelineRunName}, namespace, pipelineRunTimeout)
   120  			Expect(err).NotTo(HaveOccurred())
   121  			// Verify that the build task was created as expected.
   122  			Expect(pr.ObjectMeta.Name).To(Equal(buildPipelineRunName))
   123  			Expect(pr.ObjectMeta.Namespace).To(Equal(namespace))
   124  			Expect(fwk.AsKubeAdmin.TektonController.WatchPipelineRun(pr.Name, namespace, pipelineRunTimeout)).To(Succeed())
   125  			GinkgoWriter.Printf("The pipeline named %q in namespace %q succeeded\n", pr.ObjectMeta.Name, pr.ObjectMeta.Namespace)
   126  
   127  			// The PipelineRun resource has been updated, refresh our reference.
   128  			pr, err = fwk.AsKubeAdmin.TektonController.GetPipelineRun(pr.ObjectMeta.Name, pr.ObjectMeta.Namespace)
   129  			Expect(err).NotTo(HaveOccurred())
   130  
   131  			// Verify TaskRun has the type hinting required by Tekton Chains
   132  			digest, err := fwk.AsKubeAdmin.TektonController.GetTaskRunResult(fwk.AsKubeAdmin.CommonController.KubeRest(), pr, "build-container", "IMAGE_DIGEST")
   133  			Expect(err).NotTo(HaveOccurred())
   134  			i, err := fwk.AsKubeAdmin.TektonController.GetTaskRunResult(fwk.AsKubeAdmin.CommonController.KubeRest(), pr, "build-container", "IMAGE_URL")
   135  			Expect(err).NotTo(HaveOccurred())
   136  			Expect(i).To(Equal(image))
   137  
   138  			// Specs now have a deterministic image reference for validation \o/
   139  			imageWithDigest = fmt.Sprintf("%s@%s", image, digest)
   140  
   141  			GinkgoWriter.Printf("The image signed by Tekton Chains is %s\n", imageWithDigest)
   142  		})
   143  
   144  		It("creates signature and attestation", func() {
   145  			err := fwk.AsKubeAdmin.TektonController.AwaitAttestationAndSignature(imageWithDigest, constants.ChainsAttestationTimeout)
   146  			Expect(err).NotTo(
   147  				HaveOccurred(),
   148  				"Could not find .att or .sig ImageStreamTags within the %s timeout. "+
   149  					"Most likely the chains-controller did not create those in time. "+
   150  					"Look at the chains-controller logs.",
   151  				constants.ChainsAttestationTimeout.String(),
   152  			)
   153  			GinkgoWriter.Printf("Cosign verify pass with .att and .sig ImageStreamTags found for %s\n", imageWithDigest)
   154  		})
   155  
   156  		Context("verify-enterprise-contract task", func() {
   157  			var generator tekton.VerifyEnterpriseContract
   158  			var rekorHost string
   159  			var verifyECTaskBundle string
   160  			publicSecretName := "cosign-public-key"
   161  
   162  			BeforeAll(func() {
   163  				// Copy the public key from openshift-pipelines/signing-secrets to a new
   164  				// secret that contains just the public key to ensure that access
   165  				// to password and private key are not needed.
   166  				publicKey, err := fwk.AsKubeAdmin.TektonController.GetTektonChainsPublicKey()
   167  				Expect(err).ToNot(HaveOccurred())
   168  				GinkgoWriter.Printf("Copy public key from %s/signing-secrets to a new secret\n", constants.TEKTON_CHAINS_NS)
   169  				Expect(fwk.AsKubeAdmin.TektonController.CreateOrUpdateSigningSecret(
   170  					publicKey, publicSecretName, namespace)).To(Succeed())
   171  
   172  				rekorHost, err = fwk.AsKubeAdmin.TektonController.GetRekorHost()
   173  				Expect(err).ToNot(HaveOccurred())
   174  				GinkgoWriter.Printf("Configured Rekor host: %s\n", rekorHost)
   175  
   176  				cm, err := fwk.AsKubeAdmin.CommonController.GetConfigMap("ec-defaults", "enterprise-contract-service")
   177  				Expect(err).ToNot(HaveOccurred())
   178  				verifyECTaskBundle = cm.Data["verify_ec_task_bundle"]
   179  				Expect(verifyECTaskBundle).ToNot(BeEmpty())
   180  				GinkgoWriter.Printf("Using verify EC task bundle: %s\n", verifyECTaskBundle)
   181  			})
   182  
   183  			BeforeEach(func() {
   184  				generator = tekton.VerifyEnterpriseContract{
   185  					TaskBundle:          verifyECTaskBundle,
   186  					Name:                "verify-enterprise-contract",
   187  					Namespace:           namespace,
   188  					PolicyConfiguration: "ec-policy",
   189  					PublicKey:           fmt.Sprintf("k8s://%s/%s", namespace, publicSecretName),
   190  					Strict:              true,
   191  					EffectiveTime:       "now",
   192  					IgnoreRekor:         true,
   193  				}
   194  				generator.WithComponentImage(imageWithDigest)
   195  
   196  				// Since specs could update the config policy, make sure it has a consistent
   197  				// baseline at the start of each spec.
   198  				baselinePolicies := contract.PolicySpecWithSourceConfig(
   199  					// A simple policy that should always succeed in a cluster where
   200  					// Tekton Chains is properly setup.
   201  					defaultECP.Spec, ecp.SourceConfig{Include: []string{"slsa_provenance_available"}})
   202  				Expect(fwk.AsKubeAdmin.TektonController.CreateOrUpdatePolicyConfiguration(namespace, baselinePolicies)).To(Succeed())
   203  				// printPolicyConfiguration(baselinePolicies)
   204  			})
   205  
   206  			It("succeeds when policy is met", func() {
   207  				pr, err := fwk.AsKubeAdmin.TektonController.RunPipeline(generator, namespace, pipelineRunTimeout)
   208  				Expect(err).NotTo(HaveOccurred())
   209  				Expect(fwk.AsKubeAdmin.TektonController.WatchPipelineRun(pr.Name, namespace, pipelineRunTimeout)).To(Succeed())
   210  
   211  				// Refresh our copy of the PipelineRun for latest results
   212  				pr, err = fwk.AsKubeAdmin.TektonController.GetPipelineRun(pr.Name, pr.Namespace)
   213  				Expect(err).NotTo(HaveOccurred())
   214  
   215  				tr, err := fwk.AsKubeAdmin.TektonController.GetTaskRunStatus(fwk.AsKubeAdmin.CommonController.KubeRest(), pr, "verify-enterprise-contract")
   216  				Expect(err).NotTo(HaveOccurred())
   217  				printTaskRunStatus(tr, namespace, *kubeClient.CommonController)
   218  				GinkgoWriter.Printf("Make sure TaskRun %s of PipelineRun %s succeeded\n", tr.PipelineTaskName, pr.Name)
   219  				Expect(tekton.DidTaskRunSucceed(tr)).To(BeTrue())
   220  				GinkgoWriter.Printf("Make sure result for TaskRun %q succeeded\n", tr.PipelineTaskName)
   221  				Expect(tr.Status.TaskRunStatusFields.Results).Should(Or(
   222  					// TODO: delete the first option after https://issues.redhat.com/browse/RHTAP-810 is completed
   223  					ContainElements(tekton.MatchTaskRunResultWithJSONPathValue(constants.OldTektonTaskTestOutputName, "{$.result}", `["SUCCESS"]`)),
   224  					ContainElements(tekton.MatchTaskRunResultWithJSONPathValue(constants.TektonTaskTestOutputName, "{$.result}", `["SUCCESS"]`)),
   225  				))
   226  			})
   227  
   228  			It("does not pass when tests are not satisfied on non-strict mode", func() {
   229  				policy := contract.PolicySpecWithSourceConfig(
   230  					// The BuildahDemo pipeline used to generate the test data does not
   231  					// include the required test tasks, so this policy should always fail.
   232  					defaultECP.Spec, ecp.SourceConfig{Include: []string{"test"}})
   233  				Expect(fwk.AsKubeAdmin.TektonController.CreateOrUpdatePolicyConfiguration(namespace, policy)).To(Succeed())
   234  				// printPolicyConfiguration(policy)
   235  				generator.Strict = false
   236  				pr, err := fwk.AsKubeAdmin.TektonController.RunPipeline(generator, namespace, pipelineRunTimeout)
   237  				Expect(err).NotTo(HaveOccurred())
   238  				Expect(fwk.AsKubeAdmin.TektonController.WatchPipelineRun(pr.Name, namespace, pipelineRunTimeout)).To(Succeed())
   239  
   240  				// Refresh our copy of the PipelineRun for latest results
   241  				pr, err = fwk.AsKubeAdmin.TektonController.GetPipelineRun(pr.Name, pr.Namespace)
   242  				Expect(err).NotTo(HaveOccurred())
   243  
   244  				tr, err := fwk.AsKubeAdmin.TektonController.GetTaskRunStatus(fwk.AsKubeAdmin.CommonController.KubeRest(), pr, "verify-enterprise-contract")
   245  				Expect(err).NotTo(HaveOccurred())
   246  
   247  				printTaskRunStatus(tr, namespace, *kubeClient.CommonController)
   248  				GinkgoWriter.Printf("Make sure TaskRun %s of PipelineRun %s succeeded\n", tr.PipelineTaskName, pr.Name)
   249  				Expect(tekton.DidTaskRunSucceed(tr)).To(BeTrue())
   250  				GinkgoWriter.Printf("Make sure result for TaskRun %q succeeded\n", tr.PipelineTaskName)
   251  				Expect(tr.Status.TaskRunStatusFields.Results).Should(Or(
   252  					// TODO: delete the first option after https://issues.redhat.com/browse/RHTAP-810 is completed
   253  					ContainElements(tekton.MatchTaskRunResultWithJSONPathValue(constants.OldTektonTaskTestOutputName, "{$.result}", `["FAILURE"]`)),
   254  					ContainElements(tekton.MatchTaskRunResultWithJSONPathValue(constants.TektonTaskTestOutputName, "{$.result}", `["FAILURE"]`)),
   255  				))
   256  			})
   257  
   258  			It("fails when tests are not satisfied on strict mode", func() {
   259  				policy := contract.PolicySpecWithSourceConfig(
   260  					// The BuildahDemo pipeline used to generate the test data does not
   261  					// include the required test tasks, so this policy should always fail.
   262  					defaultECP.Spec, ecp.SourceConfig{Include: []string{"test"}})
   263  				Expect(fwk.AsKubeAdmin.TektonController.CreateOrUpdatePolicyConfiguration(namespace, policy)).To(Succeed())
   264  				// printPolicyConfiguration(policy)
   265  
   266  				generator.Strict = true
   267  				pr, err := fwk.AsKubeAdmin.TektonController.RunPipeline(generator, namespace, pipelineRunTimeout)
   268  				Expect(err).NotTo(HaveOccurred())
   269  				Expect(fwk.AsKubeAdmin.TektonController.WatchPipelineRun(pr.Name, namespace, pipelineRunTimeout)).To(Succeed())
   270  
   271  				// Refresh our copy of the PipelineRun for latest results
   272  				pr, err = fwk.AsKubeAdmin.TektonController.GetPipelineRun(pr.Name, pr.Namespace)
   273  				Expect(err).NotTo(HaveOccurred())
   274  
   275  				tr, err := fwk.AsKubeAdmin.TektonController.GetTaskRunStatus(fwk.AsKubeAdmin.CommonController.KubeRest(), pr, "verify-enterprise-contract")
   276  				Expect(err).NotTo(HaveOccurred())
   277  
   278  				printTaskRunStatus(tr, namespace, *kubeClient.CommonController)
   279  				GinkgoWriter.Printf("Make sure TaskRun %s of PipelineRun %s failed\n", tr.PipelineTaskName, pr.Name)
   280  				Expect(tekton.DidTaskRunSucceed(tr)).To(BeFalse())
   281  				// Because the task fails, no results are created
   282  			})
   283  
   284  			It("fails when unexpected signature is used", func() {
   285  				secretName := fmt.Sprintf("dummy-public-key-%s", util.GenerateRandomString(10))
   286  				publicKey := []byte("-----BEGIN PUBLIC KEY-----\n" +
   287  					"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAENZxkE/d0fKvJ51dXHQmxXaRMTtVz\n" +
   288  					"BQWcmJD/7pcMDEmBcmk8O1yUPIiFj5TMZqabjS9CQQN+jKHG+Bfi0BYlHg==\n" +
   289  					"-----END PUBLIC KEY-----")
   290  				GinkgoWriter.Println("Create an unexpected public signing key")
   291  				Expect(fwk.AsKubeAdmin.TektonController.CreateOrUpdateSigningSecret(publicKey, secretName, namespace)).To(Succeed())
   292  				generator.PublicKey = fmt.Sprintf("k8s://%s/%s", namespace, secretName)
   293  
   294  				pr, err := fwk.AsKubeAdmin.TektonController.RunPipeline(generator, namespace, pipelineRunTimeout)
   295  				Expect(err).NotTo(HaveOccurred())
   296  				Expect(fwk.AsKubeAdmin.TektonController.WatchPipelineRun(pr.Name, namespace, pipelineRunTimeout)).To(Succeed())
   297  
   298  				// Refresh our copy of the PipelineRun for latest results
   299  				pr, err = fwk.AsKubeAdmin.TektonController.GetPipelineRun(pr.Name, pr.Namespace)
   300  				Expect(err).NotTo(HaveOccurred())
   301  
   302  				tr, err := fwk.AsKubeAdmin.TektonController.GetTaskRunStatus(fwk.AsKubeAdmin.CommonController.KubeRest(), pr, "verify-enterprise-contract")
   303  				Expect(err).NotTo(HaveOccurred())
   304  
   305  				printTaskRunStatus(tr, namespace, *kubeClient.CommonController)
   306  				GinkgoWriter.Printf("Make sure TaskRun %s of PipelineRun %s failed\n", tr.PipelineTaskName, pr.Name)
   307  				Expect(tekton.DidTaskRunSucceed(tr)).To(BeFalse())
   308  				// Because the task fails, no results are created
   309  			})
   310  
   311  			Context("ec-cli command", func() {
   312  				It("verifies ec cli has error handling", func() {
   313  					generator.WithComponentImage("quay.io/redhat-appstudio/ec-golden-image:latest")
   314  					pr, err := fwk.AsKubeAdmin.TektonController.RunPipeline(generator, namespace, pipelineRunTimeout)
   315  					Expect(err).NotTo(HaveOccurred())
   316  					Expect(fwk.AsKubeAdmin.TektonController.WatchPipelineRun(pr.Name, namespace, pipelineRunTimeout)).To(Succeed())
   317  
   318  					pr, err = fwk.AsKubeAdmin.TektonController.GetPipelineRun(pr.Name, pr.Namespace)
   319  					Expect(err).NotTo(HaveOccurred())
   320  
   321  					tr, err := fwk.AsKubeAdmin.TektonController.GetTaskRunStatus(fwk.AsKubeAdmin.CommonController.KubeRest(), pr, "verify-enterprise-contract")
   322  					Expect(err).NotTo(HaveOccurred())
   323  
   324  					Expect(tr.Status.TaskRunStatusFields.Results).Should(Or(
   325  						// TODO: delete the first option after https://issues.redhat.com/browse/RHTAP-810 is completed
   326  						ContainElements(tekton.MatchTaskRunResultWithJSONPathValue(constants.OldTektonTaskTestOutputName, "{$.result}", `["FAILURE"]`)),
   327  						ContainElements(tekton.MatchTaskRunResultWithJSONPathValue(constants.TektonTaskTestOutputName, "{$.result}", `["FAILURE"]`)),
   328  					))
   329  					//Get container step-report log details from pod
   330  					reportLog, err := utils.GetContainerLogs(fwk.AsKubeAdmin.CommonController.KubeInterface(), tr.Status.PodName, "step-report", namespace)
   331  					GinkgoWriter.Printf("*** Logs from pod '%s', container '%s':\n----- START -----%s----- END -----\n", tr.Status.PodName, "step-report", reportLog)
   332  					Expect(err).NotTo(HaveOccurred())
   333  					Expect(reportLog).Should(ContainSubstring("No image attestations found matching the given public key"))
   334  				})
   335  
   336  				It("verifies ec validate accepts a list of image references", func() {
   337  					secretName := fmt.Sprintf("golden-image-public-key%s", util.GenerateRandomString(10))
   338  					GinkgoWriter.Println("Update public key to verify golden images")
   339  					goldenImagePublicKey := []byte("-----BEGIN PUBLIC KEY-----\n" +
   340  						"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEZP/0htjhVt2y0ohjgtIIgICOtQtA\n" +
   341  						"naYJRuLprwIv6FDhZ5yFjYUEtsmoNcW7rx2KM6FOXGsCX3BNc7qhHELT+g==\n" +
   342  						"-----END PUBLIC KEY-----")
   343  					Expect(fwk.AsKubeAdmin.TektonController.CreateOrUpdateSigningSecret(goldenImagePublicKey, secretName, namespace)).To(Succeed())
   344  					generator.PublicKey = fmt.Sprintf("k8s://%s/%s", namespace, secretName)
   345  
   346  					policy := contract.PolicySpecWithSourceConfig(
   347  						defaultECP.Spec, ecp.SourceConfig{Include: []string{"minimal"}})
   348  					Expect(fwk.AsKubeAdmin.TektonController.CreateOrUpdatePolicyConfiguration(namespace, policy)).To(Succeed())
   349  
   350  					generator.WithComponentImage("quay.io/redhat-appstudio/ec-golden-image:latest")
   351  					generator.AppendComponentImage("quay.io/redhat-appstudio/ec-golden-image:e2e-test-unacceptable-task")
   352  					pr, err := fwk.AsKubeAdmin.TektonController.RunPipeline(generator, namespace, pipelineRunTimeout)
   353  					Expect(err).NotTo(HaveOccurred())
   354  					Expect(fwk.AsKubeAdmin.TektonController.WatchPipelineRun(pr.Name, namespace, pipelineRunTimeout)).To(Succeed())
   355  
   356  					pr, err = fwk.AsKubeAdmin.TektonController.GetPipelineRun(pr.Name, pr.Namespace)
   357  					Expect(err).NotTo(HaveOccurred())
   358  
   359  					tr, err := fwk.AsKubeAdmin.TektonController.GetTaskRunStatus(fwk.AsKubeAdmin.CommonController.KubeRest(), pr, "verify-enterprise-contract")
   360  					Expect(err).NotTo(HaveOccurred())
   361  
   362  					Expect(tr.Status.TaskRunStatusFields.Results).Should(Or(
   363  						// TODO: delete the first option after https://issues.redhat.com/browse/RHTAP-810 is completed
   364  						ContainElements(tekton.MatchTaskRunResultWithJSONPathValue(constants.OldTektonTaskTestOutputName, "{$.result}", `["SUCCESS"]`)),
   365  						ContainElements(tekton.MatchTaskRunResultWithJSONPathValue(constants.TektonTaskTestOutputName, "{$.result}", `["SUCCESS"]`)),
   366  					))
   367  					//Get container step-report log details from pod
   368  					reportLog, err := utils.GetContainerLogs(fwk.AsKubeAdmin.CommonController.KubeInterface(), tr.Status.PodName, "step-report", namespace)
   369  					GinkgoWriter.Printf("*** Logs from pod '%s', container '%s':\n----- START -----%s----- END -----\n", tr.Status.PodName, "step-report", reportLog)
   370  					Expect(err).NotTo(HaveOccurred())
   371  				})
   372  			})
   373  
   374  			Context("Release Policy", func() {
   375  				It("verifies redhat products pass the redhat policy rule collection before release ", func() {
   376  					secretName := fmt.Sprintf("golden-image-public-key%s", util.GenerateRandomString(10))
   377  					GinkgoWriter.Println("Update public key to verify golden images")
   378  					goldenImagePublicKey := []byte("-----BEGIN PUBLIC KEY-----\n" +
   379  						"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEZP/0htjhVt2y0ohjgtIIgICOtQtA\n" +
   380  						"naYJRuLprwIv6FDhZ5yFjYUEtsmoNcW7rx2KM6FOXGsCX3BNc7qhHELT+g==\n" +
   381  						"-----END PUBLIC KEY-----")
   382  					Expect(fwk.AsKubeAdmin.TektonController.CreateOrUpdateSigningSecret(goldenImagePublicKey, secretName, namespace)).To(Succeed())
   383  					redhatECP, error := fwk.AsKubeAdmin.TektonController.GetEnterpriseContractPolicy("redhat", "enterprise-contract-service")
   384  					Expect(error).NotTo(HaveOccurred())
   385  					generator.PublicKey = fmt.Sprintf("k8s://%s/%s", namespace, secretName)
   386  					policy := contract.PolicySpecWithSourceConfig(
   387  						redhatECP.Spec,
   388  						ecp.SourceConfig{Include: []string{"redhat"}})
   389  					Expect(fwk.AsKubeAdmin.TektonController.CreateOrUpdatePolicyConfiguration(namespace, policy)).To(Succeed())
   390  
   391  					generator.WithComponentImage("quay.io/redhat-appstudio/ec-golden-image:latest")
   392  					pr, err := fwk.AsKubeAdmin.TektonController.RunPipeline(generator, namespace, pipelineRunTimeout)
   393  					Expect(err).NotTo(HaveOccurred())
   394  					Expect(fwk.AsKubeAdmin.TektonController.WatchPipelineRun(pr.Name, namespace, pipelineRunTimeout)).To(Succeed())
   395  
   396  					pr, err = fwk.AsKubeAdmin.TektonController.GetPipelineRun(pr.Name, pr.Namespace)
   397  					Expect(err).NotTo(HaveOccurred())
   398  
   399  					tr, err := fwk.AsKubeAdmin.TektonController.GetTaskRunStatus(fwk.AsKubeAdmin.CommonController.KubeRest(), pr, "verify-enterprise-contract")
   400  					Expect(err).NotTo(HaveOccurred())
   401  
   402  					Expect(tr.Status.TaskRunStatusFields.Results).Should(Or(
   403  					// TODO: delete the first option after https://issues.redhat.com/browse/RHTAP-810 is completed
   404  					ContainElements(tekton.MatchTaskRunResultWithJSONPathValue(constants.OldTektonTaskTestOutputName, "{$.result}", `["SUCCESS"]`)),
   405  					ContainElements(tekton.MatchTaskRunResultWithJSONPathValue(constants.TektonTaskTestOutputName, "{$.result}", `["SUCCESS"]`)),
   406  					))
   407  				})
   408  				It("verifies the release policy: Task bundles are in acceptable bundle list", func() {
   409  					secretName := fmt.Sprintf("golden-image-public-key%s", util.GenerateRandomString(10))
   410  					GinkgoWriter.Println("Update public key to verify golden images")
   411  					goldenImagePublicKey := []byte("-----BEGIN PUBLIC KEY-----\n" +
   412  						"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEZP/0htjhVt2y0ohjgtIIgICOtQtA\n" +
   413  						"naYJRuLprwIv6FDhZ5yFjYUEtsmoNcW7rx2KM6FOXGsCX3BNc7qhHELT+g==\n" +
   414  						"-----END PUBLIC KEY-----")
   415  					Expect(fwk.AsKubeAdmin.TektonController.CreateOrUpdateSigningSecret(goldenImagePublicKey, secretName, namespace)).To(Succeed())
   416  					generator.PublicKey = fmt.Sprintf("k8s://%s/%s", namespace, secretName)
   417  					policy := contract.PolicySpecWithSourceConfig(
   418  						defaultECP.Spec,
   419  						ecp.SourceConfig{Include: []string{
   420  							// Account for "acceptable" to "trusted" renaming. Eventually remove "acceptable" from this list
   421  							"attestation_task_bundle.task_ref_bundles_acceptable",
   422  							"attestation_task_bundle.task_ref_bundles_trusted",
   423  						}},
   424  					)
   425  					Expect(fwk.AsKubeAdmin.TektonController.CreateOrUpdatePolicyConfiguration(namespace, policy)).To(Succeed())
   426  
   427  					generator.WithComponentImage("quay.io/redhat-appstudio/ec-golden-image:e2e-test-unacceptable-task")
   428  					pr, err := fwk.AsKubeAdmin.TektonController.RunPipeline(generator, namespace, pipelineRunTimeout)
   429  					Expect(err).NotTo(HaveOccurred())
   430  					Expect(fwk.AsKubeAdmin.TektonController.WatchPipelineRun(pr.Name, namespace, pipelineRunTimeout)).To(Succeed())
   431  
   432  					pr, err = fwk.AsKubeAdmin.TektonController.GetPipelineRun(pr.Name, pr.Namespace)
   433  					Expect(err).NotTo(HaveOccurred())
   434  
   435  					tr, err := fwk.AsKubeAdmin.TektonController.GetTaskRunStatus(fwk.AsKubeAdmin.CommonController.KubeRest(), pr, "verify-enterprise-contract")
   436  					Expect(err).NotTo(HaveOccurred())
   437  
   438  					Expect(tr.Status.TaskRunStatusFields.Results).Should(Or(
   439  						// TODO: delete the first option after https://issues.redhat.com/browse/RHTAP-810 is completed
   440  						ContainElements(tekton.MatchTaskRunResultWithJSONPathValue(constants.OldTektonTaskTestOutputName, "{$.result}", `["FAILURE"]`)),
   441  						ContainElements(tekton.MatchTaskRunResultWithJSONPathValue(constants.TektonTaskTestOutputName, "{$.result}", `["FAILURE"]`)),
   442  					))
   443  
   444  					//Get container step-report log details from pod
   445  					reportLog, err := utils.GetContainerLogs(fwk.AsKubeAdmin.CommonController.KubeInterface(), tr.Status.PodName, "step-report", namespace)
   446  					GinkgoWriter.Printf("*** Logs from pod '%s', container '%s':\n----- START -----%s----- END -----\n", tr.Status.PodName, "step-report", reportLog)
   447  					Expect(err).NotTo(HaveOccurred())
   448  					Expect(reportLog).Should(MatchRegexp(`Pipeline task .* uses an (?:untrusted|unacceptable) task bundle`))
   449  				})
   450  
   451  				It("verifies the release policy: Task bundle references pinned to digest", func() {
   452  					secretName := fmt.Sprintf("unpinned-task-bundle-public-key%s", util.GenerateRandomString(10))
   453  					unpinnedTaskPublicKey := []byte("-----BEGIN PUBLIC KEY-----\n" +
   454  						"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEPfwkY/ru2JRd6FSqIp7lT3gzjaEC\n" +
   455  						"EAg+paWtlme2KNcostCsmIbwz+bc2aFV+AxCOpRjRpp3vYrbS5KhkmgC1Q==\n" +
   456  						"-----END PUBLIC KEY-----")
   457  					GinkgoWriter.Println("Update public <key to verify unpinned task image")
   458  					Expect(fwk.AsKubeAdmin.TektonController.CreateOrUpdateSigningSecret(unpinnedTaskPublicKey, secretName, namespace)).To(Succeed())
   459  					generator.PublicKey = fmt.Sprintf("k8s://%s/%s", namespace, secretName)
   460  
   461  					policy := contract.PolicySpecWithSourceConfig(
   462  						defaultECP.Spec,
   463  						ecp.SourceConfig{Include: []string{"attestation_task_bundle.task_ref_bundles_pinned"}},
   464  					)
   465  					Expect(fwk.AsKubeAdmin.TektonController.CreateOrUpdatePolicyConfiguration(namespace, policy)).To(Succeed())
   466  
   467  					generator.WithComponentImage("quay.io/redhat-appstudio-qe/enterprise-contract-tests:e2e-test-unpinned-task-bundle")
   468  					pr, err := fwk.AsKubeAdmin.TektonController.RunPipeline(generator, namespace, pipelineRunTimeout)
   469  					Expect(err).NotTo(HaveOccurred())
   470  					Expect(fwk.AsKubeAdmin.TektonController.WatchPipelineRun(pr.Name, namespace, pipelineRunTimeout)).To(Succeed())
   471  
   472  					pr, err = fwk.AsKubeAdmin.TektonController.GetPipelineRun(pr.Name, pr.Namespace)
   473  					Expect(err).NotTo(HaveOccurred())
   474  
   475  					tr, err := fwk.AsKubeAdmin.TektonController.GetTaskRunStatus(fwk.AsKubeAdmin.CommonController.KubeRest(), pr, "verify-enterprise-contract")
   476  					Expect(err).NotTo(HaveOccurred())
   477  
   478  					Expect(tr.Status.TaskRunStatusFields.Results).Should(Or(
   479  						// TODO: delete the first option after https://issues.redhat.com/browse/RHTAP-810 is completed
   480  						ContainElements(tekton.MatchTaskRunResultWithJSONPathValue(constants.OldTektonTaskTestOutputName, "{$.result}", `["WARNING"]`)),
   481  						ContainElements(tekton.MatchTaskRunResultWithJSONPathValue(constants.TektonTaskTestOutputName, "{$.result}", `["WARNING"]`)),
   482  					))
   483  
   484  					//Get container step-report log details from pod
   485  					reportLog, err := utils.GetContainerLogs(fwk.AsKubeAdmin.CommonController.KubeInterface(), tr.Status.PodName, "step-report", namespace)
   486  					GinkgoWriter.Printf("*** Logs from pod '%s', container '%s':\n----- START -----%s----- END -----\n", tr.Status.PodName, "step-report", reportLog)
   487  					Expect(err).NotTo(HaveOccurred())
   488  					Expect(reportLog).Should(MatchRegexp(`Pipeline task .* uses an unpinned task bundle reference`))
   489  				})
   490  			})
   491  		})
   492  
   493  	})
   494  })
   495  
   496  func printTaskRunStatus(tr *pipeline.PipelineRunTaskRunStatus, namespace string, sc common.SuiteController) {
   497  	if tr.Status == nil {
   498  		GinkgoWriter.Println("*** TaskRun status: nil")
   499  		return
   500  	}
   501  
   502  	if y, err := yaml.Marshal(tr.Status); err == nil {
   503  		GinkgoWriter.Printf("*** TaskRun status:\n%s\n", string(y))
   504  	} else {
   505  		GinkgoWriter.Printf("*** Unable to serialize TaskRunStatus to YAML: %#v; error: %s\n", tr.Status, err)
   506  	}
   507  
   508  	for _, s := range tr.Status.TaskRunStatusFields.Steps {
   509  		if logs, err := utils.GetContainerLogs(sc.KubeInterface(), tr.Status.PodName, s.Container, namespace); err == nil {
   510  			GinkgoWriter.Printf("*** Logs from pod '%s', container '%s':\n----- START -----%s----- END -----\n", tr.Status.PodName, s.Container, logs)
   511  		} else {
   512  			GinkgoWriter.Printf("*** Can't fetch logs from pod '%s', container '%s': %s\n", tr.Status.PodName, s.Container, err)
   513  		}
   514  	}
   515  }