Skip to content

Commit ddfd653

Browse files
committed
docs: enhance README.md. simplify trivy step
Signed-off-by: Jesse Suen <jesse@akuity.io>
1 parent 8721855 commit ddfd653

5 files changed

Lines changed: 180 additions & 10 deletions

File tree

README.md

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
# Kargo Custom Promotion Steps
2+
3+
## Overview
4+
5+
Custom Promotion Steps allow Kargo administrators to easily introduce new promotion steps to Kargo.
6+
7+
## Why custom steps?
8+
9+
While a majority of GitOps promotion workflows can be built entirely using Kargo's built-in, native steps, occasionally these may not be enough. Some use cases include:
10+
* deployments using bespoke, custom tools or scripts
11+
* interfacing with internal systems
12+
* adding support for additional CLI-based tools not officially supported by Kargo
13+
14+
## How it works
15+
16+
To define a new promotion step, it is as simple as registering a `CustomPromotionStep` resource which specifies:
17+
* the container `image` to run
18+
* the `command` to be executed in the container
19+
* how any inputs should be supplied to the command or environment variables
20+
21+
```yaml
22+
apiVersion: ee.kargo.akuity.io/v1alpha1
23+
kind: CustomPromotionStep
24+
metadata:
25+
name: sleep
26+
spec:
27+
image: ubuntu
28+
command: ["sh", "-c", "sleep ${{ config.sleepSeconds }}"]
29+
env:
30+
- name: HELLO
31+
value: ${{ config.sleep }}
32+
33+
```
34+
35+
Once registered, the step can be used like any other kargo step.
36+
37+
```yaml
38+
steps:
39+
- uses: sleep
40+
config:
41+
sleepSeconds: 10
42+
```
43+
44+
NOTE: This feature requires the use of pod-based promotions, only available in the Akuity Platform.
45+
46+
## Examples
47+
48+
This repo showcases two real-world examples of custom promotion steps:
49+
50+
* `conftest` - validate Kubernetes manifests using centrally managed OPA rules, before proceeding with promotion.
51+
* `trivy-image` - scan the promoted image for vulnerabilities, before proceeding with promotion.
52+
53+
### Conftest
54+
55+
Conftest is an open-source tool for writing and enforcing policy-as-code tests against structured configuration files (Kubernetes manifests, Dockerfiles, Terraform, etc.) using the Rego policy language.
56+
57+
This example shows how `conftest` can be used to validate Kubernetes deployment YAML against centrally managed rules.
58+
59+
```yaml
60+
apiVersion: ee.kargo.akuity.io/v1alpha1
61+
kind: CustomPromotionStep
62+
metadata:
63+
name: conftest
64+
spec:
65+
image: openpolicyagent/conftest:v0.67.0
66+
command:
67+
- conftest
68+
- test
69+
- --no-color
70+
- --update=https://raw.githubusercontent.com/jessesuen/kargo-custom-steps/master/policy/kubernetes.rego
71+
- --policy=/tmp/policy
72+
- ${{ config.path }}
73+
```
74+
75+
### Trivy
76+
77+
Trivy is an open-source, all-in-one security scanner that detects vulnerabilities, misconfigurations, secrets, and license issues across container images, filesystems, Git repositories, and cloud infrastructure.
78+
79+
The following example shows how a `trivy-image` step can scan an image for `CRITICAL` vulnerabilities before proceeding with the promotion.
80+
81+
> **Note:** The custom image `ghcr.io/jessesuen/trivy` pre-caches the vulnerability databases to avoid downloading them on every promotion run. See [`docker/trivy/README.md`](docker/trivy/README.md) for details.
82+
83+
```yaml
84+
apiVersion: ee.kargo.akuity.io/v1alpha1
85+
kind: CustomPromotionStep
86+
metadata:
87+
name: trivy-image
88+
spec:
89+
image: ghcr.io/jessesuen/trivy:0.69.3
90+
command:
91+
- trivy
92+
- image
93+
- --severity=CRITICAL
94+
- ${{ config.image }}
95+
```
96+
97+
## Putting it all together
98+
99+
The following `PromotionTask` demonstrates how built-in and custom steps compose into a complete promotion pipeline:
100+
101+
```yaml
102+
apiVersion: kargo.akuity.io/v1alpha1
103+
kind: PromotionTask
104+
metadata:
105+
name: promote
106+
namespace: custom-steps
107+
spec:
108+
vars:
109+
- name: image
110+
value: ghcr.io/jessesuen/nginx
111+
- name: repoURL
112+
value: https://github.com/jessesuen/kargo-custom-steps.git
113+
- name: branch
114+
value: main
115+
116+
steps:
117+
# 1. Clone the repo containing Helm charts and environment values
118+
- uses: git-clone
119+
config:
120+
repoURL: ${{ vars.repoURL }}
121+
checkout:
122+
- branch: ${{ vars.branch }}
123+
path: ./src
124+
125+
# 2. Update the image tag in the environment-specific values file
126+
- uses: yaml-update
127+
config:
128+
path: ./src/env/${{ ctx.stage }}/values.yaml
129+
updates:
130+
- key: image.tag
131+
value: ${{ imageFrom( vars.image ).Tag }}
132+
133+
# 3. Render Helm templates to produce Kubernetes manifests
134+
- uses: helm-template
135+
config:
136+
path: ./src/charts/app
137+
releaseName: app
138+
valuesFiles:
139+
- ./src/env/${{ ctx.stage }}/values.yaml
140+
outPath: ./out
141+
142+
# 4. (Custom) Validate rendered manifests against OPA policy rules
143+
- uses: conftest
144+
config:
145+
path: ./out
146+
147+
# 5. (Custom) Scan the promoted image for CRITICAL vulnerabilities
148+
- uses: trivy-image
149+
config:
150+
image: ${{ vars.image }}:${{ imageFrom( vars.image ).Tag }}
151+
152+
# 6. Commit and push the GitOps change to trigger the deploy
153+
- uses: git-commit
154+
config:
155+
path: ./src
156+
message: Update ${{ ctx.stage }} to ${{ vars.image }}:${{ imageFrom(vars.image).Tag }}
157+
158+
- uses: git-push
159+
config:
160+
path: ./out
161+
```
162+
163+
The custom steps (`conftest` and `trivy-image`) act as policy and security gates — if either fails, the promotion is blocked before any changes are committed.

