Skip to content

Commit

Permalink
Add Trivy as Vulnerability plugin (#228)
Browse files Browse the repository at this point in the history
* remove kubeconfig flags from plugins cmd

* add default-container annotation on plugin pods

* set KUBECONFIG env only if the Cluster has kubeconfigKeyRef

* add view permissions to zora-plugins ClusterRole

* remove kubeconfigRef from Cluster sample

* feat: add agent mode flag in helm chart

* fix: operator should have the same permissions as the plugins

* update plugins role

* set runAsNonRoot in container level

* create vulnerabilityreport crd

* create namespace on `make install`

* create trivy plugin sample

* chore: update trivy plugin

* chore: apply trivy plugin on make install

* feat: set security context on worker container

* feat: set security context on init container

* feat: do not set security context pod level

* feat: update plugins role

* feat: set allowPrivilegeEscalation to false in plugins security context

* feat: add type field in Plugin

* chore: set PLUGIN_TYPE to worker env

* chore: set type field on plugin manifests

* chore: handle misc plugins

* feat: implement trivy parse function

* chore: handle vulnerabilities in worker

* chore: generate clientset for VulnerabilityReport

* chore: add license header

* chore: update operator role

* chore: update plugins role

* feat: creating vulnerability reports in worker

* chore: update test error messages

* chore: testing parseVulnResults function

* chore: add totalResources, summary, type and score in Vulnerability types

* test: add sha256 test case

* ci: set go-version-file in setup-go@v4

* feat: add vuln reports column markers

* chore: remove non-alphanumeric from vuln reports name

* chore: log trivy report errors as info

* feat: update clusterscans and customchecks short names

* feat: update clusterissues short names

* chore: bump curl image

* chore: always apply plugins

* ci: update helm chart repository

* chore: add --no-progress flag in trivy plugin

* chore: update logs

* docs: add slack badge on README.md

* chore: delete unused file

* chore: add trivy plugin in helm chart

* chore: update imagePullSecret template name in helm chart

* feat: apply scans for both misc and vuln in helm chart

* chore: rename clusterscan template file in helm chart

* zora v0.7.0-rc3

* chore: using "misconfig" to abbreviate "misconfigurations", instead of "misc"

* chore: remove suspend and schedule fields from plugin reference in cluster scan spec

* chore: rename `issueCount` to `totalIssues` in clusterscan status;

remove `Issues` column from clusterscan;

remove `suspend` and `schedule` fields from plugin status;

* docs: update description of successfulScansHistoryLimit and failedScansHistoryLimit clusterscan fields

* chore: add successfulScansHistoryLimit and failedScansHistoryLimit fields on helm chart

* chore: update NOTES.txt

* chore: remove default trivy resources in helm chart

* chore: bump zora chart 0.7.0-rc4

* chore: update chart NOTES.txt

* chore: create a chart pre-delete hook to delete the default cluster

* chore: set label zora.undistro.io/default to "true" in default cluster and scans

* feat: add description field in Vulnerability

* feat: delete hook image as helm parameter

* bump trivy 0.45.1

* bump gh actions

* pre release v0.7.0-rc5

* chg: set plugin env variables in worker container

* feat: add ignoreUnfixed and ignoreDescriptions parameters in helm chart

* chore: add kind targets in Makefile

* bump zora chart to v0.7.0-rc6

* fix clusterscan saas hook

* docs: update docs

* docs: add pages for plugins

* docs: update chart description

* docs: update chart readme

* docs: update README.md

* docs: update bold in plugins page

* chg: update clusterscan samples

* zora 0.7.0-rc7

* docs: add a button to zora dashboard

* docs: update helm chart readme

* docs: fix helm chart page link

* docs: add resources page

* docs: update resources page title

* docs: add suspending scan page

* docs: add faq page

* docs: update faq

* docs: update logo

* docs: add retain issues page

* docs: add admonition note in suspend scan page

* docs: update key features sorting

* docs: update trivy.md page

* docs: add "ignore unfixed vulnerability" in sidebar

* docs: update switch theme icon

* docs: center try zora dashboard button

* docs: add note about vulnerability reports in Zora Dashboard

* docs: fix version links

* docs: add OCI registry support with helm

* docs: add oss vs dashboard session in index.md

* docs: add note about zora dashboard arch in overview page

* release zora 0.7.0
  • Loading branch information
matheusfm authored Oct 31, 2023
1 parent 1271995 commit 8cfdce4
Show file tree
Hide file tree
Showing 112 changed files with 8,929 additions and 9,658 deletions.
18 changes: 6 additions & 12 deletions .github/workflows/docker.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,40 +24,34 @@ jobs:
image: worker
steps:
- name: checkout
uses: actions/checkout@v3
uses: actions/checkout@v4

- name: setup qemu
uses: docker/setup-qemu-action@v2
uses: docker/setup-qemu-action@v3

- name: setup docker buildx
uses: docker/setup-buildx-action@v2
uses: docker/setup-buildx-action@v3

- name: login
uses: docker/login-action@v2
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: metadata
id: meta
uses: docker/metadata-action@v4
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}/${{ matrix.image }}
tags: |
type=schedule
type=ref,event=branch
type=ref,event=tag
type=ref,event=pr,prefix=pr-
type=sha,prefix=,format=long

