Skip to content

Commit

Permalink
feat(signature): Checksum signature verification
Browse files Browse the repository at this point in the history
Signed-off-by: Shubham Hibare <[email protected]>
  • Loading branch information
hibare committed Jan 21, 2024
1 parent 90fa3f2 commit 18b3a20
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 10 deletions.
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,13 @@ You can also choose another destination directory and release version for the in
curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | sh -s -- -b <DESTINATION_DIR> <RELEASE_VERSION>
```

#### Signature verification

To verify artifact signature before installation, pass `-v` flag to script execution as follow:
```bash
curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | sh -s -- -b /usr/local/bin -v
```

### Homebrew

```bash
Expand Down
84 changes: 74 additions & 10 deletions install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ 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=$@
COSIGN_BINARY=cosign
VERIFY_SIGN=false
CERT_FORMAT=pem
SIG_FORMAT=sig

# do not change the name of this parameter (this must always be backwards compatible)
DOWNLOAD_TAG_INSTALL_SCRIPT=${DOWNLOAD_TAG_INSTALL_SCRIPT:-true}
Expand All @@ -24,6 +28,7 @@ Usage: $this [-b] dir [-d] [tag]
-b the installation directory (dDefaults to ./bin)
-d turns on debug logging
-dd turns on trace logging
-v verify checksum signature. Require cosign binary to be installed.
[tag] the specific release to use (if missing, then the latest will be used)
EOF
exit 2
Expand Down Expand Up @@ -358,30 +363,55 @@ github_release_tag() (
echo "$tag"
)

# download_github_release_checksums [release-url-prefix] [name] [version] [output-dir]
# download_github_release_checksums_files [release-url-prefix] [name] [version] [output-dir] [filename]
#
# outputs path to the downloaded checksums file
# outputs path to the downloaded checksums related file
#
download_github_release_checksums() (
download_github_release_checksums_files() (
download_url="$1"
name="$2"
version="$3"
output_dir="$4"
filename="$5"

log_trace "download_github_release_checksums(url=${download_url}, name=${name}, version=${version}, output_dir=${output_dir})"
log_trace "download_github_release_checksums_files(url=${download_url}, name=${name}, version=${version}, output_dir=${output_dir}, filename=${filename})"

checksum_filename=${name}_${version}_checksums.txt
checksum_url=${download_url}/${checksum_filename}
output_path="${output_dir}/${checksum_filename}"
complete_filename="${name}_${version}_${filename}"
complete_url="${download_url}/${complete_filename}"
output_path="${output_dir}/${complete_filename}"

http_download "${output_path}" "${checksum_url}" ""
http_download "${output_path}" "${complete_url}" ""
asset_file_exists "${output_path}"

log_trace "download_github_release_checksums() returned '${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() (
echo "$(download_github_release_checksums_files "$@" "checksums.txt")"
)

# download_github_release_checksums_sig [release-url-prefix] [name] [version] [output-dir]
#
# outputs path to the downloaded checksums signature file
#
download_github_release_checksums_sig() (
echo "$(download_github_release_checksums_files "$@" "checksums.txt.sig")"
)

# download_github_release_checksums_cert [release-url-prefix] [name] [version] [output-dir]
#
# outputs path to the downloaded checksums certificate file
#
download_github_release_checksums_cert() (
echo "$(download_github_release_checksums_files "$@" "checksums.txt.pem")"
)

# search_for_asset [checksums-file-path] [name] [os] [arch] [format]
#
# outputs name of the asset to download
Expand Down Expand Up @@ -546,6 +576,16 @@ download_and_install_asset() (
install_asset "${asset_filepath}" "${install_path}" "${binary}"
)

verify_sign() {
log_trace "Verifying artifact $1"
${COSIGN_BINARY} verify-blob "$1" \
--certificate "$2" \
--signature "$3" \
--certificate-identity-regexp "https://github\.com/${OWNER}/${REPO}/\.github/workflows/.+" \
--certificate-oidc-issuer "https://token.actions.githubusercontent.com"
}


# download_asset [release-url-prefix] [download-path] [name] [os] [arch] [version] [format] [binary]
#
# outputs the path to the downloaded asset asset_filepath
Expand All @@ -572,6 +612,29 @@ download_asset() (
return 1
fi

if [ "$VERIFY_SIGN" = true ]; then
log_trace "checking for ${COSIGN_BINARY} binary"
if is_command "${COSIGN_BINARY}"; then
log_trace "${COSIGN_BINARY} binary is installed"
else
log_err "${COSIGN_BINARY} binary is not installed. Follow steps from https://docs.sigstore.dev/system_config/installation/ to install it."
return 1
fi

checksum_sig_file_path=$(download_github_release_checksums_sig "${download_url}" "${name}" "${version}" "${destination}")
log_info "downloaded checksums signature file: ${checksum_sig_file_path}"

checksums_cert_file_path=$(download_github_release_checksums_cert "${download_url}" "${name}" "${version}" "${destination}")
log_info "downloaded checksums certificate file: ${checksums_cert_file_path}"

verify_sign "${checksums_filepath}" "${checksums_cert_file_path}" "${checksum_sig_file_path}"
if [ $? -ne 0 ]; then
log_err "checksum signature verification failed"
return 1
fi
log_info "checksum signature verification succeeded"
fi

asset_url="${download_url}/${asset_filename}"
asset_filepath="${destination}/${asset_filename}"
http_download "${asset_filepath}" "${asset_url}" ""
Expand Down Expand Up @@ -616,7 +679,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)
Expand All @@ -628,6 +691,7 @@ main() (
log_set_priority $log_trace_priority
fi
;;
v) VERIFY_SIGN=true;;
h | \?) usage "$0" ;;
x) set -x ;;
esac
Expand Down

0 comments on commit 18b3a20

Please sign in to comment.