Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion classes/install.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
inherit: [strip, "basement::bits::libs"]
inherit: [strip, "basement::bits::libs", sbom]

# The install class provides the common methods to
# * copy the relevant parts for the different packages,
Expand Down
118 changes: 118 additions & 0 deletions classes/sbom-deploy.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
inherit: [sbom]

buildSetup: &sbom_deploy_setup |
_sbomDeployAddSingle () {
local SOURCE_PATH=$1
local FILE=$2
local added=$3
if [ -f $SOURCE_PATH/$file ]; then
if [[ $added == false ]]; then
# if the file has entries already add we need to add the `,`
# separator first
if [[ $(tail -n 1 .bob/_sbom_deploy.json) == *"}" ]]; then
echo -n "," >> .bob/_sbom_deploy.json
fi
echo "," >> .bob/_sbom_deploy.json
echo " \"files\": [" >> .bob/_sbom_deploy.json
added=true
else
echo "," >> .bob/_sbom_deploy.json
fi
echo -n " \"$file\"" >> .bob/_sbom_deploy.json
fi
echo "$added"
}

# Add a component to the list of deployed components
# Usage:
# sbomDeploy [-f FILES_TXT] [-n FILE_NAME] sourcePath
#
# arguments:
# sourcePath - workspace of the dependency to add files from
#
# options:
# -f FILES_TXT - use files from FILES_TXT
# -n FILE_NAME - add FILE_NAME
sbomDeploy() {
local FILES_FILES=()
local FILES=()
# parse arguments
OPTIND=1
local opt
while getopts "f:n:" opt ; do
case "$opt" in
f)
FILES_FILES+=( "$OPTARG" )
;;
n)
FILES+=( "$OPTARG" )
;;
\?)
echo "sbomDeploy: Invalid option: -$OPTARG" >&2
exit 1
;;
esac
done
shift $(( OPTIND -1 ))

local SOURCE_PATH=$1

if [[ ! -s $SOURCE_PATH/.bob/sbom-manifest.json ]]; then
echo "Dependency ${SOURCE_PATH} doesn't contain a sbom-manifest. \"sbom\" class missing?" 1>&2
exit 1
# TODO: should we fail here?
fi

mkdir -p .bob
if [ ! -e .bob/_sbom_deploy.json ]; then
echo " {" > .bob/_sbom_deploy.json
else
echo ", {" >> .bob/_sbom_deploy.json
fi

local added=false
local MANIFEST_ID=$(grep "bob:sbom-manifest-id" $1/.bob/sbom-manifest.json)
MANIFEST_ID=${MANIFEST_ID##*:}
MANIFEST_ID=${MANIFEST_ID/,/}

echo -n " \"bob:sbom-manifest-id\": ${MANIFEST_ID}" >> .bob/_sbom_deploy.json

for files_file in ${FILES_FILES[@]}; do
while read -r file; do
added=$(_sbomDeployAddSingle $SOURCE_PATH $file $added)
done < $files_file
done

for file in ${FILES[@]}; do
added=$(_sbomDeployAddSingle $SOURCE_PATH $file $added)
done

if [[ $added == true ]]; then
echo "" >> .bob/_sbom_deploy.json
echo " ]" >> .bob/_sbom_deploy.json
fi
echo -n " }" >> .bob/_sbom_deploy.json
}

packageSetup: *sbom_deploy_setup

packageVars: [SBOM_ENABLED]
packageFinalize: |
if [[ ${SBOM_ENABLED} ]]; then
mkdir -p .bob

echo "[" > .bob/sbom_deploy.json
if [[ -f .bob/_sbom_deploy.json ]]; then
cat .bob/_sbom_deploy.json >> .bob/sbom_deploy.json
rm .bob/_sbom_deploy.json
elif [[ -f $1/.bob/_sbom_deploy.json ]]; then
cat $1/.bob/_sbom_deploy.json >> .bob/sbom_deploy.json
fi
echo "" >> .bob/sbom_deploy.json
echo "]" >> .bob/sbom_deploy.json
fi

packageAuditFiles:
sbom_deploy:
filename: ".bob/sbom_deploy.json"

Check failure on line 117 in classes/sbom-deploy.yaml

View workflow job for this annotation

GitHub Actions / check

117:7 [indentation] wrong indentation: expected 8 but found 6
if: "${SBOM_ENABLED:-1}"
155 changes: 155 additions & 0 deletions classes/sbom.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
Config:
SBOM_FILE_TYPES:
type: str
help: |
Override the autodetected file type of the deployed files.
In Cyclonedx SBOM format varios type classes are supported - see
https://cyclonedx.org/docs/1.7/json/#metadata_tools_oneOf_i0_components_items_type
for a complete list. This class tries to autodetect 'application', 'library'
and 'file' - types. But these detection can be wrong or incomplete.
By specifying this variable as a semi-colon separated list of colon separated
file:type pairs the recipe can specify different types here, e.g. for
for linux recipes it could set:

SBOM_FILE_TYPES="bzImage:operating-system;.ko:device-driver"
default: ""
SBOM_ENABLED:
type: bool
default: True
help: If set (default) required files form SBOM generation are produced.

