diff --git a/README.rst b/README.rst index f830278..bbeeeb2 100644 --- a/README.rst +++ b/README.rst @@ -182,6 +182,10 @@ Each of these options must appear first on the command line. optionally provide the path to an ini file. +``--update_hook`` + This option can be used as part of a server side update hook by adding + `git-secrets --update_hook -- "$@"` to an update script on a git server + Options for ``--install`` ~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/git-secrets b/git-secrets index 09f18e8..5198b1e 100755 --- a/git-secrets +++ b/git-secrets @@ -38,6 +38,7 @@ f,force --install overwrites hooks if the hook already exists l,literal --add and --add-allowed patterns are escaped so that they are literal a,allowed --add adds an allowed pattern instead of a prohibited pattern global Uses the --global git config +update_hook* update hook (internal only) commit_msg_hook* commit-msg hook (internal only) pre_commit_hook* pre-commit hook (internal only) prepare_commit_msg_hook* prepare-commit-msg hook (internal only)" @@ -61,11 +62,17 @@ load_patterns() { } load_allowed() { + local new_rev="$1" git config --get-all secrets.allowed local gitallowed="$(git rev-parse --show-toplevel)/.gitallowed" if [ -e "$gitallowed" ]; then cat $gitallowed | awk 'NF && $1!~/^#/' fi + if [ -n "${new_rev}" ]; then + git show ${new_rev}:.gitallowed 2>/dev/null | awk 'NF && $1!~/^#/' + # If there is a new commit being pushed to the server, read the .gitallowed from the new commit + # not the one that is already there + fi } # load patterns and combine them with | @@ -106,6 +113,38 @@ scan_history() { process_output $? "${output}" } + +# Scans commits that have been pushed to server through update hook +update_hook() { + local old_rev=$2 + local new_rev=$3 + + local new_branch=0 + local to_scan='' + + # Deal with weirdness on new branches. Thank you stack overflow! https://stackoverflow.com/a/19738143 + if [ "${old_rev}" = '0000000000000000000000000000000000000000' ]; then + new_branch=1 + to_scan=$(git rev-list $new_rev --not --branches=*) + fi + + local combined_patterns=$(load_combined_patterns) + + [ -z "${combined_patterns}" ] && return 0 + + # Looks for differences in commit range if not a new branch + if [ $new_branch -eq 0 ]; then + local to_scan=$(git log ${old_rev}..${new_rev} -G"${combined_patterns}" --pretty=%H) + fi + [ -z "${to_scan}" ] && return 0 + + # Scan through revisions with findings to normalize output + output=$(GREP_OPTIONS= LC_ALL=C git grep -nwHEI "${combined_patterns}" $to_scan) + process_output $? "${output}" "${new_rev}" +} + + + # Performs a git-grep, taking into account patterns and options. # Note: this function returns 1 on success, 0 on error. git_grep() { @@ -129,8 +168,8 @@ regular_grep() { # Takes into account allowed patterns, and if a bad match is found, # prints an error message and exits 1. process_output() { - local status="$1" output="$2" - local allowed=$(load_allowed) + local status="$1" output="$2" new_rev="$3" + local allowed=$(load_allowed $new_rev) case "$status" in 0) [ -z "${allowed}" ] && echo "${output}" >&2 && return 1 @@ -179,6 +218,7 @@ pre_commit_hook() { scan_with_fn_or_die "scan" "${files[@]}" } + # Determines if merging in a commit will introduce tainted history. prepare_commit_msg_hook() { case "$2,$3" in @@ -324,7 +364,7 @@ case "${COMMAND}" in --add-provider) add_config "secrets.providers" "$@" ;; --register-aws) register_aws ;; --aws-provider) aws_provider "$1" ;; - --commit_msg_hook|--pre_commit_hook|--prepare_commit_msg_hook) + --commit_msg_hook|--pre_commit_hook|--prepare_commit_msg_hook|--update_hook) ${COMMAND:2} "$@" ;; --add)