- name: create dockerfile.cross
run: |
sed -e '1 s/\(^FROM\)/FROM --platform=\$\{BUILDPLATFORM\}/; t' -e ' 1,// s//FROM --platform=\$\{BUILDPLATFORM\}/' ${{ matrix.dockerfile }} > ${{ matrix.dockerfile }}.cross
cat ${{ matrix.dockerfile }}.cross
- name: build and push
uses: docker/build-push-action@v3
uses: docker/build-push-action@v5
with:
platforms: linux/arm64,linux/amd64,linux/s390x,linux/ppc64le
file: ${{ matrix.dockerfile }}.cross
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/docs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,17 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v3
uses: actions/checkout@v4

- name: setup python
uses: actions/setup-python@v4
with:
python-version: '3.10'

- name: setup go
uses: actions/setup-go@v3
uses: actions/setup-go@v4
with:
go-version: '~1.20'
go-version-file: 'go.mod'
cache: true

- name: install mkdocs and mike
Expand Down
12 changes: 6 additions & 6 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:
needs: [docker]
steps:
- name: checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
fetch-depth: 0

Expand All @@ -36,11 +36,11 @@ jobs:
- name: setup go
uses: actions/setup-go@v4
with:
go-version: '~1.20'
go-version-file: 'go.mod'
cache: true

- name: release
uses: goreleaser/goreleaser-action@v4
uses: goreleaser/goreleaser-action@v5
with:
distribution: goreleaser
version: latest
Expand All @@ -53,14 +53,14 @@ jobs:
needs: [goreleaser]
steps:
- name: checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
path: main

- name: checkout charts
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
repository: undistro/charts.undistro.io
repository: undistro/helm-charts
ref: main
fetch-depth: 1
token: ${{ secrets.BOT_TOKEN }} # GITHUB_TOKEN is scoped to the current repository, so we need a PAT to checkout a different repository and commit on it.
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v3
uses: actions/checkout@v4

- name: setup go
uses: actions/setup-go@v3
uses: actions/setup-go@v4
with:
go-version: '~1.20'
go-version-file: 'go.mod'
cache: true

- name: test
Expand Down
42 changes: 35 additions & 7 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Image URL to use all building/pushing image targets
IMG ?= controller:latest
WORKER_IMG ?= worker:latest

# ENVTEST_K8S_VERSION refers to the version of kubebuilder assets to be downloaded by envtest binary.
ENVTEST_K8S_VERSION = 1.27.1

Expand Down Expand Up @@ -33,7 +35,7 @@ all: build

.PHONY: help
help: ## Display this help.
@awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m<target>\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST)
@awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m<target>\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-20s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST)

##@ Development

Expand Down Expand Up @@ -101,12 +103,16 @@ docker-build: test ## Build docker image with the manager.

.PHONY: docker-build-worker
docker-build-worker: test ## Build docker image with worker.
docker build -t worker:latest -f cmd/worker/Dockerfile .
docker build -t ${WORKER_IMG} -f cmd/worker/Dockerfile .

.PHONY: docker-push
docker-push: ## Push docker image with the manager.
docker push ${IMG}

.PHONY: docker-push-worker
docker-push-worker: ## Push docker image with worker.
docker push ${WORKER_IMG}

# PLATFORMS defines the target platforms for the manager image be build to provide support to multiple
# architectures. (i.e. make docker-buildx IMG=myregistry/myoperator:0.0.1). To use this option you need to:
# - able to use docker buildx . More info: https://docs.docker.com/build/buildx/
Expand All @@ -130,12 +136,15 @@ ifndef ignore-not-found
ignore-not-found = false
endif

