Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add test for serverside hook #204

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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``
~~~~~~~~~~~~~~~~~~~~~~~~~

Expand Down
46 changes: 43 additions & 3 deletions git-secrets
Original file line number Diff line number Diff line change
Expand Up @@ -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)"
Expand All @@ -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 |
Expand Down Expand Up @@ -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() {
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down
128 changes: 128 additions & 0 deletions test/update.bats
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
#!/usr/bin/env bats
load test_helper

export TEST_REMOTE="$BATS_TMPDIR/test-remote.git"

setup_remote() {
delete_remote
mkdir -p $TEST_REMOTE
cd $TEST_REMOTE
git init --bare
git config --local --add secrets.patterns '@todo'
git config --local --add secrets.patterns 'forbidden|me'
git config --local --add secrets.patterns '#hash'
cat <<-SCRIPT >> hooks/update
#!/usr/bin/env bash
$(cd $BATS_TEST_DIRNAME/..; pwd)/git-secrets --update_hook -- "\$@"
SCRIPT
chmod +x hooks/update
cd -
}

delete_remote() {
[ -d $TEST_REMOTE ] && rm -rf $TEST_REMOTE || true
}

alias_function() {
eval "${1}() $(declare -f ${2} | sed 1d)"
}

alias_function _setup setup
setup() {
_setup
repo_run git config --unset-all secrets
setup_remote
}

alias_function _teardown teardown
teardown() {
_teardown
delete_remote
}

@test "Pushes branch contained allowed words" {
echo 'todo' > $TEST_REPO/test.txt
git add -A
git commit -m "Create test.txt"
run git push $TEST_REMOTE master
[ $status -eq 0 ]
}

@test "fails to push branch contained secret words" {
hashes=()

echo '@todo' > $TEST_REPO/test.txt
git add -A
git commit -m "Create test.txt"
hashes+=( $(git rev-parse HEAD) )

run git push $TEST_REMOTE master
[ $status -eq 1 ]
echo "$output" | grep -F "remote: ${hashes[0]}:test.txt:1:@todo"
}

@test "fails to push branch when secret words got mixed in a commit" {
hashes=()

cd $TEST_REPO
echo 'todo' > $TEST_REPO/test1.txt
echo '@todo' > $TEST_REPO/test2.txt
echo 'TODO' > $TEST_REPO/test3.txt
git add -A
git commit -m "Create files"
hashes+=( $(git rev-parse HEAD) )

run git push $TEST_REMOTE master
[ $status -eq 1 ]
echo "$output" | grep -F "remote: ${hashes[0]}:test2.txt:1:@todo"
}

@test "fails to push branch even if secret words are fixed" {
hashes=()

cd $TEST_REPO
echo 'todo' > $TEST_REPO/test.txt
git add -A
git commit -m "Create test.txt"
hashes+=( $(git rev-parse HEAD) )

echo '@todo' > $TEST_REPO/test.txt
git add -A
git commit -m "Update test.txt"
hashes+=( $(git rev-parse HEAD) )

echo 'todo' > $TEST_REPO/test.txt
git add -A
git commit -m "Update test.txt"
hashes+=( $(git rev-parse HEAD) )

run git push $TEST_REMOTE master
[ $status -eq 1 ]
echo "$output" | grep -F "remote: ${hashes[1]}:test.txt:1:@todo"
}

@test "Pushes branch when secret words set as allowed patterns" {
hashes=()

cd $TEST_REMOTE
git config --local --add secrets.allowed '@todo'

cd $TEST_REPO
echo 'todo' > $TEST_REPO/test.txt
git add -A
git commit -m "Create test.txt"
hashes+=( $(git rev-parse HEAD) )

echo '@todo' > $TEST_REPO/test.txt
git add -A
git commit -m "Update test.txt"
hashes+=( $(git rev-parse HEAD) )

echo 'todo' > $TEST_REPO/test.txt
git add -A
git commit -m "Update test.txt"
hashes+=( $(git rev-parse HEAD) )

run git push $TEST_REMOTE master
[ $status -eq 0 ]
}