Skip to content

Commit 4708759

Browse files
Merge pull request #19 from chef/download-grype-snapshot
Add composite action for Chef product download and Grype vulnerability scanning
2 parents ecfbad8 + 27f61d4 commit 4708759

File tree

3 files changed

+455
-0
lines changed

3 files changed

+455
-0
lines changed
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
# Chef Download + Grype Snapshot Action
2+
3+
Composite action that downloads Chef products from downloads.chef.io and runs Grype vulnerability scans.
4+
5+
## Usage
6+
7+
```yaml
8+
- name: Scan chef product
9+
uses: chef/common-github-actions/.github/actions/chef-download-grype-snapshot@main
10+
with:
11+
product: chef
12+
channel: stable
13+
download_site: commercial
14+
os: ubuntu
15+
os_version: "24.04"
16+
arch: x86_64
17+
scan_mode: native
18+
scan_root: /opt/chef
19+
license_id: ${{ secrets.LICENSE_ID }}
20+
```
21+
22+
## Inputs
23+
24+
| Input | Required | Default | Description |
25+
|-------|----------|---------|-------------|
26+
| `product` | Yes | - | Chef product name (chef, chef-workstation, chef-server, etc.) |
27+
| `channel` | Yes | - | Release channel (stable, current) |
28+
| `download_site` | Yes | commercial | Download site (commercial or community) |
29+
| `os` | Yes | ubuntu | OS platform |
30+
| `os_version` | Yes | - | OS version (e.g., 24.04) |
31+
| `arch` | Yes | x86_64 | Architecture |
32+
| `scan_mode` | Yes | native | Scan mode (native or habitat) |
33+
| `scan_root` | Yes | - | Install root path for metadata (e.g., /opt/chef) |
34+
| `resolve_version` | Yes | latest | Version resolution (latest or pinned) |
35+
| `pinned_version` | No | "" | Specific version when resolve_version=pinned |
36+
| `license_id` | No | "" | License ID for downloads (pass via secrets) |
37+
| `out_dir` | No | out | Output directory for results |
38+
| `work_dir` | No | work | Working directory for temporary files |
39+
40+
## Outputs
41+
42+
| Output | Description |
43+
|--------|-------------|
44+
| `resolved_version` | The resolved product version that was scanned |
45+
| `download_url_redacted` | Download URL with license_id removed |
46+
47+
## Output Files
48+
49+
The action generates two JSON files in the `out_dir`:
50+
51+
- **latest.json**: Complete Grype scan results
52+
- **metadata.json**: Scan metadata including version, environment, and severity counts
53+
54+
## Requirements
55+
56+
- Ubuntu runner (uses `dpkg` for package extraction)
57+
- Grype is automatically installed if not present
58+
- Valid license_id for the specified download_site:
59+
- Commercial sites require a commercial license
60+
- Community sites require a Free license
61+
62+
## Download Site Constraints
63+
64+
- **Commercial**: Supports both `stable` and `current` channels
65+
- **Community**: Only supports `stable` channel (API enforced)
66+
67+
## Error Handling
68+
69+
The action provides detailed error messages for common failures:
70+
- Missing or expired license_id
71+
- Wrong license type (commercial vs Free)
72+
- Invalid product/channel combinations
73+
- Package download failures
74+
75+
## Example with Multiple Products
76+
77+
```yaml
78+
jobs:
79+
scan:
80+
runs-on: ubuntu-latest
81+
strategy:
82+
matrix:
83+
product: [chef, chef-workstation, chef-server]
84+
channel: [stable, current]
85+
steps:
86+
- uses: chef/common-github-actions/.github/actions/chef-download-grype-snapshot@main
87+
with:
88+
product: ${{ matrix.product }}
89+
channel: ${{ matrix.channel }}
90+
download_site: commercial
91+
os: ubuntu
92+
os_version: "24.04"
93+
arch: x86_64
94+
scan_root: /opt/${{ matrix.product }}
95+
license_id: ${{ secrets.GA_DOWNLOAD_GRYPE_LICENSE_ID }}
96+
97+
- name: Upload results
98+
uses: actions/upload-artifact@v4
99+
with:
100+
name: scan-${{ matrix.product }}-${{ matrix.channel }}
101+
path: out/
102+
```
103+
104+
## Related Projects
105+
106+
- [chef-vuln-scan-orchestrator](https://github.com/chef/chef-vuln-scan-orchestrator) - Orchestration workflow using this action
107+
- [chef-vuln-scan-data](https://github.com/chef/chef-vuln-scan-data) - Data repository for scan results
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
name: "Chef Download + Grype Snapshot"
2+
description: "Resolve latest version, download package, extract, run Grype JSON scan, and generate metadata.json"
3+
inputs:
4+
product:
5+
required: true
6+
description: "Chef product (chef, chef-workstation, chef-server, etc.)"
7+
channel:
8+
required: true
9+
description: "Release channel (stable, current)"
10+
download_site:
11+
required: true
12+
description: "commercial or community"
13+
default: "commercial"
14+
os:
15+
required: true
16+
description: "OS platform (ubuntu)"
17+
default: "ubuntu"
18+
os_version:
19+
required: true
20+
description: "OS version (e.g., 24.04)"
21+
arch:
22+
required: true
23+
description: "Architecture (x86_64)"
24+
default: "x86_64"
25+
scan_mode:
26+
required: true
27+
description: "native|habitat (native for pilot)"
28+
default: "native"
29+
scan_root:
30+
required: true
31+
description: "Expected install root (for metadata; e.g., /opt/chef)"
32+
resolve_version:
33+
required: true
34+
description: "latest|pinned"
35+
default: "latest"
36+
pinned_version:
37+
required: false
38+
description: "Version to scan when resolve_version=pinned"
39+
default: ""
40+
license_id:
41+
required: false
42+
description: "License ID for commercial downloads (pass via secrets)"
43+
default: ""
44+
out_dir:
45+
required: false
46+
description: "Output directory"
47+
default: "out"
48+
work_dir:
49+
required: false
50+
description: "Working directory"
51+
default: "work"
52+
53+
outputs:
54+
resolved_version:
55+
description: "Resolved version string"
56+
value: ${{ steps.run.outputs.resolved_version }}
57+
download_url_redacted:
58+
description: "Download URL with license_id stripped"
59+
value: ${{ steps.run.outputs.download_url_redacted }}
60+
61+
runs:
62+
using: "composite"
63+
steps:
64+
- name: Run snapshot logic
65+
id: run
66+
shell: bash
67+
env:
68+
PRODUCT: ${{ inputs.product }}
69+
CHANNEL: ${{ inputs.channel }}
70+
DOWNLOAD_SITE: ${{ inputs.download_site }}
71+
OS: ${{ inputs.os }}
72+
OS_VERSION: ${{ inputs.os_version }}
73+
ARCH: ${{ inputs.arch }}
74+
SCAN_MODE: ${{ inputs.scan_mode }}
75+
SCAN_ROOT: ${{ inputs.scan_root }}
76+
RESOLVE_VERSION: ${{ inputs.resolve_version }}
77+
PINNED_VERSION: ${{ inputs.pinned_version }}
78+
LICENSE_ID: ${{ inputs.license_id }}
79+
OUT_DIR: ${{ inputs.out_dir }}
80+
WORK_DIR: ${{ inputs.work_dir }}
81+
run: |
82+
set -euo pipefail
83+
if [ -n "${LICENSE_ID:-}" ]; then
84+
echo "::add-mask::${LICENSE_ID}"
85+
fi
86+
87+
python "${GITHUB_ACTION_PATH}/run.py"
88+
89+
# expose outputs for calling workflow
90+
echo "resolved_version=$(cat ${OUT_DIR}/_resolved_version.txt)" >> "$GITHUB_OUTPUT"
91+
echo "download_url_redacted=$(cat ${OUT_DIR}/_download_url_redacted.txt)" >> "$GITHUB_OUTPUT"

0 commit comments

Comments
 (0)