Skip to content

Commit

Permalink
Merge pull request #4 from coreeng/k8-retry
Browse files Browse the repository at this point in the history
Added retry to load k8 object + replaced args with flags
  • Loading branch information
tombart authored Jul 9, 2024
2 parents 6d4d15a + eb758a5 commit ca10824
Show file tree
Hide file tree
Showing 20 changed files with 6,224 additions and 4,129 deletions.
32 changes: 16 additions & 16 deletions .github/workflows/execute-tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,19 @@ jobs:
runs-on: ubuntu-latest
name: Run tests
steps:
- uses: actions/checkout@v4
- name: Start minikube
uses: medyagh/[email protected]
- uses: actions/setup-go@v5
name: Intall and test go
with:
go-version: '^1.22.1'
- run: go version
- name: Try the cluster
run: kubectl get pods -A
- name: Apply dependencies
run:
make apply-test-resources
- name: Run tests
run:
make test
- uses: actions/checkout@v4
- name: Start minikube
uses: medyagh/[email protected]
- uses: actions/setup-go@v5
name: Intall and test go
with:
go-version: '^1.22.1'
- run: go version
- name: Try the cluster
run: kubectl get pods -A
- name: Apply dependencies
run:
make apply-test-resources
- name: Run tests
run:
make test
35 changes: 35 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
FROM golang:1.22-bullseye AS build-stage

SHELL ["/bin/bash", "-o", "pipefail", "-c"]

# Update packages
RUN apt-get update -y && apt-get upgrade -y && apt-get install unzip -y

# install kubelogin
RUN OS="$(uname | tr '[:upper:]' '[:lower:]')" && \
ARCH="$(uname -m | sed -e 's/x86_64/amd64/' -e 's/\(arm\)\(64\)\?.*/\1\2/' -e 's/aarch64$/arm64/')" && \
curl -L "https://github.com/Azure/kubelogin/releases/download/v0.0.30/kubelogin-${OS}-${ARCH}.zip" -o /tmp/kubelogin.zip && \
unzip /tmp/kubelogin.zip -d /tmp/ && \
mv /tmp/bin/linux_amd64/kubelogin /usr/bin/kubelogin && \
chmod +x /usr/bin/kubelogin

WORKDIR /app

# Copy source and build the binary
COPY go.mod go.sum ./

RUN go mod download

COPY . ./

RUN CGO_ENABLED=0 GOOS=linux go build -o vulcheck ./cmd/vulnerability-analysis/main.go

# Deploy the application binary into a lean image
FROM gcr.io/distroless/base-debian11 AS build-release-stage

WORKDIR /

COPY --from=build-stage /app/vulcheck ./vulcheck
COPY --from=build-stage /usr/bin/kubelogin ./usr/bin/kubelogin

ENTRYPOINT ["./vulcheck"]
79 changes: 64 additions & 15 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,26 +1,75 @@
projectDir := $(realpath $(dir $(firstword $(MAKEFILE_LIST))))
name = vulcheck
files := $(shell find . -path ./build -prune -o -name '*.go' -print)
pkgs := $(shell go list ./... | grep -v test)

.PHONY: default
default: help

# from https://suva.sh/posts/well-documented-makefiles/
.PHONY: help
help: Makefile
@echo "Usage: "
@sed -n 's/^##[ -]/ /p' Makefile
@echo ""
help: ## Display this help
awk 'BEGIN {FS = ":.*##"; printf "Usage:\n make \033[36m<target>\033[0m\n"} /^[a-zA-Z_-]+:.*?##/ { printf " \033[36m%-22s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST)


## make build Build golang app
.PHONY: build
build:
go build -o vulcheck ./cmd/vulnerability-analysis/main.go
## make test Run unit tests for golang app
build: check ## Build golang app
go build -o ${name} ./cmd/vulnerability-analysis/main.go

.PHONY: test
test: build
@go test ./...
run: build
./vulcheck trivy argocd index.docker.io/bitnami/etcd:3.5.12-debian-11-r3
## make apply-test-resources Applies test resources. These include the trivy CRDs and test resources
test: build ## Run unit tests for golang app
@go test ./... -cover -coverprofile=coverage.out

.PHONY: run
run: run ## Run the tool with default args
./${name} trivy -n argocd -i index.docker.io/bitnami/etcd:3.5.12-debian-11-r3

.PHONY: apply-test-resources
apply-test-resources:
apply-test-resources: ## Applies test resources. These include the trivy CRDs and test resources
@kubectl apply -f ./testdata/crds/ ; \
kubectl apply -f ./testdata/resources/ || true

.PHONY: docker-build
docker-build: ## Build docker image
docker build -t ${name} ${projectDir}

.PHONY: download
download: ## Download go dependencies
@echo "== download go.mod dependencies"
@go mod download

.PHONY: install-tools
install-tools: download ## Install build tools
@echo "== installing tools from tools.go"
@cat tools.go | grep _ | awk -F'"' '{print $$2}' | xargs -tI % go install %

.PHONY: check
check: install-tools vet lint checkformat ## Run static code checks

