Skip to content
Open
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
1 change: 1 addition & 0 deletions .pipelines/github-pr-validation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,4 @@ extends:
parameters:
aclRef: $(Build.SourceBranch)
mantleRef: 'aclmain'
testGeneratePackageManifest: true
2 changes: 2 additions & 0 deletions acl/tests/kola_enforcing.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ tests:
- name: acl.ignition.v1.users
- name: acl.ignition.v2.users

- name: acl.packages.package-manifest

- name: bpf.execsnoop
exceptions:
- imageVariants: [acl-t]
Expand Down
8 changes: 8 additions & 0 deletions build_library/build_image_util.sh
Original file line number Diff line number Diff line change
Expand Up @@ -830,6 +830,14 @@ EOF
else
# Skip this check in RPM mode - we intentionally populate ${DISTRO_SHARE_DIR}/etc earlier
finish_image_backup_etc_rpm "${root_fs_dir}"

if [[ "${IMAGE_BUILD_TYPE}" != "container" ]]; then
# Writes the image's package list and SPDX package manifest from the final rpmdb.
#
# Must be called after finish_image_backup_etc_rpm uninstalls the azurelinux-repos* packages above,
# and before the rootfs state loop deletes /var (and the rpmdb) below.
finish_image_package_manifest_rpm "${root_fs_dir}" "${image_name%.bin}"
fi
fi

# Remove the rootfs state as it should be recreated through the
Expand Down
6 changes: 5 additions & 1 deletion build_library/prod_image_util.sh
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,11 @@ create_prod_image() {
sudo rm -rf "${root_sysext_mergedir}"
fi

write_packages "${root_fs_dir}" "${BUILD_DIR}/${image_packages}"
# In RPM mode finish_image_package_manifest_rpm writes this from the final
# rpmdb, after finish_image uninstalls the azurelinux-repos* packages.
if [[ "${PACKAGE_SOURCE_MODE}" == "PORTAGE" ]]; then
write_packages "${root_fs_dir}" "${BUILD_DIR}/${image_packages}"
fi

insert_licenses "${BUILD_DIR}/${image_licenses}" "${root_fs_dir}"
insert_extra_slsa "${root_fs_dir}"
Expand Down
53 changes: 53 additions & 0 deletions build_library/reports_util.sh
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,59 @@ write_disk_space_usage() {
write_disk_space_usage_in_paths "${1}" "${2}" ./boot ./usr ./
}

# Where the SPDX package manifests are written to in a rootfs.
# systemd-sysext merges every sysext's copy of this directory over the image's,
# so a booted machine sees one directory holding the image's manifest and one
# per merged sysext.
OS_MANIFESTS_DIR="/usr/share/os-manifests"

# Usage:
#
# write_package_manifest image "${root}" "${name}" "${version}" "${packages_file}" "${created_epoch}"
# write_package_manifest sysext "${root}" "${name}" "${version}" "${packages_file}" "${created_epoch}"
#
# The kind picks the filename. An image writes package-manifest.spdx.json and a
# sysext writes package-manifest.<name>.spdx.json, so the copies merged into one
# /usr safely.
#
# The document is not validated here. Its shape is a property of the generator,
# not of any one rootfs, so it is checked against a fixture and a golden SPDX
# 2.2 document by the Build RPMs job of the ACL GitHub PR pipeline, which runs
# /build_library/rpm/tests/test_generate_package_manifest.sh.
write_package_manifest() {
local kind="${1}"
local root="${2}"
local name="${3}"
local version="${4}"
local packages_file="${5}"
local created_epoch="${6}"

local infix
case "${kind}" in
image) infix="" ;;
sysext) infix=".${name}" ;;
*) die "write_package_manifest: expected kind 'image' or 'sysext', got '${kind}'" ;;
esac

local output="${root}${OS_MANIFESTS_DIR}/package-manifest${infix}.spdx.json"

info "Writing ${output##*/}"

# build_image runs as the sdk user, so writing into an image rootfs needs sudo.
sudo install -d -m 0755 "${output%/*}"

# --force because BUILD_DIR is caller-supplied.
sudo "${BUILD_LIBRARY_DIR}/rpm/generate_package_manifest.py" \
--packages-file="${packages_file}" \
--manifest-file="${output}" \
--manifest-name="${name}" \
--manifest-version="${version}" \
--created-epoch="${created_epoch}" \
--force

sudo chmod 0644 "${output}"
}

# Write an SPDX SBOM for a rootfs tree.
write_sysext_sbom() {
local rootfs="${1}"; shift
Expand Down
29 changes: 29 additions & 0 deletions build_library/rpm/build_image_util.sh
Original file line number Diff line number Diff line change
Expand Up @@ -1451,6 +1451,35 @@ finish_image_backup_etc_rpm() {
sudo cp -a "${root_fs_dir}/etc" "${ETC_FULL_PATH}"
}

# Write the image's package list and SPDX manifest from the final rpmdb.
finish_image_package_manifest_rpm() {
local root_fs_dir="$1"
local image_base_name="$2"

if [[ -z "${BUILD_DIR:-}" ]]; then
die "RPM mode: BUILD_DIR is not set — cannot write the image package list"
fi

local packages_file="${BUILD_DIR}/${image_base_name}_packages.txt"

info "RPM mode: Writing ${packages_file##*/}"
rpm_query_packages "${root_fs_dir}" > "${packages_file}"
if [[ ! -s "${packages_file}" ]]; then
die "RPM mode: No packages in ${root_fs_dir}"
fi

local created_epoch
created_epoch=$(stat -c '%Y' "${root_fs_dir}/usr/lib/os-release")

write_package_manifest \
image \
"${root_fs_dir}" \
"${image_base_name}" \
"${IMAGE_VERSION_ID}${IMAGE_BUILD_ID:++${IMAGE_BUILD_ID}}" \
"${packages_file}" \
"${created_epoch}"
}

# Escape a string for JSON - handles quotes, backslashes, and control characters
json_escape() {
local str="$1"
Expand Down
Loading