Skip to content

Commit e6984ac

Browse files
committed
scripts: Add SBOM and SBOM generator scripts
1 parent 1f84a0c commit e6984ac

File tree

5 files changed

+1188
-0
lines changed

5 files changed

+1188
-0
lines changed

sbom/diff.sh

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
#!/usr/bin/env bash
2+
3+
set -euo pipefail
4+
5+
# This script runs sbom-generator diff against the committed SBOM.
6+
# The diff subcommand generates a fresh SBOM internally and compares
7+
# it against the existing SBOM at --output-path. Exits non-zero on
8+
# meaningful differences.
9+
10+
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd -P)"
11+
12+
WRAPPER="${REPO_ROOT}/scripts/run-from-container.sh"
13+
IMAGE="ghcr.io/elastisys/sbom-generator:0.3"
14+
CONFIG="${REPO_ROOT}/sbom/sbom.config.yaml"
15+
COMMITTED_SBOM="${REPO_ROOT}/sbom/sbom.cdx.json"
16+
17+
if [[ ! -x "${WRAPPER}" ]]; then
18+
echo "Missing or non-executable ${WRAPPER}." >&2
19+
exit 1
20+
fi
21+
22+
# Ensure cache and output directories exist
23+
XDG_CACHE_HOME="${REPO_ROOT}/.cache"
24+
mkdir -p "${XDG_CACHE_HOME}"
25+
mkdir -p "$(dirname "${COMMITTED_SBOM}")"
26+
27+
echo "[sbom] Running diff against ${COMMITTED_SBOM} ..."
28+
extra_env=()
29+
# Three different potential token-variables are mentioned, we check for all three.
30+
if [[ -n "${GITHUB_TOKEN:-}" ]]; then
31+
extra_env+=(--env GITHUB_TOKEN)
32+
elif [[ -n "${GH_TOKEN:-}" ]]; then
33+
extra_env+=(--env GITHUB_TOKEN="${GH_TOKEN}")
34+
elif [[ -n "${CK8S_GITHUB_TOKEN:-}" ]]; then
35+
extra_env+=(--env GITHUB_TOKEN="${CK8S_GITHUB_TOKEN}")
36+
fi
37+
set +e
38+
"${WRAPPER}" --env XDG_CACHE_HOME="${XDG_CACHE_HOME}" "${extra_env[@]}" \
39+
--env TERM="${TERM:-xterm-256color}" \
40+
"${IMAGE}" diff \
41+
--config "${CONFIG}" \
42+
--output-path "${COMMITTED_SBOM}"
43+
status=$?
44+
set -e
45+
46+
if [[ ${status} -eq 0 ]]; then
47+
echo "[sbom] OK: SBOM is up to date."
48+
else
49+
echo "[sbom] Drift detected: SBOM has meaningful changes." >&2
50+
echo "[sbom] Hint: run 'sbom/generate.sh' to update SBOM." >&2
51+
echo "[sbom] If charts were updated, review and update evaluations in sbom/overrides.yaml." >&2
52+
echo "If this fails in CI but works locally, ensure your branch is up to date with the main branch (rebase if necessary)." >&2
53+
fi
54+
exit ${status}

