Added signing stage for livepatches pipeline. (#5101)
This commit is contained in:
Родитель
f76930d345
Коммит
6e6bf3edbe
|
@ -0,0 +1,29 @@
|
|||
{
|
||||
"tool": "Credential Scanner",
|
||||
"suppressions": [
|
||||
{
|
||||
"file": "\\SPECS\\shadow-utils\\shadow-utils.signatures.json",
|
||||
"_justification": "This is a false positive, probably because it says the word password and has a hash. It is just a measurement of the pam.d system-password configuration file."
|
||||
},
|
||||
{
|
||||
"file": "\\toolkit\\tools\\imagegen\\configuration\\configuration_test.go",
|
||||
"_justification": "Dummy secrets used to unit test configuration code."
|
||||
},
|
||||
{
|
||||
"file": "\\toolkit\\tools\\imagegen\\configuration\\testdata\\test_configuration.json",
|
||||
"_justification": "Dummy secrets used to unit test configuration code."
|
||||
},
|
||||
{
|
||||
"file": "toolkit\\tools\\imagegen\\configuration\\user_test.go",
|
||||
"_justification": "Dummy secrets used to unit test configuration code."
|
||||
},
|
||||
{
|
||||
"file": "\\toolkit\\docs\\quick_start\\quickstart.md",
|
||||
"_justification": "Secrets for sample, non-production Mariner images."
|
||||
},
|
||||
{
|
||||
"file": "\\toolkit\\imageconfigs\\read-only-root-efi.json",
|
||||
"_justification": "Secret for a sample, non-production Mariner image."
|
||||
}
|
||||
]
|
||||
}
|
|
@ -4,6 +4,12 @@
|
|||
# Modification to this file require admin approval.
|
||||
/.github/CODEOWNERS @microsoft/cbl-mariner-admins
|
||||
|
||||
# Modifications to the build pipelines require admin approval.
|
||||
/pipelines/* @microsoft/cbl-mariner-admins
|
||||
|
||||
# Modifications to the CredScan exceptions require admin approval.
|
||||
/.config/CredScanSuppressions.json @microsoft/cbl-mariner-admins
|
||||
|
||||
# Modification to what is considered "core packages" require admin approval.
|
||||
/SPECS/core-packages/* @microsoft/cbl-mariner-admins
|
||||
|
||||
|
|
|
@ -0,0 +1,318 @@
|
|||
# Copyright (c) Microsoft Corporation.
|
||||
# Licensed under the MIT License.
|
||||
|
||||
__SAVED_SCRIPT_DIR="$SCRIPT_DIR"
|
||||
SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &> /dev/null && pwd)
|
||||
|
||||
# shellcheck source=file_tools.sh
|
||||
source "$SCRIPT_DIR/file_tools.sh"
|
||||
|
||||
SCRIPT_DIR="$__SAVED_SCRIPT_DIR"
|
||||
unset __SAVED_SCRIPT_DIR
|
||||
|
||||
# Hydrates the local build environment.
|
||||
# Can hydrate RPMs, SRPMs, and toolchain.
|
||||
# At least one of the above must be specified.
|
||||
#
|
||||
# Arguments:
|
||||
#
|
||||
# -c -> Put the RPMs inside the external cache, so that the out/RPMs directory will contain only the locally-built packages.
|
||||
# -d -> repository root directory.
|
||||
# -r -> Path to the RPMs archive or a directory containing it.
|
||||
# In the latter case we look for "rpms.tar.gz".
|
||||
# -s -> Path to the SRPMs archive or a directory containing it.
|
||||
# In the latter case we look for "srpms.tar.gz".
|
||||
# -t -> Path to the toolchain archive or a directory containing it.
|
||||
# In the latter case we look for "toolchain_built_rpms_all.tar.gz".
|
||||
hydrate_artifacts() {
|
||||
local exit_code
|
||||
local out_dir
|
||||
local repo_dir
|
||||
local rpms_archive
|
||||
local rpms_input
|
||||
local rpms_dir
|
||||
local srpms_archive
|
||||
local srpms_input
|
||||
local toolchain_archive
|
||||
local toolchain_input
|
||||
local toolkit_dir
|
||||
|
||||
local OPTIND
|
||||
while getopts "cd:r:s:t:" OPTIONS
|
||||
do
|
||||
case "${OPTIONS}" in
|
||||
c ) rpms_dir="RPMS_DIR=../build/rpms_cache/cache" ;;
|
||||
d ) repo_dir="$OPTARG" ;;
|
||||
r ) rpms_input="$OPTARG" ;;
|
||||
s ) srpms_input="$OPTARG" ;;
|
||||
t ) toolchain_input="$OPTARG" ;;
|
||||
|
||||
\? )
|
||||
echo "ERROR: Invalid Option: -$OPTARG" 1>&2
|
||||
exit 1
|
||||
;;
|
||||
: )
|
||||
echo "ERROR: Invalid Option: -$OPTARG requires an argument" 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ -z "$toolchain_input" && -z "$rpms_input" && -z "$srpms_input" ]]
|
||||
then
|
||||
echo "ERROR: must specify at least one of the following archives to hydrate: RPMs, SRPMs, or toolchain." >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [[ -n "$rpms_input" ]]
|
||||
then
|
||||
rpms_archive="$(find_file_fullpath "$rpms_input" "rpms.tar.gz")"
|
||||
if [[ ! -f "$rpms_archive" ]]
|
||||
then
|
||||
echo "ERROR: No RPMs archive 'rpms.tar.gz' found inside '$rpms_input'." >&2
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -n "$srpms_input" ]]
|
||||
then
|
||||
srpms_archive="$(find_file_fullpath "$srpms_input" "srpms.tar.gz")"
|
||||
if [[ ! -f "$srpms_archive" ]]
|
||||
then
|
||||
echo "ERROR: No SRPMs archive 'srpms.tar.gz' found inside '$srpms_input'." >&2
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -n "$toolchain_input" ]]
|
||||
then
|
||||
toolchain_archive="$(find_file_fullpath "$toolchain_input" "toolchain_built_rpms_all.tar.gz")"
|
||||
if [[ ! -f "$toolchain_archive" ]]
|
||||
then
|
||||
echo "ERROR: No toolchain archive 'toolchain_built_rpms_all.tar.gz' found inside '$toolchain_input'." >&2
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
repo_dir="$(resolve_repo_dir "$repo_dir")"
|
||||
out_dir="$repo_dir/out"
|
||||
toolkit_dir="$repo_dir/toolkit"
|
||||
|
||||
if [[ -n "$rpms_archive" ]]
|
||||
then
|
||||
echo "-- Hydrating cache of repo '$repo_dir' with RPMs from '$rpms_archive'."
|
||||
|
||||
sudo make -C "$toolkit_dir" -j"$(nproc)" hydrate-rpms PACKAGE_ARCHIVE="$rpms_archive" $rpms_dir
|
||||
exit_code=$?
|
||||
if [[ $exit_code != 0 ]]; then
|
||||
echo "ERROR: failed to hydrate repo's RPMs." >&2
|
||||
return $exit_code
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -n "$srpms_archive" ]]
|
||||
then
|
||||
echo "-- Hydrating cache of repo '$repo_dir' with SRPMs from '$srpms_archive'."
|
||||
|
||||
tar --skip-old-files -C "$out_dir" -xf "$srpms_archive"
|
||||
exit_code=$?
|
||||
if [[ $exit_code != 0 ]]; then
|
||||
echo "ERROR: failed to hydrate repo's SRPMs." >&2
|
||||
return $exit_code
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -n "$toolchain_archive" ]]
|
||||
then
|
||||
echo "-- Hydrating cache of repo '$repo_dir' with toolchain from '$toolchain_archive'."
|
||||
|
||||
sudo make -C "$toolkit_dir" -j"$(nproc)" toolchain chroot-tools TOOLCHAIN_ARCHIVE="$toolchain_archive"
|
||||
exit_code=$?
|
||||
if [[ $exit_code != 0 ]]; then
|
||||
echo "ERROR: failed to hydrate repo's toolchain." >&2
|
||||
return $exit_code
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# Overwrites local toolkit with the one from the provide archive.
|
||||
#
|
||||
# Arguments:
|
||||
#
|
||||
# -d -> repository root directory.
|
||||
# -t -> Path to the toolkit archive or a directory containing it.
|
||||
overwrite_toolkit() {
|
||||
local repo_dir
|
||||
local toolkit_input
|
||||
local toolkit_tarball
|
||||
|
||||
local OPTIND
|
||||
while getopts "d:t:" OPTIONS
|
||||
do
|
||||
case "${OPTIONS}" in
|
||||
d ) repo_dir="$OPTARG" ;;
|
||||
t ) toolkit_input="$OPTARG" ;;
|
||||
|
||||
\? )
|
||||
echo "ERROR: Invalid Option: -$OPTARG" 1>&2
|
||||
exit 1
|
||||
;;
|
||||
: )
|
||||
echo "ERROR: Invalid Option: -$OPTARG requires an argument" 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ -z "$toolkit_input" ]]
|
||||
then
|
||||
echo "ERROR: must specify a path for overwriting the toolkit." >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
toolkit_tarball="$(find_file_fullpath "$toolkit_input" "toolkit-*.tar.gz")"
|
||||
if [[ ! -f "$toolkit_tarball" ]]
|
||||
then
|
||||
echo "ERROR: No toolkit tarball found in '$toolkit_input'." >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
repo_dir="$(resolve_repo_dir "$repo_dir")"
|
||||
toolkit_dir="$repo_dir/toolkit"
|
||||
|
||||
echo "-- Extracting toolkit from '$toolkit_tarball' into '$repo_dir'."
|
||||
rm -rf "$toolkit_dir"
|
||||
tar -C "$repo_dir" -xf "$toolkit_tarball"
|
||||
}
|
||||
|
||||
parse_pipeline_boolean() {
|
||||
[[ "$1" =~ [Tt]rue ]] && echo true || echo false
|
||||
}
|
||||
|
||||
print_variable() {
|
||||
local arg_name
|
||||
local padding
|
||||
|
||||
arg_name="$1"
|
||||
padding=" "
|
||||
|
||||
printf -- "-- %s%s-> %s\n" "$arg_name" "${padding:${#arg_name}}" "${!arg_name}"
|
||||
}
|
||||
|
||||
print_variable_with_check() {
|
||||
if [[ -n ${!1} ]]
|
||||
then
|
||||
print_variable "$arg_name"
|
||||
else
|
||||
echo "ERROR: Argument '$arg_name' is required." >&2
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
print_variables_with_check() {
|
||||
local check_status=0
|
||||
|
||||
for arg_name in "$@"
|
||||
do
|
||||
if ! print_variable_with_check "$arg_name"
|
||||
then
|
||||
check_status=1
|
||||
fi
|
||||
done
|
||||
|
||||
return $check_status
|
||||
}
|
||||
|
||||
publish_build_artifacts() {
|
||||
local artifact_publish_dir
|
||||
local make_status
|
||||
local repo_dir
|
||||
local toolkit_dir
|
||||
local out_dir
|
||||
|
||||
artifact_publish_dir="$1"
|
||||
repo_dir="$(resolve_repo_dir "$2")"
|
||||
|
||||
out_dir="$repo_dir/out"
|
||||
toolkit_dir="$repo_dir/toolkit"
|
||||
|
||||
echo "-- Packing built RPMs and SRPMs."
|
||||
sudo make -C "$toolkit_dir" -j"$(nproc)" compress-srpms compress-rpms
|
||||
make_status=$?
|
||||
if [[ $make_status != 0 ]]; then
|
||||
echo "ERROR: cannot pack built RPMs and SRPMs." >&2
|
||||
return $make_status
|
||||
fi
|
||||
|
||||
echo "-- Publishing built RPMs and SRPMs to '$artifact_publish_dir'."
|
||||
mkdir -p "$artifact_publish_dir"
|
||||
sudo mv "$out_dir/"{,s}rpms.tar.gz "$artifact_publish_dir"
|
||||
}
|
||||
|
||||
publish_build_logs() {
|
||||
local logs_dir
|
||||
local logs_publish_dir
|
||||
local package_build_artifacts_dir
|
||||
local repo_dir
|
||||
|
||||
logs_publish_dir="$1"
|
||||
repo_dir="$(resolve_repo_dir "$2")"
|
||||
|
||||
logs_dir="$repo_dir/build/logs"
|
||||
package_build_artifacts_dir="$repo_dir/build/pkg_artifacts"
|
||||
|
||||
mkdir -p "$logs_publish_dir"
|
||||
|
||||
echo "-- Packing package build logs."
|
||||
if [[ -d "$logs_dir" ]]
|
||||
then
|
||||
tar -C "$logs_dir" -czf "$logs_publish_dir/pkggen.logs.tar.gz" .
|
||||
else
|
||||
echo "WARNING: no '$logs_dir' directory found." >&2
|
||||
fi
|
||||
|
||||
echo "-- Packing package build artifacts."
|
||||
if [[ -d "$package_build_artifacts_dir" ]]
|
||||
then
|
||||
tar -C "$package_build_artifacts_dir" -czf "$logs_publish_dir/pkg_artifacts.tar.gz" .
|
||||
else
|
||||
echo "WARNING: no '$package_build_artifacts_dir' directory found." >&2
|
||||
fi
|
||||
}
|
||||
|
||||
publish_toolkit() {
|
||||
local make_status
|
||||
local repo_dir
|
||||
local toolkit_dir
|
||||
local toolkit_publish_dir
|
||||
|
||||
toolkit_publish_dir="$1"
|
||||
repo_dir="$(resolve_repo_dir "$2")"
|
||||
|
||||
toolkit_dir="$repo_dir/toolkit"
|
||||
|
||||
echo "-- Packing toolkit."
|
||||
sudo make -C "$toolkit_dir" -j"$(nproc)" REBUILD_TOOLS=y package-toolkit
|
||||
make_status=$?
|
||||
if [[ $make_status != 0 ]]; then
|
||||
echo "ERROR: failed to pack toolkit." >&2
|
||||
return $make_status
|
||||
fi
|
||||
|
||||
echo "-- Publishing toolkit to '$toolkit_publish_dir'."
|
||||
mkdir -p "$toolkit_publish_dir"
|
||||
sudo mv "$repo_dir"/out/toolkit*.tar.gz "$toolkit_publish_dir"
|
||||
}
|
||||
|
||||
resolve_repo_dir() {
|
||||
local repo_dir
|
||||
|
||||
repo_dir="$1"
|
||||
|
||||
if [[ -z "$repo_dir" ]]
|
||||
then
|
||||
repo_dir="$(git rev-parse --show-toplevel)"
|
||||
fi
|
||||
|
||||
realpath "$repo_dir"
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
# Copyright (c) Microsoft Corporation.
|
||||
# Licensed under the MIT License.
|
||||
|
||||
TEMP_DIR=""
|
||||
|
||||
command_diff() {
|
||||
local input_command
|
||||
local first_file_path
|
||||
local second_file_path
|
||||
|
||||
input_command="$1"
|
||||
first_file_path="$2"
|
||||
second_file_path="$3"
|
||||
|
||||
if ! diff <(eval "$input_command" "$first_file_path") <(eval "$input_command" "$second_file_path"); then
|
||||
echo "ERROR: comparison for command ($input_command) failed! See lines above for details." >&2
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
find_file_fullpath() {
|
||||
local file_pattern
|
||||
local input_path
|
||||
local output_path
|
||||
|
||||
input_path="$1"
|
||||
file_pattern="$2"
|
||||
|
||||
output_path="$input_path"
|
||||
if [[ ! -f "$input_path" ]]
|
||||
then
|
||||
output_path="$(find "$input_path" -name "$file_pattern" -type f -print -quit)"
|
||||
fi
|
||||
|
||||
if [[ -f "$output_path" ]]
|
||||
then
|
||||
realpath "$output_path"
|
||||
fi
|
||||
}
|
||||
|
||||
temp_dir_cleanup() {
|
||||
if [[ -d "$TEMP_DIR" ]]
|
||||
then
|
||||
echo "Cleaning up '$TEMP_DIR'."
|
||||
rm -rf "$TEMP_DIR"
|
||||
fi
|
||||
}
|
|
@ -0,0 +1,144 @@
|
|||
# Copyright (c) Microsoft Corporation.
|
||||
# Licensed under the MIT License.
|
||||
|
||||
# Extracts files from the specified RPM file.
|
||||
# If no pattern is specified, all files are extracted.
|
||||
#
|
||||
# Arguments:
|
||||
#
|
||||
# -f -> flatten the extracted files into the output directory
|
||||
# WARNING: this will overwrite files with the same name.
|
||||
# -i -> input RPM file.
|
||||
# -o -> output directory.
|
||||
# -p -> files pattern.
|
||||
# Default: '*'.
|
||||
# -w -> temporary work directory.
|
||||
rpm_extract_file() {
|
||||
local files_pattern="*"
|
||||
local flatten
|
||||
local output_dir
|
||||
local rpm_name
|
||||
local rpm_path
|
||||
local work_dir
|
||||
|
||||
local OPTIND
|
||||
while getopts "fi:o:p:w:" OPTIONS
|
||||
do
|
||||
case "${OPTIONS}" in
|
||||
f ) flatten=true ;;
|
||||
i ) rpm_path="$OPTARG" ;;
|
||||
o ) output_dir="$OPTARG" ;;
|
||||
p ) files_pattern="$OPTARG" ;;
|
||||
w ) work_dir="$OPTARG" ;;
|
||||
|
||||
\? )
|
||||
echo "ERROR: Invalid Option: -$OPTARG" 1>&2
|
||||
exit 1
|
||||
;;
|
||||
: )
|
||||
echo "ERROR: Invalid Option: -$OPTARG requires an argument" 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ ! -f "$rpm_path" ]]
|
||||
then
|
||||
echo "ERROR: RPM file ($rpm_path) not found." >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [[ -z "$output_dir" ]]
|
||||
then
|
||||
echo "ERROR: output path not specified." >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [[ -f "$output_dir" ]]
|
||||
then
|
||||
echo "ERROR: output path ($output_dir) is a file. Expected a directory or a non-existing path." >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
rpm_name="$(basename "$rpm_path" .rpm)"
|
||||
|
||||
if [[ ! -d "$work_dir" ]]
|
||||
then
|
||||
work_dir="$(mktemp -d)"
|
||||
fi
|
||||
work_dir="$work_dir/$rpm_name"
|
||||
mkdir -p "$work_dir"
|
||||
|
||||
mkdir -p "$output_dir"
|
||||
|
||||
echo "Extracting ($files_pattern) from ($rpm_path) into ($output_dir)."
|
||||
|
||||
rpm2cpio "$rpm_path" | cpio --quiet -D "$work_dir" -idmv "$files_pattern"
|
||||
if $flatten
|
||||
then
|
||||
find "$work_dir" -name "$files_pattern" -exec mv -v {} "$output_dir" \;
|
||||
else
|
||||
mv "$work_dir" "$output_dir"
|
||||
fi
|
||||
}
|
||||
|
||||
# Extracts files from the specified directory or RPM file.
|
||||
# If no pattern is specified, all files are extracted.
|
||||
# Arguments:
|
||||
# -f -> flatten the extracted files into the output directory
|
||||
# WARNING: this will overwrite files with the same name.
|
||||
# -i -> input directory or RPM file.
|
||||
# -o -> output directory.
|
||||
# -p -> files pattern.
|
||||
# Default: '*'.
|
||||
# -w -> temporary work directory.
|
||||
rpm_extract_files() {
|
||||
local files_pattern="*"
|
||||
local flatten_arg
|
||||
local input
|
||||
local output_dir
|
||||
local output_subdir
|
||||
local rpm_name
|
||||
local rpm_path
|
||||
local work_dir
|
||||
|
||||
local OPTIND
|
||||
while getopts "fi:o:p:w:" OPTIONS
|
||||
do
|
||||
case "${OPTIONS}" in
|
||||
f ) flatten_arg="-f" ;;
|
||||
i ) input="$OPTARG" ;;
|
||||
o ) output_dir="$OPTARG" ;;
|
||||
p ) files_pattern="$OPTARG" ;;
|
||||
w ) work_dir="$OPTARG" ;;
|
||||
|
||||
\? )
|
||||
echo "ERROR: Invalid Option: -$OPTARG" 1>&2
|
||||
exit 1
|
||||
;;
|
||||
: )
|
||||
echo "ERROR: Invalid Option: -$OPTARG requires an argument" 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ ! -d "$input" && ! -f "$input" ]]
|
||||
then
|
||||
echo "ERROR: input ($input) not found." >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! find "$input" -name "*.rpm" -type f -print0 | grep -q .
|
||||
then
|
||||
echo "ERROR: input ($input) is neither an RPM file nor a directory containing RPM files." >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
while IFS= read -r -d '' rpm_path
|
||||
do
|
||||
rpm_name="$(basename "$rpm_path" .rpm)"
|
||||
output_subdir="$output_dir/$rpm_name"
|
||||
rpm_extract_file -i "$rpm_path" -p "$files_pattern" -w "$work_dir" -o "$output_subdir" $flatten_arg
|
||||
done < <(find "$input" -name "*.rpm" -type f -print0)
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
ROOT_DIR="$(git rev-parse --show-toplevel)"
|
||||
|
||||
# shellcheck source=../common/libs/build_tools.sh
|
||||
source "$ROOT_DIR/pipelines/common/libs/build_tools.sh"
|
||||
|
||||
compress_rpms() {
|
||||
local artifacts_dir
|
||||
local compressed_dir
|
||||
local compressed_dir_lowercase
|
||||
local output_dir
|
||||
|
||||
artifacts_dir="$1"
|
||||
output_dir="$2"
|
||||
|
||||
mkdir -p "$output_dir"
|
||||
|
||||
for compressed_dir in RPMS SRPMS
|
||||
do
|
||||
if [[ -d "$artifacts_dir/$compressed_dir" ]]
|
||||
then
|
||||
compressed_dir_lowercase="${compressed_dir,,}"
|
||||
|
||||
echo "-- Compressing the '$compressed_dir' directory into ($output_dir)."
|
||||
tar -C "$artifacts_dir" -cf "$output_dir/$compressed_dir_lowercase.tar.gz" "$compressed_dir"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
validate_rpm_signatures() {
|
||||
local artifacts_dir
|
||||
local key_id
|
||||
local rpm_name
|
||||
local rpm_path
|
||||
local signatures_ok
|
||||
|
||||
artifacts_dir="$1"
|
||||
key_id="$2"
|
||||
|
||||
signatures_ok=true
|
||||
|
||||
echo "-- Validating RPM signatures with key ID ($key_id)."
|
||||
|
||||
while IFS= read -r -d '' rpm_path
|
||||
do
|
||||
rpm_name="$(basename "$rpm_path")"
|
||||
|
||||
echo "-- Validating signature key for ($rpm_name)."
|
||||
|
||||
verification_output="$(rpm -v --checksig "$rpm_path" 2>&1)"
|
||||
if ! grep -q "key ID $key_id: OK" <<< "$verification_output"
|
||||
then
|
||||
echo -e "ERROR: RPM signature key validation failed for ($rpm_name). Details:\n$verification_output" >&2
|
||||
signatures_ok=false
|
||||
fi
|
||||
done < <(find "$artifacts_dir" -name "*.rpm")
|
||||
|
||||
$signatures_ok
|
||||
}
|
||||
|
||||
# Script parameters:
|
||||
#
|
||||
# -a -> input artifacts directory path
|
||||
# -k -> signing key ID to verify the RPMs' signatures
|
||||
# -o -> output directory
|
||||
while getopts "a:k:o:" OPTIONS
|
||||
do
|
||||
case "${OPTIONS}" in
|
||||
a ) ARTIFACTS_DIR=$OPTARG ;;
|
||||
k ) EXPECTED_KEY_ID=$OPTARG ;;
|
||||
o ) OUTPUT_DIR=$OPTARG ;;
|
||||
|
||||
\? )
|
||||
echo "ERROR: Invalid Option: -$OPTARG" 1>&2
|
||||
exit 1
|
||||
;;
|
||||
: )
|
||||
echo "ERROR: Invalid Option: -$OPTARG requires an argument" 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ ! -d "$ARTIFACTS_DIR/RPMS" && ! -d "$ARTIFACTS_DIR/SRPMS" ]]
|
||||
then
|
||||
echo "ERROR: input directory ($ARTIFACTS_DIR) must contain at least the 'RPMS' or 'SRPMS' subdirectory." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
print_variables_with_check ARTIFACTS_DIR EXPECTED_KEY_ID OUTPUT_DIR
|
||||
|
||||
validate_rpm_signatures "$ARTIFACTS_DIR" "$EXPECTED_KEY_ID"
|
||||
|
||||
compress_rpms "$ARTIFACTS_DIR" "$OUTPUT_DIR"
|
|
@ -1,97 +0,0 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
echo "Configuring CBL-Mariner build machine."
|
||||
|
||||
function verify_image {
|
||||
echo "verify_image"
|
||||
|
||||
# Verify proper filesystem type for /mnt
|
||||
#
|
||||
# Good: /dev/sda1 ext4 126G 94M 119G 1% /mnt
|
||||
# Bad: /dev/sda1 fuseblk 128G 125M 128G 1% /mnt
|
||||
MNT_FILESYSTEM_TYPE=$(df -Th | grep '/mnt$' | awk '{ print $2 }')
|
||||
if [[ "$MNT_FILESYSTEM_TYPE" == "ext4" ]]; then
|
||||
echo "Detected proper /mnt filesystem type is 'ext4'. Continuing."
|
||||
else
|
||||
echo "Error detected: /mnt filesystem type is '$MNT_FILESYSTEM_TYPE' instead of 'ext4'. Failing build." >&2
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
function configure_image {
|
||||
echo "configure_image"
|
||||
# Install apps applicable to both X64 and ARM64
|
||||
sudo tdnf -y install dotnet-sdk-6.0 createrepo jq yum-utils rpm cpio dnf-utils acl
|
||||
# ensure golang 1.17 is installed
|
||||
sudo tdnf -y install "golang < 1.18"
|
||||
sudo tdnf -y install git make tar rpm-build gcc glibc-devel binutils \
|
||||
kernel-headers wget curl rpm qemu-img cdrkit python bison \
|
||||
gawk parted dosfstools pigz moby-engine moby-cli
|
||||
|
||||
# Enable Docker daemon at boot
|
||||
sudo systemctl enable --now docker.service
|
||||
# Add current user to docker group
|
||||
sudo usermod -aG docker "$USER"
|
||||
|
||||
# Install architecture-specific
|
||||
if [[ "$(uname -i)" == "x86_64" ]]; then
|
||||
configure_image_x64
|
||||
else
|
||||
configure_image_arm64
|
||||
fi
|
||||
}
|
||||
|
||||
function configure_image_x64 {
|
||||
echo "configure_image_x64"
|
||||
# These are only available for X64.
|
||||
sudo tdnf -y install azure-cli powershell
|
||||
}
|
||||
|
||||
function configure_image_arm64 {
|
||||
echo "configure_image_arm64"
|
||||
# Install Azure CLI via script. This requires python3-devel.
|
||||
sudo tdnf -y install python3-devel
|
||||
install_az_cli_with_script
|
||||
}
|
||||
|
||||
function install_az_cli_with_script {
|
||||
echo "install_az_cli_with_script"
|
||||
pushd /tmp/
|
||||
#Work-around to make the script non-interactive and install az with default values
|
||||
cat > /tmp/non_interact.sh <<EOF
|
||||
sed -i 's/def prompt_input_with_default(msg, default):/def prompt_input_with_default(msg, default):\n return default/g' \$1
|
||||
sed -i 's/def prompt_y_n(msg, default=None):/def prompt_y_n(msg, default=None):\n return "y"/g' \$1
|
||||
# The no-indentation is intentional. EOF with indentation is not considered as EOF.
|
||||
EOF
|
||||
chmod +x /tmp/non_interact.sh
|
||||
curl -sL https://aka.ms/InstallAzureCli > /tmp/azcli_ins.sh
|
||||
sed -i 's/echo "Running install script."/echo "Running install script."\n\/tmp\/non_interact.sh \$install_script/g' /tmp/azcli_ins.sh
|
||||
sed -i "s/\$python_cmd \$install_script < \$_TTY/\$python_cmd \$install_script/g" /tmp/azcli_ins.sh
|
||||
bash /tmp/azcli_ins.sh
|
||||
sudo ln -svf /home/"$USER"/bin/az /usr/bin/az | true
|
||||
az extension add --name azure-devops
|
||||
az devops configure --defaults organization="https://dev.azure.com/mariner-org" project="mariner"
|
||||
az version
|
||||
popd
|
||||
}
|
||||
|
||||
function print_app_versions {
|
||||
echo "print_app_versions"
|
||||
|
||||
echo "Kernel version: $(uname -r)"
|
||||
echo "Architecture: $(uname -m)"
|
||||
docker --version
|
||||
go version
|
||||
echo "Dotnet version: $(dotnet --version)"
|
||||
# Note: powershell and azcli might not be available (on mariner arm64). Ignore errors
|
||||
pwsh --version || true
|
||||
echo "Az cli version: "
|
||||
az version || true
|
||||
}
|
||||
|
||||
configure_image
|
||||
|
||||
verify_image
|
||||
|
||||
print_app_versions
|
|
@ -1,163 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
hydrate_cache() {
|
||||
local make_status
|
||||
local repo_dir
|
||||
local rpms_archive
|
||||
local toolchain_archive
|
||||
local toolkit_dir
|
||||
|
||||
toolchain_archive="$1"
|
||||
rpms_archive="$2"
|
||||
repo_dir="$(resolve_repo_dir "$3")"
|
||||
|
||||
toolkit_dir="$repo_dir/toolkit"
|
||||
|
||||
echo "-- Hydrating cache of repo '$repo_dir' with toolchain from '$toolchain_archive'."
|
||||
|
||||
sudo make -C "$toolkit_dir" -j"$(nproc)" toolchain chroot-tools TOOLCHAIN_ARCHIVE="$toolchain_archive"
|
||||
make_status=$?
|
||||
if [[ $make_status != 0 ]]; then
|
||||
echo "-- ERROR: failed to hydrate repo's toolchain." >&2
|
||||
return $make_status
|
||||
fi
|
||||
|
||||
if [[ -n "$rpms_archive" ]]
|
||||
then
|
||||
# We put the RPMs into the cache directory, so that the built RPMs directory only contains the built packages.
|
||||
echo "-- Hydrating cache of repo '$repo_dir' with RPMS from '$rpms_archive'."
|
||||
|
||||
sudo make -C "$toolkit_dir" -j"$(nproc)" hydrate-rpms PACKAGE_ARCHIVE="$rpms_archive" RPMS_DIR="$repo_dir/build/rpms_cache/cache"
|
||||
make_status=$?
|
||||
if [[ $make_status != 0 ]]; then
|
||||
echo "-- ERROR: failed to hydrate repo's RPMs." >&2
|
||||
return $make_status
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
overwrite_toolkit() {
|
||||
local repo_dir
|
||||
local toolkit_tarball
|
||||
|
||||
toolkit_tarball="$1"
|
||||
repo_dir="$(resolve_repo_dir "$2")"
|
||||
|
||||
toolkit_dir="$repo_dir/toolkit"
|
||||
|
||||
pushd "$repo_dir" > /dev/null || true
|
||||
|
||||
echo "-- Extracting toolkit from '$toolkit_tarball' into '$repo_dir'."
|
||||
rm -rf "$toolkit_dir"
|
||||
tar -C "$repo_dir" -xf "$toolkit_tarball"
|
||||
|
||||
popd > /dev/null || true
|
||||
}
|
||||
|
||||
parse_pipeline_boolean() {
|
||||
[[ "$1" =~ [Tt]rue ]] && echo true || echo false
|
||||
}
|
||||
|
||||
print_variable() {
|
||||
local arg_name
|
||||
local padding
|
||||
|
||||
arg_name="$1"
|
||||
padding=" "
|
||||
|
||||
printf -- "-- %s%s-> %s\n" "$arg_name" "${padding:${#arg_name}}" "${!arg_name}"
|
||||
}
|
||||
|
||||
print_variable_with_check() {
|
||||
if [[ -n ${!1} ]]
|
||||
then
|
||||
print_variable "$arg_name"
|
||||
else
|
||||
echo "ERROR: Argument '$arg_name' is required." >&2
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
print_variables_with_check() {
|
||||
local check_status=0
|
||||
|
||||
for arg_name in "$@"
|
||||
do
|
||||
if ! print_variable_with_check "$arg_name"
|
||||
then
|
||||
check_status=1
|
||||
fi
|
||||
done
|
||||
|
||||
return $check_status
|
||||
}
|
||||
|
||||
publish_build_artifacts() {
|
||||
local artifact_publish_dir
|
||||
local make_status
|
||||
local repo_dir
|
||||
local toolkit_dir
|
||||
local out_dir
|
||||
|
||||
artifact_publish_dir="$1"
|
||||
repo_dir="$(resolve_repo_dir "$2")"
|
||||
|
||||
toolkit_dir="$repo_dir/toolkit"
|
||||
out_dir="$repo_dir/out"
|
||||
|
||||
echo "-- Packing built RPMs and SRPMs."
|
||||
sudo make -C "$toolkit_dir" -j"$(nproc)" compress-srpms compress-rpms
|
||||
make_status=$?
|
||||
if [[ $make_status != 0 ]]; then
|
||||
echo "-- ERROR: cannot pack built RPMs and SRPMs." >&2
|
||||
return $make_status
|
||||
fi
|
||||
|
||||
echo "-- Publishing built RPMs and SRPMs to '$artifact_publish_dir'."
|
||||
mkdir -p "$artifact_publish_dir"
|
||||
sudo mv "$out_dir/"{,s}rpms.tar.gz "$artifact_publish_dir"
|
||||
}
|
||||
|
||||
publish_build_logs() {
|
||||
local logs_dir
|
||||
local logs_publish_dir
|
||||
local package_build_artifacts_dir
|
||||
local repo_dir
|
||||
|
||||
logs_publish_dir="$1"
|
||||
repo_dir="$(resolve_repo_dir "$2")"
|
||||
|
||||
logs_dir="$repo_dir/build/logs"
|
||||
package_build_artifacts_dir="$repo_dir/build/pkg_artifacts"
|
||||
|
||||
mkdir -p "$logs_publish_dir"
|
||||
|
||||
echo "-- Packing package build logs."
|
||||
if [[ -d "$logs_dir" ]]
|
||||
then
|
||||
tar -C "$logs_dir" -czf "$logs_publish_dir/pkggen.logs.tar.gz" .
|
||||
else
|
||||
echo "-- WARNING: no '$logs_dir' directory found." >&2
|
||||
fi
|
||||
|
||||
echo "-- Packing package build artifacts."
|
||||
if [[ -d "$package_build_artifacts_dir" ]]
|
||||
then
|
||||
tar -C "$package_build_artifacts_dir" -czf "$logs_publish_dir/pkg_artifacts.tar.gz" .
|
||||
else
|
||||
echo "-- WARNING: no '$package_build_artifacts_dir' directory found."
|
||||
fi
|
||||
}
|
||||
|
||||
resolve_repo_dir() {
|
||||
local repo_dir
|
||||
|
||||
repo_dir="$1"
|
||||
|
||||
if [[ -z "$repo_dir" ]]
|
||||
then
|
||||
repo_dir="$(git rev-parse --show-toplevel)"
|
||||
fi
|
||||
|
||||
realpath "$repo_dir"
|
||||
}
|
|
@ -4,8 +4,8 @@ set -e
|
|||
|
||||
ROOT_DIR="$(git rev-parse --show-toplevel)"
|
||||
|
||||
# shellcheck source=../common/utilities/build_tools.sh
|
||||
source "$ROOT_DIR/pipelines/common/utilities/build_tools.sh"
|
||||
# shellcheck source=../common/libs/build_tools.sh
|
||||
source "$ROOT_DIR/pipelines/common/libs/build_tools.sh"
|
||||
|
||||
build_package() {
|
||||
local package_name
|
||||
|
@ -33,75 +33,46 @@ build_package() {
|
|||
LOG_LEVEL=info
|
||||
}
|
||||
|
||||
hydrate_build_artifacts() {
|
||||
local artifacts_dir
|
||||
local rpms_archive
|
||||
local toolchain_archive
|
||||
local toolkit_archive
|
||||
|
||||
artifacts_dir="$1"
|
||||
|
||||
rpms_archive="$(find "$artifacts_dir" -name '*rpms.tar.gz' -type f -print -quit)"
|
||||
if [[ ! -f "$rpms_archive" ]]
|
||||
then
|
||||
echo "ERROR: No RPMs archive found in '$artifacts_dir'." >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
toolchain_archive="$(find "$artifacts_dir" -name '*toolchain_built_rpms_all.tar.gz' -type f -print -quit)"
|
||||
if [[ ! -f "$toolchain_archive" ]]
|
||||
then
|
||||
echo "ERROR: No toolchain archive found in '$artifacts_dir'." >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
toolkit_archive="$(find "$artifacts_dir" -name '*toolkit-*.tar.gz' -type f -print -quit)"
|
||||
if [[ ! -f "$toolkit_archive" ]]
|
||||
then
|
||||
echo "ERROR: No toolkit tarball found in '$artifacts_dir'." >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
overwrite_toolkit "$toolkit_archive"
|
||||
hydrate_cache "$toolchain_archive" "$rpms_archive"
|
||||
}
|
||||
|
||||
# Script parameters:
|
||||
#
|
||||
# -a -> input artifacts directory path
|
||||
# -k -> kernel version to be livepatched
|
||||
# -l -> published logs directory path
|
||||
# -p -> published artifacts directory path
|
||||
# -o -> built artifacts' output directory path
|
||||
# -s -> use toolkit's RPMs snapshot to populate the packages cache
|
||||
while getopts "a:k:l:p:s:" OPTIONS
|
||||
while getopts "a:k:l:o:s:" OPTIONS
|
||||
do
|
||||
case "${OPTIONS}" in
|
||||
a ) ARTIFACTS_DIR=$OPTARG ;;
|
||||
k ) KERNEL_VERSION=$OPTARG ;;
|
||||
l ) LOG_PUBLISH_DIR=$OPTARG ;;
|
||||
p ) ARTIFACTS_PUBLISH_DIR=$OPTARG ;;
|
||||
o ) ARTIFACTS_OUTPUT_DIR=$OPTARG ;;
|
||||
s ) USE_RPMS_SNAPSHOT="$(parse_pipeline_boolean "$OPTARG")" ;;
|
||||
|
||||
\? )
|
||||
echo "Error - Invalid Option: -$OPTARG" 1>&2
|
||||
echo "ERROR: Invalid Option: -$OPTARG" 1>&2
|
||||
exit 1
|
||||
;;
|
||||
: )
|
||||
echo "Error - Invalid Option: -$OPTARG requires an argument" 1>&2
|
||||
echo "ERROR: Invalid Option: -$OPTARG requires an argument" 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
print_variables_with_check ARTIFACTS_DIR KERNEL_VERSION LOG_PUBLISH_DIR ARTIFACTS_PUBLISH_DIR USE_RPMS_SNAPSHOT
|
||||
print_variables_with_check ARTIFACTS_DIR KERNEL_VERSION LOG_PUBLISH_DIR ARTIFACTS_OUTPUT_DIR USE_RPMS_SNAPSHOT
|
||||
|
||||
hydrate_build_artifacts "$ARTIFACTS_DIR"
|
||||
overwrite_toolkit -t "$ARTIFACTS_DIR"
|
||||
|
||||
hydrate_artifacts -c -t "$ARTIFACTS_DIR" -r "$ARTIFACTS_DIR"
|
||||
|
||||
# Making sure we publish build logs even if the build fails.
|
||||
build_package "livepatch-$KERNEL_VERSION" "$USE_RPMS_SNAPSHOT" || BUILD_SUCCEEDED=false
|
||||
|
||||
publish_build_logs "$LOG_PUBLISH_DIR"
|
||||
|
||||
publish_build_artifacts "$ARTIFACTS_PUBLISH_DIR"
|
||||
publish_build_artifacts "$ARTIFACTS_OUTPUT_DIR"
|
||||
|
||||
publish_toolkit "$ARTIFACTS_OUTPUT_DIR"
|
||||
|
||||
${BUILD_SUCCEEDED:-true}
|
||||
|
|
|
@ -0,0 +1,137 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
ROOT_DIR="$(git rev-parse --show-toplevel)"
|
||||
|
||||
# shellcheck source=../common/libs/build_tools.sh
|
||||
source "$ROOT_DIR/pipelines/common/libs/build_tools.sh"
|
||||
|
||||
# shellcheck source=../common/libs/file_tools.sh
|
||||
source "$ROOT_DIR/pipelines/common/libs/file_tools.sh"
|
||||
|
||||
build_package_signed() {
|
||||
local package_cache_summary
|
||||
local package_name
|
||||
local toolkit_dir
|
||||
local use_rpms_snapshot
|
||||
|
||||
package_name="$1"
|
||||
use_rpms_snapshot="$2"
|
||||
|
||||
toolkit_dir="toolkit"
|
||||
|
||||
if $use_rpms_snapshot
|
||||
then
|
||||
package_cache_summary="$toolkit_dir/rpms_snapshot.json"
|
||||
echo "-- Using RPMs snapshot as package cache summary."
|
||||
fi
|
||||
|
||||
sudo make -C "toolkit" -j"$(nproc)" build-packages \
|
||||
CONFIG_FILE= \
|
||||
REBUILD_TOOLS=y \
|
||||
PACKAGE_BUILD_LIST="$package_name" \
|
||||
PACKAGE_CACHE_SUMMARY="$package_cache_summary" \
|
||||
SRPM_PACK_LIST="$package_name-signed" \
|
||||
SRPM_FILE_SIGNATURE_HANDLING=update \
|
||||
SPECS_DIR="../SPECS-SIGNED" \
|
||||
LOG_LEVEL=info
|
||||
}
|
||||
|
||||
hydrate_signed_sources() {
|
||||
local kernel_modules_dir
|
||||
local livepatch_folder
|
||||
|
||||
livepatch_folder="livepatch-$1"
|
||||
kernel_modules_dir="$2"
|
||||
|
||||
cp "$kernel_modules_dir/$livepatch_folder"*/*.ko SPECS-SIGNED/"$livepatch_folder-signed"
|
||||
}
|
||||
|
||||
verify_built_package() {
|
||||
local kernel_version
|
||||
local no_errors
|
||||
local rpm_name
|
||||
local signed_rpm_path
|
||||
local tmpdir
|
||||
local unsigned_rpm_path
|
||||
|
||||
kernel_version="$1"
|
||||
tmpdir="$2"
|
||||
|
||||
while IFS= read -r -d '' signed_rpm_path
|
||||
do
|
||||
rpm_name="$(basename "$signed_rpm_path")"
|
||||
|
||||
echo "Verifying RPM ($rpm_name)."
|
||||
|
||||
unsigned_rpm_path="$(find "$tmpdir" -name "$rpm_name" -print -quit)"
|
||||
if [[ -z "$unsigned_rpm_path" ]]
|
||||
then
|
||||
echo "ERROR: RPM ($rpm_name) not found in the unsigned version." >&2
|
||||
no_errors=false
|
||||
continue
|
||||
fi
|
||||
|
||||
if ! command_diff "rpm -qp --provides" "$unsigned_rpm_path" "$signed_rpm_path" || \
|
||||
! command_diff "rpm -qp --requires" "$unsigned_rpm_path" "$signed_rpm_path" || \
|
||||
! command_diff "rpm -qlp" "$unsigned_rpm_path" "$signed_rpm_path"
|
||||
then
|
||||
no_errors=false
|
||||
fi
|
||||
done < <(find "out/RPMS" -name "livepatch-$kernel_version*.rpm" -and -not -name "*debuginfo*" -print0)
|
||||
|
||||
${no_errors:-true}
|
||||
}
|
||||
|
||||
# Script parameters:
|
||||
#
|
||||
# -a -> input artifacts directory path
|
||||
# -k -> kernel version to be livepatched
|
||||
# -l -> published logs directory path
|
||||
# -o -> built artifacts' output directory path
|
||||
# -s -> use toolkit's RPMs snapshot to populate the packages cache
|
||||
while getopts "a:k:l:o:s:" OPTIONS
|
||||
do
|
||||
case "${OPTIONS}" in
|
||||
a ) ARTIFACTS_DIR=$OPTARG ;;
|
||||
k ) KERNEL_VERSION=$OPTARG ;;
|
||||
l ) LOG_PUBLISH_DIR=$OPTARG ;;
|
||||
o ) ARTIFACTS_OUTPUT_DIR=$OPTARG ;;
|
||||
s ) USE_RPMS_SNAPSHOT="$(parse_pipeline_boolean "$OPTARG")" ;;
|
||||
|
||||
\? )
|
||||
echo "ERROR: Invalid Option: -$OPTARG" 1>&2
|
||||
exit 1
|
||||
;;
|
||||
: )
|
||||
echo "ERROR: Invalid Option: -$OPTARG requires an argument" 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
print_variables_with_check ARTIFACTS_DIR KERNEL_VERSION LOG_PUBLISH_DIR ARTIFACTS_OUTPUT_DIR USE_RPMS_SNAPSHOT
|
||||
|
||||
TEMP_DIR="$(mktemp -d)"
|
||||
trap temp_dir_cleanup EXIT
|
||||
|
||||
overwrite_toolkit -t "$ARTIFACTS_DIR"
|
||||
|
||||
hydrate_artifacts -r "$ARTIFACTS_DIR" -s "$ARTIFACTS_DIR"
|
||||
|
||||
# Saving the unsigned version for the sake of comparing with the signed one after it's built.
|
||||
find "out/RPMS" -name "livepatch-$KERNEL_VERSION*.rpm" -and -not -name "*debuginfo*" -exec mv {} "$TEMP_DIR" \;
|
||||
|
||||
hydrate_signed_sources "$KERNEL_VERSION" "$ARTIFACTS_DIR"
|
||||
|
||||
# Making sure we publish build logs even if the build fails.
|
||||
build_package_signed "livepatch-$KERNEL_VERSION" "$USE_RPMS_SNAPSHOT" || BUILD_SUCCEEDED=false
|
||||
|
||||
publish_build_logs "$LOG_PUBLISH_DIR"
|
||||
|
||||
publish_build_artifacts "$ARTIFACTS_OUTPUT_DIR"
|
||||
|
||||
${BUILD_SUCCEEDED:-true}
|
||||
|
||||
verify_built_package "$KERNEL_VERSION" "$TEMP_DIR"
|
|
@ -1,19 +1,37 @@
|
|||
trigger: none
|
||||
|
||||
variables:
|
||||
# Required by used templates.
|
||||
- group: "Mariner Automation"
|
||||
|
||||
- name: 'buildArtifactsFolder'
|
||||
value: build-artifacts
|
||||
|
||||
- name: 'buildLogsFolder'
|
||||
value: 'LOGS'
|
||||
|
||||
- name: 'pipelinesRepoFolder'
|
||||
value: 'CBL-Mariner-Pipelines'
|
||||
|
||||
- name: 'pipelinesRepoRoot'
|
||||
value: '$(Agent.BuildDirectory)/$(pipelinesRepoFolder)'
|
||||
|
||||
- name: 'selfRepoFolder'
|
||||
value: 'CBL-Mariner'
|
||||
|
||||
- name: 'selfRepoRoot'
|
||||
value: '$(Agent.BuildDirectory)/$(selfRepoFolder)'
|
||||
|
||||
- name: 'rpmSigningKeyID'
|
||||
value: '3135ce90'
|
||||
|
||||
parameters:
|
||||
- name: livepatchKernelVersion
|
||||
displayName: 'Version of the kernel, which is used to build the livepatch (example: 5.15.92.1-1.cm2).'
|
||||
type: string
|
||||
|
||||
- name: useKernelBuildArtifacts
|
||||
displayName: 'Use toolkit and packages from the time the kernel was built.'
|
||||
- name: downloadKernelBuildArtifacts
|
||||
displayName: 'Download toolkit and packages from the time the kernel was built.'
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
|
@ -22,12 +40,22 @@ parameters:
|
|||
type: boolean
|
||||
default: false
|
||||
|
||||
- name: publishRPMs
|
||||
displayName: 'PRODUCTION RUN. WILL PUBLISH PACKAGES TO PMC.'
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
resources:
|
||||
repositories:
|
||||
- repository: 1ESPipelineTemplates
|
||||
type: git
|
||||
name: 1ESPipelineTemplates/1ESPipelineTemplates
|
||||
ref: refs/tags/canary
|
||||
ref: refs/tags/release
|
||||
|
||||
- repository: CBL-Mariner-Pipelines
|
||||
type: git
|
||||
name: mariner/CBL-Mariner-Pipelines
|
||||
ref: refs/heads/pawelwi/signing_livepatches
|
||||
|
||||
extends:
|
||||
template: v1/1ES.Official.PipelineTemplate.yml@1ESPipelineTemplates
|
||||
|
@ -52,22 +80,18 @@ extends:
|
|||
- output: pipelineArtifact
|
||||
displayName: 'Publish build artifacts'
|
||||
targetPath: $(Build.ArtifactStagingDirectory)/$(buildArtifactsFolder)
|
||||
artifactName: build-artifacts
|
||||
artifactName: $(buildArtifactsFolder)_BUILD
|
||||
|
||||
- output: pipelineArtifact
|
||||
displayName: 'Publish logs'
|
||||
targetPath: $(Build.ArtifactStagingDirectory)/$(buildLogsFolder)
|
||||
artifactName: LOGS
|
||||
artifactName: LOGS_BUILD
|
||||
|
||||
steps:
|
||||
- bash: |
|
||||
pipelines/common/utilities/Configure-1ES.sh
|
||||
displayName: 'Install 1ES host machine applications'
|
||||
|
||||
- bash: |
|
||||
mariner_version="$(make -sC toolkit printvar-RELEASE_MAJOR_ID CONFIG_FILE=)"
|
||||
download_tags="$mariner_version-stable"
|
||||
if [[ "${{ parameters.useKernelBuildArtifacts }}" =~ [Tt]rue ]]
|
||||
if [[ "${{ parameters.downloadKernelBuildArtifacts }}" =~ [Tt]rue ]]
|
||||
then
|
||||
download_tags+=",kernel-${{ parameters.livepatchKernelVersion }}"
|
||||
fi
|
||||
|
@ -86,28 +110,155 @@ extends:
|
|||
tags: '$(downloadTags)'
|
||||
artifact: $(buildArtifactsFolder)
|
||||
patterns: |
|
||||
**/toolkit-*.tar.gz
|
||||
**/toolchain_built_rpms_all.tar.gz
|
||||
**/rpms.tar.gz
|
||||
**/toolchain_built_rpms_all.tar.gz
|
||||
**/toolkit-*.tar.gz
|
||||
path: '$(System.ArtifactsDirectory)'
|
||||
|
||||
- task: Bash@3
|
||||
displayName: 'Build livepatch'
|
||||
inputs:
|
||||
filePath: '$(Build.SourcesDirectory)/pipelines/livepatching/BuildLivepatch.sh'
|
||||
filePath: 'pipelines/livepatching/BuildLivepatch.sh'
|
||||
arguments: '-a "$(System.ArtifactsDirectory)"
|
||||
-k "${{ parameters.livepatchKernelVersion }}"
|
||||
-l "$(Build.ArtifactStagingDirectory)/$(buildLogsFolder)"
|
||||
-p "$(Build.ArtifactStagingDirectory)/$(buildArtifactsFolder)"
|
||||
-o "$(Build.ArtifactStagingDirectory)/$(buildArtifactsFolder)"
|
||||
-s "${{ parameters.useRPMsSnapshot }}"'
|
||||
|
||||
- stage: Sign
|
||||
jobs:
|
||||
- job:
|
||||
- job: Kernel_modules
|
||||
templateContext:
|
||||
outputs:
|
||||
- output: pipelineArtifact
|
||||
displayName: 'Publish build artifacts'
|
||||
targetPath: $(Build.ArtifactStagingDirectory)/$(buildArtifactsFolder)
|
||||
artifactName: $(buildArtifactsFolder)_KERNEL_MODULES
|
||||
|
||||
pool:
|
||||
# The kernel modules signing task works only on Ubuntu.
|
||||
name: mariner-core-x64-1es-ubuntu2204-gpt-test
|
||||
|
||||
steps:
|
||||
- checkout: self
|
||||
path: '$(selfRepoFolder)'
|
||||
|
||||
- checkout: CBL-Mariner-Pipelines
|
||||
path: '$(pipelinesRepoFolder)'
|
||||
|
||||
- task: DownloadPipelineArtifact@2
|
||||
displayName: 'Download livepatch RPMs'
|
||||
inputs:
|
||||
source: current
|
||||
artifact: '$(buildArtifactsFolder)_BUILD'
|
||||
patterns: '**/rpms.tar.gz'
|
||||
path: '$(System.ArtifactsDirectory)'
|
||||
|
||||
- task: Bash@3
|
||||
displayName: 'Extract kernel modules'
|
||||
inputs:
|
||||
filePath: '$(selfRepoRoot)/pipelines/livepatching/ExtractKernelModules.sh'
|
||||
arguments: '-a "$(System.ArtifactsDirectory)"
|
||||
-o "$(Build.ArtifactStagingDirectory)/$(buildArtifactsFolder)"'
|
||||
workingDirectory: '$(selfRepoRoot)'
|
||||
|
||||
- template: .pipelines/templates/KernelModulesSigning.yml@CBL-Mariner-Pipelines
|
||||
parameters:
|
||||
artifactsFolder: '$(Build.ArtifactStagingDirectory)/$(buildArtifactsFolder)'
|
||||
repoRootPath: '$(pipelinesRepoRoot)'
|
||||
|
||||
# Once we enable signing kernel modules on Mariner images, merge this job with the previous one to simplify the pipeline.
|
||||
- job: Kernel_modules_packaging
|
||||
dependsOn: Kernel_modules
|
||||
templateContext:
|
||||
outputs:
|
||||
- output: pipelineArtifact
|
||||
displayName: 'Publish build artifacts'
|
||||
targetPath: $(Build.ArtifactStagingDirectory)/$(buildArtifactsFolder)
|
||||
artifactName: $(buildArtifactsFolder)_KERNEL_MODULES_PACKAGING
|
||||
|
||||
- output: pipelineArtifact
|
||||
displayName: 'Publish logs'
|
||||
targetPath: $(Build.ArtifactStagingDirectory)/$(buildLogsFolder)
|
||||
artifactName: LOGS_KERNEL_MODULES_PACKAGING
|
||||
|
||||
steps:
|
||||
- task: DownloadPipelineArtifact@2
|
||||
displayName: 'Download RPMs and toolkit archives'
|
||||
inputs:
|
||||
source: current
|
||||
artifact: '$(buildArtifactsFolder)_BUILD'
|
||||
patterns: |
|
||||
**/*rpms.tar.gz
|
||||
**/toolkit-*.tar.gz
|
||||
path: '$(System.ArtifactsDirectory)'
|
||||
|
||||
- task: DownloadPipelineArtifact@2
|
||||
displayName: 'Download signed kernel modules'
|
||||
inputs:
|
||||
source: current
|
||||
artifact: '$(buildArtifactsFolder)_KERNEL_MODULES'
|
||||
patterns: '**/*.ko'
|
||||
path: '$(System.ArtifactsDirectory)'
|
||||
|
||||
- task: Bash@3
|
||||
displayName: 'Build livepatch-signed RPM'
|
||||
inputs:
|
||||
filePath: 'pipelines/livepatching/BuildLivepatchSigned.sh'
|
||||
arguments: '-a "$(System.ArtifactsDirectory)"
|
||||
-k "${{ parameters.livepatchKernelVersion }}"
|
||||
-l "$(Build.ArtifactStagingDirectory)/$(buildLogsFolder)"
|
||||
-o "$(Build.ArtifactStagingDirectory)/$(buildArtifactsFolder)"
|
||||
-s "${{ parameters.useRPMsSnapshot }}"'
|
||||
|
||||
- job: RPMs
|
||||
dependsOn: Kernel_modules_packaging
|
||||
templateContext:
|
||||
outputs:
|
||||
- output: pipelineArtifact
|
||||
displayName: 'Publish build artifacts'
|
||||
targetPath: $(Build.ArtifactStagingDirectory)/$(buildArtifactsFolder)
|
||||
artifactName: $(buildArtifactsFolder)_RPMS
|
||||
|
||||
steps:
|
||||
- task: DownloadPipelineArtifact@2
|
||||
displayName: 'Download RPMs and SRPMs archives'
|
||||
inputs:
|
||||
source: current
|
||||
artifact: '$(buildArtifactsFolder)_KERNEL_MODULES_PACKAGING'
|
||||
patterns: '**/*rpms.tar.gz'
|
||||
path: '$(System.ArtifactsDirectory)'
|
||||
|
||||
- bash: |
|
||||
sleep 1
|
||||
displayName: 'Signing placeholder'
|
||||
find "$(System.ArtifactsDirectory)" -name '*rpms.tar.gz' -exec tar -C "$(System.ArtifactsDirectory)" -xf {} \;
|
||||
displayName: 'Expand SRPM/RPM tarballs'
|
||||
|
||||
# JSON config generated from https://portal.esrp.microsoft.com/Onboarding/JSONGenerator
|
||||
- task: EsrpCodeSigning@2
|
||||
displayName: 'Sign RPMs'
|
||||
inputs:
|
||||
ConnectedServiceName: 'ESRP RPM Signing 1ES PTs'
|
||||
FolderPath: '$(System.ArtifactsDirectory)'
|
||||
Pattern: '*.rpm'
|
||||
signConfigType: inlineSignParams
|
||||
inlineOperation: |
|
||||
[
|
||||
{
|
||||
"KeyCode": "CP-459159-Pgp",
|
||||
"OperationCode": "LinuxSign",
|
||||
"Parameters": {},
|
||||
"ToolName": "sign",
|
||||
"ToolVersion": "1.0"
|
||||
}
|
||||
]
|
||||
|
||||
- task: Bash@3
|
||||
displayName: 'Validate and package signed RPMs'
|
||||
inputs:
|
||||
filePath: 'pipelines/common/scripts/PackageSignedRPMs.sh'
|
||||
arguments: '-a "$(System.ArtifactsDirectory)"
|
||||
-k "$(rpmSigningKeyID)"
|
||||
-o "$(Build.ArtifactStagingDirectory)/$(buildArtifactsFolder)"'
|
||||
|
||||
- stage: Test
|
||||
jobs:
|
||||
|
@ -118,6 +269,7 @@ extends:
|
|||
displayName: 'Test placeholder'
|
||||
|
||||
- stage: Publish
|
||||
condition: ${{ parameters.publishRPMs }}
|
||||
jobs:
|
||||
- job:
|
||||
steps:
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Copyright (c) Microsoft Corporation.
|
||||
# Licensed under the MIT License.
|
||||
|
||||
ROOT_DIR="$(git rev-parse --show-toplevel)"
|
||||
|
||||
# shellcheck source=../common/libs/file_tools.sh
|
||||
source "$ROOT_DIR"/pipelines/common/libs/file_tools.sh
|
||||
|
||||
# shellcheck source=../common/libs/rpm_tools.sh
|
||||
source "$ROOT_DIR"/pipelines/common/libs/rpm_tools.sh
|
||||
|
||||
set -e
|
||||
|
||||
# Script parameters:
|
||||
#
|
||||
# -a -> artifacts directory where the RPMs archive is located.
|
||||
# -o -> output directory where the RPMs will be extracted.
|
||||
while getopts "a:o:" OPTIONS
|
||||
do
|
||||
case "${OPTIONS}" in
|
||||
a ) ARTIFACTS_DIR=$OPTARG ;;
|
||||
o ) OUTPUT_DIR=$OPTARG ;;
|
||||
|
||||
\? )
|
||||
echo "ERROR: Invalid Option: -$OPTARG" 1>&2
|
||||
exit 1
|
||||
;;
|
||||
: )
|
||||
echo "ERROR: Invalid Option: -$OPTARG requires an argument" 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
rpms_archive="$(find_file_fullpath "$ARTIFACTS_DIR" "rpms.tar.gz")"
|
||||
if [[ ! -f "$rpms_archive" ]]
|
||||
then
|
||||
echo "ERROR: No RPMs archive found in '$ARTIFACTS_DIR'." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
TEMP_DIR="$(mktemp -d)"
|
||||
trap temp_dir_cleanup EXIT
|
||||
|
||||
tar -C "$TEMP_DIR" -xf "$rpms_archive"
|
||||
|
||||
rpm_extract_files -f -i "$TEMP_DIR" -p "*.ko" -o "$OUTPUT_DIR" -w "$TEMP_DIR"
|
Загрузка…
Ссылка в новой задаче