Drop 'fetch', add 'pull', support custom gpg binaries via env.

This commit is contained in:
Lance Vick 2023-05-05 18:17:42 -07:00
parent 7164bd6724
commit 03bbbcc350
Signed by: lrvick
GPG Key ID: 8E47A1EC35A1551D
1 changed files with 36 additions and 61 deletions

97
git-sig
View File

@ -6,6 +6,9 @@ readonly MIN_GPG_VERSION=2.2
readonly MIN_OPENSSL_VERSION=1.1 readonly MIN_OPENSSL_VERSION=1.1
readonly MIN_GETOPT_VERSION=2.33 readonly MIN_GETOPT_VERSION=2.33
GIT_SIG_GPG_VERIFY_COMMAND=${GIT_SIG_GPG_VERIFY_COMMAND:-gpg}
GIT_SIG_SIGN_COMMAND=${GIT_SIG_SIGN_COMMAND:-gpg}
## Private Functions ## Private Functions
### Exit with error message ### Exit with error message
@ -97,7 +100,7 @@ check_tools(){
for cmd in "$@"; do for cmd in "$@"; do
command -v "$1" >/dev/null || die "Error: $cmd not found" command -v "$1" >/dev/null || die "Error: $cmd not found"
case $cmd in case $cmd in
gpg) ${GIT_SIG_VERIFY_COMMAND})
version=$(gpg --version | head -n1 | cut -d" " -f3) version=$(gpg --version | head -n1 | cut -d" " -f3)
check_version "gnupg" "${version}" "${MIN_GPG_VERSION}" check_version "gnupg" "${version}" "${MIN_GPG_VERSION}"
;; ;;
@ -116,7 +119,7 @@ check_tools(){
### Get primary UID for a given fingerprint ### Get primary UID for a given fingerprint
get_uid(){ get_uid(){
local -r fp="${1?}" local -r fp="${1?}"
gpg --list-keys --with-colons "${fp}" 2>&1 \ ${GIT_SIG_VERIFY_COMMAND} --list-keys --with-colons "${fp}" 2>&1 \
| awk -F: '$1 == "uid" {print $10}' \ | awk -F: '$1 == "uid" {print $10}' \
| head -n1 | head -n1
} }
@ -124,7 +127,7 @@ get_uid(){
### Get primary fingerprint for given search ### Get primary fingerprint for given search
get_primary_fp(){ get_primary_fp(){
local -r search="${1?}" local -r search="${1?}"
gpg --list-keys --with-colons "${search}" 2>&1 \ ${GIT_SIG_VERIFY_COMMAND} --list-keys --with-colons "${search}" 2>&1 \
| awk -F: '$1 == "fpr" {print $10}' \ | awk -F: '$1 == "fpr" {print $10}' \
| head -n1 | head -n1
} }
@ -132,7 +135,7 @@ get_primary_fp(){
### Get fingerprint for a given pgp file ### Get fingerprint for a given pgp file
get_file_fp(){ get_file_fp(){
local -r filename="${1?}" local -r filename="${1?}"
gpg --list-packets "${filename}" \ ${GIT_SIG_VERIFY_COMMAND} --list-packets "${filename}" \
| grep keyid \ | grep keyid \
| sed 's/.*keyid //g' | sed 's/.*keyid //g'
} }
@ -168,7 +171,7 @@ group_add_fp(){
done done
echo "Adding key \"${fp}\" to group \"${group_name}\"" echo "Adding key \"${fp}\" to group \"${group_name}\""
gpg --list-keys >/dev/null 2>&1 ${GIT_SIG_VERIFY_COMMAND} --list-keys >/dev/null 2>&1
printf 'group:0:%s' "${data%?}" \ printf 'group:0:%s' "${data%?}" \
| gpgconf --change-options gpg >/dev/null 2>&1 | gpgconf --change-options gpg >/dev/null 2>&1
} }
@ -176,7 +179,7 @@ group_add_fp(){
### Get fingerprints for a given group ### Get fingerprints for a given group
group_get_fps(){ group_get_fps(){
local -r group_name=${1?} local -r group_name=${1?}
gpg --with-colons --list-config group \ ${GIT_SIG_VERIFY_COMMAND} --with-colons --list-config group \
| grep -i "^cfg:group:${group_name}:" \ | grep -i "^cfg:group:${group_name}:" \
| cut -d ':' -f4 | cut -d ':' -f4
} }
@ -221,7 +224,7 @@ sig_generate(){
local -r body="sig:$version:$vcs_ref:$tree_hash:$review_hash:$sig_type" local -r body="sig:$version:$vcs_ref:$tree_hash:$review_hash:$sig_type"
local -r signature=$(\ local -r signature=$(\
printf "%s" "$body" \ printf "%s" "$body" \
| gpg \ | ${GIT_SIG_SIGN_COMMAND} \
--detach-sign \ --detach-sign \
--local-user "$key" \ --local-user "$key" \
| openssl base64 -A \ | openssl base64 -A \
@ -286,7 +289,7 @@ verify_git_note(){
return 1; return 1;
} }
gpg_sig_raw="$( gpg_sig_raw="$(
gpg --verify --status-fd=1 \ ${GIT_SIG_VERIFY_COMMAND} --verify --status-fd=1 \
<(printf '%s' "$sig" | openssl base64 -d -A) \ <(printf '%s' "$sig" | openssl base64 -d -A) \
<(printf '%s' "$body") 2>/dev/null \ <(printf '%s' "$body") 2>/dev/null \
)" )"
@ -314,7 +317,13 @@ verify_git_notes(){
verify_git_commit(){ verify_git_commit(){
local -r ref="${1:-HEAD}" local -r ref="${1:-HEAD}"
local gpg_sig_raw local gpg_sig_raw
gpg_sig_raw=$(git verify-commit "$ref" --raw 2>&1) gpg_sig_raw=$( \
git \
-c "gpg.program=$GIT_SIG_VERIFY_COMMAND" \
verify-commit "$ref" \
--raw \
2>&1 \
)
parse_gpg_status "$gpg_sig_raw" parse_gpg_status "$gpg_sig_raw"
} }
@ -340,7 +349,7 @@ verify(){
local -r ref=${3:-HEAD} local -r ref=${3:-HEAD}
local sig_count=0 seen_fps fp commit_sig tag_sigs note_sigs local sig_count=0 seen_fps fp commit_sig tag_sigs note_sigs
git rev-parse --git-dir >/dev/null 2>&1 \ git rev-parse --git-dir >/dev/null 2>&1 \
|| die "Error: This folder is not a git repository" || die "Error: This folder is not a git repository"
if [[ $(git diff --stat) != '' ]]; then if [[ $(git diff --stat) != '' ]]; then
die "Error: git tree is dirty" die "Error: git tree is dirty"
fi fi
@ -468,7 +477,6 @@ cmd_verify() {
--) shift; break ;; --) shift; break ;;
esac done esac done
git fetch "$remote" refs/notes/signatures:refs/notes/signatures
local -r head=$(git rev-parse --short HEAD) local -r head=$(git rev-parse --short HEAD)
if [ -n "$diff" ] && [ -z "$ref" ]; then if [ -n "$diff" ] && [ -z "$ref" ]; then
while read -r commit; do while read -r commit; do
@ -491,49 +499,6 @@ cmd_verify() {
return 1 return 1
} }
cmd_fetch() {
local opts group="" group_fps=""
opts="$(getopt -o g: -l group: -n "$PROGRAM" -- "$@")"
eval set -- "$opts"
while true; do case $1 in
-g|--group) group="${2:-1}"; shift 2 ;;
--) shift; break ;;
esac done
[ $# -eq 1 ] || \
die "Usage: $PROGRAM fetch <fingerprint> [-g,--group=<group>]"
local -r fingerprint=${1}
if [ -n "$group" ]; then
group_fps=$(group_get_fps "${group_name}")
if [[ "${group_fps}" == *"${fingerprint}"* ]]; then
echo "Key \"${fingerprint}\" is already in group \"${group}\""
else
group_add_fp "${fingerprint}" "${group}"
fi
fi
gpg --list-keys "${fingerprint}" > /dev/null 2>&1 \
&& echo "Key \"${fingerprint}\" is already in local keychain" \
&& return 0
echo "Requested key is not in keyring. Trying keyservers..."
for server in \
keys.openpgp.org \
ha.pool.sks-keyservers.net \
hkp://keyserver.ubuntu.com:80 \
hkp://p80.pool.sks-keyservers.net:80 \
pgp.mit.edu \
; do
echo "Fetching key \"${fingerprint}\" from \"${server}\"";
gpg \
--recv-key \
--keyserver "$server" \
--keyserver-options timeout=10 \
--recv-keys "${fingerprint}" \
&& break
done
}
cmd_add(){ cmd_add(){
local opts method="" push="0" local opts method="" push="0"
opts="$(getopt -o m:p:: -l method:,push:: -n "$PROGRAM" -- "$@")" opts="$(getopt -o m:p:: -l method:,push:: -n "$PROGRAM" -- "$@")"
@ -558,17 +523,27 @@ cmd_push() {
-r|--remote) remote="$2"; shift 2 ;; -r|--remote) remote="$2"; shift 2 ;;
--) shift; break ;; --) shift; break ;;
esac done esac done
git fetch "$remote" refs/notes/signatures:refs/notes/signatures
git notes --ref signatures merge -s cat_sort_uniq "${remote}"/signatures
git push --tags "$remote" refs/notes/signatures git push --tags "$remote" refs/notes/signatures
} }
cmd_pull() {
local opts remote="origin"
opts="$(getopt -o r: -l remote: -n "$PROGRAM" -- "$@")"
eval set -- "$opts"
while true; do case $1 in
-r|--remote) remote="$2"; shift 2 ;;
--) shift; break ;;
esac done
git fetch "$remote" refs/notes/signatures:refs/notes/${remote}/signatures
git notes --ref signatures merge -s cat_sort_uniq "${remote}"/signatures
}
cmd_version() { cmd_version() {
cat <<-_EOF cat <<-_EOF
========================================== ==========================================
= git-sig: multisig trust for git = = git-sig: multisig trust for git =
= = = =
= v0.3 = = v0.4 =
= = = =
= https://codeberg.org/distrust/git-sig = = https://codeberg.org/distrust/git-sig =
========================================== ==========================================
@ -587,8 +562,8 @@ cmd_usage() {
Verify m-of-n signatures by given group are present for directory. Verify m-of-n signatures by given group are present for directory.
git sig push [-r,--remote=<remote>] git sig push [-r,--remote=<remote>]
Push all signatures on current ref Push all signatures on current ref
git sig fetch [-g,--group=<group>] git sig pull [-r,--remote=<remote>]
Fetch key by fingerprint. Optionally add to group. Pull all signatures for current ref
git sig help git sig help
Show this text. Show this text.
git sig version git sig version
@ -597,7 +572,7 @@ cmd_usage() {
} }
# Verify all tools in this list are installed at needed versions # Verify all tools in this list are installed at needed versions
check_tools git head cut find sort sed getopt gpg openssl check_tools git head cut find sort sed getopt openssl ${GIT_SIG_VERIFY_COMMAND}
# Allow entire script to be namespaced based on filename # Allow entire script to be namespaced based on filename
readonly PROGRAM="${0##*/}" readonly PROGRAM="${0##*/}"
@ -607,8 +582,8 @@ case "$1" in
verify) shift; cmd_verify "$@" ;; verify) shift; cmd_verify "$@" ;;
add) shift; cmd_add "$@" ;; add) shift; cmd_add "$@" ;;
remove) shift; cmd_remove "$@" ;; remove) shift; cmd_remove "$@" ;;
fetch) shift; cmd_fetch "$@" ;;
push) shift; cmd_push "$@" ;; push) shift; cmd_push "$@" ;;
pull) shift; cmd_pull "$@" ;;
version|--version) shift; cmd_version "$@" ;; version|--version) shift; cmd_version "$@" ;;
help|--help) shift; cmd_usage "$@" ;; help|--help) shift; cmd_usage "$@" ;;
*) cmd_usage "$@" ;; *) cmd_usage "$@" ;;