NAMESPACE ?= zora-system
.PHONY: install
install: manifests kustomize ## Install CRDs into the K8s cluster specified in ~/.kube/config.
$(KUSTOMIZE) build config/crd | $(KUBECTL) apply -f -
@$(KUBECTL) apply -f config/samples/zora_v1alpha1_plugin_popeye_all.yaml
@$(KUBECTL) apply -f config/samples/zora_v1alpha1_plugin_marvin.yaml
@$(KUBECTL) apply -f config/samples/zora_v1alpha1_customcheck_labels.yaml
@$(KUBECTL) create namespace $(NAMESPACE) || true
@$(KUBECTL) apply -f config/samples/zora_v1alpha1_plugin_popeye_all.yaml -n $(NAMESPACE)
@$(KUBECTL) apply -f config/samples/zora_v1alpha1_plugin_marvin.yaml -n $(NAMESPACE)
@$(KUBECTL) apply -f config/samples/zora_v1alpha1_plugin_trivy.yaml -n $(NAMESPACE)
@$(KUBECTL) apply -f config/samples/zora_v1alpha1_customcheck_labels.yaml -n $(NAMESPACE)
@$(KUBECTL) apply -f config/rbac/zora_plugins_role.yaml
@$(KUBECTL) create -f config/rbac/zora_plugins_role_binding.yaml || true

Expand All @@ -156,6 +165,18 @@ template: manifests kustomize ## Build kustomize configurations.
undeploy: ## Undeploy controller from the K8s cluster specified in ~/.kube/config. Call with ignore-not-found=true to ignore resource not found errors during deletion.
$(KUSTOMIZE) build config/default | $(KUBECTL) delete --ignore-not-found=$(ignore-not-found) -f -

##@ Kind

CLUSTER_NAME ?= kind
.PHONY: kind-create-cluster
kind-create-cluster: kind ## Create a local Kubernetes cluster with Kind
$(KIND) create cluster --name $(CLUSTER_NAME)

.PHONY: kind-load-images
kind-load-images: kind docker-build docker-build-worker ## Build and load docker images into Kind nodes
$(KIND) load docker-image ${IMG}
$(KIND) load docker-image ${WORKER_IMG}

##@ Build Dependencies

## Location to install dependencies to
Expand All @@ -170,10 +191,13 @@ CONTROLLER_GEN ?= $(LOCALBIN)/controller-gen
ENVTEST ?= $(LOCALBIN)/setup-envtest
ADDLICENSE ?= $(LOCALBIN)/addlicense
HELM_DOCS ?= $(LOCALBIN)/helm-docs
KIND ?= $(LOCALBIN)/kind

## Tool Versions
KUSTOMIZE_VERSION ?= v5.0.0
CONTROLLER_TOOLS_VERSION ?= v0.11.3
HELM_DOCS_VERSION ?= v1.11.2
KIND_VERSION ?= v0.20.0

KUSTOMIZE_INSTALL_SCRIPT ?= "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh"
.PHONY: kustomize
Expand Down Expand Up @@ -202,7 +226,11 @@ $(ADDLICENSE): $(LOCALBIN)
test -s $(LOCALBIN)/addlicense || GOBIN=$(LOCALBIN) go install github.com/google/addlicense@latest

.PHONY: helm-docs
helm-docs: $(HELM_DOCS) ## Download helm-docs if necessary
helm-docs: $(HELM_DOCS) ## Download helm-docs locally if necessary
$(HELM_DOCS): $(LOCALBIN)
test -s $(LOCALBIN)/helm-docs || GOBIN=$(LOCALBIN) go install github.com/norwoodj/helm-docs/cmd/helm-docs@v1.8.1
test -s $(LOCALBIN)/helm-docs || GOBIN=$(LOCALBIN) go install github.com/norwoodj/helm-docs/cmd/helm-docs@$(HELM_DOCS_VERSION)