.PHONY: vet
vet: ## Run go vet
@echo "== vet $(pkgs)"
@go vet $(pkgs)

.PHONY: lint
lint: ## Run go lint
@echo "== lint"
@for pkg in $(pkgs); do \
golint -set_exit_status $$pkg || exit 1 ; \
done;

.PHONY: checkformat
checkformat: ## Run goimports
@echo "== check formatting"
ifneq "$(shell goimports -l $(files))" ""
@echo "code needs formatting. Run make format"
@exit 1
endif

.PHONY: format
format: ## Format all go files
@echo "== format"
@goimports -w $(files)
@sync

.PHONY: build-all
build-all: format test docker-build ## Format, lint, test, build local executable and docker image
90 changes: 68 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,50 +1,96 @@
# Vulnerability Analysis

## What's this tool?
The goal of this tool is to be used during image promotion. Based on the exit code, it should allow or block certain images from being promoted based on the security vulnerabilities

The goal of this tool is to be used during image promotion. Based on the exit code, it should allow or block certain
images from being promoted based on the security vulnerabilities
Exit codes:

* 0: Image was found and has the number of vulnerabilities below the thresholds
* 1: Image was found and has the number of vulnerabilities above the thresholds
* 2: Something went wrong on the execution (eg, report for the image not found)
* 2: Something went wrong on the execution (e.g., report for the image not found)

## Supported Integrations

The goal of this tool is to support multiple vulnerability scanner integration. Currently supporting:

* [Trivy](#trivy)

### Trivy

When invoked with `trivy` argument, the tool pulls `aquasecurity.github.io/v1alpha1.VulnerabilityReport` for a given
namespace and image and analyse the report according to the configuration file passed.
To wait for the report, pass optional `--timeout` flag. When passed, the tool will keep retrying with [exponential
backoff](https://pkg.go.dev/github.com/cenkalti/backoff/v4#ExponentialBackOff) until timeout is reached. If you pass
`0`, it'll retry forever.

#### Usage

## Usage
```bash
make build
./vulcheck trivy <namespace> <registry>/<imageName>:<imageVersion> <config-file-path>
./vulcheck trivy -n <namespace> -i <registry>/<imageName>:<imageVersion> -c <config-file-path> -t <timeout>
```
## Supported Integrations
The goal of this tool is to support multiple vulnerability scanner integration. Currently supporting:
* Trivy

## Testing
For testing, we're spinning up a minikube and adding the necessary CRDs and resources. For local development you can execute:

For testing, we're spinning up a minikube and adding the necessary CRDs and resources. For local development, you can
execute:

```bash
minikube start
make apply-test-resources
make test
```
CI will do a similar setup: create a minikube cluster, apply the CRDs and resources and execute the tests.

Merging to main will also trigger the tests and it will create a semantic version tag if tests are successful.
CI will do a similar setup: create a minikube cluster, apply the CRDs and resources, and execute the tests.

Merging to main will also trigger the tests, and it will create a semantic version tag if tests are successful.

## Default Thresholds

This tool will analyse the number of vulnerabilities, and based on a threshold, it will either succeed or fail. The
current defaults are

## Defaults Thresholds
This tool will analyse the number of vulnerabilities and based on a threshold it will either succeed or fail. The current defaults are
* Critical: 2
* High : -
* Medium: -
* High: -
* Medium: -
* Low: -
* Unknown: -

## Config file

### Default config file
The application will try to read a config file to understand the configured thresholds. If left empty, it will try to read from `./config/config.yaml`. You may specify the path on the 3rd argument of the CLI.
The config file has the follwing structure:

The application will try to read a config file to understand the configured thresholds. If left empty, it will try to
read from `./config/config.yaml`. You may specify the path by passing flag `--config` to the client.
The config file has the following structure:

```yaml
threshold:
criticalCount: 2
highCount: 1001
mediumCount: 1002
lowCount: 1003
unknownCount: 1004
criticalCount: 2
highCount: 1001
mediumCount: 1002
lowCount: 1003
unknownCount: 1004
```
All fields are optional. If you leave a field unspecified, it will have the default value described above.
All fields are optional. If you leave any filed unspecified, it will have the default value described above.
## Docker
You can build a docker image with the tool embedded in it. To build run:
```
make docker-build
```

To run the tool:

```
docker run -v <kube_config_path>:/root/.kube -v $(pwd):/cfg docker run vulcheck:latest <ingegration> -n <namespace> -i <image> -c /cfg/vulnerability-config.yaml -t 60s
```

e.g.
```
docker run -v ${HOME}/.kube:/root/.kube -v $(pwd):/cfg vulcheck:latest trivy -n default -i ubuntu:latest -c /cfg/testdata/config/config.yaml -t 60s
```
3 changes: 3 additions & 0 deletions cmd/vulnerability-analysis/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@ package main
import (
"os"

log "github.com/sirupsen/logrus"

"github.com/coreeng/vulnerability-analysis/pkg/cmd"
)

func main() {
log.SetFormatter(&log.TextFormatter{ForceColors: true})
statusCode := cmd.Run()
os.Exit(statusCode)
}
Loading

0 comments on commit ca10824

Please sign in to comment.