docker/trivy/README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
# Trivy Image
22

3-
This is a trivy image with the database pre-downloaded, in order to avoid downloading the
4-
database every time a custom executes.
3+
This is a trivy image with the vulnerability database pre-cached,
4+
in order to avoid downloading the entire database every time the
5+
`trivy-image` step executes. It also bakes in a `trivy.yaml`
6+
configuration file with settings that work well in Kargo.

docker/trivy/trivy.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,8 @@ scan:
1919

2020
cache:
2121
dir: /home/nonroot/.cache/trivy
22+
23+
format: template
24+
template: |
25+
{{range .}}{{range .Vulnerabilities}}{{.VulnerabilityID}} ({{.PkgName}})
26+
{{end}}{{end}}

kargo/custom-steps/trivy-image/trivy-image.yaml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,5 @@ spec:
77
command:
88
- trivy
99
- image
10-
- --format=template
11-
- --template='{{range .}}{{range .Vulnerabilities}}{{.VulnerabilityID}} ({{.PkgName}}){{"\n"}}{{end}}{{end}}'
1210
- --severity=CRITICAL
1311
- ${{ config.image }}

kargo/promote.yaml

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,11 @@ spec:
4343
config:
4444
image: ${{ vars.image }}:${{ imageFrom( vars.image ).Tag }}
4545

46-
# - uses: git-commit
47-
# as: commit
48-
# config:
49-
# path: ./src
50-
# message: |
51-
# Update ${{ ctx.stage }} to ${{ vars.image }}:${{ imageFrom(vars.image).Tag }}
46+
- uses: git-commit
47+
config:
48+
path: ./src
49+
message: Update ${{ ctx.stage }} to ${{ vars.image }}:${{ imageFrom(vars.image).Tag }}
50+
51+
- uses: git-push
52+
config:
53+
path: ./out

0 commit comments

Comments
 (0)