Skip to content

Commit e19d50e

Browse files
authored
feat: add generate_sbom command (#46)
The command generates SBOM from the Docker image. Under the hood uses Syft to accomplish this. Sources image from Docker daemon or tarball file from disk.
1 parent 192d5e3 commit e19d50e

File tree

5 files changed

+131
-1
lines changed

5 files changed

+131
-1
lines changed

.circleci/test-deploy.yml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ version: 2.1
22
orbs:
33
orb-tools: circleci/orb-tools@12.0
44
core: studion/core@1.0.0
5+
docker: circleci/docker@2.8.2
56
security: {}
67

78
filters: &filters
@@ -47,6 +48,29 @@ jobs:
4748
- checkout
4849
- security/scan_dockerfile:
4950
dockerfile_dir: ./sample
51+
generate_sbom:
52+
machine:
53+
image: ubuntu-2204:current
54+
steps:
55+
- checkout
56+
- docker/build:
57+
image: security-sample
58+
tag: v1
59+
path: ./sample
60+
docker-context: ./sample
61+
- security/install_syft
62+
- security/generate_sbom:
63+
image: docker.io/security-sample:v1
64+
out_path: /tmp/sample-sbom.json
65+
- run:
66+
name: Check SBOM output
67+
command: |
68+
if [ ! -f "/tmp/sample-sbom.json" ]; then
69+
echo "SBOM output not found"
70+
exit 1
71+
fi
72+
73+
rm -f /tmp/sample-sbom.json
5074
install_trivy:
5175
executor: core/node
5276
steps:
@@ -95,6 +119,8 @@ workflows:
95119
filters: *filters
96120
- scan_dockerfile:
97121
filters: *filters
122+
- generate_sbom:
123+
filters: *filters
98124
- security/detect_secrets_dir:
99125
name: detect_secrets_dir
100126
filters: *filters
@@ -141,6 +167,7 @@ workflows:
141167
- scan_dependencies_prod_pnpm
142168
- scan_dependencies_command
143169
- scan_dockerfile
170+
- generate_sbom
144171
- detect_secrets_dir
145172
- detect_secrets_git_base_revision
146173
- analyze_code_diff

sample/Dockerfile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@ RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --prod --frozen-l
2727

2828
FROM install as build
2929

30-
COPY ./src tsconfig.json tsconfig.tsbuildinfo ./
30+
# Explicitly preserve src dir hierarchy to resolve TS18003 during the build phase
31+
COPY src/ ./src/
32+
COPY tsconfig.json tsconfig.tsbuildinfo ./
3133
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile
3234
RUN pnpm run build
3335

src/commands/generate_sbom.yml

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
description: >
2+
Generate Software Bill of Materials (SBOM) from Docker image.
3+
All the work is done by Syft, for details see https://github.com/anchore/syft?tab=readme-ov-file#getting-started.
4+
It is possible to provide additional configurable values by following this
5+
guide https://github.com/anchore/syft/wiki/configuration#config-file.
6+
However some options cannot be overridden, such as output and source
7+
since they are passed as command line arguments and thus have the highest precedence.
8+
9+
parameters:
10+
image:
11+
type: string
12+
description: >
13+
The Docker image to generate SBOM from. Support following schemes
14+
(1) repo-name/image-name:tag (2) /path/to/image.tar. Bases on provided scheme
15+
it will either use local Docker daemon or tarball archive from disk as a source.
16+
format:
17+
type: enum
18+
enum:
19+
- cyclonedx-json
20+
- spdx-json
21+
- github-json
22+
- syft-json
23+
default: cyclonedx-json
24+
description: >
25+
Choose the output format of generated SBOM. By default a JSON report
26+
conforming to the CycloneDX specification.
27+
out_path:
28+
type: string
29+
default: /tmp/sbom.json
30+
description: Path to the file to write the SBOM report to.
31+
exclude:
32+
type: string
33+
default: ""
34+
description: >
35+
Space delimited list of GLOB expressions specifying files and paths to
36+
exclude from the source.
37+
38+
steps:
39+
- run:
40+
name: Generate SBOM
41+
environment:
42+
PARAM_STR_IMAGE: <<parameters.image>>
43+
PARAM_ENUM_FORMAT: <<parameters.format>>
44+
PARAM_STR_OUT_PATH: <<parameters.out_path>>
45+
PARAM_STR_EXCLUDE: <<parameters.exclude>>
46+
command: <<include(scripts/generate-sbom.sh)>>

src/examples/image_sbom.yml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
description: |
2+
The "generate_sbom" command generates SBOM from the Docker image.
3+
By default, the Docker daemon is used as a source. This can be changed
4+
to use the Docker archive from the disk by providing the path to the tarball
5+
file as the "image".
6+
There is an option to customize output path of the report, exclude
7+
directories or files from the scan with glob expressions or use
8+
different output format.
9+
10+
usage:
11+
version: 2.1
12+
orbs:
13+
security: studion/security@x.y.z
14+
jobs:
15+
sbom:
16+
executor: security/node
17+
steps:
18+
- checkout
19+
- security/generate_sbom:
20+
image: studiondev/node-security:lts
21+
format: github-json
22+
out_path: /tmp/reports/lts-sbom.json
23+
exclude: /etc /home/**/*.json
24+
workflows:
25+
compliance:
26+
jobs:
27+
- sbom

src/scripts/generate-sbom.sh

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#!/bin/bash
2+
3+
if [[ -z "${PARAM_STR_IMAGE}" ]]; then
4+
echo "Specify image and retry."
5+
6+
exit 1
7+
fi
8+
9+
IMAGE_SOURCE="docker"
10+
11+
if [[ "${PARAM_STR_IMAGE}" == *.tar ]]; then
12+
IMAGE_SOURCE="docker-archive"
13+
fi
14+
15+
SBOM_ARGS=("${IMAGE_SOURCE}:${PARAM_STR_IMAGE}")
16+
SBOM_ARGS+=("-o" "${PARAM_ENUM_FORMAT}=${PARAM_STR_OUT_PATH}")
17+
18+
if [[ -n "${PARAM_STR_EXCLUDE}" ]]; then
19+
set -f # Disable glob expansion
20+
for exclude_glob in ${PARAM_STR_EXCLUDE}; do
21+
SBOM_ARGS+=("--exclude=$exclude_glob")
22+
done
23+
set +f
24+
fi
25+
26+
set -x
27+
syft "${SBOM_ARGS[@]}"
28+
set +x

0 commit comments

Comments
 (0)