Git hooks to automatically timestamp commits using RFC3161 and RFC5816 tokens
This commit is contained in:
131
hooks/post-commit
Normal file
131
hooks/post-commit
Normal file
@@ -0,0 +1,131 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# RFC3161 and RFC5816 Timestamping for git repositories.
|
||||
#
|
||||
# Copyright (c) 2020 Mabulous GmbH
|
||||
# Authors: Matthias Bühlmann
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
#
|
||||
# The interactive user interfaces in modified source and object code versions
|
||||
# of this program must display Appropriate Legal Notices, as required under
|
||||
# Section 5 of the GNU Affero General Public License version 3.
|
||||
#
|
||||
# You can be released from the requirements of the license by purchasing
|
||||
# a commercial license. Buying such a license is mandatory as soon as you
|
||||
# develop commercial activities involving this software without
|
||||
# disclosing the source code of your own applications.
|
||||
# These activities include: offering paid services to customers as an ASP,
|
||||
# providing data storage and archival services, shipping this software with a
|
||||
# closed source product.
|
||||
#
|
||||
# For more information, please contact Mabulous GmbH at this
|
||||
# address: info@mabulous.com
|
||||
#
|
||||
|
||||
DIR="${BASH_SOURCE%/*}"
|
||||
if [[ ! -d "$DIR" ]]; then DIR="$PWD"; fi
|
||||
. "$DIR/timestamping"
|
||||
|
||||
extended_exit_trap() {
|
||||
local EXIT_CODE="$?"
|
||||
if [ "$EXIT_CODE" -gt 0 ]; then
|
||||
echo_error "Aborting commit."
|
||||
git reset --soft HEAD^
|
||||
fi
|
||||
rm -rf -- "$TMP_DIR"
|
||||
exit "$EXIT_CODE"
|
||||
}
|
||||
trap "extended_exit_trap" EXIT
|
||||
|
||||
COMMIT_MSG=$(git show --pretty=format:"%B" --no-patch HEAD)
|
||||
|
||||
#avoid recursion and validate timestamp
|
||||
if [[ "$COMMIT_MSG" == "$SUBJECT_LINE"* ]]; then
|
||||
log "exiting recursion"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo_info "Adding Timestamp commit"
|
||||
|
||||
#prepare commit message
|
||||
COMMIT_MSG_FILE="$TMP_DIR"/commit_msg.txt
|
||||
echo "$SUBJECT_LINE" > "$COMMIT_MSG_FILE"
|
||||
|
||||
#get hash of unstamped commit
|
||||
DIGEST=$(git rev-parse --verify HEAD)
|
||||
#request a timestamp token for each TSA defined
|
||||
TSA_IDX=-1
|
||||
while : ; do
|
||||
((TSA_IDX++))
|
||||
TSA_URL=$(git config timestamping.tsa"$TSA_IDX".url)
|
||||
if [ -z "$TSA_URL" ]; then
|
||||
if [ "$TSA_IDX" -eq 0 ]; then
|
||||
echo_error "Error: no TSA url set. Define at least an url for TSA0 using git config timestamp.tsa0.url ... to set TSA URL".
|
||||
exit 1
|
||||
else
|
||||
break
|
||||
fi
|
||||
fi
|
||||
echo_info "for TSA $TSA_URL"
|
||||
TOKEN_OPTIONAL=$(git config --type=bool timestamping.tsa"$TSA_IDX".optional)
|
||||
#retrieve token
|
||||
TOKEN_FILE="$TMP_DIR"/token.tst
|
||||
if ! request_token "$TSA_URL" "$DIGEST" false "$TOKEN_FILE"; then
|
||||
if [ ! "$TOKEN_OPTIONAL" ]; then
|
||||
echo_error "Error: Retrieving timestamp token for critical TSA$TSA_IDX failed."
|
||||
exit 1
|
||||
else
|
||||
echo_warning "Warning: Retrieving timestamp token for optional TSA$TSA_IDX failed. Token won't be added."
|
||||
continue
|
||||
fi
|
||||
fi
|
||||
#validate token and download LTV data
|
||||
if ! verify_token_and_add_ltv_data "$TOKEN_FILE" "$DIGEST" "$TSA_URL"; then
|
||||
if [ ! "$TOKEN_OPTIONAL" ]; then
|
||||
echo_error "Error: Validating timestamp token for critical TSA$TSA_IDX failed."
|
||||
exit 1
|
||||
else
|
||||
echo_warning "Warning: Validating timestamp token for optional TSA$TSA_IDX failed. Token won't be added."
|
||||
continue
|
||||
fi
|
||||
fi
|
||||
#add token to commit message
|
||||
openssl ts -reply -token_in -in "$TOKEN_FILE" -token_out -text -out "$TMP_DIR"/token.txt &> "$OUT_STREAM"
|
||||
TOKENBASE64=$(openssl base64 -in "$TOKEN_FILE")
|
||||
TOKENTEXT=$(cat "$TMP_DIR"/token.txt)
|
||||
INFO="Info: Token digest is hash of parent commit."
|
||||
TRAILER_VALUE="$TSA_URL"$'\n'"$INFO"$'\n\n'"$TOKENTEXT"$'\n\n'"$TOKEN_HEADER"$'\n'"$TOKENBASE64"$'\n'"$TOKEN_FOOTER"
|
||||
#fold
|
||||
TRAILER_VALUE=$(echo -n "$TRAILER_VALUE" | sed -e 's/^/ /')
|
||||
git interpret-trailers --where end --if-exists addIfDifferent --no-divider --trailer "Timestamp:$TRAILER_VALUE" --in-place "$COMMIT_MSG_FILE"
|
||||
done
|
||||
|
||||
#add all ltv files
|
||||
if [ ! -d "$LTV_DIR"/certs ]; then
|
||||
mkdir -p "$LTV_DIR"/certs
|
||||
fi
|
||||
if [ ! -d "$LTV_DIR"/crls ]; then
|
||||
mkdir -p "$LTV_DIR"/crls
|
||||
fi
|
||||
ls "$TMP_LTV_DIR"/*/* | while read SOURCE_FILE; do
|
||||
TARGET_FILE="$LTV_DIR"${SOURCE_FILE#"$TMP_LTV_DIR"}
|
||||
mv -f "$SOURCE_FILE" "$TARGET_FILE"
|
||||
git add "$TARGET_FILE"
|
||||
done
|
||||
|
||||
git commit --allow-empty --quiet -F "$COMMIT_MSG_FILE"
|
||||
|
||||
echo_info "Timestamping complete"
|
||||
exit 0
|
||||
Reference in New Issue
Block a user