Compare commits
2 Commits
main
...
4f911c69d4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4f911c69d4
|
||
|
|
9006f166f7
|
@@ -1,32 +0,0 @@
|
|||||||
name: Validate Trusted Timestamps Actions Demo
|
|
||||||
run-name: ${{ gitea.actor }} is validating the trusted timestamps of all commits 🚀
|
|
||||||
on: [push]
|
|
||||||
|
|
||||||
variables:
|
|
||||||
EXPECTED_TRUSTANCHORS_HASH: "70a1c7e2fc62a0b62e44063f0e730b20b0f209d15c84b310ad06ce616c352829"
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
Validate:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
timeout-minutes: 2
|
|
||||||
steps:
|
|
||||||
- name: Install extra software
|
|
||||||
run: |
|
|
||||||
apt-get update
|
|
||||||
apt-get install -y xxd
|
|
||||||
- name: Check out repository code
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
- name: Setup timestamping authorities
|
|
||||||
run: |
|
|
||||||
git config --local timestamping.tsa0.url https://freetsa.org/tsr
|
|
||||||
bash -c 'yes | ./hooks/trust.sh https://freetsa.org/tsr'
|
|
||||||
git config --local timestamping.tsa1.url https://tsa.cesnet.cz:3162/tsa
|
|
||||||
bash -c 'yes | ./hooks/trust.sh https://tsa.cesnet.cz:3162/tsa'
|
|
||||||
- name: Check hashes of all trustanchors
|
|
||||||
run: |
|
|
||||||
./hooks/validate_trustanchors_hash.sh .git/hoqoks/trustanchors ${{ EXPECTED_TRUSTANCHORS_HASH }}
|
|
||||||
- name: Validate timestamps of all commits
|
|
||||||
run: |
|
|
||||||
./hooks/validate.sh --minversion 0
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -2,17 +2,17 @@
|
|||||||
MIIC5jCCAc4CAQEwDQYJKoZIhvcNAQELBQAwcjELMAkGA1UEBhMCVVMxFTATBgNV
|
MIIC5jCCAc4CAQEwDQYJKoZIhvcNAQELBQAwcjELMAkGA1UEBhMCVVMxFTATBgNV
|
||||||
BAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTExMC8G
|
BAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTExMC8G
|
||||||
A1UEAxMoRGlnaUNlcnQgU0hBMiBBc3N1cmVkIElEIFRpbWVzdGFtcGluZyBDQRcN
|
A1UEAxMoRGlnaUNlcnQgU0hBMiBBc3N1cmVkIElEIFRpbWVzdGFtcGluZyBDQRcN
|
||||||
MjUwMjEyMDUyMjQ1WhcNMjUwMjE5MDUyMjQ1WjCB9TAhAhAL2v0LKRQzmpYSZqw1
|
MjUwMTIyMDUxMzE2WhcNMjUwMTI5MDUxMzE2WjCB9TAhAhAL2v0LKRQzmpYSZqw1
|
||||||
OkdEFw0xNjEwMjQxNzQyNDlaMCECEAH40oMtKRkZcbNQw9u8pQAXDTE2MTExMTE1
|
OkdEFw0xNjEwMjQxNzQyNDlaMCECEAH40oMtKRkZcbNQw9u8pQAXDTE2MTExMTE1
|
||||||
MjEzNFowIQIQClKwbEb16yWgi9U/3Ht4hhcNMTgwOTAzMTIxMTQyWjAhAhAFlx7K
|
MjEzNFowIQIQClKwbEb16yWgi9U/3Ht4hhcNMTgwOTAzMTIxMTQyWjAhAhAFlx7K
|
||||||
SlmJinvPTLfjd5doFw0xOTA5MzAwODE2MjRaMCECEAxFkEkmQLBOlEh/jEwCeJAX
|
SlmJinvPTLfjd5doFw0xOTA5MzAwODE2MjRaMCECEAxFkEkmQLBOlEh/jEwCeJAX
|
||||||
DTIxMDIwOTIyMzk0MlowIQIQBMvnUVSd49EL7YN0yV7iRBcNMjEwMjA5MjMyMzM3
|
DTIxMDIwOTIyMzk0MlowIQIQBMvnUVSd49EL7YN0yV7iRBcNMjEwMjA5MjMyMzM3
|
||||||
WjAhAhALmUrhw5aLANVesgZ0jpseFw0yMTAyMDkyMzI0MjNaoDAwLjAfBgNVHSME
|
WjAhAhALmUrhw5aLANVesgZ0jpseFw0yMTAyMDkyMzI0MjNaoDAwLjAfBgNVHSME
|
||||||
GDAWgBT0tuEgHf4prtLkYaWyoiWyyBc1bjALBgNVHRQEBAICDO8wDQYJKoZIhvcN
|
GDAWgBT0tuEgHf4prtLkYaWyoiWyyBc1bjALBgNVHRQEBAICDNowDQYJKoZIhvcN
|
||||||
AQELBQADggEBALr4VopJYkMfQ97HiyqytcWRY/vgyU/LxOwlH0/1DBSeeObQB0Nj
|
AQELBQADggEBAFxgvuHLyxJ88doIv2nQk02kaURi2IaTraKX+pknGhW6f2v9foSX
|
||||||
uF7vcF2bhbpnxba7gvzOPryudwtbqquf2cl3CJG6MC2D8Nk1XzntDnpxCjVSfsAr
|
Ywhx/fyfqpA0eChER6jAReMQil1t+5RLmVU8QGG77wz83TBclMpcNxQNINV7JKVh
|
||||||
158zAWPevyiuj3yzFz04mYALt/ZmOJMTF0vyKN8cg5bwfLu3itV6b6vhpuloIhRc
|
rqyCemrNrTW+RKgVO/EL02fqRTf9f3mSbSLEo07dI88BYTY1YXtnkrbcwxq1ARPp
|
||||||
Hmsbgr3BtCVHkf4vJWq/qKDEMcOhSrJ6wxGCzVyphenewSIbVcogj19cRZDFPWOC
|
kCAAoGRHWqxQ9hIKrOhWWnGzG43Vghmo0E8l2xJut+3zyLv16/WBFBgxtTWSK3xI
|
||||||
3sAy/GY3Rz0qK30tDvNbE1uum8gy5ijXFmepJ/lEetRCvrIsxTsXJOj0tqVZfIIQ
|
SNSsTcZaQY286Akco+sNnss6JuzG7Lm0/0Hv6zjVJys6qYDZsPP+G6hc1RTAI6w2
|
||||||
E1YWUZ57TiBBrdS+dTgmRxkN/zaAfYVAIck=
|
MEzWgX64tLBdo3L33ZJbVoBhg6mX/euck04=
|
||||||
-----END X509 CRL-----
|
-----END X509 CRL-----
|
||||||
|
|||||||
0
hooks/post-commit
Executable file → Normal file
0
hooks/post-commit
Executable file → Normal file
2
hooks/timestamping
Executable file → Normal file
2
hooks/timestamping
Executable file → Normal file
@@ -553,7 +553,7 @@ download_crls_for_chain() {
|
|||||||
local URL=$(openssl x509 -inform PEM -in $EXTRACTED_CERT -text -noout \
|
local URL=$(openssl x509 -inform PEM -in $EXTRACTED_CERT -text -noout \
|
||||||
| awk '/CRL Distribution Points:/{f=1} f && /URI:/ {print; exit}' \
|
| awk '/CRL Distribution Points:/{f=1} f && /URI:/ {print; exit}' \
|
||||||
| sed 's/^.*URI://1')
|
| sed 's/^.*URI://1')
|
||||||
if curl -L "$URL" --output "$CRL_TMP" &> "$OUT_STREAM"; then
|
if curl "$URL" --output "$CRL_TMP" &> "$OUT_STREAM"; then
|
||||||
if openssl crl -in "$CRL_TMP" -inform DER -noout &> "$OUT_STREAM"; then
|
if openssl crl -in "$CRL_TMP" -inform DER -noout &> "$OUT_STREAM"; then
|
||||||
openssl crl -in "$CRL_TMP" -inform DER >> "$OUTPUT_FILE"
|
openssl crl -in "$CRL_TMP" -inform DER >> "$OUTPUT_FILE"
|
||||||
elif openssl crl -in "$CRL_TMP" -inform PEM -noout &> "$OUT_STREAM"; then
|
elif openssl crl -in "$CRL_TMP" -inform PEM -noout &> "$OUT_STREAM"; then
|
||||||
|
|||||||
0
hooks/trust.sh
Executable file → Normal file
0
hooks/trust.sh
Executable file → Normal file
121
hooks/validate.sh
Executable file → Normal file
121
hooks/validate.sh
Executable file → Normal file
@@ -42,12 +42,8 @@ if [[ ! -d "$DIR" ]]; then DIR="$PWD"; fi
|
|||||||
. "$DIR/timestamping"
|
. "$DIR/timestamping"
|
||||||
|
|
||||||
declare -i MINVERSION=$TIMESTAMPING_VERSION
|
declare -i MINVERSION=$TIMESTAMPING_VERSION
|
||||||
declare -i MAX_COMMITS_TO_CHECK=0
|
|
||||||
declare -A PROCESSED_COMMIT
|
|
||||||
declare -A COMMITS
|
|
||||||
declare -A COMMIT_TIMES
|
|
||||||
|
|
||||||
while [[ $# -gt 0 ]]; do
|
while [[ $# -gt 1 ]]; do
|
||||||
KEY="$1"
|
KEY="$1"
|
||||||
|
|
||||||
case $KEY in
|
case $KEY in
|
||||||
@@ -65,27 +61,17 @@ while [[ $# -gt 0 ]]; do
|
|||||||
shift # past argument
|
shift # past argument
|
||||||
shift # past value
|
shift # past value
|
||||||
;;
|
;;
|
||||||
-max|--maxcommits)
|
|
||||||
INTEGER_REGEX='^[0-9]+$'
|
|
||||||
if ! [[ "$2" =~ $INTEGER_REGEX ]]; then
|
|
||||||
echo_error "$KEY: expected positive integer"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
MAX_COMMITS_TO_CHECK="$2"
|
|
||||||
shift # past argument
|
|
||||||
shift # past value
|
|
||||||
;;
|
|
||||||
-v|--verbose)
|
-v|--verbose)
|
||||||
OUT_STREAM=/dev/stdout
|
OUT_STREAM=/dev/stdout
|
||||||
shift # past argument
|
shift # past argument
|
||||||
;;
|
;;
|
||||||
*) # unknown option
|
*) # unknown option
|
||||||
OBJECT=$KEY
|
echo_error "Unknown argument: $KEY"
|
||||||
shift # past argument
|
exit 1
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
OBJECT="$1"
|
||||||
if [ -z "$OBJECT" ]; then
|
if [ -z "$OBJECT" ]; then
|
||||||
OBJECT="HEAD"
|
OBJECT="HEAD"
|
||||||
fi
|
fi
|
||||||
@@ -103,10 +89,6 @@ fi
|
|||||||
# tokens, the function will return 0 but echo a warning about the invalid token.
|
# tokens, the function will return 0 but echo a warning about the invalid token.
|
||||||
validate_commit() {
|
validate_commit() {
|
||||||
local COMMIT_HASH="$1"
|
local COMMIT_HASH="$1"
|
||||||
if [[ ${PROCESSED_COMMIT[$COMMIT_HASH]} ]]; then
|
|
||||||
log "validate_commit for $COMMIT_HASH has already been validated"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
log "validate_commit for $COMMIT_HASH"
|
log "validate_commit for $COMMIT_HASH"
|
||||||
|
|
||||||
local TIMESTAMP_COMMIT_VERSION
|
local TIMESTAMP_COMMIT_VERSION
|
||||||
@@ -293,11 +275,9 @@ validate_commit() {
|
|||||||
#assert that all extracted timestamps have been processed
|
#assert that all extracted timestamps have been processed
|
||||||
assert "[ $NUM_PROCESSED -eq $NUM_EXTRACTED ]" "All extracted token must be processed."
|
assert "[ $NUM_PROCESSED -eq $NUM_EXTRACTED ]" "All extracted token must be processed."
|
||||||
|
|
||||||
PROCESSED_COMMIT[$COMMIT_HASH]=1
|
|
||||||
|
|
||||||
if [ $NUM_VALID -gt 0 ]; then
|
if [ $NUM_VALID -gt 0 ]; then
|
||||||
if [ $NUM_INVALID -gt 0 ]; then
|
if [ $NUM_INVALID -gt 0 ]; then
|
||||||
echo_warning "Warning: While commit $COMMIT_HASH contains $NUM_VALID valid timestamp tokens and thus is considered properly timestamped, it also contains $NUM_INVALID invalid timestamp tokens."
|
echo_warning "Warning: While commit $COMMIT_HASH contains $NUM_VALID valid timestamp tokens and thus is considered proppely timestamped, it also contains $NUM_INVALID invalid timestamp tokens."
|
||||||
fi
|
fi
|
||||||
DATE_STRING=$(date -d @"$EARLIEST_VALID_UNIX_TIME")
|
DATE_STRING=$(date -d @"$EARLIEST_VALID_UNIX_TIME")
|
||||||
echo_info "Commit $COMMIT_HASH, which timestamps commit $PARENT_HASH at $DATE_STRING, contains $NUM_VALID valid timestamp tokens."
|
echo_info "Commit $COMMIT_HASH, which timestamps commit $PARENT_HASH at $DATE_STRING, contains $NUM_VALID valid timestamp tokens."
|
||||||
@@ -313,13 +293,6 @@ validate_commit() {
|
|||||||
# param1: commit hash
|
# param1: commit hash
|
||||||
# returns: 0 if the validation of the commit and all its ancestors succeeded
|
# returns: 0 if the validation of the commit and all its ancestors succeeded
|
||||||
validate_commit_and_parents() {
|
validate_commit_and_parents() {
|
||||||
# If MAX_COMMITS_TO_CHECK is zero (or a negative number) then that is understood as "infinity".
|
|
||||||
# So finish if we have reached the limit, and if the limit is not "infinity".
|
|
||||||
NUM_COMMITS_CHECKED=${#PROCESSED_COMMIT[@]}
|
|
||||||
if [[ ${NUM_COMMITS_CHECKED} -ge ${MAX_COMMITS_TO_CHECK} ]] && [[ ${MAX_COMMITS_TO_CHECK} -ge 1 ]]; then
|
|
||||||
# enough commits have already been checked, so return early
|
|
||||||
return 0;
|
|
||||||
fi
|
|
||||||
local COMMIT_HASH="$1"
|
local COMMIT_HASH="$1"
|
||||||
log "validate_commit_and_parents for $COMMIT_HASH"
|
log "validate_commit_and_parents for $COMMIT_HASH"
|
||||||
|
|
||||||
@@ -327,7 +300,6 @@ validate_commit_and_parents() {
|
|||||||
if ! validate_commit "$COMMIT_HASH"; then
|
if ! validate_commit "$COMMIT_HASH"; then
|
||||||
ALL_PASSED=false
|
ALL_PASSED=false
|
||||||
fi
|
fi
|
||||||
NUM_COMMITS_CHECKED=${#PROCESSED_COMMIT[@]}
|
|
||||||
local PARENTS=$(git cat-file -p "$COMMIT_HASH" | awk '/^$/{exit} /parent/ {print}' | sed 's/parent //')
|
local PARENTS=$(git cat-file -p "$COMMIT_HASH" | awk '/^$/{exit} /parent/ {print}' | sed 's/parent //')
|
||||||
#iterate over all parents of commit
|
#iterate over all parents of commit
|
||||||
if [ ! -z "$PARENTS" ]; then
|
if [ ! -z "$PARENTS" ]; then
|
||||||
@@ -337,65 +309,7 @@ validate_commit_and_parents() {
|
|||||||
fi
|
fi
|
||||||
done <<< $(printf "%s" "$PARENTS")
|
done <<< $(printf "%s" "$PARENTS")
|
||||||
fi
|
fi
|
||||||
if [ "$ALL_PASSED" = true ]; then
|
if [ "$ALL_PASSED"=true ]; then
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
# Recursive function to find all ancestors of commit
|
|
||||||
# param1: commit hash
|
|
||||||
# creates an array COMMITS, key is the commit hash, value is the commit time (Unix epoch seconds)
|
|
||||||
# the array contains all commits found in all paths from the passed-in commit hash back to the root commit of the repo
|
|
||||||
# the array is global so it can be accessed after the function returns
|
|
||||||
find_all_commits() {
|
|
||||||
local COMMIT_HASH="$1"
|
|
||||||
log "find_all_commits for $COMMIT_HASH"
|
|
||||||
# git show "ct" format returns the commit time as Unix epoch seconds
|
|
||||||
COMMIT_TIME=$(git show --no-patch --format=%ct "$COMMIT_HASH")
|
|
||||||
COMMITS[$COMMIT_HASH]="${COMMIT_TIME}"
|
|
||||||
|
|
||||||
local PARENTS=$(git cat-file -p "$COMMIT_HASH" | awk '/^$/{exit} /parent/ {print}' | sed 's/parent //')
|
|
||||||
# iterate over all parents of commit
|
|
||||||
if [ ! -z "$PARENTS" ]; then
|
|
||||||
while read PARENT_HASH; do
|
|
||||||
if [[ ${COMMITS[$PARENT_HASH]} ]]; then
|
|
||||||
log "commit $PARENT_HASH has already been processed"
|
|
||||||
else
|
|
||||||
find_all_commits "$PARENT_HASH"
|
|
||||||
fi
|
|
||||||
done <<< $(printf "%s" "$PARENTS")
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# Validate the commits in the COMMITS array, up to MAX_COMMITS_TO_CHECK
|
|
||||||
# returns: 0 if the validation of the commits succeeded
|
|
||||||
validate_commits() {
|
|
||||||
ALL_PASSED=true
|
|
||||||
# create an associative array with keys using the Unix epoch commit time and value the commit hash
|
|
||||||
# this array can be easily used to sort in (forward or reverse) order of time
|
|
||||||
for HASH in "${!COMMITS[@]}"; do
|
|
||||||
UNIX_EPOCH_TIME="${COMMITS[$HASH]}"
|
|
||||||
# two commits could have the exact same Unix epoch in seconds
|
|
||||||
# so make that unique by appending an "x" and the hash
|
|
||||||
UNIQUE_KEY="${UNIX_EPOCH_TIME}x${HASH}"
|
|
||||||
COMMIT_TIMES[$UNIQUE_KEY]="${HASH}"
|
|
||||||
done
|
|
||||||
# sort into reverse order
|
|
||||||
SORTED_KEYS=($(printf "%s\n" "${!COMMIT_TIMES[@]}" | sort -r))
|
|
||||||
# process the commits from latest time to oldest time
|
|
||||||
ALL_PASSED=true
|
|
||||||
for ENTRY in "${SORTED_KEYS[@]}"; do
|
|
||||||
COMMIT_HASH=${COMMIT_TIMES[${ENTRY}]}
|
|
||||||
log "${ENTRY} has value ${COMMIT_HASH}"
|
|
||||||
NUM_COMMITS_CHECKED=${#PROCESSED_COMMIT[@]}
|
|
||||||
if [[ ${NUM_COMMITS_CHECKED} -lt ${MAX_COMMITS_TO_CHECK} ]]; then
|
|
||||||
if ! validate_commit "$COMMIT_HASH"; then
|
|
||||||
ALL_PASSED=false
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
if [ "$ALL_PASSED" = true ]; then
|
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
return 1
|
return 1
|
||||||
@@ -412,21 +326,10 @@ echo ""
|
|||||||
|
|
||||||
echo_info "Validating timestamps. This may take a while..."
|
echo_info "Validating timestamps. This may take a while..."
|
||||||
echo ""
|
echo ""
|
||||||
if [[ ${MAX_COMMITS_TO_CHECK} -ge 1 ]]; then
|
if validate_commit_and_parents "$COMMIT_HASH"; then
|
||||||
find_all_commits "$COMMIT_HASH"
|
echo_success "Validation OK: All timestamped commits in the commit history of $COMMIT_HASH contain at least one valid timestamp."
|
||||||
if validate_commits; then
|
exit 0
|
||||||
echo_success "Validation OK: ${NUM_COMMITS_CHECKED} timestamped commits in the commit history of $COMMIT_HASH contain at least one valid timestamp."
|
|
||||||
exit 0
|
|
||||||
else
|
|
||||||
echo_error "Validation Failed: There are timestamped commits in the commit history of $COMMIT_HASH which do not contain any valid timestamps."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
else
|
else
|
||||||
if validate_commit_and_parents "$COMMIT_HASH"; then
|
echo_error "Validation Failed: There are timestamped commits in the commit history of $COMMIT_HASH which do not contain any valid timestamps."
|
||||||
echo_success "Validation OK: All timestamped commits in the commit history of $COMMIT_HASH contain at least one valid timestamp."
|
exit 1
|
||||||
exit 0
|
fi
|
||||||
else
|
|
||||||
echo_error "Validation Failed: There are timestamped commits in the commit history of $COMMIT_HASH which do not contain any valid timestamps."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
Reference in New Issue
Block a user