mirror of
https://github.com/falcosecurity/falco.git
synced 2025-05-14 10:49:36 +00:00
267 lines
7.6 KiB
Bash
Executable File
267 lines
7.6 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -e
|
|
|
|
usage() {
|
|
echo "usage: $0 -f <package_x86_64.deb> -f <package_aarch64.deb> -r <deb|deb-dev> [-s]"
|
|
exit 1
|
|
}
|
|
|
|
check_program() {
|
|
if ! command -v $1 &> /dev/null
|
|
then
|
|
echo "$1 is required and could not be found"
|
|
exit
|
|
fi
|
|
}
|
|
|
|
# Used to get comma separated list of architectures
|
|
join_arr() {
|
|
local IFS="$1"
|
|
shift
|
|
echo "$*"
|
|
}
|
|
|
|
# Updates the signature of a DEB package in the local repository
|
|
#
|
|
# $1: path of the repository.
|
|
# $2: suite (eg. "stable")
|
|
# $3: path of the DEB file.
|
|
sign_deb() {
|
|
pushd $1/$2 > /dev/null
|
|
rm -f $(basename -- $3).asc
|
|
gpg --detach-sign --digest-algo SHA256 --armor $(basename -- $3)
|
|
popd > /dev/null
|
|
}
|
|
|
|
# Add a package to the local DEB repository
|
|
#
|
|
# $1: path of the repository.
|
|
# $2: suite (eg. "stable")
|
|
# $3: path of the DEB file.
|
|
add_deb() {
|
|
cp -f $3 $1/$2
|
|
sign_deb $1 $2 $3
|
|
|
|
# Get package architecture from dpkg
|
|
local arch=$(dpkg --info $3 | awk '/Architecture/ {printf "%s", $2}')
|
|
# Store architecture in array
|
|
architectures+=("${arch}")
|
|
}
|
|
|
|
falco_arch_from_deb_arch() {
|
|
case "$1" in
|
|
"amd64")
|
|
echo -n "x86_64"
|
|
;;
|
|
"arm64")
|
|
echo -n "aarch64"
|
|
;;
|
|
*)
|
|
echo "Wrong arch."
|
|
exit 1
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# Sign the local DEB repository
|
|
#
|
|
# $1: path of the repository
|
|
# $2: suite (eg. "stable")
|
|
sign_repo() {
|
|
local release_dir=dists/$2
|
|
pushd $1 > /dev/null
|
|
|
|
# release signature - Release.gpg file
|
|
gpg --detach-sign --digest-algo SHA256 --armor ${release_dir}/Release
|
|
rm -f ${release_dir}/Release.gpg
|
|
mv ${release_dir}/Release.asc ${release_dir}/Release.gpg
|
|
|
|
# release signature - InRelease file
|
|
gpg --armor --sign --clearsign --digest-algo SHA256 ${release_dir}/Release
|
|
rm -f ${release_dir}/InRelease
|
|
mv ${release_dir}/Release.asc ${release_dir}/InRelease
|
|
|
|
popd > /dev/null
|
|
}
|
|
|
|
# Update the local DEB repository
|
|
#
|
|
# $1: path of the repository
|
|
# $2: suite (eg. "stable")
|
|
update_repo() {
|
|
local component=main
|
|
local debs_dir=$2
|
|
local release_dir=dists/$2
|
|
|
|
pushd $1 > /dev/null
|
|
|
|
# packages metadata
|
|
for arch in "${architectures[@]}"; do
|
|
local packages_dir=${release_dir}/${component}/binary-${arch}
|
|
mkdir -p ${packages_dir}
|
|
truncate -s 0 ${packages_dir}/Packages
|
|
# Find all ${arch} deb files.
|
|
# Note that debian uses {arm64,amd64}, while
|
|
# Falco packages use {x86_64,aarch64}.
|
|
find ${debs_dir} -name "falco-*-$(falco_arch_from_deb_arch ${arch}).deb" -exec apt-ftparchive packages {} \; >> ${packages_dir}/Packages
|
|
gzip -c ${packages_dir}/Packages > ${packages_dir}/Packages.gz
|
|
bzip2 -z -c ${packages_dir}/Packages > ${packages_dir}/Packages.bz2
|
|
done
|
|
|
|
# release metadata
|
|
apt-ftparchive release \
|
|
-o APT::FTPArchive::Release::Origin=Falco \
|
|
-o APT::FTPArchive::Release::Label=Falco \
|
|
-o APT::FTPArchive::Release::Suite=$2 \
|
|
-o APT::FTPArchive::Release::Codename=$2 \
|
|
-o APT::FTPArchive::Release::Components=${component} \
|
|
-o APT::FTPArchive::Release::Architectures="$(join_arr , "${architectures[@]}")" \
|
|
${release_dir} > ${release_dir}/Release
|
|
|
|
popd > /dev/null
|
|
}
|
|
|
|
reduce_dir_size() {
|
|
local DIR=$1
|
|
local MAX_SIZE_GB=$2
|
|
local EXTENSION=$3
|
|
local MAX_SIZE=$((MAX_SIZE_GB*1024*1024)) # Convert GB to KB for du command
|
|
|
|
# Check if directory exists
|
|
if [[ ! -d "$DIR" ]]; then
|
|
echo "The directory $DIR does not exist."
|
|
return 1
|
|
fi
|
|
|
|
# Calculate current directory size in KB
|
|
local CUR_SIZE=$(du -sk "$DIR" | cut -f1)
|
|
|
|
# Check if we need to delete any files
|
|
if ((CUR_SIZE <= MAX_SIZE)); then
|
|
return 0
|
|
fi
|
|
|
|
# Calculate size to delete in bytes
|
|
local DEL_SIZE=$(( (CUR_SIZE - MAX_SIZE) * 1024 ))
|
|
|
|
local ACC_SIZE=0
|
|
find "$DIR" -maxdepth 1 -type f -name "*.$EXTENSION" -printf "%T+ %s %p\n" | sort | while read -r date size file; do
|
|
if ((ACC_SIZE + size < DEL_SIZE)); then
|
|
rm "$file"
|
|
ACC_SIZE=$((ACC_SIZE + size))
|
|
|
|
local asc_file="$file.asc"
|
|
if [[ -e "$asc_file" ]]; then
|
|
local asc_size=$(stat --format="%s" "$asc_file")
|
|
rm "$asc_file"
|
|
ACC_SIZE=$((ACC_SIZE + asc_size))
|
|
fi
|
|
else
|
|
break
|
|
fi
|
|
done
|
|
}
|
|
|
|
# parse options
|
|
while getopts ":f::r::s" opt; do
|
|
case "${opt}" in
|
|
f )
|
|
files+=("${OPTARG}")
|
|
;;
|
|
r )
|
|
repo="${OPTARG}"
|
|
[[ "${repo}" == "deb" || "${repo}" == "deb-dev" ]] || usage
|
|
;;
|
|
s )
|
|
sign_all="true"
|
|
;;
|
|
: )
|
|
echo "invalid option: ${OPTARG} requires an argument" 1>&2
|
|
exit 1
|
|
;;
|
|
\?)
|
|
echo "invalid option: ${OPTARG}" 1>&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
shift $((OPTIND-1))
|
|
|
|
# check options
|
|
if ([ ${#files[@]} -eq 0 ] && [ -z "${sign_all}" ]) || [ -z "${repo}" ]; then
|
|
usage
|
|
fi
|
|
|
|
# check prerequisites
|
|
check_program apt-ftparchive
|
|
check_program gzip
|
|
check_program bzip2
|
|
check_program gpg
|
|
check_program aws
|
|
check_program dpkg
|
|
|
|
# settings
|
|
debSuite=stable
|
|
s3_bucket_repo="s3://falco-distribution/packages/${repo}"
|
|
cloudfront_path="/packages/${repo}"
|
|
tmp_repo_path=/tmp/falco-$repo
|
|
|
|
# prepare repository local copy
|
|
echo "Fetching ${s3_bucket_repo}..."
|
|
mkdir -p ${tmp_repo_path}
|
|
aws s3 cp ${s3_bucket_repo} ${tmp_repo_path} --recursive
|
|
|
|
# update signatures for all existing packages
|
|
if [ "${sign_all}" ]; then
|
|
for file in ${tmp_repo_path}/${debSuite}/*; do
|
|
if [ -f "$file" ]; then # exclude directories, symlinks, etc...
|
|
if [[ ! $file == *.asc ]]; then # exclude signature files
|
|
package=$(basename -- ${file})
|
|
echo "Signing ${package}..."
|
|
sign_deb ${tmp_repo_path} ${debSuite} ${file}
|
|
|
|
echo "Syncing ${package}.asc to ${s3_bucket_repo}..."
|
|
aws s3 cp ${tmp_repo_path}/${debSuite}/${package}.asc ${s3_bucket_repo}/${debSuite}/${package}.asc --acl public-read
|
|
fi
|
|
fi
|
|
done
|
|
aws cloudfront create-invalidation --distribution-id ${AWS_CLOUDFRONT_DIST_ID} --paths ${cloudfront_path}/${debSuite}/*.asc
|
|
sign_repo ${tmp_repo_path} ${debSuite}
|
|
fi
|
|
|
|
# remove old dev packages if necessary
|
|
if [[ ${repo} == "deb-dev" ]]; then
|
|
reduce_dir_size "${tmp_repo_path}/${debSuite}" 10 deb
|
|
fi
|
|
|
|
# update the repo by adding new packages
|
|
if ! [ ${#files[@]} -eq 0 ]; then
|
|
for file in "${files[@]}"; do
|
|
echo "Adding ${file}..."
|
|
add_deb ${tmp_repo_path} ${debSuite} ${file}
|
|
done
|
|
update_repo ${tmp_repo_path} ${debSuite}
|
|
sign_repo ${tmp_repo_path} ${debSuite}
|
|
|
|
# publish
|
|
for file in "${files[@]}"; do
|
|
package=$(basename -- ${file})
|
|
echo "Publishing ${package} to ${s3_bucket_repo}..."
|
|
aws s3 cp ${tmp_repo_path}/${debSuite}/${package} ${s3_bucket_repo}/${debSuite}/${package} --acl public-read
|
|
aws s3 cp ${tmp_repo_path}/${debSuite}/${package}.asc ${s3_bucket_repo}/${debSuite}/${package}.asc --acl public-read
|
|
|
|
aws cloudfront create-invalidation --distribution-id ${AWS_CLOUDFRONT_DIST_ID} --paths ${cloudfront_path}/${debSuite}/${package}
|
|
aws cloudfront create-invalidation --distribution-id ${AWS_CLOUDFRONT_DIST_ID} --paths ${cloudfront_path}/${debSuite}/${package}.asc
|
|
done
|
|
fi
|
|
|
|
# sync dists
|
|
aws s3 sync ${tmp_repo_path}/dists ${s3_bucket_repo}/dists --delete --acl public-read
|
|
aws cloudfront create-invalidation --distribution-id ${AWS_CLOUDFRONT_DIST_ID} --paths ${cloudfront_path}/dists/*
|
|
|
|
# delete packages that have been pruned
|
|
# the dryrun option is there so we can check that we're doing the right thing, can be removed after testing
|
|
if [[ ${repo} == "deb-dev" ]]; then
|
|
aws s3 sync "${tmp_repo_path}/${debSuite}" ${s3_bucket_repo} --dryrun --delete --acl public-read
|
|
fi
|