Skip to content

Commit

Permalink
test(operator): Assert that ConfigAuditReports are created when Conft…
Browse files Browse the repository at this point in the history
…est is used as a scanner (#556)

Resolves: #480

Signed-off-by: Daniel Pacak <pacak.daniel@gmail.com>
  • Loading branch information
danielpacak committed May 7, 2021
1 parent 66cf6a2 commit b2d8284
Show file tree
Hide file tree
Showing 10 changed files with 304 additions and 30 deletions.
34 changes: 34 additions & 0 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,40 @@ jobs:
uses: codecov/codecov-action@v1
with:
files: ./itest/starboard-operator/coverage.txt
integration-operator-conftest:
name: Integration / Operator / Conftest
runs-on: ubuntu-18.04
steps:
- name: Setup Go
uses: actions/setup-go@v1
with:
go-version: ${{ env.GO_VERSION }}
- name: Checkout code
uses: actions/checkout@v2
- name: Setup Kubernetes cluster (KIND)
uses: engineerd/setup-kind@v0.5.0
with:
version: ${{ env.KIND_VERSION }}
image: ${{ env.KIND_IMAGE }}
- name: Run integration tests
run: |
kubectl apply -f deploy/crd/vulnerabilityreports.crd.yaml \
-f deploy/crd/configauditreports.crd.yaml \
-f deploy/crd/ciskubebenchreports.crd.yaml
kubectl apply -f deploy/static/01-starboard-operator.ns.yaml \
-f deploy/static/02-starboard-operator.sa.yaml \
-f deploy/static/03-starboard-operator.clusterrole.yaml \
-f deploy/static/04-starboard-operator.clusterrolebinding.yaml
make integration-operator-conftest
env:
KUBECONFIG: /home/runner/.kube/config
OPERATOR_NAMESPACE: starboard-operator
OPERATOR_SERVICE_ACCOUNT: starboard-operator
OPERATOR_TARGET_NAMESPACES: default
- name: Upload code coverage
uses: codecov/codecov-action@v1
with:
files: ./itest/starboard-operator/configauditreport/conftest/coverage.txt
verify-code:
name: Verify code
runs-on: ubuntu-18.04
Expand Down
31 changes: 31 additions & 0 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -81,12 +81,43 @@ jobs:
OPERATOR_NAMESPACE: starboard-operator
OPERATOR_SERVICE_ACCOUNT: starboard-operator
OPERATOR_TARGET_NAMESPACES: default
integration-operator-conftest:
name: Integration / Operator / Conftest
runs-on: ubuntu-18.04
steps:
- name: Setup Go
uses: actions/setup-go@v1
with:
go-version: ${{ env.GO_VERSION }}
- name: Checkout code
uses: actions/checkout@v2
- name: Setup Kubernetes cluster (KIND)
uses: engineerd/setup-kind@v0.5.0
with:
version: ${{ env.KIND_VERSION }}
image: ${{ env.KIND_IMAGE }}
- name: Run integration tests
run: |
kubectl apply -f deploy/crd/vulnerabilityreports.crd.yaml \
-f deploy/crd/configauditreports.crd.yaml \
-f deploy/crd/ciskubebenchreports.crd.yaml
kubectl apply -f deploy/static/01-starboard-operator.ns.yaml \
-f deploy/static/02-starboard-operator.sa.yaml \
-f deploy/static/03-starboard-operator.clusterrole.yaml \
-f deploy/static/04-starboard-operator.clusterrolebinding.yaml
make integration-operator-conftest
env:
KUBECONFIG: /home/runner/.kube/config
OPERATOR_NAMESPACE: starboard-operator
OPERATOR_SERVICE_ACCOUNT: starboard-operator
OPERATOR_TARGET_NAMESPACES: default
release:
name: Release
needs:
- unit-tests
- itest-starboard
- itest-starboard-operator
- integration-operator-conftest
runs-on: ubuntu-18.04
steps:
- name: Setup Go
Expand Down
18 changes: 18 additions & 0 deletions .run/idea/Integration _ Operator _ Conftest.run.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Integration / Operator / Conftest" type="GoTestRunConfiguration" factoryName="Go Test">
<module name="starboard" />
<working_directory value="$PROJECT_DIR$/itest/starboard-operator/configauditreport/conftest" />
<envs>
<env name="OPERATOR_NAMESPACE" value="starboard-operator" />
<env name="OPERATOR_TARGET_NAMESPACES" value="default" />
</envs>
<root_directory value="$PROJECT_DIR$" />
<kind value="PACKAGE" />
<package value="github.com/aquasecurity/starboard/itest/starboard-operator/configauditreport/conftest" />
<directory value="$PROJECT_DIR$" />
<filePath value="$PROJECT_DIR$" />
<framework value="gotest" />
<pattern value="^\QTestIntegrationOperatorWithConftest\E$" />
<method v="2" />
</configuration>
</component>
14 changes: 14 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,20 @@ itests-starboard-operator: check-env get-ginkgo
github.com/aquasecurity/starboard/pkg/kubebench \
./itest/starboard-operator

.PHONY: integration-operator-conftest
integration-operator-conftest: check-env get-ginkgo
$(GOBIN)/ginkgo \
--progress \
--v \
-coverprofile=coverage.txt \
-coverpkg=github.com/aquasecurity/starboard/pkg/operator,\
github.com/aquasecurity/starboard/pkg/operator/predicate,\
github.com/aquasecurity/starboard/pkg/operator/controller,\
github.com/aquasecurity/starboard/pkg/plugin,\
github.com/aquasecurity/starboard/pkg/plugin/conftest,\
github.com/aquasecurity/starboard/pkg/configauditreport \
./itest/starboard-operator/configauditreport/conftest

check-env:
ifndef KUBECONFIG
$(error Environment variable KUBECONFIG is not set)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package starboard_operator
package behavior

import (
. "github.com/onsi/ginkgo"
Expand All @@ -17,18 +17,19 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
)

// SharedBehaviorInputs represents required inputs to shared behavior containers.
type SharedBehaviorInputs struct {
// Inputs represents required inputs to shared behavior containers.
type Inputs struct {
AssertTimeout time.Duration
PrimaryNamespace string
PrimaryWorkloadPrefix string

client.Client
*helper.Helper
}

// VulnerabilityScannerBehavior returns the container of specs that describe behavior
// of a vulnerability scanner with the given inputs.
func VulnerabilityScannerBehavior(inputs *SharedBehaviorInputs) func() {
func VulnerabilityScannerBehavior(inputs *Inputs) func() {
return func() {

Context("When unmanaged Pod is created", func() {
Expand Down Expand Up @@ -204,7 +205,7 @@ func VulnerabilityScannerBehavior(inputs *SharedBehaviorInputs) func() {

// ConfigurationCheckerBehavior returns the container of specs that describe behavior
// of a configuration checker with the given inputs.
func ConfigurationCheckerBehavior(inputs *SharedBehaviorInputs) func() {
func ConfigurationCheckerBehavior(inputs *Inputs) func() {
return func() {

Context("When unmanaged Pod is created", func() {
Expand Down Expand Up @@ -416,3 +417,24 @@ func ConfigurationCheckerBehavior(inputs *SharedBehaviorInputs) func() {
// TODO Add scenario for DaemonSet
}
}

// CISKubernetesBenchmarkBehavior returns the container of specs that describe behavior
// of a CIS Kubernetes Benchmark with the given inputs.
func CISKubernetesBenchmarkBehavior(inputs *Inputs) func() {
return func() {

Context("When operator is started", func() {

It("Should create CISKubeBenchReports", func() {
var nodeList corev1.NodeList
err := inputs.List(context.Background(), &nodeList)
Expect(err).ToNot(HaveOccurred())
for _, node := range nodeList.Items {
Eventually(inputs.HasCISKubeBenchReportOwnedBy(node), inputs.AssertTimeout).Should(BeTrue())
}
})

})

}
}
8 changes: 8 additions & 0 deletions itest/starboard-operator/configauditreport/conftest/a_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package conftest

import (
. "github.com/aquasecurity/starboard/itest/starboard-operator/behavior"
. "github.com/onsi/ginkgo"
)

var _ = Describe("Conftest", ConfigurationCheckerBehavior(&inputs))
133 changes: 133 additions & 0 deletions itest/starboard-operator/configauditreport/conftest/suite_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
package conftest

import (
_ "embed"

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

"context"
"testing"
"time"

"github.com/aquasecurity/starboard/itest/helper"
"github.com/aquasecurity/starboard/itest/starboard-operator/behavior"
"github.com/aquasecurity/starboard/pkg/operator"
"github.com/aquasecurity/starboard/pkg/operator/etc"
"github.com/aquasecurity/starboard/pkg/starboard"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
logf "sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/log/zap"
)

var (
buildInfo = starboard.BuildInfo{
Version: "dev",
Commit: "none",
Date: "unknown",
}
)

var (
scheme *runtime.Scheme
kubeClient client.Client
startCtx context.Context
stopFunc context.CancelFunc
)

var (
inputs behavior.Inputs
)

var (
starboardCM *corev1.ConfigMap
conftestCM *corev1.ConfigMap

//go:embed testdata/run_as_root.rego
runAsRootPolicy string
)

func TestIntegrationOperatorWithConftest(t *testing.T) {
if testing.Short() {
t.Skip("Skipping integration test")
}
RegisterFailHandler(Fail)
RunSpecs(t, "Conftest")
}

var _ = BeforeSuite(func() {
operatorConfig, err := etc.GetOperatorConfig()
Expect(err).ToNot(HaveOccurred())

logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(operatorConfig.LogDevMode)))

kubeConfig, err := ctrl.GetConfig()
Expect(err).ToNot(HaveOccurred())

scheme = starboard.NewScheme()
kubeClient, err = client.New(kubeConfig, client.Options{
Scheme: scheme,
})
Expect(err).ToNot(HaveOccurred())

inputs = behavior.Inputs{
AssertTimeout: 3 * time.Minute,
PrimaryNamespace: corev1.NamespaceDefault,
PrimaryWorkloadPrefix: "wordpress",

Client: kubeClient,
Helper: helper.NewHelper(scheme, kubeClient),
}

// We can disable vulnerability scanner and CIS benchmarks
operatorConfig.VulnerabilityScannerEnabled = false
operatorConfig.CISKubernetesBenchmarkEnabled = false

starboardCM = &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Namespace: operatorConfig.Namespace,
Name: starboard.ConfigMapName,
},
Data: map[string]string{
"configAuditReports.scanner": "Conftest",
"conftest.imageRef": "docker.io/openpolicyagent/conftest:v0.23.0",
},
}
err = kubeClient.Create(context.Background(), starboardCM)
Expect(err).ToNot(HaveOccurred())

conftestCM = &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Namespace: operatorConfig.Namespace,
Name: starboard.GetPluginConfigMapName("Conftest"),
},
Data: map[string]string{
"conftest.policy.runs_as_root.rego": runAsRootPolicy,
},
}
err = kubeClient.Create(context.Background(), conftestCM)
Expect(err).ToNot(HaveOccurred())

startCtx, stopFunc = context.WithCancel(context.Background())

go func() {
defer GinkgoRecover()
By("Starting Starboard operator")
err = operator.Start(startCtx, buildInfo, operatorConfig)
Expect(err).ToNot(HaveOccurred())
}()

})

var _ = AfterSuite(func() {
By("Stopping Starboard operator")
stopFunc()
err := kubeClient.Delete(context.Background(), starboardCM)
Expect(err).ToNot(HaveOccurred())
err = kubeClient.Delete(context.Background(), conftestCM)
Expect(err).ToNot(HaveOccurred())
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package main

deny[res] {
input.kind == "ReplicaSet"
not input.spec.template.spec.securityContext.runAsNonRoot

res := {
"msg": "Containers must not run as root",
"title": "Run as root"
}
}

deny[res] {
input.kind == "Pod"
not input.spec.securityContext.runAsNonRoot

res := {
"msg": "Containers must not run as root",
"title": "Run as root"
}
}

deny[res] {
input.kind == "CronJob"
not input.spec.jobTemplate.spec.template.spec.securityContext.runAsNonRoot

res := {
"msg": "Containers must not run as root",
"title": "Run as root"
}
}

0 comments on commit b2d8284

Please sign in to comment.