.PHONY: kind
kind: $(KIND) ## Download kind locally if necessary
$(KIND): $(LOCALBIN)
test -s $(LOCALBIN)/kind || GOBIN=$(LOCALBIN) go install sigs.k8s.io/kind@$(KIND_VERSION)
8 changes: 8 additions & 0 deletions PROJECT
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,12 @@ resources:
kind: CustomCheck
path: github.com/undistro/zora/api/zora/v1alpha1
version: v1alpha1
- api:
crdVersion: v1
namespaced: true
domain: undistro.io
group: zora
kind: VulnerabilityReport
path: github.com/undistro/zora/api/zora/v1alpha1
version: v1alpha1
version: "3"
16 changes: 11 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,30 @@
[![license](https://img.shields.io/github/license/undistro/zora)](https://github.com/undistro/zora/blob/main/LICENSE)
![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/undistro/zora?display_name=tag&sort=semver&color=blue)
[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fundistro%2Fzora.svg?type=shield)](https://app.fossa.com/projects/git%2Bgithub.com%2Fundistro%2Fzora?ref=badge_shield)
[![slack](https://img.shields.io/badge/Slack-Join-4a154b?logo=slack)](https://join.slack.com/t/undistrocommunity/shared_invite/zt-21slyrao4-dTW_XtOB90QVj05txOX6rA)

</div>

## Introduction

Zora is a multi-cluster scan that helps you identify potential issues and vulnerabilities
in your Kubernetes clusters in a centralized way, ensuring that the recommended best practices are in place.
Zora is an open-source solution that helps you achieve compliance with Kubernetes best practices recommended by
industry-leading frameworks.

Zora is the first product created by Undistro's initiative. Visit our [website](https://undistro.io) for more information about the project and sign up for our newsletter to stay up to date with Zora's new features and Undistro's new initiatives.
By scanning your cluster with multiple plugins at scheduled times, Zora identifies potential issues, misconfigurations,
and vulnerabilities.

_Please [star :star:](https://github.com/undistro/zora/stargazers) the repo if you want us to continue developing and improving Zora!_ :grin:

## Getting Started

Check out our live [documentation](https://zora-docs.undistro.io) for details about how to install Zora and start to scan your clusters.

## Contributing

We are in alpha stage and we'd love it if you contributed to Zora. For information on contributing to this project, please see our [guideline](https://github.com/undistro/zora/blob/main/CONTRIBUTING.md).
Please refer to the [contributing guide](https://github.com/undistro/zora/blob/main/CONTRIBUTING.md) and the
[code of conduct](https://github.com/undistro/zora/blob/main/CODE_OF_CONDUCT.md)
for more information on how to contribute.

## License

Zora is a Undistro product, backed by [Getup.io](https://getup.io) under the [Apache License 2.0](LICENSE).
Zora is released under the Apache 2.0 license. See the [LICENSE](LICENSE) file for details.
2 changes: 1 addition & 1 deletion api/zora/v1alpha1/clusterissue_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ type ClusterIssueStatus struct {

//+kubebuilder:object:root=true
//+kubebuilder:subresource:status
//+kubebuilder:resource:shortName="ci"
//+kubebuilder:resource:shortName={issue,issues,misconfig,misconfigs,misconfigurations}
//+kubebuilder:printcolumn:name="Cluster",type="string",JSONPath=".spec.cluster",priority=0
//+kubebuilder:printcolumn:name="ID",type="string",JSONPath=".spec.id",priority=0
//+kubebuilder:printcolumn:name="Message",type="string",JSONPath=".spec.message",priority=0
Expand Down
32 changes: 8 additions & 24 deletions api/zora/v1alpha1/clusterscan_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,16 +39,14 @@ type ClusterScanSpec struct {
// The list of Plugin references that are used to scan the referenced Cluster. Defaults to 'popeye'
Plugins []PluginReference `json:"plugins,omitempty"`

// SuccessfulScansHistoryLimit specifies the amount of successfully
// completed scan Jobs to be kept in the cluster. This field is analogous
// to <Cronjob.Spec.SuccessfulJobsHistoryLimit> from the <batch> package.
// The number of successful finished scans and their issues to retain. Value must be non-negative integer.
// Defaults to 3.
// +kubebuilder:validation:Minimum=0
// +kubebuilder:default=3
SuccessfulScansHistoryLimit *int32 `json:"successfulScansHistoryLimit,omitempty"`

// FailedScansHistoryLimit specifies the amount of failed scan Jobs to be
// kept in the cluster. This field is analogous to
// <Cronjob.Spec.FailedScansHistoryLimit> from the <batch> package.
// The number of failed finished scans to retain. Value must be non-negative integer.
// Defaults to 1.
// +kubebuilder:validation:Minimum=0
// +kubebuilder:default=1
FailedScansHistoryLimit *int32 `json:"failedScansHistoryLimit,omitempty"`
Expand All @@ -61,13 +59,6 @@ type PluginReference struct {
// Namespace defines the space within which the Plugin name must be unique.
Namespace string `json:"namespace,omitempty"`

// This flag tells the controller to suspend subsequent executions, it does
// not apply to already started executions. Defaults to false.
Suspend *bool `json:"suspend,omitempty"`

// The schedule in Cron format for this Plugin, see https://en.wikipedia.org/wiki/Cron.
Schedule string `json:"schedule,omitempty"`

// List of environment variables to set in the Plugin container.
Env []corev1.EnvVar `json:"env,omitempty"`
}
Expand Down Expand Up @@ -221,30 +212,23 @@ type PluginScanStatus struct {
// LastErrorMsg contains a plugin error message from the last failed scan.
LastErrorMsg string `json:"lastErrorMsg,omitempty"`

// IssueCount holds the sum of ClusterIssues found in the last successful scan.
IssueCount *int `json:"issueCount,omitempty"`

// Suspend field value from ClusterScan spec.plugins.*.suspend
Suspend bool `json:"suspend,omitempty"`

// The Cron schedule of this plugin
Schedule string `json:"schedule,omitempty"`
// TotalIssues holds the sum of ClusterIssues found in the last successful scan.
TotalIssues *int `json:"totalIssues,omitempty"`
}

//+kubebuilder:object:root=true
//+kubebuilder:subresource:status
//+kubebuilder:resource:shortName="cscan"
//+kubebuilder:resource:shortName={scan,scans}
//+kubebuilder:printcolumn:name="Cluster",type="string",JSONPath=".spec.clusterRef.name",priority=0
//+kubebuilder:printcolumn:name="Schedule",type="string",JSONPath=".spec.schedule",priority=0
//+kubebuilder:printcolumn:name="Suspend",type="boolean",JSONPath=".status.suspend",priority=0
//+kubebuilder:printcolumn:name="Plugins",type="string",JSONPath=".status.pluginNames",priority=0
//+kubebuilder:printcolumn:name="Last Status",type="string",JSONPath=".status.lastStatus",priority=0
//+kubebuilder:printcolumn:name="Last Schedule",type="date",JSONPath=".status.lastScheduleTime",priority=0
//+kubebuilder:printcolumn:name="Last Successful",type="date",JSONPath=".status.lastSuccessfulTime",priority=0
//+kubebuilder:printcolumn:name="Issues",type="integer",JSONPath=".status.totalIssues",priority=0
//+kubebuilder:printcolumn:name="Ready",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].status",priority=0
//+kubebuilder:printcolumn:name="SaaS",type="string",JSONPath=".status.conditions[?(@.type==\"SaaS\")].reason",priority=0
//+kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",priority=0
//+kubebuilder:printcolumn:name="SaaS",type="string",JSONPath=".status.conditions[?(@.type==\"SaaS\")].reason",priority=1
//+kubebuilder:printcolumn:name="Next Schedule",type="string",JSONPath=".status.nextScheduleTime",priority=1

// ClusterScan is the Schema for the clusterscans API
Expand Down
2 changes: 1 addition & 1 deletion api/zora/v1alpha1/clusterscan_types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -440,7 +440,7 @@ func TestSyncStatus(t *testing.T) {
css.Plugins = tt.plugins
css.SyncStatus()
if !reflect.DeepEqual(css, tt.want) {
t.Errorf("SyncStatus() = %s", cmp.Diff(css, tt.want))
t.Errorf("SyncStatus() mismatch (-want +got):\n%s", cmp.Diff(tt.want, css))
}
})
}
Expand Down
2 changes: 1 addition & 1 deletion api/zora/v1alpha1/customcheck_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ type CustomCheckStatus struct {

//+kubebuilder:object:root=true
//+kubebuilder:subresource:status
//+kubebuilder:resource:shortName="checks"
//+kubebuilder:resource:shortName={check,checks}
//+kubebuilder:printcolumn:name="Message",type="string",JSONPath=".spec.message",priority=0
//+kubebuilder:printcolumn:name="Severity",type="string",JSONPath=".spec.severity",priority=0
//+kubebuilder:printcolumn:name="Ready",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].status",priority=0
Expand Down
Loading

0 comments on commit 8cfdce4

Please sign in to comment.