github.com/redhat-appstudio/e2e-tests@v0.0.0-20230619105049-9a422b2094d7/tests/enterprise-contract/contract.go (about)

     1  package enterprisecontract
     2  
     3  import (
     4  	"fmt"
     5  	"time"
     6  
     7  	"github.com/devfile/library/pkg/util"
     8  	ecp "github.com/enterprise-contract/enterprise-contract-controller/api/v1alpha1"
     9  	. "github.com/onsi/ginkgo/v2"
    10  	. "github.com/onsi/gomega"
    11  	"github.com/redhat-appstudio/e2e-tests/pkg/constants"
    12  	"github.com/redhat-appstudio/e2e-tests/pkg/framework"
    13  	"github.com/redhat-appstudio/e2e-tests/pkg/utils"
    14  	"github.com/redhat-appstudio/e2e-tests/pkg/utils/tekton"
    15  )
    16  
    17  var _ = framework.EnterpriseContractSuiteDescribe("Enterprise Contract E2E tests", Label("enterprise-contract", "HACBS"), func() {
    18  
    19  	defer GinkgoRecover()
    20  	var fwk *framework.Framework
    21  	var err error
    22  	var namespace string
    23  	var kubeController tekton.KubeController
    24  	var policySource []ecp.Source
    25  	var policyConfig *ecp.EnterpriseContractPolicyConfiguration
    26  	var imageWithDigest string
    27  	var pipelineRunTimeout int
    28  	var generator tekton.VerifyEnterpriseContract
    29  	var verifyECTaskBundle string
    30  	publicSecretName := "cosign-public-key"
    31  
    32  	BeforeAll(func() {
    33  		fwk, err = framework.NewFramework(utils.GetGeneratedNamespace(constants.TEKTON_CHAINS_E2E_USER))
    34  		Expect(err).NotTo(HaveOccurred())
    35  		Expect(fwk.UserNamespace).NotTo(BeNil(), "failed to create sandbox user")
    36  		namespace = fwk.UserNamespace
    37  		kubeController = tekton.KubeController{
    38  			Commonctrl: *fwk.AsKubeAdmin.CommonController,
    39  			Tektonctrl: *fwk.AsKubeAdmin.TektonController,
    40  			Namespace:  namespace,
    41  		}
    42  		publicKey, err := kubeController.GetTektonChainsPublicKey()
    43  		Expect(err).ToNot(HaveOccurred())
    44  		GinkgoWriter.Printf("Copy public key from %s/signing-secrets to a new secret\n", constants.TEKTON_CHAINS_NS)
    45  		Expect(kubeController.CreateOrUpdateSigningSecret(
    46  			publicKey, publicSecretName, namespace)).To(Succeed())
    47  
    48  		defaultEcp, err := kubeController.GetEnterpriseContractPolicy("default", "enterprise-contract-service")
    49  		Expect(err).NotTo(HaveOccurred())
    50  		policyConfig = defaultEcp.Spec.Configuration
    51  		policySource = defaultEcp.Spec.Sources
    52  
    53  		cm, err := kubeController.Commonctrl.GetConfigMap("ec-defaults", "enterprise-contract-service")
    54  		Expect(err).ToNot(HaveOccurred())
    55  		verifyECTaskBundle = cm.Data["verify_ec_task_bundle"]
    56  		Expect(verifyECTaskBundle).ToNot(BeEmpty())
    57  		GinkgoWriter.Printf("Using verify EC task bundle: %s\n", verifyECTaskBundle)
    58  		imageWithDigest = "quay.io/redhat-appstudio/ec-golden-image:latest"
    59  	})
    60  	Context("ec-cli command verification", func() {
    61  		BeforeAll(func() {
    62  			generator = tekton.VerifyEnterpriseContract{
    63  				Bundle:              verifyECTaskBundle,
    64  				Image:               imageWithDigest,
    65  				Name:                "verify-enterprise-contract",
    66  				Namespace:           namespace,
    67  				PolicyConfiguration: "ec-policy",
    68  				PublicKey:           fmt.Sprintf("k8s://%s/%s", namespace, publicSecretName),
    69  				SSLCertDir:          "/var/run/secrets/kubernetes.io/serviceaccount",
    70  				Strict:              false,
    71  				EffectiveTime:       "now",
    72  			}
    73  			pipelineRunTimeout = int(time.Duration(5) * time.Minute)
    74  			baselinePolicies := ecp.EnterpriseContractPolicySpec{
    75  				Configuration: policyConfig,
    76  				Sources:       policySource,
    77  			}
    78  			Expect(kubeController.CreateOrUpdatePolicyConfiguration(namespace, baselinePolicies)).To(Succeed())
    79  		})
    80  		It("verifies ec cli has error handling", func() {
    81  			generator.Image = "quay.io/redhat-appstudio/ec-golden-image:latest"
    82  			pr, err := kubeController.RunPipeline(generator, pipelineRunTimeout)
    83  			Expect(err).NotTo(HaveOccurred())
    84  			Expect(kubeController.WatchPipelineRun(pr.Name, pipelineRunTimeout)).To(Succeed())
    85  
    86  			pr, err = kubeController.Tektonctrl.GetPipelineRun(pr.Name, pr.Namespace)
    87  			Expect(err).NotTo(HaveOccurred())
    88  
    89  			tr, err := kubeController.GetTaskRunStatus(fwk.AsKubeAdmin.CommonController.KubeRest(), pr, "verify-enterprise-contract")
    90  			Expect(err).NotTo(HaveOccurred())
    91  
    92  			Expect(tr.Status.TaskRunResults).Should(Or(
    93  				// TODO: delete the first option after https://issues.redhat.com/browse/RHTAP-810 is completed
    94  				ContainElements(tekton.MatchTaskRunResultWithJSONPathValue(constants.OldTektonTaskTestOutputName, "{$.result}", `["FAILURE"]`)),
    95  				ContainElements(tekton.MatchTaskRunResultWithJSONPathValue(constants.TektonTaskTestOutputName, "{$.result}", `["FAILURE"]`)),
    96  			))
    97  			//Get container step-report log details from pod
    98  			reportLog, err := utils.GetContainerLogs(fwk.AsKubeAdmin.CommonController.KubeInterface(), tr.Status.PodName, "step-report", namespace)
    99  			GinkgoWriter.Printf("*** Logs from pod '%s', container '%s':\n----- START -----%s----- END -----\n", tr.Status.PodName, "step-report", reportLog)
   100  			Expect(err).NotTo(HaveOccurred())
   101  			Expect(reportLog).Should(ContainSubstring("msg: No image attestations found matching the given public key"))
   102  		})
   103  	})
   104  
   105  	Context("Release Policy", func() {
   106  		BeforeAll(func() {
   107  			secretName := fmt.Sprintf("golden-image-public-key%s", util.GenerateRandomString(10))
   108  			//The staging public key for verificaiton image
   109  			publicKey := []byte("-----BEGIN PUBLIC KEY-----\n" +
   110  				"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEZP/0htjhVt2y0ohjgtIIgICOtQtA\n" +
   111  				"naYJRuLprwIv6FDhZ5yFjYUEtsmoNcW7rx2KM6FOXGsCX3BNc7qhHELT+g==\n" +
   112  				"-----END PUBLIC KEY-----")
   113  			GinkgoWriter.Println("Create golden image public signing key")
   114  			Expect(kubeController.CreateOrUpdateSigningSecret(publicKey, secretName, namespace)).To(Succeed())
   115  			generator = tekton.VerifyEnterpriseContract{
   116  				Bundle:              verifyECTaskBundle,
   117  				Image:               imageWithDigest,
   118  				Name:                "verify-enterprise-contract",
   119  				Namespace:           namespace,
   120  				PolicyConfiguration: "ec-policy",
   121  				PublicKey:           fmt.Sprintf("k8s://%s/%s", namespace, secretName),
   122  				SSLCertDir:          "/var/run/secrets/kubernetes.io/serviceaccount",
   123  				Strict:              false,
   124  				EffectiveTime:       "now",
   125  			}
   126  			pipelineRunTimeout = int(time.Duration(5) * time.Minute)
   127  		})
   128  
   129  		It("verifies ec validate accepts a list of image references", func() {
   130  			policy := ecp.EnterpriseContractPolicySpec{
   131  				Sources: policySource,
   132  				Configuration: &ecp.EnterpriseContractPolicyConfiguration{
   133  					Include: []string{"minimal"},
   134  				},
   135  			}
   136  			Expect(kubeController.CreateOrUpdatePolicyConfiguration(namespace, policy)).To(Succeed())
   137  
   138  			generator.Image = snapshotComponent
   139  			pr, err := kubeController.RunPipeline(generator, pipelineRunTimeout)
   140  			Expect(err).NotTo(HaveOccurred())
   141  			Expect(kubeController.WatchPipelineRun(pr.Name, pipelineRunTimeout)).To(Succeed())
   142  
   143  			pr, err = kubeController.Tektonctrl.GetPipelineRun(pr.Name, pr.Namespace)
   144  			Expect(err).NotTo(HaveOccurred())
   145  
   146  			tr, err := kubeController.GetTaskRunStatus(fwk.AsKubeAdmin.CommonController.KubeRest(), pr, "verify-enterprise-contract")
   147  			Expect(err).NotTo(HaveOccurred())
   148  
   149  			Expect(tr.Status.TaskRunResults).Should(Or(
   150  				// TODO: delete the first option after https://issues.redhat.com/browse/RHTAP-810 is completed
   151  				ContainElements(tekton.MatchTaskRunResultWithJSONPathValue(constants.OldTektonTaskTestOutputName, "{$.result}", `["SUCCESS"]`)),
   152  				ContainElements(tekton.MatchTaskRunResultWithJSONPathValue(constants.TektonTaskTestOutputName, "{$.result}", `["SUCCESS"]`)),
   153  			))
   154  			//Get container step-report log details from pod
   155  			reportLog, err := utils.GetContainerLogs(fwk.AsKubeAdmin.CommonController.KubeInterface(), tr.Status.PodName, "step-report", namespace)
   156  			GinkgoWriter.Printf("*** Logs from pod '%s', container '%s':\n----- START -----%s----- END -----\n", tr.Status.PodName, "step-report", reportLog)
   157  			Expect(err).NotTo(HaveOccurred())
   158  
   159  		})
   160  
   161  		It("verifies the release policy: Task bundle is not acceptable", func() {
   162  			policy := ecp.EnterpriseContractPolicySpec{
   163  				Sources: policySource,
   164  				Configuration: &ecp.EnterpriseContractPolicyConfiguration{
   165  					Include: []string{"attestation_task_bundle.task_ref_bundles_acceptable"},
   166  				},
   167  			}
   168  			Expect(kubeController.CreateOrUpdatePolicyConfiguration(namespace, policy)).To(Succeed())
   169  
   170  			generator.Image = "quay.io/redhat-appstudio/ec-golden-image:e2e-test-unacceptable-task"
   171  			pr, err := kubeController.RunPipeline(generator, pipelineRunTimeout)
   172  			Expect(err).NotTo(HaveOccurred())
   173  			Expect(kubeController.WatchPipelineRun(pr.Name, pipelineRunTimeout)).To(Succeed())
   174  
   175  			pr, err = kubeController.Tektonctrl.GetPipelineRun(pr.Name, pr.Namespace)
   176  			Expect(err).NotTo(HaveOccurred())
   177  
   178  			tr, err := kubeController.GetTaskRunStatus(fwk.AsKubeAdmin.CommonController.KubeRest(), pr, "verify-enterprise-contract")
   179  			Expect(err).NotTo(HaveOccurred())
   180  
   181  			Expect(tr.Status.TaskRunResults).Should(Or(
   182  				// TODO: delete the first option after https://issues.redhat.com/browse/RHTAP-810 is completed
   183  				ContainElements(tekton.MatchTaskRunResultWithJSONPathValue(constants.OldTektonTaskTestOutputName, "{$.result}", `["FAILURE"]`)),
   184  				ContainElements(tekton.MatchTaskRunResultWithJSONPathValue(constants.TektonTaskTestOutputName, "{$.result}", `["FAILURE"]`)),
   185  			))
   186  
   187  			//Get container step-report log details from pod
   188  			reportLog, err := utils.GetContainerLogs(fwk.AsKubeAdmin.CommonController.KubeInterface(), tr.Status.PodName, "step-report", namespace)
   189  			GinkgoWriter.Printf("*** Logs from pod '%s', container '%s':\n----- START -----%s----- END -----\n", tr.Status.PodName, "step-report", reportLog)
   190  			Expect(err).NotTo(HaveOccurred())
   191  			Expect(reportLog).Should(ContainSubstring("msg: Pipeline task 'build-container' uses an unacceptable task bundle"))
   192  		})
   193  
   194  		It("verifies the release policy: Task bundle is out of date", func() {
   195  			policy := ecp.EnterpriseContractPolicySpec{
   196  				Sources: []ecp.Source{
   197  					{
   198  						Policy: []string{
   199  							"oci::quay.io/hacbs-contract/ec-release-policy:git-086f871@sha256:373a5c4c1d34123836cbfc11826f6bbf6fdf8f0dfae333a2686bbe941c4f79ef",
   200  						},
   201  						Data: []string{
   202  							"oci::quay.io/hacbs-contract/ec-policy-data:git-8629680@sha256:ee5708dda57216647f63032dd3e63375e70e2353cb1ad10c9ab5493b9236c23e",
   203  						},
   204  					},
   205  				},
   206  				Configuration: &ecp.EnterpriseContractPolicyConfiguration{
   207  					Include: []string{"attestation_task_bundle.task_ref_bundles_current"},
   208  				},
   209  			}
   210  			Expect(kubeController.CreateOrUpdatePolicyConfiguration(namespace, policy)).To(Succeed())
   211  
   212  			generator.Image = "quay.io/redhat-appstudio/ec-golden-image:e2e-test-out-of-date-task"
   213  			generator.EffectiveTime = "2023-03-31T00:00:00Z"
   214  			pr, err := kubeController.RunPipeline(generator, pipelineRunTimeout)
   215  			Expect(err).NotTo(HaveOccurred())
   216  			Expect(kubeController.WatchPipelineRun(pr.Name, pipelineRunTimeout)).To(Succeed())
   217  
   218  			pr, err = kubeController.Tektonctrl.GetPipelineRun(pr.Name, pr.Namespace)
   219  			Expect(err).NotTo(HaveOccurred())
   220  
   221  			tr, err := kubeController.GetTaskRunStatus(fwk.AsKubeAdmin.CommonController.KubeRest(), pr, "verify-enterprise-contract")
   222  			Expect(err).NotTo(HaveOccurred())
   223  
   224  			Expect(tr.Status.TaskRunResults).Should(Or(
   225  				// TODO: delete the first option after https://issues.redhat.com/browse/RHTAP-810 is completed
   226  				ContainElements(tekton.MatchTaskRunResultWithJSONPathValue(constants.OldTektonTaskTestOutputName, "{$.result}", `["WARNING"]`)),
   227  				ContainElements(tekton.MatchTaskRunResultWithJSONPathValue(constants.TektonTaskTestOutputName, "{$.result}", `["WARNING"]`)),
   228  			))
   229  
   230  			//Get container step-report log details from pod
   231  			reportLog, err := utils.GetContainerLogs(fwk.AsKubeAdmin.CommonController.KubeInterface(), tr.Status.PodName, "step-report", namespace)
   232  			GinkgoWriter.Printf("*** Logs from pod '%s', container '%s':\n----- START -----%s----- END -----\n", tr.Status.PodName, "step-report", reportLog)
   233  			Expect(err).NotTo(HaveOccurred())
   234  			Expect(reportLog).Should(ContainSubstring("Pipeline task 'build-container' uses an out of date task bundle"))
   235  		})
   236  	})
   237  })