sbom/generate.sh

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
#!/usr/bin/env bash
2+
3+
set -euo pipefail
4+
5+
function usage() {
6+
echo "Usage: ${0} [FLAGS] [VERSION]" >&2
7+
echo "Example: ${0} --require-evaluation 1.2.3" >&2
8+
echo "If omitted, VERSION defaults to 'latest'" >&2
9+
exit 1
10+
}
11+
12+
full_version_raw=""
13+
forward_args=()
14+
15+
# Parse flags to forward to the image and optional VERSION
16+
while [[ ${#} -gt 0 ]]; do
17+
case "${1}" in
18+
-h | --help)
19+
usage
20+
;;
21+
-*)
22+
forward_args+=("${1}")
23+
shift
24+
;;
25+
*)
26+
if [[ -n "${full_version_raw}" ]]; then
27+
echo "Too many positional arguments." >&2
28+
usage
29+
fi
30+
full_version_raw="${1}"
31+
shift
32+
;;
33+
esac
34+
done
35+
36+
# Default to 'latest' if VERSION not provided
37+
full_version_raw="${full_version_raw:-latest}"
38+
39+
# Accept X.Y.Z (preferred) or vX.Y.Z (tolerated), or 'latest'
40+
full_version="${full_version_raw#v}"
41+
42+
# Compute version flag for sbom-generator
43+
if [[ "${full_version}" == "latest" ]]; then
44+
version_arg="latest"
45+
else
46+
version_arg="v${full_version}"
47+
fi
48+
49+
# Resolve repository root relative to this script
50+
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd -P)"
51+
52+
# Paths relative to repository root (use absolute for reliability)
53+
SBOM_OUTPUT="${REPO_ROOT}/sbom/sbom.cdx.json"
54+
CONFIG="${REPO_ROOT}/sbom/sbom.config.yaml"
55+
56+
# Use container wrapper for consistent docker/podman behavior
57+
WRAPPER="${REPO_ROOT}/scripts/run-from-container.sh"
58+
IMAGE="ghcr.io/elastisys/sbom-generator:0.3"
59+
60+
if [[ ! -x "${WRAPPER}" ]]; then
61+
echo "Missing or non-executable ${WRAPPER}." >&2
62+
exit 1
63+
fi
64+
# Ensure a writable cache directory inside the repo
65+
XDG_CACHE_HOME="${REPO_ROOT}/.cache"
66+
mkdir -p "${XDG_CACHE_HOME}"
67+
# Ensure output directory exists
68+
mkdir -p "$(dirname "${SBOM_OUTPUT}")"
69+
70+
echo "Generating SBOM to ${SBOM_OUTPUT} ..."
71+
# Forward optional GitHub token to avoid rate limits
72+
extra_env=()
73+
if [[ -n "${CK8S_GITHUB_TOKEN:-}" ]]; then
74+
extra_env+=(--env "GITHUB_TOKEN=${CK8S_GITHUB_TOKEN}")
75+
elif [[ -n "${GITHUB_TOKEN:-}" ]]; then
76+
extra_env+=(--env GITHUB_TOKEN)
77+
fi
78+
"${WRAPPER}" --env XDG_CACHE_HOME="${XDG_CACHE_HOME}" "${extra_env[@]}" \
79+
"${IMAGE}" "${forward_args[@]}" generate \
80+
--config "${CONFIG}" \
81+
--output-path "${SBOM_OUTPUT}" \
82+
--version "${version_arg}" \
83+
--force
84+
85+
echo "Validating SBOM ${SBOM_OUTPUT} ..."
86+
"${WRAPPER}" --env XDG_CACHE_HOME="${XDG_CACHE_HOME}" "${extra_env[@]}" \
87+
"${IMAGE}" "${forward_args[@]}" validate "${SBOM_OUTPUT}" --config "${CONFIG}"
88+
89+
# Ensure file ends with a single newline to satisfy linters
90+
if [[ -s "${SBOM_OUTPUT}" ]]; then
91+
# Append a newline only if the last byte is not a newline
92+
if [[ $(tail -c1 "${SBOM_OUTPUT}" | wc -l) -eq 0 ]]; then
93+
printf '\n' >>"${SBOM_OUTPUT}"
94+
fi
95+
fi
96+
97+
echo "SBOM generated and validated: ${SBOM_OUTPUT}"

sbom/ignores.yaml

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
directories:
2+
- "kubespray/scripts"
3+
- "kubespray/test-infra"
4+
- "kubespray/tests"
5+
- "kubespray/venv"
6+
7+
- "kubespray/roles/adduser"
8+
- "kubespray/roles/container-engine"
9+
- "kubespray/roles/kubernetes/preinstall"
10+
- "kubespray/roles/network_plugin/weave"
11+
- "kubespray/roles/bastion-ssh-config"
12+
- "kubespray/roles/kubernetes-apps/csi_driver/gcp_pd"
13+
- "kubespray/roles/kubernetes-apps/csi_driver/vsphere"
14+
- "kubespray/roles/kubernetes-apps/external_cloud_controller/hcloud"
15+
- "kubespray/roles/kubernetes-apps/external_cloud_controller/huaweicloud"
16+
- "kubespray/roles/kubernetes-apps/external_cloud_controller/oci"
17+
- "kubespray/roles/kubernetes-apps/external_cloud_controller/vsphere"
18+
- "kubespray/roles/kubernetes-apps/ingress_controller/alb_ingress_controller"
19+
- "kubespray/roles/network_plugin/flannel"
20+
- "kubespray/roles/network_plugin/kube-ovn"
21+
- "kubespray/roles/network_plugin/kube-router"
22+
- "kubespray/roles/network_plugin/macvlan/"
23+
- "kubespray/roles/network_plugin/multus"
24+
- "kubespray/roles/etcdctl_etcdutl"
25+
- "kubespray/contrib/azurerm/roles/generate-inventory"
26+
- "kubespray/roles/kubernetes-apps/metallb"
27+
28+
files:
29+
# Requires another template to be rendered and added as a value in a task.
30+
# Should not render any BOM material though.
31+
- "kubespray/roles/kubernetes-apps/csi_driver/azuredisk/templates/azure-csi-cloud-config.j2"
32+
- "kubespray/roles/kubernetes-apps/csi_driver/azuredisk/templates/azure-csi-cloud-config-secret.yml.j2"
33+
- "kubespray/roles/kubernetes-apps/external_cloud_controller/openstack/templates/external-openstack-cloud-config-secret.yml.j2"
34+
- "kubespray/roles/kubernetes-apps/csi_driver/cinder/templates/cinder-csi-cloud-config-secret.yml.j2"
35+
# Requires two unset variables, `etcd_metrics_service_labels` and `etcd_metrics_port`.
36+
# Should not render any BOM material though.
37+
- "kubespray/roles/kubernetes-apps/ansible/templates/etcd_metrics-service.yml.j2"
38+
# Requires etcd health check task to register `etcd_cluster_is_healthy` and `etcd_events_cluster_is_healthy` first.
39+
# Should not render any BOM material though.
40+
- "kubespray/roles/etcd/templates/etcd.env.j2"
41+
- "kubespray/roles/etcd/templates/etcd-events.env.j2"

0 commit comments

Comments
 (0)