Skip to content
This repository has been archived by the owner on Oct 14, 2020. It is now read-only.

feat: Use deterministic names for VulnerabilityReports #43

Merged
merged 1 commit into from
Sep 24, 2020
Merged
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
67 changes: 51 additions & 16 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -182,22 +182,57 @@ the operator in the same namespace as supervised workloads.
You'll need an OperatorGroup to denote which namespaces the operator should watch. It must exist in the namespace
where you want to deploy the operator.

3. Create the Subscription resource:

```
cat << EOF | kubectl apply -f -
apiVersion: operators.coreos.com/v1alpha1
kind: Subscription
metadata:
name: starboard-operator
namespace: marketplace
spec:
channel: alpha
name: starboard-operator
source: $QUAY_NAMESPACE-operators
sourceNamespace: marketplace
EOF
```
3. Create the Subscription resource
1. with Trivy scanner, which is enabled by default:

```
$ cat << EOF | kubectl apply -f -
apiVersion: operators.coreos.com/v1alpha1
kind: Subscription
metadata:
name: starboard-operator
namespace: marketplace
spec:
channel: alpha
name: starboard-operator
source: $QUAY_NAMESPACE-operators
sourceNamespace: marketplace
EOF
```
2. with Aqua CSP scanner:

```
$ kubectl create secret generic starboard-operator \
--namespace marketplace \
--from-literal OPERATOR_SCANNER_AQUA_CSP_USERNAME=$AQUA_CONSOLE_USERNAME \
--from-literal OPERATOR_SCANNER_AQUA_CSP_PASSWORD=$AQUA_CONSOLE_PASSWORD \
--from-literal OPERATOR_SCANNER_AQUA_CSP_VERSION=$AQUA_VERSION \
--from-literal OPERATOR_SCANNER_AQUA_CSP_HOST=http://csp-console-svc.aqua:8080
```

```
$ cat << EOF | kubectl apply -f -
apiVersion: operators.coreos.com/v1alpha1
kind: Subscription
metadata:
name: starboard-operator
namespace: marketplace
spec:
channel: alpha
name: starboard-operator
source: $QUAY_NAMESPACE-operators
sourceNamespace: marketplace
config:
env:
- name: OPERATOR_SCANNER_TRIVY_ENABLED
value: "false"
- name: OPERATOR_SCANNER_AQUA_CSP_ENABLED
value: "true"
envFrom:
- secretRef:
name: starboard-operator
EOF
```

A Subscription links the previous steps together by selecting an operator and one of its channels. OLM uses this
information to start the corresponding operator Pod. The example above creates a new Subscription to the `alpha`
Expand Down
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ modules:
build: operator scanner

scanner: $(SOURCES)
go build -o bin/scanner cmd/scanner/main.go
GOOS=linux go build -o bin/scanner cmd/scanner/main.go

operator: $(SOURCES)
go build -o bin/operator cmd/operator/main.go
GOOS=linux go build -o bin/operator cmd/operator/main.go

