Skip to content

Commit

Permalink
feat: replace plugin with example
Browse files Browse the repository at this point in the history
  • Loading branch information
tomwwright committed Oct 17, 2023
1 parent fecfbd2 commit 1a8ab24
Show file tree
Hide file tree
Showing 29 changed files with 199 additions and 989 deletions.
133 changes: 12 additions & 121 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,135 +1,26 @@
# ECR Scan Results Buildkite Plugin
# Example Go Buildkite Plugin

Buildkite plugin to retrieve ECR scan results from AWS's ECR image scanning
service. By default the plugin will cause the step to fail if there are critical
or high vulnerabilities reported, but there are configurable thresholds on this
behaviour.
An example Buildkite plugin written in Go, demonstrating on-demand download of the
public release files from Github and execution.

> ℹ️ TIP: if you want the build to continue when vulnerabilities are found, be
> sure to supply values for `max-criticals` and `max-highs` parameters. If these
> are set to high values your build will never fail, but details will be
> supplied in the annotation.
>
> Check out the FAQs below for more information
To demonstrate interaction with the Buildkite agent, the example includes code
to annotate the build with a message.

This example is reverse engineered from [@cultureamp/ecr-scan-results-buildkite-plugin](https://github.com/cultureamp/ecr-scan-results-buildkite-plugin).

## Example

Add the following lines to your `pipeline.yml`:

```yml
steps:
- command: "command which creates an image"
# the docker-compose plugin may be used here instead of a command
plugins:
- cultureamp/ecr-scan-results#v1.2.0:
image-name: "$BUILD_REPO:deploy-$BUILD_TAG"
```
In a pipeline this will look something like:
```yml
steps:
- label: ":docker: Build and push CDK deployment image"
command: "bin/ci_cdk_build_and_push.sh"
agents:
queue: ${BUILD_AGENT}
plugins:
- cultureamp/aws-assume-role:
role: ${BUILD_ROLE}
- cultureamp/ecr-scan-results#v1.2.0:
image-name: "$BUILD_REPO:deploy-$BUILD_TAG"
```
If you want the pipeline to pass with some vulnerabilities then set
`max-criticals` and `max-highs` like below. This pipeline will pass if there is
one critical vulenerability but fail if there are two. Similarly it will fail if
there are eleven high vulnerabilities.

```yml
steps:
- label: ":docker: Build and push CDK deployment image"
command: "bin/ci_cdk_build_and_push.sh"
agents:
queue: ${BUILD_AGENT}
plugins:
- cultureamp/aws-assume-role:
role: ${BUILD_ROLE}
- cultureamp/ecr-scan-results#v1.2.0:
image-name: "$BUILD_REPO:deploy-$BUILD_TAG"
max-criticals: "1"
max-highs: "10"
- plugins:
- cultureamp/example-go#v0.1.0:
message: "This is the message that will be annotated!"
```
## Configuration
### `image-name` (Required, string)

The name of the container image in ECR. This should be the same string that is
supplied as an arguement to the `docker push` command used to push the image to
AWS ECR. It should have the form:
`AWS_ACCOUNT_ID.dkr.ecr.REGION.amazonaws.com/REPOSITORY_NAME:IMAGE_TAG` with the
text in capitals replaced with the appropriate values for your environment.

### `max-criticals` (Optional, string)

If the number of critical vulnerabilities in the image exceeds this threshold
the build is failed. Defaults to 0. Use a sufficiently large number (e.g. 999)
to allow the build to always pass.

### `max-highs` (Optional, string)

If the number of high vulnerabilities in the image exceeds this threshold the
build is failed. Defaults to 0. Use a sufficiently large number (e.g. 999) to
allow the build to always pass.

### `image-label` (Optional, string)

When supplied, this is used to title the report annotation in place of the
repository name and tag. Useful sometimes when the repo name and tag make the
reports harder to scan visually.

## Requirements

### ECR Scan on Push

This plugin assumes that the ECR repository has the `ScanOnPush` setting set (see
the [AWS
docs](https://docs.aws.amazon.com/AmazonECR/latest/userguide/image-scanning.html)
for more information). By default this is not set on AWS ECR repositories.
However `Base Infrastructure for Services` configures this for all repostories
that it creates so for `cultureamp` pipelines no change should be required.

### Agent role requires the ecr:DescribeImages permission

The Buildkite agent needs the AWS IAM `ecr:DescribeImages` permission to
retrieve the vulnerability scan counts. Culture Amp build-roles created by `Base
Infrastructure for Services` have all been modified to include this permission.

### Scratch images are not supported

ECR cannot scan scratch based images, and this should be OK as the underlying
container doesn't contain packages to scan.

If this plugin is installed and pointed at a scratch image you may receive an
error and it may block the pipeline as a result. The error
`UnsupportedImageError` is expected in this scenario; see [the ECR
docs](https://docs.aws.amazon.com/AmazonECR/latest/userguide/image-scanning-troubleshooting.html)
for more information.

## FAQ

### I have a vulnerability that isn't resolved yet, but I can wait on fixing. How do I do configure this plugin so I can unblock my builds?

Refer to how to set your [max-criticals](https://github.com/cultureamp/ecr-scan-results-buildkite-plugin#max-criticals-optional-string), and [max-highs](https://github.com/cultureamp/ecr-scan-results-buildkite-plugin#max-highs-optional-string).

### Are there guidelines on using up?

Yes. Changing the `max-criticals` and `max-high` settings should not be taken lightly.

This option is effectively a deferral of fixing the vulnerability. **Assess the situation first**. If the CVE describes a scenario that aligns with how your project is used, then you should be working to fix it rather than defer it. For help on this, check out the following the steps outlined [here](https://cultureamp.atlassian.net/wiki/spaces/PST/pages/2960916852/Central+SRE+Support+FAQs#I-have-high%2Fcritical-vulnerabilities-for-my-ECR-image%2C-and-its-blocking-my-builds.-What%E2%80%99s-going-on%3F).

Below are some recommendations if you choose to exercise this option:

1. Set the thresholds to the number of identified high or critical vulnerabilities. This is so you’re not permitting more vulnerabilities than you should. Especially for those you can fix by updating dependencies or packages.
### `message` (Required, string)

2. Set a scheduled reminder for your team to check if a fix is available for the CVE. If a fix is available, address it, and then lower your threshold for the respective vulnerability severity.
The message to annotate onto the build.
10 changes: 5 additions & 5 deletions catalog-info-component.yaml
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
name: ecr-scan-results-buildkite-plugin
name: example-go-buildkite-plugin
description: |
Buildkite plugin to retrieve ECR scan results
Example Buildkite plugin to demonstate Github release delivery
tags:
- camp-sre
- data-internal-use-only
- users-internal
annotations:
github.com/project-slug: cultureamp/ecr-scan-results-buildkite-plugin
github.com/team-slug: cultureamp/sre-foundations
github.com/project-slug: cultureamp/example-go-buildkite-plugin
github.com/team-slug: cultureamp/sre-enablement
spec:
type: library
owner: sre-foundations
owner: sre-enablement
lifecycle: production
2 changes: 1 addition & 1 deletion catalog-info.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
apiVersion: backstage.io/v1alpha1
kind: Location
metadata:
name: ecr-scan-results-buildkite-plugin-location
name: example-go-buildkite-plugin-location
tags:
- camp-foundations
spec:
Expand Down
2 changes: 1 addition & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
services:
lint:
image: buildkite/plugin-linter
command: ['--id', 'cultureamp/ecr-scan-results']
command: ["--id", "cultureamp/example-go"]
volumes:
- ".:/plugin:ro"

Expand Down
File renamed without changes.
20 changes: 8 additions & 12 deletions lib/download.bash
Original file line number Diff line number Diff line change
Expand Up @@ -65,15 +65,15 @@ downloader() {

get_version() {
local _plugin=${BUILDKITE_PLUGINS:-""}
local _version;_version=$(echo "$_plugin" | sed -e 's/.*ecr-scan-results-buildkite-plugin//' -e 's/\".*//')
local _version;_version=$(echo "$_plugin" | sed -e 's/.*example-go-buildkite-plugin//' -e 's/\".*//')
RETVAL="$_version"
}

download_binary_and_run() {
get_architecture || return 1
local _arch="$RETVAL"
local _executable="ecr-scan-results-buildkite-plugin"
local _repo="https://github.com/cultureamp/ecr-scan-results-buildkite-plugin"
local _executable="example-go-buildkite-plugin"
local _repo="https://github.com/cultureamp/example-go-buildkite-plugin"

get_version || return 1
local _version="$RETVAL"
Expand All @@ -84,16 +84,12 @@ download_binary_and_run() {
_url=${_repo}/releases/download/${_version:1}/${_executable}_${_arch}
fi

# local test_mode="${BUILDKITE_PLUGIN_ECR_SCAN_RESULTS_BUILDKITE_PLUGIN_TEST_MODE:-false}"

# if [[ "$test_mode" == "false" ]]; then
if ! downloader "$_url" "$_executable"; then
say "failed to download $_url"
exit 1
fi
if ! downloader "$_url" "$_executable"; then
say "failed to download $_url"
exit 1
fi

chmod +x ${_executable}
# fi
chmod +x ${_executable}

./${_executable}
}
21 changes: 6 additions & 15 deletions plugin.yml
Original file line number Diff line number Diff line change
@@ -1,20 +1,11 @@
name: ECR Scan Results
name: Example Go
description: >
Retrieves vulnerability scan results from ECR, creating a report as an
annotation on the build. Will fail the step if vulnerabilities exist (though
this is configurable).
Demonstrates an on-demand Github release download
and run pattern for delivery Go-based Buildkite
plugins.
author: https://github.com/cultureamp
requirements:
- docker
- jq
requirements: []
configuration:
properties:
image-name:
message:
type: string
max-criticals:
type: string
max-highs:
type: string
image-label:
type: string
additionalProperties: false
7 changes: 3 additions & 4 deletions src/.goreleaser.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
builds:
- binary: ecr-scan-results-buildkite-plugin
- binary: example-go-buildkite-plugin
env:
- CGO_ENABLED=0
goos:
Expand All @@ -13,16 +13,15 @@ builds:
- ppc64le

checksum:
name_template: 'checksums.txt'
name_template: "checksums.txt"

archives:
- format: 'binary'
- format: "binary"
name_template: "{{ .ProjectName }}_{{ .Os }}_{{ .Arch }}"

snapshot:
name_template: "{{ incpatch .Version }}-next"

changelog:
use: github-native

# yaml-language-server: $schema=https://goreleaser.com/static/schema.json
6 changes: 3 additions & 3 deletions src/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@ COPY . ./
# build as a static binary without debug symbols
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build \
-ldflags='-w -s -extldflags "-static"' -a \
-o /dist/ecrscanresults .
-o /dist/examplego .

# runtime image using static distroless base
# using static nonroot image
# user:group is nobody:nobody, uid:gid = 65534:65534
FROM ${DISTROLESS_IMAGE}

COPY --from=builder /dist/ecrscanresults /ecrscanresults
COPY --from=builder /dist/examplego /examplego

ENTRYPOINT ["/ecrscanresults"]
ENTRYPOINT ["/examplego"]
6 changes: 1 addition & 5 deletions src/buildkite/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,10 @@ import (
type Agent struct {
}

func (a Agent) Annotate(ctx context.Context, message string, style string, annotationContext string) error {
func (a *Agent) Annotate(ctx context.Context, message string, style string, annotationContext string) error {
return execCmd(ctx, "buildkite-agent", &message, "annotate", "--style", style, "--context", annotationContext)
}

func (a Agent) ArtifactUpload(ctx context.Context, path string) error {
return execCmd(ctx, "buildkite-agent", nil, "artifact", "upload", path)
}

func execCmd(ctx context.Context, executableName string, stdin *string, args ...string) error {
Logf("Executing: %s %s\n", executableName, strings.Join(args, " "))

Expand Down
38 changes: 8 additions & 30 deletions src/go.mod
Original file line number Diff line number Diff line change
@@ -1,43 +1,21 @@
module github.com/cultureamp/ecrscanresults
module github.com/cultureamp/examplego

go 1.20

require (
github.com/MarvinJWendt/testza v0.4.1
github.com/aws/aws-sdk-go-v2 v1.17.7
github.com/aws/aws-sdk-go-v2/config v1.18.19
github.com/aws/aws-sdk-go-v2/service/ecr v1.18.7
github.com/justincampbell/timeago v0.0.0-20160528003754-027f40306f1d
github.com/kelseyhightower/envconfig v1.4.0
github.com/stretchr/testify v1.7.1
github.com/stretchr/testify v1.8.4
)

require github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.6 // indirect
require (
github.com/kr/pretty v0.1.0 // indirect
github.com/stretchr/objx v0.5.0 // indirect
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
)

require (
github.com/atomicgo/cursor v0.0.1 // indirect
github.com/aws/aws-sdk-go-v2/credentials v1.13.18 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.1 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.31 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.25 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.32 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.25 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.12.6 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.18.7 // indirect
github.com/aws/smithy-go v1.13.5 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/gookit/color v1.5.0 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/justincampbell/bigduration v0.0.0-20160531141349-e45bf03c0666 // indirect
github.com/klauspost/cpuid/v2 v2.0.12 // indirect
github.com/mattn/go-runewidth v0.0.13 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/pterm/pterm v0.12.41 // indirect
github.com/rivo/uniseg v0.2.0 // indirect
github.com/sergi/go-diff v1.2.0 // indirect
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect
golang.org/x/sys v0.6.0
golang.org/x/term v0.0.0-20220411215600-e5f449aeb171 // indirect
golang.org/x/text v0.8.0
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
Loading

0 comments on commit 1a8ab24

Please sign in to comment.