Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rapidast on rhwa FAR operator #310

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 0 additions & 7 deletions images/rhwa/dast/Dockerfile

This file was deleted.

46 changes: 0 additions & 46 deletions images/rhwa/dast/config/rapidastConfig.yaml

This file was deleted.

23 changes: 22 additions & 1 deletion tests/rhwa/far-operator/far_suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,20 @@ import (

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/openshift-kni/eco-goinfra/pkg/namespace"
"github.com/openshift-kni/eco-goinfra/pkg/reportxml"
"github.com/openshift-kni/eco-gotests/tests/internal/params"
"github.com/openshift-kni/eco-gotests/tests/internal/reporter"
"github.com/openshift-kni/eco-gotests/tests/rhwa/far-operator/internal/farparams"
_ "github.com/openshift-kni/eco-gotests/tests/rhwa/far-operator/tests"
. "github.com/openshift-kni/eco-gotests/tests/rhwa/internal/rhwainittools"
"github.com/openshift-kni/eco-gotests/tests/rhwa/internal/rhwaparams"
)

var _, currentFile, _, _ = runtime.Caller(0)
var (
_, currentFile, _, _ = runtime.Caller(0)
testNS = namespace.NewBuilder(APIClient, rhwaparams.TestNamespaceName)
)

func TestFAR(t *testing.T) {
_, reporterConfig := GinkgoConfiguration()
Expand All @@ -23,6 +29,15 @@ func TestFAR(t *testing.T) {
RunSpecs(t, "FAR", Label(farparams.Labels...), reporterConfig)
}

var _ = BeforeSuite(func() {
By("Creating test namespace with privileged labels")
for key, value := range params.PrivilegedNSLabels {
testNS.WithLabel(key, value)
}
_, err := testNS.Create()
Expect(err).ToNot(HaveOccurred(), "error to create test namespace")
})

var _ = JustAfterEach(func() {
reporter.ReportIfFailed(
CurrentSpecReport(), currentFile, farparams.ReporterNamespacesToDump, farparams.ReporterCRDsToDump)
Expand All @@ -32,3 +47,9 @@ var _ = ReportAfterSuite("", func(report Report) {
reportxml.Create(
report, RHWAConfig.GetReportPath(), RHWAConfig.TCPrefix)
})

var _ = AfterSuite(func() {
By("Deleting test namespace")
err := testNS.DeleteAndWait(rhwaparams.DefaultTimeout)
Expect(err).ToNot(HaveOccurred(), "error to delete test namespace")
})
61 changes: 61 additions & 0 deletions tests/rhwa/far-operator/tests/dast.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package tests

import (
"encoding/json"
"fmt"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"

"github.com/openshift-kni/eco-goinfra/pkg/deployment"
"github.com/openshift-kni/eco-goinfra/pkg/reportxml"

"github.com/openshift-kni/eco-gotests/tests/rhwa/far-operator/internal/farparams"
rapidast "github.com/openshift-kni/eco-gotests/tests/rhwa/internal/rapidast"
. "github.com/openshift-kni/eco-gotests/tests/rhwa/internal/rhwainittools"
"github.com/openshift-kni/eco-gotests/tests/rhwa/internal/rhwaparams"
)

var _ = Describe(
"FAR Post Deployment tests",
Ordered,
ContinueOnFailure,
Label(farparams.Label), Label("dast"), func() {
BeforeAll(func() {
By("Get FAR deployment object")
farDeployment, err := deployment.Pull(
APIClient, farparams.OperatorDeploymentName, rhwaparams.RhwaOperatorNs)
Expect(err).ToNot(HaveOccurred(), "Failed to get FAR deployment")

By("Verify FAR deployment is Ready")
Expect(farDeployment.IsReady(rhwaparams.DefaultTimeout)).To(BeTrue(), "FAR deployment is not Ready")
})

It("Verify FAR Operator passes trivy scan without vulnerabilities", reportxml.ID("76877"), func() {

By("Creating rapidast pod")
dastTestPod := rapidast.PrepareRapidastPod(APIClient)

output, err := rapidast.RunRapidastScan(*dastTestPod, rhwaparams.RhwaOperatorNs)
Expect(err).ToNot(HaveOccurred())

By("Checking vulnerability scan results")
var parsableStruct rapidast.DASTReport
err = json.Unmarshal(output.Bytes(), &parsableStruct)
Expect(err).ToNot(HaveOccurred())

var vulnerabilityFound = false
for _, resource := range parsableStruct.Resources {
for _, result := range resource.Results {
if result.MisconfSummary.Failures > 0 {
fmt.Printf("%d vulnerability(s) found in %s\n", result.MisconfSummary.Failures, resource.Name)
for _, misconfiguration := range result.Misconfigurations {
fmt.Printf("- %+v\n", misconfiguration)
}
vulnerabilityFound = true
}
}
}
Expect(vulnerabilityFound).NotTo(BeTrue(), "Found vulnerability(s)")
})
})
34 changes: 34 additions & 0 deletions tests/rhwa/internal/rapidast/dastreport.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package rapidast

// DASTReport struct that receives the results of the rapidast scan.
type DASTReport struct {
ClusterName string
Resources []struct {
Name string
Namespace string
Results []struct {
Target string
Class string
Type string
MisconfSummary struct {
Success int
Failures int
Exceptions int
}
Misconfigurations []struct {
Type string
ID string
AVDID string
Description string
Message string
Namespace string
Query string
Resolution string
Severity string
PrimaryURL string
References []string
Status string
}
}
}
}
88 changes: 88 additions & 0 deletions tests/rhwa/internal/rapidast/rapidast.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package rapidast

import (
"bytes"
"fmt"
"time"

"github.com/golang/glog"
"github.com/openshift-kni/eco-goinfra/pkg/clients"
"github.com/openshift-kni/eco-goinfra/pkg/nodes"
"github.com/openshift-kni/eco-goinfra/pkg/pod"
"github.com/openshift-kni/eco-goinfra/pkg/rbac"
"github.com/openshift-kni/eco-goinfra/pkg/serviceaccount"
. "github.com/openshift-kni/eco-gotests/tests/rhwa/internal/rhwainittools"
"github.com/openshift-kni/eco-gotests/tests/rhwa/internal/rhwaparams"

v1 "k8s.io/api/rbac/v1"
)

const (
logLevel = rhwaparams.LogLevel
)

// PrepareRapidastPod initializes the pod in the cluster that allows to run rapidast.
Copy link

@clobrano clobrano Jan 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function comment uses the expression "allows to" which can be a bit vague. If this pod is directly responsible for running the scanner, which is what I assume from the comment, it would be clearer to say it explicitly.
What do you think about something like

PrepareRapidastPod initializes the pod responsible for running rapidast scanner

func PrepareRapidastPod(apiClient *clients.Settings) *pod.Builder {
Copy link

@clobrano clobrano Jan 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider returning the error from one of the error condition you already handle below with logging only.
E.g. if one of the NewBuilder.Create functions return error

nodes, err := nodes.List(apiClient)
if err != nil {
glog.V(logLevel).Infof(
"Error in node list retrieval %s", err.Error())
}

_, err = serviceaccount.NewBuilder(APIClient, "trivy-service-account", rhwaparams.TestNamespaceName).Create()
if err != nil {
glog.V(logLevel).Infof(
"Error in service acount creation %s", err.Error())

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo: s/acount/account

}

_, err = rbac.NewClusterRoleBuilder(APIClient, "trivy-clusterrole", v1.PolicyRule{
APIGroups: []string{
"",
},
Resources: []string{
"pods",
},
Verbs: []string{
"get",
"list",
"watch",
},
}).Create()
if err != nil {
glog.V(logLevel).Infof(
"Error in ClusterRoleBuilder creation %s", err.Error())
}

_, err = rbac.NewClusterRoleBindingBuilder(APIClient, "trivy-clusterrole-binding", "trivy-clusterrole", v1.Subject{
Kind: "ServiceAccount",
Name: "trivy-service-account",
Namespace: rhwaparams.TestNamespaceName,
}).Create()
if err != nil {
glog.V(logLevel).Infof(
"Error in ClusterRoleBindingBuilder creation %s", err.Error())
}

dastTestPod := pod.NewBuilder(
APIClient, "rapidastclientpod", rhwaparams.TestNamespaceName, rhwaparams.TestContainerDast).
DefineOnNode(nodes[0].Object.Name).
WithTolerationToMaster().
WithPrivilegedFlag()
dastTestPod.Definition.Spec.ServiceAccountName = "trivy-service-account"

_, err = dastTestPod.CreateAndWaitUntilRunning(time.Minute)
if err != nil {
glog.V(logLevel).Infof(
"Error in rapidast client pod creation %s", err.Error())
}

return dastTestPod
}

// RunRapidastScan executes the rapidast scan configured in the container.
func RunRapidastScan(dastTestPod pod.Builder, namespace string) (bytes.Buffer, error) {
command := []string{"bash", "-c",
fmt.Sprintf("NAMESPACE=%s rapidast.py --config ./config/rapidastConfig.yaml 2> /dev/null", namespace)}

return dastTestPod.ExecCommand(command)
}
6 changes: 6 additions & 0 deletions tests/rhwa/internal/rhwaparams/const.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,10 @@ const (
RhwaOperatorNs = "openshift-workload-availability"
// DefaultTimeout represents the default timeout.
DefaultTimeout = 300 * time.Second
// TestNamespaceName namespace where all dast test cases are performed.
TestNamespaceName = "dast-tests"
// LogLevel for the supporting functions.
LogLevel = 90
// TestContainerDast specifies the container image to use for rapidast tests.
TestContainerDast = "quay.io/ocp-edge-qe/eco-dast:latest"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if using always the latest version of the image could affect the reproducibility of scans.

)
Loading