Skip to content
Draft
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
2 changes: 1 addition & 1 deletion nvm.sh
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ nvm_download() {

nvm_sanitize_auth_header() {
# Remove potentially dangerous characters
nvm_echo "$1" | command sed 's/[^a-zA-Z0-9:;_. -]//g'
nvm_echo "$1" | command sed 's/[^a-zA-Z0-9:;_./+=~ -]//g'
}

nvm_has_system_node() {
Expand Down
7 changes: 6 additions & 1 deletion test/fast/Unit tests/nvm_download
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,12 @@ nvm_download "https://raw.githubusercontent.com/nvm-sh/nvm/HEAD/install.sh" >/de
# nvm_download should pass when calling with auth header
docker pull kennethreitz/httpbin && SHELL=bash docker run -d --name httpbin -p 80:80 kennethreitz/httpbin
sleep 1 # wait for httpbin to start
NVM_AUTH_HEADER="Bearer test-token" nvm_download "http://127.0.0.1/bearer" > /dev/null || die 'nvm_download with auth header should send correctly'
# NOTE: The test token here is derived from the RFC at https://datatracker.ietf.org/doc/html/rfc6750#section-2.1 and includes additional
# valid bearer token characters.
expected='{"authenticated":true,"token":"mF_9.B5f-4.1JqM~+/="}'
actual="$(NVM_AUTH_HEADER="Bearer mF_9.B5f-4.1JqM~+/=" nvm_download "http://127.0.0.1/bearer" | tr -d "[:space:]")"
[ "$?" = "0" ] || die 'nvm_download with auth header should send correctly'
[ "${expected}" = "${actual}" ] || die 'nvm_download with auth header should send correct bearer token'

# nvm_download should fail when calling without auth header
nvm_download "http://127.0.0.1/bearer" > /dev/null && die 'nvm_download with no auth header should not send the header and should fail'
Expand Down
28 changes: 28 additions & 0 deletions test/fast/Unit tests/nvm_download_with_basic_auth
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#!/bin/sh

cleanup () {
unset -f die cleanup
docker stop httpbin && docker rm httpbin
}
die () { echo "$@" ; cleanup ; exit 1; }

\. ../../../nvm.sh

set -ex

# nvm_download install.sh
nvm_download "https://raw.githubusercontent.com/nvm-sh/nvm/HEAD/install.sh" >/dev/null || die "nvm_download unable to download install.sh"

# nvm_download should pass when calling with basic auth header with correct username and password
docker pull kennethreitz/httpbin && SHELL=bash docker run -d --name httpbin -p 80:80 kennethreitz/httpbin
sleep 1 # wait for httpbin to start
proxy="http://127.0.0.1/basic-auth/test/123%3F45%3E6"
# These credentials were generated by running `printf 'test:123?45>6' | base64`. These credentials were chosen because their
# base64 encoded value contain the necessary special characters '+', '/', and '='.
base64_encoded_credentials="dGVzdDoxMjM/NDU+Ng=="
NVM_AUTH_HEADER="Basic ${base64_encoded_credentials}" nvm_download "${proxy}" > /dev/null || die 'nvm_download should pass when calling with basic auth header with correct username and password'

# nvm_download should fail when calling with basic auth header with incorrect password
NVM_AUTH_HEADER="Basic $(printf 'test:123?45>67' | base64)" nvm_download "${proxy}" > /dev/null && die 'nvm_download should fail when calling with basic auth header with incorrect password'

cleanup
85 changes: 85 additions & 0 deletions test/fast/Unit tests/nvm_ls_remote_with_proxy_requiring_basic_auth
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
#!/bin/sh
# shellcheck shell=dash
# shellcheck disable=SC2039 # local is non-POSIX

temp_nodejs_tmp_root=""
temp_iojs_tmp_root=""
cleanup () {
unset -f die cleanup NVM_NODEJS_ORG_MIRROR
docker stop ferron-nodejs-mirror && docker rm ferron-nodejs-mirror
docker stop ferron-iojs-mirror && docker rm ferron-iojs-mirror
if [ -n "${temp_nodejs_tmp_root}" ]; then
rm -rf -- "${temp_nodejs_tmp_root}"
fi
if [ -n "${temp_iojs_tmp_root}" ]; then
rm -rf -- "${temp_iojs_tmp_root}"
fi
}
die () { echo "$@" ; cleanup ; exit 1; }

set -e

# shellcheck source=/dev/null # The nvm.sh script is checked separately.
\. ../../../nvm.sh

# Setup the temporary directories to host the mock nodejs and iojs mirrors.
MOCKS_DIR="$PWD/mocks"
temp_nodejs_tmp_root="$(mktemp --directory)"
mkdir -p "${temp_nodejs_tmp_root}/dist"
cp "$MOCKS_DIR/nodejs.org-dist-index.tab" "${temp_nodejs_tmp_root}/dist/index.tab"
temp_iojs_tmp_root="$(mktemp --directory)"
mkdir -p "${temp_iojs_tmp_root}/dist"
cp "$MOCKS_DIR/iojs.org-dist-index.tab" "${temp_iojs_tmp_root}/dist/index.tab"

# Add necessary ferron config file needed for both containers.
# NOTE: The valid credentials for these test servers are 'test:123?45>6'.
cat <<EOF >"${temp_nodejs_tmp_root}/ferron.kdl"
:8080 {
log "/dev/stderr"
error_log "/dev/stderr"
status 401 users="test" brute_protection=#false
user "test" "\$argon2id\$v=19\$m=19456,t=2,p=1\$emTillHaS3OqFuvITdXxzg\$G00heP8QSXk5H/ruTiLt302Xk3uETfU5QO8hBIwUq08"
root "/mnt/www"
}
EOF
cat <<EOF >"${temp_iojs_tmp_root}/ferron.kdl"
:8081 {
log "/dev/stderr"
error_log "/dev/stderr"
status 401 users="test" brute_protection=#false
user "test" "\$argon2id\$v=19\$m=19456,t=2,p=1\$emTillHaS3OqFuvITdXxzg\$G00heP8QSXk5H/ruTiLt302Xk3uETfU5QO8hBIwUq08"
root "/mnt/www"
}
EOF
# Need to adjust permissions to ensure ferron running under container can read the files in the temp directories.
chmod a+rx "${temp_nodejs_tmp_root}"
chmod a+rx "${temp_iojs_tmp_root}"

# Start containers
docker run --detach --name ferron-nodejs-mirror --publish 8080:8080 --volume "${temp_nodejs_tmp_root}:/mnt/www" --workdir "/mnt/www" ferronserver/ferron:2 ferron --config /mnt/www/ferron.kdl
docker run --detach --name ferron-iojs-mirror --publish 8081:8081 --volume "${temp_iojs_tmp_root}:/mnt/www" --workdir "/mnt/www" ferronserver/ferron:2 ferron --config /mnt/www/ferron.kdl
sleep 1 # wait for ferron containers to start

export NVM_NODEJS_ORG_MIRROR="http://localhost:8080/dist"
export NVM_IOJS_ORG_MIRROR="http://localhost:8081/dist"
# These credentials were generated by running `printf 'test:123?45>6' | base64`. These credentials were chosen because their
# base64 encoded value contain the necessary special characters '+', '/', and '='.
base64_encoded_credentials="dGVzdDoxMjM/NDU+Ng=="
export NVM_AUTH_HEADER="Basic ${base64_encoded_credentials}"

OUTPUT="$(nvm_ls_remote)"
echo "nvm_ls_remote output: ${OUTPUT}"
[ -n "${OUTPUT}" ] || die nvm_ls_remote_with_proxy_requiring_basic_auth Failed to run nvm_ls_remote through nodejs mirror requiring basic auth.

OUTPUT="$(nvm_ls_remote_iojs)"
echo "nvm_ls_remote_iojs output: ${OUTPUT}"
[ -n "${OUTPUT}" ] || die nvm_ls_remote_with_proxy_requiring_basic_auth Failed to run nvm_ls_remote_iojs through iojs mirror requiring basic auth.

# Remove auth header and try using mirrors. This time it should fail due to missing creds.
unset NVM_AUTH_HEADER

nvm_ls_remote && die nvm_ls_remote_with_proxy_requiring_basic_auth Unexpected success of run of nvm_ls_remote through nodejs mirror without required credentials.

nvm_ls_remote_iojs && die nvm_ls_remote_with_proxy_requiring_basic_auth Unexpected success of run of nvm_ls_remote_iojs through iojs mirror without required credentials.

cleanup
Loading