packageVars: [PKG_VERSION, PKG_LICENSE, SBOM_FILE_TYPES]
packageSetup: |
# Create file manifest
sbomCreateManifest()
{
local manifest_file=".bob/sbom-manifest.json"
local files=()
declare -A file_types

mkdir -p .bob

# split the SBOM_FILE_TYPES="<file>:<type>;<file><:type>"
IFS=';' read -ra items <<< "${SBOM_FILE_TYPES:-}"
for item in "${items[@]}"; do
[[ -z ${item} ]] && continue;
local file=${item%%:*}
local type=${item#*:}
file_types["$file"]=$type
done

while IFS= read -r -d '' file; do
files+=("${file#./}")
done < <(find . -type f -not -path "./.bob/*" -print0 2>/dev/null || true)

# Create JSON manifest with file info and hashes
{
echo "{"
echo ' "file_components": ['
first=true
for file in "${files[@]}"; do
if [[ $first == true ]]; then
first=false
echo ' {'
else
echo ", {"
fi

echo " \"hashes\": [ "
echo " {\"alg\": \"SHA-256\", \"content\": \"$(sha256sum $file | cut -d' ' -f1)\" },"
echo " {\"alg\": \"SHA-384\", \"content\": \"$(sha384sum $file | cut -d' ' -f1)\" },"
echo " {\"alg\": \"SHA-512\", \"content\": \"$(sha512sum $file | cut -d' ' -f1)\" }"
echo " ],"
echo " \"name\": \"$file\","

# determine file type. See https://cyclonedx.org/docs/1.7/json/#metadata_tools_oneOf_i0_components_items_type

Check failure on line 65 in classes/sbom.yaml

View workflow job for this annotation

GitHub Actions / check

65:121 [line-length] line too long (125 > 120 characters)
# for a list of valid types. For now we only support 'application', 'library' and 'file'.
# The recipe can set `SBOM_FILE_TYPES` to override auto detection.

local file_type=
for f in ${!file_types[@]}; do
if [[ "$file" == *"$f"* ]]; then
file_type=${file_types[$f]}
fi
done
if [[ -z "$file_type" ]]; then
local type="$(file -b "$file")"
if [[ type == *executable* ]]; then
file_type="application"
elif [[ type == *shared* ]]; then
file_type="library"
else
file_type="file"
fi
fi
echo -n " \"type\": \"${file_type}\""

if [ -n "${PKG_VERSION:-}" ]; then
echo ","
echo -n " \"version\": \"${PKG_VERSION}\""
fi

if [[ -e .bsi-properties/$file ]]; then
echo ","
cat .bsi-properties/$file
else
# add properties as required by BSI TR-03183-2 using the cyclonedx bsi::component
# namespace (https://github.com/BSI-Bund/tr-03183-cyclonedx-property-taxonomy)

local is_executable="false"
[[ -x "$file" ]] && is_executable="true"

# Determine BSI properties
local is_archive="false"
local is_structured="false"

# Check if file is an archive or structured (contains metadata for decomposition)
case "${file##*.}" in
tar|zip|7z|jar|war|ear|deb|rpm|a|lib|iso)
is_archive="true"
is_structured="true"
;;
gz|bz2|xz)
# Check for compressed tar archives
if [[ "$file" == *.tar.* ]]; then
is_archive="true"
fi
is_structured="true"
;;
esac

# Section 3.2.1: Only executable and archive files MUST be listed.
if [[ $is_archive == true ]] || [[ $is_executable == true ]]; then
echo ","
echo " \"properties\": ["
echo " {\"name\": \"bsi:component:archive\", \"value\": \"$is_archive\" },"
if [ -n "${PKG_LICENSE:-}" ]; then
echo " {\"name\": \"bsi:component:effectiveLicence\", \"value\": \"${PKG_LICENSE}\" },"
fi
echo " {\"name\": \"bsi:component:executable\", \"value\": \"$is_executable\" },"
local rel_path="$(basename $file)"
echo " {\"name\": \"bsi:component:filename\", \"value\": \"$rel_path\" },"
echo " {\"name\": \"bsi:component:structured\", \"value\": \"$is_structured\" }"
echo -n " ]"
fi
fi
echo ""
echo -n " }"
done
echo ""
echo ' ],'
} > "$manifest_file"
echo " \"bob:sbom-manifest-id\": \"$(sha256sum $manifest_file | cut -d' ' -f1)\"" >> $manifest_file
echo "}" >> $manifest_file
}

packageVars: [SBOM_ENABLED]

Check failure on line 146 in classes/sbom.yaml

View workflow job for this annotation

GitHub Actions / check

146:1 [key-duplicates] duplication of key "packageVars" in mapping
packageFinalize: |
if [[ ${SBOM_ENABLED} ]]; then
sbomCreateManifest
fi

packageAuditFiles:
sbom_manifest:
filename: ".bob/sbom-manifest.json"

Check failure on line 154 in classes/sbom.yaml

View workflow job for this annotation

GitHub Actions / check

154:7 [indentation] wrong indentation: expected 8 but found 6
if: "${SBOM_ENABLED}"
1 change: 1 addition & 0 deletions config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ plugins:
- vsenv
- msbuild
- config
- sbom
Loading
Loading