diff --git a/README.md b/README.md index 98de042..bfa6d4c 100644 --- a/README.md +++ b/README.md @@ -72,6 +72,13 @@ filed named `.gitkeep`. Finally, create individual locks by making an empty file retrying to acquire a lock or release a lock. The default is 10 seconds. Valid values: `60s`, `90m`, `1h`. +* `https_tunnel`: *Optional.* Information about an HTTPS proxy that will be used to tunnel SSH-based git commands over. + Has the following sub-properties: + * `proxy_host`: *Required.* The host name or IP of the proxy server + * `proxy_port`: *Required.* The proxy server's listening port + * `proxy_user`: *Optional.* If the proxy requires authentication, use this username + * `proxy_password`: *Optional.* If the proxy requires authentication, use this password + ### Example Fetching a repo with only 100 commits of history: @@ -234,6 +241,29 @@ example: params: {release: specific-aws-env} ``` +### Configuring resource to proxy SSH commands through an HTTP proxy + +``` +resources: +- name: aws-environments + type: pool + source: + uri: git@github.com:concourse/locks.git + branch: master + pool: aws + private_key: | + -----BEGIN RSA PRIVATE KEY----- + MIIEowIBAAKCAQEAtCS10/f7W7lkQaSgD/mVeaSOvSF9ql4hf/zfMwfVGgHWjj+W + + DWiJL+OFeg9kawcUL6hQ8JeXPhlImG6RTUffma9+iGQyyBMCGd1l + -----END RSA PRIVATE KEY----- + https_tunnel: + proxy_host: proxy-server.mycorp.com + proxy_port: 3128 + proxy_user: myuser + proxy_password: myverysecurepassword +``` + ## Development ### Prerequisites @@ -258,6 +288,29 @@ docker build -t pool-resource --target tests -f dockerfiles/alpine/Dockerfile . docker build -t pool-resource --target tests -f dockerfiles/ubuntu/Dockerfile . ``` +#### Note about the integration tests + +If you want to run the integration tests, a bit more work is required. You will require +an actual git repo to which you can push and pull, configured for SSH access. To do this, +add two files to `integration-tests/ssh` (note that names **are** important): +* `test_key`: This is the private key used to authenticate against your repo. +* `test_repo`: This file contains one line of the form `test_repo_url[#test_branch]`. + If the branch is not specified, it defaults to `main`. For example, + `git@github.com:concourse-git-tester/git-resource-integration-tests.git` or + `git@github.com:concourse-git-tester/git-resource-integration-tests.git#testing` + +To set up or reset the contents of the repo, use the `integration-tests/ssh/init-repo.sh` script. +The script clones the configured repository, (re-)creates the relevant directories, +commits and pushes the changes. If you'd rather execute the commands yourself, view the script +contents to understand the directory structure expected by the integration tests. + +Then run the tests for both `alpine` and `ubuntu` images: + +```sh +docker build -t pool-resource --target integrationtests -f dockerfiles/alpine/Dockerfile . +docker build -t pool-resource --build-arg base_image=concourse/golang-builder --target integrationtests -f dockerfiles/ubuntu/Dockerfile . +``` + ### Contributing Please make all pull requests to the `master` branch and ensure tests pass diff --git a/assets/check b/assets/check index 6fc7b12..911966c 100755 --- a/assets/check +++ b/assets/check @@ -16,6 +16,7 @@ payload=$TMPDIR/git-resource-request cat > $payload <&0 load_pubkey $payload +configure_https_tunnel $payload configure_credentials $payload uri=$(jq -r '.source.uri // ""' < $payload) diff --git a/assets/common.sh b/assets/common.sh index 2432efc..1bad43d 100644 --- a/assets/common.sh +++ b/assets/common.sh @@ -22,6 +22,31 @@ EOF fi } +configure_https_tunnel() { + tunnel=$(jq -r '.source.https_tunnel // empty' < $1) + + if [ ! -z "$tunnel" ]; then + host=$(echo "$tunnel" | jq -r '.proxy_host // empty') + port=$(echo "$tunnel" | jq -r '.proxy_port // empty') + user=$(echo "$tunnel" | jq -r '.proxy_user // empty') + password=$(echo "$tunnel" | jq -r '.proxy_password // empty') + + pass_file="" + if [ ! -z "$user" ]; then + cat > ~/.ssh/tunnel_config <> ~/.ssh/config + fi + fi +} + configure_credentials() { local username=$(jq -r '.source.username // ""' < $1) local password=$(jq -r '.source.password // ""' < $1) diff --git a/assets/in b/assets/in index d1ee0ea..3abca25 100755 --- a/assets/in +++ b/assets/in @@ -33,6 +33,7 @@ payload=$(mktemp $TMPDIR/pool-resource-request.XXXXXX) cat > $payload <&0 load_pubkey $payload +configure_https_tunnel $payload configure_credentials $payload uri=$(jq -r '.source.uri // ""' < $payload) diff --git a/assets/out b/assets/out index 594b40e..a037700 100755 --- a/assets/out +++ b/assets/out @@ -10,6 +10,7 @@ exec 1>&2 # redirect all output to stderr for logging payload=$(mktemp $TMPDIR/pool-resource-request.XXXXXX) cat > $payload <&0 load_pubkey $payload +configure_https_tunnel $payload configure_credentials $payload /opt/go/out $1 >&3 < $payload diff --git a/dockerfiles/alpine/Dockerfile b/dockerfiles/alpine/Dockerfile index 731079f..c39765d 100644 --- a/dockerfiles/alpine/Dockerfile +++ b/dockerfiles/alpine/Dockerfile @@ -11,14 +11,23 @@ RUN set -e; for pkg in $(go list ./...); do \ done FROM ${base_image} AS resource -RUN apk add --no-cache bash jq git git-daemon openssh +RUN apk add --no-cache bash jq git git-daemon openssh make g++ libressl-dev RUN git config --global user.email "git@localhost" RUN git config --global user.name "git" + ADD assets/ /opt/resource/ RUN chmod +x /opt/resource/* COPY --from=builder /assets /opt/go RUN chmod +x /opt/go/out +WORKDIR /root +RUN git clone https://github.com/proxytunnel/proxytunnel.git && \ + cd proxytunnel && \ + make -j4 && \ + install -c proxytunnel /usr/bin/proxytunnel && \ + cd .. && \ + rm -rf proxytunnel + FROM resource AS tests COPY --from=builder /tests /go/resource-tests/ RUN set -e; for test in /go/resource-tests/*.test; do \ @@ -27,4 +36,10 @@ RUN set -e; for test in /go/resource-tests/*.test; do \ ADD test/ /opt/resource-tests RUN /opt/resource-tests/all.sh +FROM resource AS integrationtests +RUN apk --no-cache add squid +ADD test/ /opt/resource-tests/test +ADD integration-tests /opt/resource-tests/integration-tests +RUN /opt/resource-tests/integration-tests/integration.sh + FROM resource diff --git a/dockerfiles/ubuntu/Dockerfile b/dockerfiles/ubuntu/Dockerfile index 2d3215c..3e6115c 100644 --- a/dockerfiles/ubuntu/Dockerfile +++ b/dockerfiles/ubuntu/Dockerfile @@ -11,7 +11,7 @@ RUN set -e; for pkg in $(go list ./...); do \ done FROM ${base_image} AS resource -RUN apt-get update && apt-get install -y jq git +RUN apt-get update && apt-get install -y jq git make g++ libssl-dev openssh-client RUN git config --global user.email "git@localhost" RUN git config --global user.name "git" @@ -20,6 +20,14 @@ RUN chmod +x /opt/resource/* COPY --from=builder /assets /opt/go RUN chmod +x /opt/go/out +WORKDIR /root +RUN git clone https://github.com/proxytunnel/proxytunnel.git && \ + cd proxytunnel && \ + make -j4 && \ + install -c proxytunnel /usr/bin/proxytunnel && \ + cd .. && \ + rm -rf proxytunnel + FROM resource AS tests COPY --from=builder /tests /go/resource-tests/ RUN set -e; for test in /go/resource-tests/*.test; do \ @@ -28,4 +36,10 @@ RUN set -e; for test in /go/resource-tests/*.test; do \ ADD test/ /opt/resource-tests RUN /opt/resource-tests/all.sh +FROM resource AS integrationtests +RUN apt-get update && apt-get install -y squid net-tools +ADD test/ /opt/resource-tests/test +ADD integration-tests /opt/resource-tests/integration-tests +RUN /opt/resource-tests/integration-tests/integration.sh + FROM resource diff --git a/integration-tests/helpers.sh b/integration-tests/helpers.sh new file mode 100755 index 0000000..6de60f9 --- /dev/null +++ b/integration-tests/helpers.sh @@ -0,0 +1,203 @@ +#!/bin/bash + +set -e -u +set -o pipefail + +init_integration_tests() { + local test_dir=$1 + + if [[ ! -f "$test_dir/ssh/test_key" || ! -f "$test_dir/ssh/test_repo" ]]; then + echo "$test_dir/ssh/test_key and $test_dir/ssh/test_repo must BOTH exist. Skipping integration tests." 1>&2 + exit 0 + fi + + cp $test_dir/tunnel/squid-noauth.conf /etc/squid/squid.conf + squid + sleep 2 + + export INTG_REPO=$(cat $test_dir/ssh/test_repo | cut -d '#' -f1) + + branch=$(cat $test_dir/ssh/test_repo | cut -d '#' -f2) + [[ "$INTG_REPO" == "$branch" ]] && branch=main + + export INTG_BRANCH=$branch +} + +check_uri_with_private_key_and_incomplete_tunnel_info() { + local pool=$3 + + jq -n "{ + source: { + uri: $(echo $INTG_REPO | jq -R .), + pool: \"$pool\", + private_key: $(cat $1 | jq -s -R .), + branch: $(echo $INTG_BRANCH | jq -R .), + https_tunnel: {} + } + }" | ${resource_dir}/check "$2" | tee /dev/stderr +} + +check_uri_with_private_key_and_tunnel_info() { + local pool=$3 + local auth=${4:-""} + + jq -n "{ + source: { + uri: $(echo $INTG_REPO | jq -R .), + pool: \"$pool\", + private_key: $(cat $1 | jq -s -R .), + branch: $(echo $INTG_BRANCH | jq -R .), + https_tunnel: { + proxy_host: \"localhost\", + proxy_port: 3128 + $(add_proxy_auth "$auth") + } + } + }" | ${resource_dir}/check "$2" | tee /dev/stderr +} + +get_uri_with_private_key_and_tunnel_info() { + local pool=$3 + local auth=${4:-""} + + jq -n "{ + source: { + uri: $(echo $INTG_REPO | jq -R .), + pool: \"$pool\", + private_key: $(cat $1 | jq -s -R .), + branch: $(echo $INTG_BRANCH | jq -R .), + https_tunnel: { + proxy_host: \"localhost\", + proxy_port: 3128 + $(add_proxy_auth "$auth") + } + } + }" | ${resource_dir}/in "$2" | tee /dev/stderr +} + +put_acquire_uri_with_private_key_and_tunnel_info() { + local pool=$3 + local auth=${4:-""} + + jq -n "{ + source: { + uri: $(echo $INTG_REPO | jq -R .), + pool: \"$pool\", + private_key: $(cat $1| jq -s -R .), + branch: $(echo $INTG_BRANCH | jq -R .), + https_tunnel: { + proxy_host: \"localhost\", + proxy_port: 3128 + $(add_proxy_auth "$auth") + } + }, + params: { + acquire: true + } + }" | ${resource_dir}/out "$2" | tee /dev/stderr +} + +put_release_uri_with_private_key_and_tunnel_info() { + local pool=${4} + local auth=${5:-""} + + jq -n "{ + source: { + uri: $(echo $INTG_REPO | jq -R .), + pool: \"$pool\", + private_key: $(cat $1| jq -s -R .), + branch: $(echo $INTG_BRANCH | jq -R .), + https_tunnel: { + proxy_host: \"localhost\", + proxy_port: 3128 + $(add_proxy_auth "$auth") + } + }, + params: { + release: $(echo $3 | jq -R .) + } + }" | ${resource_dir}/out "$2" | tee /dev/stderr +} + +add_proxy_auth() { + local file=$1 + + [[ -f "$file" ]] || exit 0 + + user=$(cat $file | cut -d : -f1) + pass=$(cat $file | cut -d : -f2) + + echo ", proxy_user: \"$user\", proxy_password: \"$pass\"" +} + +test_auth_failure() { + test_failure "$1" 'HTTP return code: 407 Proxy Authentication Required' +} + +test_failure() { + local output=$1 + local expected_message=$2 + + echo "$output" + + set -e + + ( echo "$output" | grep "$expected_message" >/dev/null 2>&1 ) + rc=$? + + test "$rc" -eq "0" +} + +run_with_unauthenticated_proxy() { + local basedir=$1 + shift + + cp $basedir/tunnel/squid-noauth.conf /etc/squid/squid.conf + + __run "without" "$@" +} + +run_with_authenticated_proxy() { + local basedir=$1 + shift + + cp $basedir/tunnel/squid-auth.conf /etc/squid/squid.conf + + __run "with" "$@" +} + +__run() { + export TMPDIR=$(mktemp -d ${TMPDIR_ROOT}/git-tests.XXXXXX) + authtype=$1 + shift + + echo -e 'running \e[33m'"$1"$'\e[0m'" $authtype authentication enabled ..." + echo 'Reconfiguring proxy...' + + squid -k reconfigure + + set +e + attempts=10 + while (( attempts )); do + ( netstat -an | grep LISTEN | grep 3128 ) >/dev/null 2>&1 + rc=$? + + if [[ $rc == 0 ]]; then + break + else + echo "Waiting for proxy to finish reconfiguring..." + (( attempts-- )) + sleep 1 + fi + done + + if [[ $attempts == 0 ]]; then + echo "Timed out waiting for proxy to reconfigure!" 1>&2 + exit 1 + fi + set -e + + + eval "$@" 2>&1 | sed -e 's/^/ /g' + echo "" +} diff --git a/integration-tests/integration.sh b/integration-tests/integration.sh new file mode 100755 index 0000000..db67d87 --- /dev/null +++ b/integration-tests/integration.sh @@ -0,0 +1,120 @@ +#!/bin/bash + +set -e + +export TMPDIR_ROOT=$(mktemp -d /tmp/git-tests.XXXXXX) + +basedir="$(dirname "$0")" +. "$basedir/../test/helpers.sh" +. "$basedir/helpers.sh" + +it_can_check_with_empty_tunnel_information() { + local pool=${1:-"no-auth"} + + output=$(check_uri_with_private_key_and_incomplete_tunnel_info "$(dirname "$0")/ssh/test_key" $TMPDIR/destination "$pool" "${@:2}" 2>&1) + echo "$output" + + set +e + ( echo "$output" | grep 'Via localhost:3128 ->' >/dev/null 2>&1 ) + rc=$? + set -e + + test "$rc" -ne "0" +} + +it_can_check_through_a_tunnel() { + local pool=${1:-"no-auth"} + + output=$(check_uri_with_private_key_and_tunnel_info "$(dirname "$0")/ssh/test_key" $TMPDIR/destination "$pool" "${@:2}" 2>&1) + echo "$output" + + (echo "$output" | grep 'Via localhost:3128 ->' >/dev/null 2>&1) + rc=$? + + test "$rc" -eq "0" +} + +it_can_get_through_a_tunnel() { + local pool=${1:-"no-auth"} + + get_uri_with_private_key_and_tunnel_info "$(dirname "$0")/ssh/test_key" $TMPDIR/destination "$pool" "${@:2}" +} + +it_can_put_acquire_through_a_tunnel() { + local pool=${1:-"no-auth"} + + put_acquire_uri_with_private_key_and_tunnel_info "$(dirname "$0")/ssh/test_key" $TMPDIR/destination "$pool" "${@:2}" +} + +it_can_put_release_through_a_tunnel() { + local pool=${1:-"no-auth"} + + get_uri_with_private_key_and_tunnel_info "$(dirname "$0")/ssh/test_key" $TMPDIR/destination "$pool" "${@:2}" + put_release_uri_with_private_key_and_tunnel_info "$(dirname "$0")/ssh/test_key" $TMPDIR destination "$pool" "${@:2}" +} + +it_can_check_through_a_tunnel_with_auth() { + it_can_check_through_a_tunnel with-auth "$basedir/tunnel/auth" +} + +it_can_get_through_a_tunnel_with_auth() { + it_can_get_through_a_tunnel with-auth "$basedir/tunnel/auth" +} + +it_can_put_acquire_through_a_tunnel_with_auth() { + it_can_put_acquire_through_a_tunnel with-auth "$basedir/tunnel/auth" +} + +it_can_put_release_through_a_tunnel_with_auth() { + it_can_put_release_through_a_tunnel with-auth "$basedir/tunnel/auth" +} + +it_cant_check_through_a_tunnel_without_auth() { + set +e + test_auth_failure "$(check_uri_with_private_key_and_tunnel_info "$(dirname "$0")/ssh/test_key" $TMPDIR/destination no-auth 2>&1)" +} + +it_cant_get_through_a_tunnel_without_auth() { + set +e + test_auth_failure "$(get_uri_with_private_key_and_tunnel_info "$(dirname "$0")/ssh/test_key" $TMPDIR/destination no-auth 2>&1)" +} + +it_cant_put_acquire_through_a_tunnel_without_auth() { + # The standard error is not captured by the 'out' command when cloning a repository, + # thus making it impossible to grep a more specific error message. + set +e + test_failure "$(put_acquire_uri_with_private_key_and_tunnel_info "$(dirname "$0")/ssh/test_key" $TMPDIR/destination no-auth "$@" 2>&1)" 'exit status 128' +} + +it_cant_put_release_through_a_tunnel_without_auth() { + local pool="no-auth" + + # Get with auth + get_uri_with_private_key_and_tunnel_info "$(dirname "$0")/ssh/test_key" $TMPDIR/destination "$pool" "$basedir/tunnel/auth" + + # Release without auth + # The standard error is not captured by the 'out' command when cloning a repository, + # thus making it impossible to grep a more specific error message. + set +e + test_failure "$(put_release_uri_with_private_key_and_tunnel_info "$(dirname "$0")/ssh/test_key" $TMPDIR destination "$pool" 2>&1)" 'exit status 128' +} + +init_integration_tests $basedir +run it_can_check_with_empty_tunnel_information +run_with_unauthenticated_proxy "$basedir" it_can_check_through_a_tunnel +run_with_unauthenticated_proxy "$basedir" it_can_get_through_a_tunnel +run_with_unauthenticated_proxy "$basedir" it_can_put_acquire_through_a_tunnel +run_with_unauthenticated_proxy "$basedir" it_can_put_release_through_a_tunnel +run_with_unauthenticated_proxy "$basedir" it_can_check_through_a_tunnel_with_auth +run_with_unauthenticated_proxy "$basedir" it_can_get_through_a_tunnel_with_auth +run_with_unauthenticated_proxy "$basedir" it_can_put_acquire_through_a_tunnel_with_auth +run_with_unauthenticated_proxy "$basedir" it_can_put_release_through_a_tunnel_with_auth + +run_with_authenticated_proxy "$basedir" it_can_check_through_a_tunnel_with_auth +run_with_authenticated_proxy "$basedir" it_can_get_through_a_tunnel_with_auth +run_with_authenticated_proxy "$basedir" it_can_put_acquire_through_a_tunnel_with_auth +run_with_authenticated_proxy "$basedir" it_can_put_release_through_a_tunnel_with_auth +run_with_authenticated_proxy "$basedir" it_cant_check_through_a_tunnel_without_auth +run_with_authenticated_proxy "$basedir" it_cant_get_through_a_tunnel_without_auth +run_with_authenticated_proxy "$basedir" it_cant_put_acquire_through_a_tunnel_without_auth +run_with_authenticated_proxy "$basedir" it_cant_put_release_through_a_tunnel_without_auth diff --git a/integration-tests/ssh/.gitignore b/integration-tests/ssh/.gitignore new file mode 100644 index 0000000..145f5d7 --- /dev/null +++ b/integration-tests/ssh/.gitignore @@ -0,0 +1 @@ +test_* diff --git a/integration-tests/ssh/init-repo.sh b/integration-tests/ssh/init-repo.sh new file mode 100755 index 0000000..9e5255e --- /dev/null +++ b/integration-tests/ssh/init-repo.sh @@ -0,0 +1,86 @@ +#!/usr/bin/env bash + +set -e -u +set -o pipefail + +basedir="$(dirname "$0")" +dest=test_repo_clone + +# This is the directory structure expected by the integration tests: +#. +#├── no-auth +#│ ├── claimed +#│ │ └── .gitkeep +#│ └── unclaimed +#│ ├── .gitkeep +#│ └── lock +#└── with-auth +# ├── claimed +# │ └── .gitkeep +# └── unclaimed +# ├── .gitkeep +# └── lock +build_lock_structure() { + local dir=$1 + rm -rf "${dir}" + + mkdir -p "${dir}/unclaimed" + touch "${dir}/unclaimed/.gitkeep" + touch "${dir}/unclaimed/lock" + + mkdir -p "${dir}/claimed" + touch "${dir}/claimed/.gitkeep" + + git add ${dir} +} + +clone_repo() { + local repo=$1 + local branch=$2 + local dest=$3 + + git clone -b "$branch" "$repo" "$dest" + pushd "$dest" >/dev/null + git config pull.rebase false + popd >/dev/null +} + +main() { + pushd "${basedir}" >/dev/null + repo=$(cut -d '#' -f1 /dev/null + existing_repo=$(git config --get remote.origin.url) + if [[ "$repo" != "$existing_repo" ]]; then + echo "error: unexpected repo, '$repo' != '$existing_repo'" + exit 1 + fi + + existing_branch=$(git branch --show-current) + if [[ "$branch" != "$existing_branch" ]]; then + echo "error: unexpected branch, '$branch' != '$existing_branch'" + exit 1 + fi + + git pull + build_lock_structure "no-auth" + build_lock_structure "with-auth" + + if [[ $(git status --porcelain) ]]; then + git commit -m "reset" + git push + else + echo "no changes" + fi + popd >/dev/null + popd >/dev/null +} + +main "$@" diff --git a/integration-tests/tunnel/auth b/integration-tests/tunnel/auth new file mode 100644 index 0000000..3663ae8 --- /dev/null +++ b/integration-tests/tunnel/auth @@ -0,0 +1 @@ +admin:admin \ No newline at end of file diff --git a/integration-tests/tunnel/passwd b/integration-tests/tunnel/passwd new file mode 100644 index 0000000..3ad027a --- /dev/null +++ b/integration-tests/tunnel/passwd @@ -0,0 +1 @@ +admin:$apr1$qUcrUmJN$LCi7cragcviMqJ2g2OdAp1 \ No newline at end of file diff --git a/integration-tests/tunnel/squid-auth.conf b/integration-tests/tunnel/squid-auth.conf new file mode 100644 index 0000000..92de933 --- /dev/null +++ b/integration-tests/tunnel/squid-auth.conf @@ -0,0 +1,9 @@ +auth_param basic program /usr/lib/squid/basic_ncsa_auth /opt/resource-tests/integration-tests/tunnel/passwd + +acl Safe_ports port 22 +acl authenticated proxy_auth REQUIRED +acl CONNECT method CONNECT +http_port 3128 + +http_access allow authenticated +http_access allow CONNECT Safe_ports diff --git a/integration-tests/tunnel/squid-noauth.conf b/integration-tests/tunnel/squid-noauth.conf new file mode 100644 index 0000000..acca63e --- /dev/null +++ b/integration-tests/tunnel/squid-noauth.conf @@ -0,0 +1,6 @@ +acl Safe_ports port 22 +acl CONNECT method CONNECT + +http_port 3128 + +http_access allow CONNECT Safe_ports diff --git a/test/all.sh b/test/all.sh index c5c8bb8..a0383ea 100755 --- a/test/all.sh +++ b/test/all.sh @@ -4,6 +4,7 @@ set -e export TMPDIR_ROOT=$(mktemp -d /tmp/git-tests.XXXXXX) +$(dirname $0)/image.sh $(dirname $0)/check.sh echo -e '\e[32mall tests passed!\e[0m' diff --git a/test/check.sh b/test/check.sh index 2f3b93c..131e36c 100755 --- a/test/check.sh +++ b/test/check.sh @@ -131,6 +131,37 @@ it_supports_private_key_without_user() { ! grep "^User " $HOME/.ssh/config } +it_configures_http_tunnel() { + local repo=$(init_repo) + local key=$TMPDIR/key-no-passphrase + local host=proxy-server.mycorp.com + local port=3128 + + ssh-keygen -f $key + check_uri_with_key_and_tunnel $repo $key $host $port + + local expected_pass_file="" + grep "ProxyCommand /usr/bin/proxytunnel $expected_pass_file -p $host:$port -d %h:%p" $HOME/.ssh/config +} + +it_configures_http_tunnel_with_authentication() { + local repo=$(init_repo) + local key=$TMPDIR/key-no-passphrase + local host=proxy-server.mycorp.com + local port=3128 + local username=username + local password=password + + ssh-keygen -f $key + check_uri_with_key_and_tunnel_with_authentication $repo $key $host $port $username $password + + local expected_pass_file="-F ~/.ssh/tunnel_config" + grep "ProxyCommand /usr/bin/proxytunnel $expected_pass_file -p $host:$port -d %h:%p" $HOME/.ssh/config + + grep "proxy_user = $username" ~/.ssh/tunnel_config + grep "proxy_passwd = $password" ~/.ssh/tunnel_config +} + it_clears_netrc_even_after_errors() { local repo=$(init_repo) local ref=$(make_commit $repo) @@ -156,4 +187,6 @@ run it_checks_given_pool run it_can_check_when_not_ff run it_can_check_with_credentials run it_supports_private_key_without_user +run it_configures_http_tunnel +run it_configures_http_tunnel_with_authentication run it_clears_netrc_even_after_errors diff --git a/test/helpers.sh b/test/helpers.sh index 1dd4268..d29f566 100644 --- a/test/helpers.sh +++ b/test/helpers.sh @@ -188,3 +188,47 @@ check_uri_with_key() { } }" | ${resource_dir}/check | tee /dev/stderr } + +check_uri_with_key_and_tunnel() { + local uri=$1 + local key=$2 + local host=$3 + local port=$4 + + jq -n "{ + source: { + uri: $(echo $uri | jq -R .), + branch: \"master\", + pool: \"my_pool\", + private_key: $(cat $key | jq -s -R .), + https_tunnel: { + proxy_host: $(echo $host | jq -R .), + proxy_port: $(echo $port | jq -R .), + }, + } + }" | ${resource_dir}/check | tee /dev/stderr +} + +check_uri_with_key_and_tunnel_with_authentication() { + local uri=$1 + local key=$2 + local host=$3 + local port=$4 + local username=$5 + local password=$6 + + jq -n "{ + source: { + uri: $(echo $uri | jq -R .), + branch: \"master\", + pool: \"my_pool\", + private_key: $(cat $key | jq -s -R .), + https_tunnel: { + proxy_host: $(echo $host | jq -R .), + proxy_port: $(echo $port | jq -R .), + proxy_user: $(echo $username | jq -R .), + proxy_password: $(echo $password | jq -R .), + }, + } + }" | ${resource_dir}/check | tee /dev/stderr +} diff --git a/test/image.sh b/test/image.sh new file mode 100755 index 0000000..fa98d3c --- /dev/null +++ b/test/image.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +set -e + +. "$(dirname "$0")/helpers.sh" + +it_has_installed_proxytunnel() { + test -x /usr/bin/proxytunnel +} + +it_cleans_up_installation_artifacts() { + test ! -d /root/proxytunnel +} + +run it_has_installed_proxytunnel +run it_cleans_up_installation_artifacts