From 741b0b1fa3df065d72b227933c6af2422806ff94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yann=20B=C3=BCchau?= Date: Mon, 27 Sep 2021 17:08:47 +0200 Subject: [PATCH 1/6] Make ots-git-gpg-wrapper.sh configurable - via `git config opentimestamps.enable` option - via environment variables OPENTIMESTAMPS* --- ots-git-gpg-wrapper.sh | 73 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 72 insertions(+), 1 deletion(-) diff --git a/ots-git-gpg-wrapper.sh b/ots-git-gpg-wrapper.sh index 32668e7..938463d 100755 --- a/ots-git-gpg-wrapper.sh +++ b/ots-git-gpg-wrapper.sh @@ -5,4 +5,75 @@ # Required because git's gpg.program option doesn't allow you to set command # line options; see the doc/git-integration.md -ots-git-gpg-wrapper --gpg-program "`which gpg`" -- "$@" +############################## +### Configuration Examples ### +############################## + +# Disable OpenTimestamps for the current repository: +# +# > git config opentimestamps.enable false +# +# Disable OpenTimestamps by default for all git repositories on this machine: +# +# > git config --global opentimestamps.enable false +# +# Temporarily (re)enable OpenTimestamps signatures in `git log`: +# +# > OPENTIMESTAMPS=true git log --show-signature +# +# Temporarily ignore OpenTimestamps signatures in `git log`: +# +# > OPENTIMESTAMPS=false git log --show-signature +# +# Don't use OpenTimestamps for timestamping for one commit: +# +# > OPENTIMESTAMPS=false git commit -m "commit message" +# +# Debug the OpenTimeStamps process: +# +# > OPENTIMESTAMPS_GIT_GPG_WRAPPER_DEBUG=true OPENTIMESTAMPS_GIT_GPG_WRAPPER_FLAGS='-vvvvv' git log --show-signature + +# defaults +test -n "$GPG" || GPG=gpg +test -n "$OPENTIMESTAMPS_GIT_GPG_WRAPPER_DEBUG" || OPENTIMESTAMPS_GIT_GPG_WRAPPER_DEBUG=false +test -n "$OPENTIMESTAMPS_GIT_GPG_WRAPPER" || OPENTIMESTAMPS_GIT_GPG_WRAPPER=ots-git-gpg-wrapper +test -n "$OPENTIMESTAMPS_GIT_GPG_WRAPPER_FLAGS" || OPENTIMESTAMPS_GIT_GPG_WRAPPER_FLAGS= + +function debug() { if is_true "$OPENTIMESTAMPS_GIT_GPG_WRAPPER_DEBUG";then echo >&2 "ots: $@";fi } + +# config value pattern matching +true_pattern='^(y(es)?|true|enable)$' +false_pattern='^(no?|false|disable)$' +function check_pattern() { echo "$1" | grep -Eiq "$2"; } +function is_true() { if check_pattern "$1" "$false_pattern";then return 1;fi;check_pattern "$1" "$true_pattern"; } +function opentimestamps_enabled() { + if test -n "$OPENTIMESTAMPS";then + if is_true "$OPENTIMESTAMPS";then + debug "Enabling OpenTimestamps due to OPENTIMESTAMPS='$OPENTIMESTAMPS'" + return 0 + else + debug "Disabling OpenTimestamps due to OPENTIMESTAMPS='$OPENTIMESTAMPS'" + return 1 + fi + fi + git_config_opentimestamps_enable="`git config opentimestamps.enable`" + if test -n "$git_config_opentimestamps_enable";then + if is_true "$git_config_opentimestamps_enable";then + debug "Enabling OpenTimestamps due to \`git config opentimestamps.enable\` = '$git_config_opentimestamps_enable'" + return 0 + else + debug "Disabling OpenTimestamps due to \`git config opentimestamps.enable\` = '$git_config_opentimestamps_enable'" + return 1 + fi + fi + debug "Enabling OpenTimestamps as both \`git config opentimestamps.enable\` and OPENTIMESTAMPS are unset" + return 0 +} + +if opentimestamps_enabled;then + debug "executing >>>$OPENTIMESTAMPS_GIT_GPG_WRAPPER $OPENTIMESTAMPS_GIT_GPG_WRAPPER_FLAGS -- $@<<<" + exec $OPENTIMESTAMPS_GIT_GPG_WRAPPER $OPENTIMESTAMPS_GIT_GPG_WRAPPER_FLAGS -- "$@" +else + debug "executing >>>$GPG $@<<<" + exec $GPG "$@" +fi From 50d485836ddf4ae5ac82e65e99ab427d9678691c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yann=20B=C3=BCchau?= Date: Tue, 28 Sep 2021 09:15:21 +0200 Subject: [PATCH 2/6] Let ots-git-gpg-wrapper find gpg, not the wrapper This is more straight-forward than to hard-code /usr/bin/gpg in ots-git-gpg-wrapper and then using `which` in the ots-git-gpg-wrapper.sh to find gpg. --- otsclient/git_gpg_wrapper.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/otsclient/git_gpg_wrapper.py b/otsclient/git_gpg_wrapper.py index 698ec84..871c53b 100644 --- a/otsclient/git_gpg_wrapper.py +++ b/otsclient/git_gpg_wrapper.py @@ -16,6 +16,7 @@ import bitcoin import logging import subprocess +import shutil import git from opentimestamps.core.git import GitTreeTimestamper @@ -30,7 +31,7 @@ def main(): parser = otsclient.args.make_common_options_arg_parser() - parser.add_argument("-g", "--gpg-program", action="store", default="/usr/bin/gpg", + parser.add_argument("-g", "--gpg-program", action="store", default=shutil.which("gpg") or "/usr/bin/gpg", help="Path to the GnuPG binary (default %(default)s)") parser.add_argument('-c','--calendar', metavar='URL', dest='calendar_urls', action='append', type=str, From 116221fac667cd32768454fa91c55cea9b86da52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yann=20B=C3=BCchau?= Date: Tue, 28 Sep 2021 09:41:14 +0200 Subject: [PATCH 3/6] Install ots-git-gpg-wrapper.sh next to ots-git-gpg-wrapper --- setup.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/setup.py b/setup.py index 86c105c..e72b2c6 100644 --- a/setup.py +++ b/setup.py @@ -101,4 +101,7 @@ 'ots-git-gpg-wrapper = otsclient.git_gpg_wrapper:main', ], }, + + # Install the ots-git-gpg-wrapper.sh-script + scripts = ["ots-git-gpg-wrapper.sh"], ) From ff6ef6e78128a6389cad5d0ff7447a3443d29a7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yann=20B=C3=BCchau?= Date: Tue, 28 Sep 2021 09:51:27 +0200 Subject: [PATCH 4/6] Update git integration docs --- doc/git-integration.md | 57 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 53 insertions(+), 4 deletions(-) diff --git a/doc/git-integration.md b/doc/git-integration.md index 401d4da..c7c9b22 100644 --- a/doc/git-integration.md +++ b/doc/git-integration.md @@ -112,10 +112,23 @@ To create and verify these signatures we simply wrap the gpg binary with our own code, `ots-git-gpg-wrapper`. Git allows you to override the default GnuPG binary (`/usr/bin/gpg`) with your own using the `gpg.program` config option. Unfortunately that option doesn't let you set additional command line flags, so -we use one more wrapper, `ots-git-gpg-wrapper.sh`. You can set all this up with the -following: - - git config --global gpg.program +we use one more wrapper, `ots-git-gpg-wrapper.sh`. You can set all this up with +either of the following: + +```bash +# just specify ots-git-gpg-wrapper.sh and let `git` find it itself +git config --global gpg.program ots-git-gpg-wrapper.sh +# manually enter the full path to ots-git-gpg-wrapper.sh +git config --global gpg.program +# auto-detect the full path using `which` +git config --global gpg.program "`which ots-git-gpg-wrapper.sh`" +``` + +> **Note:** If you get errors that it doesn't find the +> `ots-git-gpg-wrapper.sh`, make sure that your `PATH` includes the +> installation location, e.g. by appending `export +> PATH="$PATH:$HOME/.local/bin"` to your `.bashrc`. You can check the +> installation location with `pip show -f opentimestamps-client`. Now try creating a test repository and signing a commit: @@ -347,3 +360,39 @@ calendar servers: gpg: using RSA key 6399011044E8AFB2 gpg: Good signature from "Peter Todd " gpg: aka "[jpeg image of size 5220]" + + +Configuration +------------- + +The OpenTimestamps GPG wrapper can be configured in the following ways: + + +```bash +# Disable OpenTimestamps for the current repository: +git config opentimestamps.enable false + +# Disable OpenTimestamps by default for all git repositories on this machine: +git config --global opentimestamps.enable false + +# Temporarily (re)enable OpenTimestamps signatures in `git log`: +OPENTIMESTAMPS=true git log --show-signature + +# Temporarily ignore OpenTimestamps signatures in `git log`: +OPENTIMESTAMPS=false git log --show-signature + +# Don't use OpenTimestamps for timestamping for one commit: +OPENTIMESTAMPS=false git commit -m "commit message" +``` + +Troubleshooting +--------------- + +You can troubleshoot the OpenTimestamps process like this: + +```bash +# Debug the OpenTimeStamps process +GIT_TRACE=true OPENTIMESTAMPS_GIT_GPG_WRAPPER_DEBUG=true OPENTIMESTAMPS_GIT_GPG_WRAPPER_FLAGS='-vvvvv' git log --show-signature +``` + +This however does not seem to work properly for `git commit` unfortunately. From 31c1bde501d31f7391ffd9e2f669782d7873fc47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yann=20B=C3=BCchau?= Date: Fri, 15 Oct 2021 14:25:58 +0200 Subject: [PATCH 5/6] Introduce git config opentimestamps.{flags,debug} --- doc/git-integration.md | 8 ++++++++ ots-git-gpg-wrapper.sh | 37 +++++++++++++++++++++++++++++++------ 2 files changed, 39 insertions(+), 6 deletions(-) diff --git a/doc/git-integration.md b/doc/git-integration.md index c7c9b22..230c9cf 100644 --- a/doc/git-integration.md +++ b/doc/git-integration.md @@ -383,6 +383,14 @@ OPENTIMESTAMPS=false git log --show-signature # Don't use OpenTimestamps for timestamping for one commit: OPENTIMESTAMPS=false git commit -m "commit message" + +# Only use OpenTimestamps for `git show` and `git commit` (not e.g. `git log`) +git config --global opentimestamps.only-for show,commit + +# Don't try to use a local Bitcoin node for verification. +# This gets rids of error messages in `git show` and `git log` +# when you don't have a Bitcoin node running. +git config --global opentimestamps.flags '--no-bitcoin' ``` Troubleshooting diff --git a/ots-git-gpg-wrapper.sh b/ots-git-gpg-wrapper.sh index 938463d..c250c23 100755 --- a/ots-git-gpg-wrapper.sh +++ b/ots-git-gpg-wrapper.sh @@ -29,15 +29,24 @@ # # > OPENTIMESTAMPS=false git commit -m "commit message" # -# Debug the OpenTimeStamps process: +# Debug the OpenTimeStamps process for one call: # # > OPENTIMESTAMPS_GIT_GPG_WRAPPER_DEBUG=true OPENTIMESTAMPS_GIT_GPG_WRAPPER_FLAGS='-vvvvv' git log --show-signature +# +# Always debug the OpenTimeStamps process: +# +# > git config --global opentimestamps.debug true +# > git config --global opentimestamps.flags -vvvvvvv +# +# Don't attempt to connect to a local Bitcoin node (e.g. for verification). +# +# > git config --global opentimestamps.flags '--no-bitcoin' # defaults test -n "$GPG" || GPG=gpg -test -n "$OPENTIMESTAMPS_GIT_GPG_WRAPPER_DEBUG" || OPENTIMESTAMPS_GIT_GPG_WRAPPER_DEBUG=false -test -n "$OPENTIMESTAMPS_GIT_GPG_WRAPPER" || OPENTIMESTAMPS_GIT_GPG_WRAPPER=ots-git-gpg-wrapper -test -n "$OPENTIMESTAMPS_GIT_GPG_WRAPPER_FLAGS" || OPENTIMESTAMPS_GIT_GPG_WRAPPER_FLAGS= +test -n "$OPENTIMESTAMPS_GIT_GPG_WRAPPER_DEBUG" || OPENTIMESTAMPS_GIT_GPG_WRAPPER_DEBUG="`git config opentimestamps.debug 2>/dev/null || true`" +test -n "$OPENTIMESTAMPS_GIT_GPG_WRAPPER" || OPENTIMESTAMPS_GIT_GPG_WRAPPER=ots-git-gpg-wrapper +test -n "$OPENTIMESTAMPS_GIT_GPG_WRAPPER_FLAGS" || OPENTIMESTAMPS_GIT_GPG_WRAPPER_FLAGS="`git config opentimestamps.flags 2>/dev/null || true`" function debug() { if is_true "$OPENTIMESTAMPS_GIT_GPG_WRAPPER_DEBUG";then echo >&2 "ots: $@";fi } @@ -46,6 +55,13 @@ true_pattern='^(y(es)?|true|enable)$' false_pattern='^(no?|false|disable)$' function check_pattern() { echo "$1" | grep -Eiq "$2"; } function is_true() { if check_pattern "$1" "$false_pattern";then return 1;fi;check_pattern "$1" "$true_pattern"; } +# This git subcommand-detection fails if there are direct arguments to `git` before the subcommand. +# The full git cmdline should be parsed properly. Instead, we skip the git subcommand check in this case. +git_command="`cat /proc/"$PPID"/cmdline | tr '\0' '\n' | tail -n+2 | head -n1`" +if (echo "$git_command" | grep -vx '[a-z]\+');then + debug "Can't determine git command if there are direct options to git, sorry..." + git_command= +fi function opentimestamps_enabled() { if test -n "$OPENTIMESTAMPS";then if is_true "$OPENTIMESTAMPS";then @@ -56,7 +72,16 @@ function opentimestamps_enabled() { return 1 fi fi - git_config_opentimestamps_enable="`git config opentimestamps.enable`" + git_config_opentimestamps_only_for="`git config opentimestamps.only-for 2>/dev/null`" + if test -n "$git_config_opentimestamps_only_for" -a -n "$git_command";then + if (echo "$git_config_opentimestamps_only_for" | grep -o '[a-z]\+' | grep -qFx "$git_command" >/dev/null 2>/dev/null);then + debug "Enabling OpenTimestamps as \`git config opentimestamps.only-for\` = '$git_config_opentimestamps_only_for' contains the current git command '$git_command'" + else + debug "Disabling OpenTimestamps as \`git config opentimestamps.only-for\` = '$git_config_opentimestamps_only_for' doesn't contain the current git command '$git_command'" + return 1 + fi + fi + git_config_opentimestamps_enable="`git config opentimestamps.enable 2>/dev/null`" if test -n "$git_config_opentimestamps_enable";then if is_true "$git_config_opentimestamps_enable";then debug "Enabling OpenTimestamps due to \`git config opentimestamps.enable\` = '$git_config_opentimestamps_enable'" @@ -66,7 +91,7 @@ function opentimestamps_enabled() { return 1 fi fi - debug "Enabling OpenTimestamps as both \`git config opentimestamps.enable\` and OPENTIMESTAMPS are unset" + debug "Enabling OpenTimestamps" return 0 } From 9d34cb1ac79668e84a55bdf0b42681dc34b77c03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yann=20B=C3=BCchau?= Date: Thu, 26 Jan 2023 18:52:02 +0100 Subject: [PATCH 6/6] =?UTF-8?q?=F0=9F=A9=B9=20Fix=20creation=20of=20invali?= =?UTF-8?q?d=20PGP=20signatures=20with=20git=20options?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Options directly passed to git (like `git -c config.bla` or `git --git-dir=...`) caused the first argument to show up before the PGP signature, breaking git {log,show} --show-signature and thus also OTS verification. This was especially annyoing as `git annex sync` or `datalad save` pass options like this to git when committing. With quite some `strace`ing and debugging I was finally able to track down this bug to this missing `-q` to that one grep in the OTS shell wrapper 🤦 It might be a good idea to ditch the shell wrapper and use a proper Python for this. Wouldn't have happened with Python... --- ots-git-gpg-wrapper.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ots-git-gpg-wrapper.sh b/ots-git-gpg-wrapper.sh index c250c23..c38ec28 100755 --- a/ots-git-gpg-wrapper.sh +++ b/ots-git-gpg-wrapper.sh @@ -58,7 +58,7 @@ function is_true() { if check_pattern "$1" "$false_pattern";then return 1;fi;che # This git subcommand-detection fails if there are direct arguments to `git` before the subcommand. # The full git cmdline should be parsed properly. Instead, we skip the git subcommand check in this case. git_command="`cat /proc/"$PPID"/cmdline | tr '\0' '\n' | tail -n+2 | head -n1`" -if (echo "$git_command" | grep -vx '[a-z]\+');then +if (echo "$git_command" | grep -qvx '[a-z]\+');then debug "Can't determine git command if there are direct options to git, sorry..." git_command= fi