.PHONY: test
test:
Expand Down
34 changes: 21 additions & 13 deletions cmd/operator/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,36 +81,44 @@ func run() error {

targetNamespaces := config.Operator.GetTargetNamespaces()

setupLog.Info("Resolving multitenancy support",
"operatorNamespace", operatorNamespace,
"targetNamespaces", targetNamespaces)

installMode, err := etc.ResolveInstallMode(operatorNamespace, targetNamespaces)
installMode, err := config.Operator.GetInstallMode()
if err != nil {
return fmt.Errorf("resolving install mode: %w", err)
return fmt.Errorf("getting install mode: %w", err)
}
setupLog.Info("Resolving install mode", "mode", installMode)
setupLog.Info("Resolving install mode", "installMode", installMode,
"operatorNamespace", operatorNamespace,
"targetNamespaces", targetNamespaces)

// Set the default manager options.
options := manager.Options{
Scheme: scheme,
}

if len(targetNamespaces) == 1 && targetNamespaces[0] == operatorNamespace {
// Add support for OwnNamespace set in STARBOARD_TARGET_NAMESPACES (e.g. ns1).
switch installMode {
case etc.InstallModeOwnNamespace:
// Add support for OwnNamespace set in STARBOARD_NAMESPACE (e.g. marketplace) and STARBOARD_TARGET_NAMESPACES (e.g. marketplace)
setupLog.Info("Constructing single-namespaced cache", "namespace", targetNamespaces[0])
options.Namespace = targetNamespaces[0]
} else if len(targetNamespaces) > 0 {
// Add support for SingleNamespace and MultiNamespace set in STARBOARD_TARGET_NAMESPACES (e.g. ns1,ns2).
case etc.InstallModeSingleNamespace:
// Add support for SingleNamespace set in STARBOARD_NAMESPACE (e.g. marketplace) and STARBOARD_TARGET_NAMESPACES (e.g. foo)
cachedNamespaces := append(targetNamespaces, operatorNamespace)
setupLog.Info("Constructing multi-namespaced cache", "namespaces", cachedNamespaces)
options.Namespace = targetNamespaces[0]
options.NewCache = cache.MultiNamespacedCacheBuilder(cachedNamespaces)
case etc.InstallModeMultiNamespace:
// Add support for MultiNamespace set in STARBOARD_NAMESPACE (e.g. marketplace) and STARBOARD_TARGET_NAMESPACES (e.g. foo,bar).
// Note that we may face performance issues when using this with a high number of namespaces.
// More: https://godoc.org/github.com/kubernetes-sigs/controller-runtime/pkg/cache#MultiNamespacedCacheBuilder
cachedNamespaces := append(targetNamespaces, operatorNamespace)
setupLog.Info("Constructing multi-namespaced cache", "namespaces", cachedNamespaces)
options.Namespace = ""
options.NewCache = cache.MultiNamespacedCacheBuilder(cachedNamespaces)
} else if len(targetNamespaces) == 0 {
setupLog.Info("Disabling cache and watching all namespaces")
case etc.InstallModeAllNamespaces:
// Add support for AllNamespaces set in STARBOARD_NAMESPACE (e.g. marketplace) and STARBOARD_TARGET_NAMESPACES left blank.
setupLog.Info("Watching all namespaces")
options.Namespace = ""
default:
return fmt.Errorf("unrecognized install mode: %v", installMode)
}

kubernetesConfig, err := ctrl.GetConfig()
Expand Down
5 changes: 3 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ module github.com/aquasecurity/starboard-operator
go 1.14

require (
github.com/aquasecurity/starboard v0.3.1-0.20200915085831-05e4ce57da65
github.com/aquasecurity/starboard v0.4.1-0.20200923101908-ca60574a118f
github.com/beorn7/perks v1.0.1 // indirect
github.com/caarlos0/env/v6 v6.2.2
github.com/go-logr/logr v0.1.0
github.com/google/go-containerregistry v0.1.1
Expand All @@ -16,7 +17,7 @@ require (
k8s.io/apimachinery v0.19.0-alpha.3
k8s.io/client-go v0.19.0-alpha.3
k8s.io/utils v0.0.0-20200603063816-c1c6865ac451
sigs.k8s.io/controller-runtime v0.6.2
sigs.k8s.io/controller-runtime v0.6.3
)

replace (
Expand Down
11 changes: 6 additions & 5 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,8 @@ github.com/apex/log v1.3.0/go.mod h1:jd8Vpsr46WAe3EZSQ/IUMs2qQD/GOycT5rPWCO1yGcs
github.com/apex/logs v0.0.4/go.mod h1:XzxuLZ5myVHDy9SAmYpamKKRNApGj54PfYLcFrXqDwo=
github.com/aphistic/golf v0.0.0-20180712155816-02c07f170c5a/go.mod h1:3NqKYiepwy8kCu4PNA+aP7WUV72eXWJeP9/r3/K9aLE=
github.com/aphistic/sweet v0.2.0/go.mod h1:fWDlIh/isSE9n6EPsRmC0det+whmX6dJid3stzu0Xys=
github.com/aquasecurity/starboard v0.3.1-0.20200915085831-05e4ce57da65 h1:uRoIOcMb/uTZwlnFZtEKL373eojYTW24UpFSnwW1w5g=
github.com/aquasecurity/starboard v0.3.1-0.20200915085831-05e4ce57da65/go.mod h1:Xdodbl8+u6Na3ah5DoeBONtVavbCrwMA7CcpKYDBizo=
github.com/aquasecurity/starboard v0.4.1-0.20200923101908-ca60574a118f h1:rrdkeHqSnE6z/og/Pse54kKnMF1l/bD6SJVlRIPlIKI=
github.com/aquasecurity/starboard v0.4.1-0.20200923101908-ca60574a118f/go.mod h1:Xdodbl8+u6Na3ah5DoeBONtVavbCrwMA7CcpKYDBizo=
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
Expand Down Expand Up @@ -192,8 +192,9 @@ github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.m
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/evanphx/json-patch v4.5.0+incompatible h1:ouOWdg56aJriqS0huScTkVXPC5IcNrDCXZ6OoTAWu7M=
github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/evanphx/json-patch v4.9.0+incompatible h1:kLcOMZeuLAJvL2BPWLMIj5oaZQobrkAqrL+WFZwQses=
github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
github.com/fortytw2/leaktest v1.2.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
Expand Down Expand Up @@ -1123,8 +1124,8 @@ rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.7/go.mod h1:PHgbrJT7lCHcxMU+mDHEm+nx46H4zuuHZkDP6icnhu0=
sigs.k8s.io/controller-runtime v0.6.2 h1:jkAnfdTYBpFwlmBn3pS5HFO06SfxvnTZ1p5PeEF/zAA=
sigs.k8s.io/controller-runtime v0.6.2/go.mod h1:vhcq/rlnENJ09SIRp3EveTaZ0yqH526hjf9iJdbUJ/E=
sigs.k8s.io/controller-runtime v0.6.3 h1:SBbr+inLPEKhvlJtrvDcwIpm+uhDvp63Bl72xYJtoOE=
sigs.k8s.io/controller-runtime v0.6.3/go.mod h1:WlZNXcM0++oyaQt4B7C2lEE5JYRs8vJUzRP4N4JpdAY=
sigs.k8s.io/kustomize v2.0.3+incompatible/go.mod h1:MkjgH3RdOWrievjo6c9T245dYlB5QeXV4WCbnt/PEpU=
sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI=
sigs.k8s.io/structured-merge-diff v1.0.1-0.20191108220359-b1b620dd3f06 h1:zD2IemQ4LmOcAumeiyDWXKUI2SO0NYDe3H6QGvPOVgU=
Expand Down
6 changes: 3 additions & 3 deletions pkg/aqua/scanner.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ func NewScanner(version etc.VersionInfo, config etc.ScannerAquaCSP) scanner.Vuln
}
}

func (s *aquaScanner) NewScanJob(resource kube.Object, spec corev1.PodSpec, options scanner.Options) (*batchv1.Job, *corev1.Secret, error) {
func (s *aquaScanner) NewScanJob(resource kube.Object, spec corev1.PodSpec, options scanner.Options) (*batchv1.Job, error) {
jobName := uuid.New().String()
initContainerName := jobName

Expand All @@ -50,7 +50,7 @@ func (s *aquaScanner) NewScanJob(resource kube.Object, spec corev1.PodSpec, opti

containerImagesAsJSON, err := containerImages.AsJSON()
if err != nil {
return nil, nil, err
return nil, err
}

return &batchv1.Job{
Expand Down Expand Up @@ -122,7 +122,7 @@ func (s *aquaScanner) NewScanJob(resource kube.Object, spec corev1.PodSpec, opti
},
},
},
}, nil, nil
}, nil
}

func (s *aquaScanner) newScanJobContainer(podContainer corev1.Container) corev1.Container {
Expand Down
47 changes: 6 additions & 41 deletions pkg/controllers/job_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ package controllers
import (
"context"
"fmt"
"reflect"

"github.com/aquasecurity/starboard-operator/pkg/resources"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

"github.com/aquasecurity/starboard-operator/pkg/etc"
Expand Down Expand Up @@ -55,7 +55,7 @@ func (r *JobReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) {
}

if len(job.Status.Conditions) == 0 {
log.Info("Ignoring Job with unknown status condition")
log.Info("Ignoring Job without status conditions")
return ctrl.Result{}, nil
}

Expand Down Expand Up @@ -85,12 +85,12 @@ func (r *JobReconciler) processCompleteScanJob(ctx context.Context, scanJob *bat
return fmt.Errorf("getting workload from scan job labels set: %w", err)
}

containerImages, err := r.getContainerImagesFrom(scanJob)
containerImages, err := resources.GetContainerImagesFromJob(scanJob)
if err != nil {
return err
return fmt.Errorf("getting container images: %w", err)
}

hasVulnerabilityReports, err := r.hasVulnerabilityReports(ctx, workload, containerImages)
hasVulnerabilityReports, err := r.Store.HasVulnerabilityReports(ctx, workload, containerImages)
if err != nil {
return err
}
Expand Down Expand Up @@ -146,41 +146,6 @@ func (r *JobReconciler) GetPodControlledBy(ctx context.Context, job *batchv1.Job
return podList.Items[0].DeepCopy(), nil
}

func (r *JobReconciler) hasVulnerabilityReports(ctx context.Context, owner kube.Object, containerImages kube.ContainerImages) (bool, error) {
vulnerabilityReports, err := r.Store.Read(ctx, owner)
if err != nil {
return false, err
}

actual := map[string]bool{}
for containerName, _ := range vulnerabilityReports {
actual[containerName] = true
}

expected := map[string]bool{}
for containerName, _ := range containerImages {
expected[containerName] = true
}

return reflect.DeepEqual(actual, expected), nil
}

// TODO We have similar code in other places
func (r *JobReconciler) getContainerImagesFrom(job *batchv1.Job) (kube.ContainerImages, error) {
var containerImagesAsJSON string
var ok bool

if containerImagesAsJSON, ok = job.Annotations[kube.AnnotationContainerImages]; !ok {
return nil, fmt.Errorf("scan job does not have required annotation: %s", kube.AnnotationContainerImages)
}
containerImages := kube.ContainerImages{}
err := containerImages.FromJSON(containerImagesAsJSON)
if err != nil {
return nil, fmt.Errorf("reading scan job annotation: %s: %w", kube.AnnotationContainerImages, err)
}
return containerImages, nil
}

func (r *JobReconciler) processFailedScanJob(ctx context.Context, scanJob *batchv1.Job) error {
pod, err := r.GetPodControlledBy(ctx, scanJob)
if err != nil {
Expand All @@ -194,7 +159,7 @@ func (r *JobReconciler) processFailedScanJob(ctx context.Context, scanJob *batch
r.Log.Error(nil, "Scan job container", "container", container, "status.reason", status.Reason, "status.message", status.Message)
}
r.Log.Info("Deleting failed scan job")
return r.Client.Delete(ctx, scanJob)
return r.Client.Delete(ctx, scanJob, client.PropagationPolicy(metav1.DeletePropagationBackground))
}

func (r *JobReconciler) SetupWithManager(mgr ctrl.Manager) error {
Expand Down
Loading