From ac707517671e6e68f6874b6d1d11c2af0fb6645e Mon Sep 17 00:00:00 2001 From: Chuanying Du Date: Wed, 18 Dec 2019 09:55:01 -0800 Subject: [PATCH] Change git credential from cache to store and also add test for username/password case. For cache to store change: * By default, cache only last 900 seconds, gitsync will break after that. See https://git-scm.com/docs/git-credential-cache. * The test won't work with cache since the test don't have access to the default unix socket location; XDG_CACHE_HOME override also can pre-create a socket in advance. * `store` put the credential into a file, much easier to debug than cache. * Considering anyone have access to the pod already able to get the credential via environment variables or yaml configs, so put it in file won't make it less secure. For the new password test: 1. askpass_git.sh provided to simulate a git with password challenge. 2. Need and only need to similate "clone" action, need to bypass other actions like config/credential setup. 3. See `credential fill` is the official git action to ask password, see https://git-scm.com/docs/git-credential. This change resolved issue #196. --- askpass_git.sh | 25 ++++++++++++++++++++++ cmd/git-sync/main.go | 2 +- test_e2e.sh | 51 +++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 76 insertions(+), 2 deletions(-) create mode 100755 askpass_git.sh diff --git a/askpass_git.sh b/askpass_git.sh new file mode 100755 index 0000000..27589cf --- /dev/null +++ b/askpass_git.sh @@ -0,0 +1,25 @@ +#!/bin/sh +# Ask pass when cloning new repo, fail if it mismatched the magic password. + +mkdir -p "${XDG_CONFIG_HOME}/git/" +# Override the default 'git --global' config location, the default location +# outside the e2e test environment. See https://git-scm.com/docs/git-config +touch "${XDG_CONFIG_HOME}/git/config" +# Override the default 'git credential store' config location, the default location +# outside the e2e test environment. See https://git-scm.com/docs/git-credential-store +touch "${XDG_CONFIG_HOME}/git/credentials" + +if [ "$1" != "clone" ]; then + git "$@" + exit $? +fi + +REPO=$(echo "$@" | grep -o "file://[^ ]*") +PASSWD=$(echo "url=${REPO}" | git credential fill | grep -o "password=.*") +# Test case much match the magic password below. +if [ "${PASSWD}" != "password=Lov3!k0os" ]; then + echo "invalid password ${PASSWD}, try Lov3!k0os next time." + exit 1 +fi + +git "$@" diff --git a/cmd/git-sync/main.go b/cmd/git-sync/main.go index f21ab1a..832bb0b 100644 --- a/cmd/git-sync/main.go +++ b/cmd/git-sync/main.go @@ -695,7 +695,7 @@ func runCommandWithStdin(ctx context.Context, cwd, stdin, command string, args . func setupGitAuth(ctx context.Context, username, password, gitURL string) error { log.V(1).Info("setting up git credential cache") - _, err := runCommand(ctx, "", *flGitCmd, "config", "--global", "credential.helper", "cache") + _, err := runCommand(ctx, "", *flGitCmd, "config", "--global", "credential.helper", "store") if err != nil { return fmt.Errorf("error setting up git credentials: %v", err) } diff --git a/test_e2e.sh b/test_e2e.sh index c680362..8609248 100755 --- a/test_e2e.sh +++ b/test_e2e.sh @@ -89,6 +89,8 @@ function GIT_SYNC() { -u $(id -u):$(id -g) \ -v "$DIR":"$DIR" \ -v "$(pwd)/slow_git.sh":"/slow_git.sh" \ + -v "$(pwd)/askpass_git.sh":"/askpass_git.sh" \ + --env XDG_CONFIG_HOME=$DIR \ --network="host" \ --rm \ e2e/git-sync:$(make -s version)__$(go env GOOS)_$(go env GOARCH) \ @@ -102,6 +104,7 @@ function remove_sync_container() { } SLOW_GIT=/slow_git.sh +ASKPASS_GIT=/askpass_git.sh REPO="$DIR/repo" mkdir "$REPO" @@ -621,6 +624,52 @@ remove_sync_container wait pass +############################################## +# Test password +############################################## +testcase "password" +echo "$TESTCASE 1" > "$REPO"/file +git -C "$REPO" commit -qam "$TESTCASE 1" +# run with askpass_git but with wrong password +GIT_SYNC \ + --git=$ASKPASS_GIT \ + --username="you@example.com" \ + --password="I have no idea what the password is." \ + --logtostderr \ + --v=5 \ + --wait=0.1 \ + --repo="file://$REPO" \ + --branch=master \ + --rev=HEAD \ + --root="$ROOT" \ + --dest="link" \ + > "$DIR"/log."$TESTCASE" 2>&1 & +sleep 3 +# check for failure +assert_file_absent "$ROOT"/link/file +# run with askpass_git with correct password +GIT_SYNC \ + --git=$ASKPASS_GIT \ + --username="you@example.com" \ + --password="Lov3!k0os" \ + --logtostderr \ + --v=5 \ + --wait=0.1 \ + --repo="file://$REPO" \ + --branch=master \ + --rev=HEAD \ + --root="$ROOT" \ + --dest="link" \ + > "$DIR"/log."$TESTCASE" 2>&1 & +sleep 3 +assert_link_exists "$ROOT"/link +assert_file_exists "$ROOT"/link/file +assert_file_eq "$ROOT"/link/file "$TESTCASE 1" +# Wrap up +remove_sync_container +wait +pass + ############################################## # Test webhook ############################################## @@ -788,7 +837,7 @@ assert_file_absent "$ROOT"/link/$SUBMODULE_REPO_NAME/$NESTED_SUBMODULE_REPO_NAME # Remove submodule git -C "$REPO" submodule deinit -q $SUBMODULE_REPO_NAME rm -rf "$REPO"/.git/modules/$SUBMODULE_REPO_NAME -git -C "$REPO" rm -qf $SUBMODULE_REPO_NAME +git -C "$REPO" rm -qf $SUBMODULE_REPO_NAME git -C "$REPO" commit -aqm "delete submodule" sleep 3 assert_link_exists "$ROOT"/link