feat(signature): Checksum signature verification (#1670)

* feat(signature): Checksum signature verification

Signed-off-by: Shubham Hibare <shubham@hibare.in>
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* Update message

Signed-off-by: Shubham Hibare <shubham@hibare.in>
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* address comments

Signed-off-by: Shubham Hibare <shubham@hibare.in>
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* consider -v flag across supported releases

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* add tests for install.sh signature verification

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* check that release is run from main

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* summarize install.sh flags and recommendations

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* remove regex use on cosign verify-blob

Co-authored-by: Dominique Martinet <asmadeus@codewreck.org>
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* simplify the compare_semver install function

Co-authored-by: Dominique Martinet <asmadeus@codewreck.org>
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* add more tests to compare_semver

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* nit copy change for install help

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* keep original compare_semver implementation

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* update copy to include default install path

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

---------

Signed-off-by: Shubham Hibare <shubham@hibare.in>
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
Co-authored-by: Alex Goodman <wagoodman@users.noreply.github.com>
Co-authored-by: Dominique Martinet <asmadeus@codewreck.org>
This commit is contained in:
Shubham Hibare 2024-06-07 02:53:04 +05:30 committed by GitHub
parent e5b341b87a
commit 17b104771a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 459 additions and 73 deletions

View file

@ -14,6 +14,16 @@ jobs:
environment: release
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 #v4.1.1
- name: Check if running on main
if: github.ref != 'refs/heads/main'
# we are using the following flag when running `cosign blob-verify` for checksum signature verification:
# --certificate-identity-regexp "https://github.com/anchore/.github/workflows/release.yaml@refs/heads/main"
# if we are not on the main branch, the signature will not be verifiable since the suffix requires the main branch
# at the time of when the OIDC token was issued on the Github Actions runner.
run: echo "This can only be run on the main branch otherwise releases produced will not be verifiable with cosign" && exit 1
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 #v4.1.6
- name: Check if pinned syft is a release version

View file

@ -177,6 +177,9 @@ jobs:
needs: [Build-Snapshot-Artifacts]
runs-on: macos-latest
steps:
- name: Install Cosign
uses: sigstore/cosign-installer@v3.5.0
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 #v4.1.6
- name: Download snapshot build

View file

@ -60,12 +60,10 @@ If you encounter an issue, please [let us know using the issue tracker](https://
```bash
curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | sh -s -- -b /usr/local/bin
```
You can also choose another destination directory and release version for the installation. The destination directory doesn't need to be `/usr/local/bin`, it just needs to be a location found in the user's PATH and writable by the user that's installing Grype.
```
curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | sh -s -- -b <DESTINATION_DIR> <RELEASE_VERSION>
```
Install script options:
- `-b`: Specify a custom installation directory (defaults to `./bin`)
- `-d`: More verbose logging levels (`-d` for debug, `-dd` for trace)
- `-v`: Verify the signature of the downloaded artifact before installation (requires [`cosign`](https://github.com/sigstore/cosign) to be installed)
### Chocolatey

View file

@ -2,34 +2,26 @@
# note: we require errors to propagate (don't set -e)
set -u
PROJECT_NAME="grype"
PROJECT_NAME=grype
OWNER=anchore
REPO="${PROJECT_NAME}"
GITHUB_DOWNLOAD_PREFIX=https://github.com/${OWNER}/${REPO}/releases/download
INSTALL_SH_BASE_URL=https://raw.githubusercontent.com/${OWNER}/${PROJECT_NAME}
PROGRAM_ARGS=$@
# signature verification options
# the location to the cosign binary (allowed to be overridden by the user)
COSIGN_BINARY=${COSIGN_BINARY:-cosign}
VERIFY_SIGN=false
# this is the earliest tag in the repo where cosign sign-blob was introduced in the release process (see the goreleaser config)
VERIFY_SIGN_SUPPORTED_VERSION=v0.72.0
# this is the earliest tag in the repo where the -v flag was introduced to this install.sh script
VERIFY_SIGN_FLAG_VERSION=v0.79.0
# do not change the name of this parameter (this must always be backwards compatible)
DOWNLOAD_TAG_INSTALL_SCRIPT=${DOWNLOAD_TAG_INSTALL_SCRIPT:-true}
#
# usage [script-name]
#
usage() (
this=$1
cat <<EOF
$this: download go binaries for anchore/syft
Usage: $this [-b] dir [-d] [tag]
-b the installation directory (dDefaults to ./bin)
-d turns on debug logging
-dd turns on trace logging
[tag] the specific release to use (if missing, then the latest will be used)
EOF
exit 2
)
# ------------------------------------------------------------------------
# https://github.com/client9/shlib - portable posix shell functions
# Public domain - http://unlicense.org
@ -270,21 +262,21 @@ hash_sha256() (
)
hash_sha256_verify() (
TARGET=$1
target=$1
checksums=$2
if [ -z "$checksums" ]; then
log_err "hash_sha256_verify checksum file not specified in arg2"
log_err "hash_sha256_verify checksum file not specified as argument"
return 1
fi
BASENAME=${TARGET##*/}
want=$(grep "${BASENAME}" "${checksums}" 2>/dev/null | tr '\t' ' ' | cut -d ' ' -f 1)
target_basename=${target##*/}
want=$(grep "${target_basename}" "${checksums}" 2>/dev/null | tr '\t' ' ' | cut -d ' ' -f 1)
if [ -z "$want" ]; then
log_err "hash_sha256_verify unable to find checksum for '${TARGET}' in '${checksums}'"
log_err "hash_sha256_verify unable to find checksum for '${target}' in '${checksums}'"
return 1
fi
got=$(hash_sha256 "$TARGET")
got=$(hash_sha256 "$target")
if [ "$want" != "$got" ]; then
log_err "hash_sha256_verify checksum for '$TARGET' did not verify ${want} vs $got"
log_err "hash_sha256_verify checksum for '$target' did not verify ${want} vs $got"
return 1
fi
)
@ -358,28 +350,69 @@ github_release_tag() (
echo "$tag"
)
# github_release_asset_url [release-url-prefix] [name] [version] [output-dir] [filename]
#
# outputs the url to the release asset
#
github_release_asset_url() (
download_url="$1"
name="$2"
version="$3"
filename="$4"
complete_filename="${name}_${version}_${filename}"
complete_url="${download_url}/${complete_filename}"
echo "${complete_url}"
)
# download_github_release_checksums_files [release-url-prefix] [name] [version] [output-dir] [filename]
#
# outputs path to the downloaded checksums related file
#
download_github_release_checksums_files() (
download_url="$1"
name="$2"
version="$3"
output_dir="$4"
filename="$5"
log_trace "download_github_release_checksums_files(url=${download_url}, name=${name}, version=${version}, output_dir=${output_dir}, filename=${filename})"
complete_filename="${name}_${version}_${filename}"
complete_url=$(github_release_asset_url "${download_url}" "${name}" "${version}" "${filename}")
output_path="${output_dir}/${complete_filename}"
http_download "${output_path}" "${complete_url}" ""
asset_file_exists "${output_path}"
log_trace "download_github_release_checksums_files() returned '${output_path}' for file '${complete_filename}'"
echo "${output_path}"
)
# download_github_release_checksums [release-url-prefix] [name] [version] [output-dir]
#
# outputs path to the downloaded checksums file
#
download_github_release_checksums() (
download_url="$1"
name="$2"
version="$3"
output_dir="$4"
download_github_release_checksums_files "$@" "checksums.txt"
)
log_trace "download_github_release_checksums(url=${download_url}, name=${name}, version=${version}, output_dir=${output_dir})"
# github_release_checksums_sig_url [release-url-prefix] [name] [version]
#
# outputs the url to the release checksums signature file
#
github_release_checksums_sig_url() (
github_release_asset_url "$@" "checksums.txt.sig"
)
checksum_filename=${name}_${version}_checksums.txt
checksum_url=${download_url}/${checksum_filename}
output_path="${output_dir}/${checksum_filename}"
http_download "${output_path}" "${checksum_url}" ""
asset_file_exists "${output_path}"
log_trace "download_github_release_checksums() returned '${output_path}'"
echo "${output_path}"
# github_release_checksums_cert_url [release-url-prefix] [name] [version]
#
# outputs the url to the release checksums certificate file
#
github_release_checksums_cert_url() (
github_release_asset_url "$@" "checksums.txt.pem"
)
# search_for_asset [checksums-file-path] [name] [os] [arch] [format]
@ -535,7 +568,10 @@ download_and_install_asset() (
format="$8"
binary="$9"
asset_filepath=$(download_asset "${download_url}" "${download_path}" "${name}" "${os}" "${arch}" "${version}" "${format}")
if ! asset_filepath=$(download_asset "${download_url}" "${download_path}" "${name}" "${os}" "${arch}" "${version}" "${format}"); then
log_err "could not download asset for os='${os}' arch='${arch}' format='${format}'"
return 1
fi
# don't continue if we couldn't download an asset
if [ -z "${asset_filepath}" ]; then
@ -546,6 +582,36 @@ download_and_install_asset() (
install_asset "${asset_filepath}" "${install_path}" "${binary}"
)
# verify_sign [checksums-file-path] [certificate-reference] [signature-reference] [version]
#
# attempts verify the signature of the checksums file from the release workflow in Github Actions run against the main branch.
#
verify_sign() {
checksums_file=$1
cert_reference=$2
sig_reference=$3
log_trace "verifying artifact $1"
log_file=$(mktemp)
${COSIGN_BINARY} \
verify-blob "$checksums_file" \
--certificate "$cert_reference" \
--signature "$sig_reference" \
--certificate-identity "https://github.com/${OWNER}/${REPO}/.github/workflows/release.yaml@refs/heads/main" \
--certificate-oidc-issuer "https://token.actions.githubusercontent.com" > "${log_file}" 2>&1
if [ $? -ne 0 ]; then
log_err "$(cat "${log_file}")"
rm -f "${log_file}"
return 1
fi
rm -f "${log_file}"
}
# download_asset [release-url-prefix] [download-path] [name] [os] [arch] [version] [format] [binary]
#
# outputs the path to the downloaded asset asset_filepath
@ -572,6 +638,20 @@ download_asset() (
return 1
fi
if [ "$VERIFY_SIGN" = true ]; then
checksum_sig_file_url=$(github_release_checksums_sig_url "${download_url}" "${name}" "${version}")
log_trace "checksums signature url: ${checksum_sig_file_url}"
checksums_cert_file_url=$(github_release_checksums_cert_url "${download_url}" "${name}" "${version}")
log_trace "checksums certificate url: ${checksums_cert_file_url}"
if ! verify_sign "${checksums_filepath}" "${checksums_cert_file_url}" "${checksum_sig_file_url}"; then
log_err "signature verification failed"
return 1
fi
log_info "signature verification succeeded"
fi
asset_url="${download_url}/${asset_filename}"
asset_filepath="${destination}/${asset_filename}"
http_download "${asset_filepath}" "${asset_url}" ""
@ -609,6 +689,79 @@ install_asset() (
install "${archive_dir}/${binary}" "${destination}/"
)
# compare two semver strings. Returns 0 if version1 >= version2, 1 otherwise.
# Note: pre-release (-) and metadata (+) are not supported.
compare_semver() {
# remove leading 'v' if present
version1=${1#v}
version2=${2#v}
IFS=. read -r major1 minor1 patch1 <<EOF
$version1
EOF
IFS=. read -r major2 minor2 patch2 <<EOF
$version2
EOF
if [ "$major1" -gt "$major2" ]; then
return 0
elif [ "$major1" -lt "$major2" ]; then
return 1
fi
if [ "$minor1" -gt "$minor2" ]; then
return 0
elif [ "$minor1" -lt "$minor2" ]; then
return 1
fi
if [ "$patch1" -gt "$patch2" ]; then
return 0
elif [ "$patch1" -lt "$patch2" ]; then
return 1
fi
# versions are equal
return 0
}
prep_signature_verification() {
version="$1"
if [ "$VERIFY_SIGN" != true ]; then
return 0
fi
# is there any cryptographic material produced at release that we can use for signature verification?
if ! compare_semver "$version" "$VERIFY_SIGN_SUPPORTED_VERSION"; then
log_err "${PROJECT_NAME} release '$version' does not support signature verification"
log_err "you can still install ${PROJECT_NAME} by removing the -v flag or using a release that supports signature verification (>= '$VERIFY_SIGN_SUPPORTED_VERSION')"
log_err "aborting installation"
return 1
else
log_trace "${PROJECT_NAME} release '$version' supports signature verification (>= '$VERIFY_SIGN_SUPPORTED_VERSION')"
fi
# will invoking an earlier version of this script work (considering the -v flag)?
if ! compare_semver "$version" "$VERIFY_SIGN_FLAG_VERSION"; then
# the -v argument did not always exist, so we cannot be guaranteed that invoking an earlier version of this script
# will work (error with "illegal option -v"). However, the user requested signature verification, so we will
# attempt to install the application with this version of the script (keeping signature verification).
DOWNLOAD_TAG_INSTALL_SCRIPT=false
log_debug "provided version install script does not support -v flag (>= '$VERIFY_SIGN_FLAG_VERSION'), using current script for installation"
else
log_trace "provided version install script supports -v flag (>= '$VERIFY_SIGN_FLAG_VERSION')"
fi
# check to see if the cosign binary is installed
if is_command "${COSIGN_BINARY}"; then
log_trace "${COSIGN_BINARY} binary is installed"
else
log_err "signature verification is requested but ${COSIGN_BINARY} binary is not installed (see https://docs.sigstore.dev/system_config/installation/ to install it)"
return 1
fi
}
main() (
# parse arguments
@ -616,7 +769,7 @@ main() (
install_dir=${install_dir:-./bin}
# note: never change the program flags or arguments (this must always be backwards compatible)
while getopts "b:dh?x" arg; do
while getopts "b:dvh?x" arg; do
case "$arg" in
b) install_dir="$OPTARG" ;;
d)
@ -628,11 +781,25 @@ main() (
log_set_priority $log_trace_priority
fi
;;
h | \?) usage "$0" ;;
v) VERIFY_SIGN=true;;
h | \?)
cat <<EOF
Download and install a released binary for ${OWNER}/${REPO} from the github releases page
Usage: $0 [-v] [-b DIR] [-d] [TAG]
-b DIR the installation directory (defaults to ./bin)
-d turns on debug logging
-dd turns on trace logging
-v verify checksum signature (requires cosign binary to be installed).
TAG the specific release to use (if missing, then the latest will be used)
EOF
exit 0
;;
x) set -x ;;
esac
done
shift $((OPTIND - 1))
set +u
tag=$1
@ -644,9 +811,7 @@ main() (
fi
set -u
tag=$(get_release_tag "${OWNER}" "${REPO}" "${tag}")
if [ "$?" != "0" ]; then
if ! tag=$(get_release_tag "${OWNER}" "${REPO}" "${tag}"); then
log_err "unable to find tag='${tag}'"
log_err "do not specify a version or select a valid version from https://github.com/${OWNER}/${REPO}/releases"
return 1
@ -661,6 +826,10 @@ main() (
binary=$(get_binary_name "${os}" "${arch}" "${PROJECT_NAME}")
download_url="${GITHUB_DOWNLOAD_PREFIX}/${tag}"
if ! prep_signature_verification "$version"; then
return 1
fi
# we always use the install.sh script that is associated with the tagged release. Why? the latest install.sh is not
# guaranteed to be able to install every version of the application. We use the DOWNLOAD_TAG_INSTALL_SCRIPT env var
# to indicate if we should continue processing with the existing script or to download the script from the given tag.
@ -678,10 +847,8 @@ main() (
log_debug "downloading files into ${download_dir}"
download_and_install_asset "${download_url}" "${download_dir}" "${install_dir}" "${PROJECT_NAME}" "${os}" "${arch}" "${version}" "${format}" "${binary}"
# don't continue if we couldn't install the asset
if [ "$?" != "0" ]; then
if ! download_and_install_asset "${download_url}" "${download_dir}" "${install_dir}" "${PROJECT_NAME}" "${os}" "${arch}" "${version}" "${format}" "${binary}"; then
log_err "failed to install ${PROJECT_NAME}"
return 1
fi

View file

@ -38,3 +38,48 @@ test_search_for_asset_snapshot() {
}
run_test_case test_search_for_asset_snapshot
# verify 256 digest of a file
test_hash_sha256() {
target=./test-fixtures/assets/valid/grype_0.78.0_linux_arm64.tar.gz
# hash_sha256 [target]
# positive case
actual=$(hash_sha256 "${target}")
assertEquals "8d57abb57a0dae3ff23c8f0df1f51951b7772822e0d560e860d6f68c24ef6d3d" "${actual}" "mismatched checksum"
}
run_test_case test_hash_sha256
# verify 256 digest of a file relative to the checksums file
test_hash_sha256_verify() {
# hash_sha256_verify [target] [checksums]
# positive case
checksums=./test-fixtures/assets/valid/checksums.txt
target=./test-fixtures/assets/valid/grype_0.78.0_linux_arm64.tar.gz
hash_sha256_verify "${target}" "${checksums}"
assertEquals "0" "$?" "mismatched checksum"
# negative case
# we are expecting error messages, which is confusing to look at in passing tests... disable logging for now
log_set_priority -1
checksums=./test-fixtures/assets/invalid/checksums.txt
target=./test-fixtures/assets/invalid/grype_0.78.0_linux_arm64.tar.gz
hash_sha256_verify "${target}" "${checksums}"
assertEquals "1" "$?" "verification did not catch mismatched checksum"
# restore logging...
log_set_priority 0
}
run_test_case test_hash_sha256_verify

View file

@ -31,6 +31,10 @@ test_download_release_asset() {
release=$(get_release_tag "${OWNER}" "${REPO}" "latest" )
# exercise all possible assets against a real github release (based on asset listing from https://github.com/anchore/grype/releases/tag/v0.32.0)
# verify all downloads against the checksums file + checksums file signature
VERIFY_SIGN=true
run_test_case test_download_release_asset "${release}" "darwin" "amd64" "tar.gz" "application/gzip"
run_test_case test_download_release_asset "${release}" "darwin" "arm64" "tar.gz" "application/gzip"
run_test_case test_download_release_asset "${release}" "linux" "amd64" "tar.gz" "application/gzip"

View file

@ -0,0 +1,89 @@
. test_harness.sh
test_compare_semver() {
# compare_semver [version1] [version2]
# positive cases (version1 >= version2)
compare_semver "0.32.0" "0.32.0"
assertEquals "0" "$?" "+ versions should equal"
compare_semver "0.32.1" "0.32.0"
assertEquals "0" "$?" "+ patch version should be greater"
compare_semver "0.33.0" "0.32.0"
assertEquals "0" "$?" "+ minor version should be greater"
compare_semver "0.333.0" "0.32.0"
assertEquals "0" "$?" "+ minor version should be greater (different length)"
compare_semver "00.33.00" "0.032.0"
assertEquals "0" "$?" "+ minor version should be greater (different length reversed)"
compare_semver "1.0.0" "0.9.9"
assertEquals "0" "$?" "+ major version should be greater"
compare_semver "v1.0.0" "1.0.0"
assertEquals "0" "$?" "+ can remove leading 'v' from version"
# negative cases (version1 < version2)
compare_semver "0.32.0" "0.32.1"
assertEquals "1" "$?" "- patch version should be less"
compare_semver "0.32.7" "0.33.0"
assertEquals "1" "$?" "- minor version should be less"
compare_semver "00.00032.070" "0.33.0"
assertEquals "1" "$?" "- minor version should be less (different length)"
compare_semver "0.32.7" "00.0033.000"
assertEquals "1" "$?" "- minor version should be less (different length reversed)"
compare_semver "1.9.9" "2.0.1"
assertEquals "1" "$?" "- major version should be less"
compare_semver "1.0.0" "v2.0.0"
assertEquals "1" "$?" "- can remove leading 'v' from version"
}
run_test_case test_compare_semver
# ensure that various signature verification pre-requisites are correctly checked for
test_prep_signature_verification() {
# prep_sign_verification [version]
# we are expecting error messages, which is confusing to look at in passing tests... disable logging for now
log_set_priority -1
# backup original values...
OG_COSIGN_BINARY=${COSIGN_BINARY}
# check the verification path...
VERIFY_SIGN=true
# release does not support signature verification
prep_signature_verification "0.71.0"
assertEquals "1" "$?" "release does not support signature verification"
# check that the COSIGN binary exists
COSIGN_BINARY=fake-cosign-that-doesnt-exist
prep_signature_verification "0.80.0"
assertEquals "1" "$?" "cosign binary verification failed"
# restore original values...
COSIGN_BINARY=${OG_COSIGN_BINARY}
# ignore any failing conditions since we are not verifying the signature
VERIFY_SIGN=false
prep_signature_verification "0.71.0"
assertEquals "0" "$?" "release support verification should not have been triggered"
COSIGN_BINARY=fake-cosign-that-doesnt-exist
prep_signature_verification "0.80.0"
assertEquals "0" "$?" "cosign binary verification should not have been triggered"
# restore original values...
COSIGN_BINARY=${OG_COSIGN_BINARY}
# restore logging...
log_set_priority 0
}
run_test_case test_prep_signature_verification

View file

@ -1,18 +1,22 @@
NAME=grype
# for local testing (not testing within containers) use the binny-managed version of cosign.
# this also means that the user does not need to install cosign on their system to run tests.
COSIGN_BINARY=../../.tool/cosign
IMAGE_NAME=$(NAME)-install.sh-env
UBUNTU_IMAGE=$(IMAGE_NAME):ubuntu-20.04
ALPINE_IMAGE=$(IMAGE_NAME):alpine-3.6
BUSYBOX_IMAGE=busybox:1.36.1-musl
BUSYBOX_IMAGE=$(IMAGE_NAME):busybox-1.36
ENVS=./environments
DOCKER_RUN=docker run --rm -t -w /project/test/install -v $(shell pwd)/../../:/project
UNIT=make unit-local
UNIT=make unit-run
# acceptance testing is running the current install.sh against the latest release. Note: this could be a problem down
# the line if there are breaking changes made that don't align with the latest release (but will be OK with the next
# release)
ACCEPTANCE_CMD=sh -c '../../install.sh -b /usr/local/bin && grype version'
# release). This tests both installing with signature verification and without.
ACCEPTANCE_CMD=sh -c '../../install.sh -v -b /usr/local/bin && grype version && rm /usr/local/bin/grype && ../../install.sh -b /usr/local/bin && grype version'
# we also want to test against a previous release to ensure that install.sh defers execution to a former install.sh
# this version should be at least as recent as when grype was publishing for darwin arm64 as that is what the github runner uses for osx validation
PREVIOUS_RELEASE=v0.60.0
@ -29,17 +33,22 @@ endef
test: unit acceptance
.PHONY: ci-test-mac
ci-test-mac: unit-local acceptance-local
ci-test-mac: unit-run acceptance-local
# note: do not add acceptance-local to this list
.PHONY: acceptance
acceptance: acceptance-ubuntu-20.04 acceptance-alpine-3.6 acceptance-busybox
acceptance: acceptance-ubuntu-20.04 acceptance-alpine-3.6 acceptance-busybox-1.36
.PHONY: unit
unit: unit-ubuntu-20.04
.PHONY: unit-local
unit-local:
$(call title,unit tests)
@for f in $(shell ls *_test.sh); do echo "Running unit test suite '$${f}'"; bash -c "COSIGN_BINARY=$(COSIGN_BINARY) ./$${f}" || exit 1; done
.PHONY: unit-run
unit-run:
$(call title,unit tests)
@for f in $(shell ls *_test.sh); do echo "Running unit test suite '$${f}'"; bash $${f} || exit 1; done
@ -56,7 +65,7 @@ acceptance-previous-release-local:
grype version | grep $(shell echo $(PREVIOUS_RELEASE)| tr -d "v")
.PHONY: save
save: ubuntu-20.04 alpine-3.6 pull-busybox
save: ubuntu-20.04 alpine-3.6 busybox-1.36
@mkdir cache || true
docker image save -o cache/ubuntu-env.tar $(UBUNTU_IMAGE)
docker image save -o cache/alpine-env.tar $(ALPINE_IMAGE)
@ -108,17 +117,17 @@ alpine-3.6:
# note: busybox by default will not have cacerts, so you will get TLS warnings (we want to test under these conditions)
.PHONY: acceptance-busybox
acceptance-busybox: pull-busybox
$(call title,busybox - acceptance)
.PHONY: acceptance-busybox-1.36
acceptance-busybox-1.36: busybox-1.36
$(call title,busybox-1.36 - acceptance)
$(DOCKER_RUN) $(BUSYBOX_IMAGE) \
$(ACCEPTANCE_CMD)
@echo "\n*** test note: you should see grype spit out a 'x509: certificate signed by unknown authority' error --this is expected ***"
.PHONY: pull-busybox
pull-busybox:
$(call title,busybox - build environment)
docker pull $(BUSYBOX_IMAGE)
.PHONY: busybox-1.36
busybox-1.36:
$(call title,busybox-1.36 - build environment)
docker build -t $(BUSYBOX_IMAGE) -f $(ENVS)/Dockerfile-busybox-1.36 .
## For CI ########################################################

View file

@ -1,2 +1,5 @@
FROM alpine:3.6@sha256:66790a2b79e1ea3e1dabac43990c54aca5d1ddf268d9a5a0285e4167c8b24475
RUN apk update && apk add python3 wget unzip make ca-certificates
FROM alpine:3.6
RUN apk update && apk add python3 wget curl unzip make ca-certificates
RUN curl -O -L "https://github.com/sigstore/cosign/releases/latest/download/cosign-linux-amd64" && \
mv cosign-linux-amd64 /usr/local/bin/cosign && \
chmod +x /usr/local/bin/cosign

View file

@ -0,0 +1,21 @@
FROM alpine as certs
RUN apk update && apk add ca-certificates
# note: using qemu with a multi-arch image results in redirects not working with wget
# so let docker pull the image that matches the hosts architecture first and then pull the correct asset
FROM busybox:1.36.1-musl
RUN ARCH=$(uname -m) && \
if [ "$ARCH" = "x86_64" ]; then \
COSIGN_ARCH="amd64"; \
elif [ "$ARCH" = "aarch64" ]; then \
COSIGN_ARCH="arm64"; \
else \
echo "Unsupported architecture: $ARCH" && exit 1; \
fi && \
echo "Downloading cosign for $COSIGN_ARCH" && \
wget https://github.com/sigstore/cosign/releases/latest/download/cosign-linux-${COSIGN_ARCH} && \
mv cosign-linux-${COSIGN_ARCH} /bin/cosign && \
chmod +x /bin/cosign
COPY --from=certs /etc/ssl/certs /etc/ssl/certs

View file

@ -1,2 +1,5 @@
FROM ubuntu:20.04@sha256:33a5cc25d22c45900796a1aca487ad7a7cb09f09ea00b779e3b2026b4fc2faba
FROM --platform=linux/amd64 ubuntu:20.04@sha256:33a5cc25d22c45900796a1aca487ad7a7cb09f09ea00b779e3b2026b4fc2faba
RUN apt update -y && apt install make python3 curl unzip -y
RUN LATEST_VERSION=$(curl https://api.github.com/repos/sigstore/cosign/releases/latest | grep tag_name | cut -d : -f2 | tr -d "v\", ") && \
curl -O -L "https://github.com/sigstore/cosign/releases/latest/download/cosign_${LATEST_VERSION}_amd64.deb" && \
dpkg -i cosign_${LATEST_VERSION}_amd64.deb

View file

@ -0,0 +1 @@
!grype_0.78.0_linux_arm64.tar.gz

View file

@ -0,0 +1,15 @@
cb4f335e106532b927dac14d4857b7be2333ec1b8bd2aea82be3f9112bb2728f grype_0.78.0_darwin_amd64.tar.gz
51249ee801b41272218252af2c72a644a7ef037b0b27d7b0eae3b55361e82cf6 grype_0.78.0_darwin_arm64.tar.gz
cc3cf4fcc856898fcd05ba2b8590de06e380b958fea5957b0a3e4eff5e8aeeaf grype_0.78.0_linux_amd64.deb
3a9af0f08d1aaf15853f8292be0aa896639e09328416a50d5deaefef894bab61 grype_0.78.0_linux_amd64.rpm
6037fd3763b6112302b98db559bb5390fbb06f0011c0585a4be03ca851daa838 grype_0.78.0_linux_amd64.tar.gz
0f2e3e07be5b5eb08637ac9071f4b0f95f8b4c7c7ea66592852ca82fea4adb93 grype_0.78.0_linux_arm64.deb
89a7f68676a18eb9dc0b706036dacbfb8b78833ed0950b8c6fa63ac159b93781 grype_0.78.0_linux_arm64.rpm
0d560e860d6f68cf23c8f0df1f5124ef6d3d8d57abb57a0dae3f951b7772822e grype_0.78.0_linux_arm64.tar.gz
7b22795114e27c3d147998edc9e803988d7c987cad2623d7fb1d7bf730b4e176 grype_0.78.0_linux_ppc64le.deb
91813ac66ad2ef761ce9629eb4213988de594abd4cab9148a85d71bfa80f6699 grype_0.78.0_linux_ppc64le.rpm
cb923a08fb9f367410190675f187b6aa5a04c1d538f055700c89c8350b826dcb grype_0.78.0_linux_ppc64le.tar.gz
4beb9d31d61df6212c3f996fc8f33239520eeea083dbe70b0969f23739d44dd1 grype_0.78.0_linux_s390x.deb
28f723777b1a136d2fadbdca0ae5e7e9b26f9bd08114095dbd2898def7e8b0b6 grype_0.78.0_linux_s390x.rpm
6c3e7e54ce40aa33ca5fc774c3be664fb910a99aa77b1e5e3cee77156e8399f4 grype_0.78.0_linux_s390x.tar.gz
31ca5d02a75dbb8f3361ac9836a2384013a67a7d9e2e437cb80e4ddfbd4c7812 grype_0.78.0_windows_amd64.zip

View file

@ -0,0 +1 @@
fake archive

View file

@ -0,0 +1 @@
!grype_0.78.0_linux_arm64.tar.gz

View file

@ -0,0 +1,15 @@
cb4f335e106532b927dac14d4857b7be2333ec1b8bd2aea82be3f9112bb2728f grype_0.78.0_darwin_amd64.tar.gz
51249ee801b41272218252af2c72a644a7ef037b0b27d7b0eae3b55361e82cf6 grype_0.78.0_darwin_arm64.tar.gz
cc3cf4fcc856898fcd05ba2b8590de06e380b958fea5957b0a3e4eff5e8aeeaf grype_0.78.0_linux_amd64.deb
3a9af0f08d1aaf15853f8292be0aa896639e09328416a50d5deaefef894bab61 grype_0.78.0_linux_amd64.rpm
6037fd3763b6112302b98db559bb5390fbb06f0011c0585a4be03ca851daa838 grype_0.78.0_linux_amd64.tar.gz
0f2e3e07be5b5eb08637ac9071f4b0f95f8b4c7c7ea66592852ca82fea4adb93 grype_0.78.0_linux_arm64.deb
89a7f68676a18eb9dc0b706036dacbfb8b78833ed0950b8c6fa63ac159b93781 grype_0.78.0_linux_arm64.rpm
8d57abb57a0dae3ff23c8f0df1f51951b7772822e0d560e860d6f68c24ef6d3d grype_0.78.0_linux_arm64.tar.gz
7b22795114e27c3d147998edc9e803988d7c987cad2623d7fb1d7bf730b4e176 grype_0.78.0_linux_ppc64le.deb
91813ac66ad2ef761ce9629eb4213988de594abd4cab9148a85d71bfa80f6699 grype_0.78.0_linux_ppc64le.rpm
cb923a08fb9f367410190675f187b6aa5a04c1d538f055700c89c8350b826dcb grype_0.78.0_linux_ppc64le.tar.gz
4beb9d31d61df6212c3f996fc8f33239520eeea083dbe70b0969f23739d44dd1 grype_0.78.0_linux_s390x.deb
28f723777b1a136d2fadbdca0ae5e7e9b26f9bd08114095dbd2898def7e8b0b6 grype_0.78.0_linux_s390x.rpm
6c3e7e54ce40aa33ca5fc774c3be664fb910a99aa77b1e5e3cee77156e8399f4 grype_0.78.0_linux_s390x.tar.gz
31ca5d02a75dbb8f3361ac9836a2384013a67a7d9e2e437cb80e4ddfbd4c7812 grype_0.78.0_windows_amd64.zip

View file

@ -0,0 +1 @@
fake archive