Skip to content

Commit 979696c

Browse files
authored
Merge pull request #7 from shawnhankim/awssig-v4
feat: unit test
2 parents bf2c2fd + 4d2883a commit 979696c

30 files changed

+3268
-0
lines changed

Dockerfile.oss

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
FROM nginx:1.23.3
2+
3+
ENV NGINX_VERSION "1.23.3"
4+
ENV NJS_VERSION 0.7.10
5+
6+
ENV PROXY_CACHE_VALID_OK "1h"
7+
ENV PROXY_CACHE_VALID_NOTFOUND "1m"
8+
ENV PROXY_CACHE_VALID_FORBIDDEN "30s"
9+
ENV CORS_ENABLED 0
10+
11+
# We modify the nginx base image by:
12+
# 1. Adding configuration files needed for proxying private S3 buckets
13+
# 2. Adding a directory for proxied objects to be stored
14+
# 3. Replacing the entrypoint script with a modified version that explicitly
15+
# sets resolvers.
16+
# 4. Explicitly install the version of njs coded in the environment variable
17+
# above.
18+
19+
COPY test/common/etc /etc
20+
COPY test/common/docker-entrypoint.sh /docker-entrypoint.sh
21+
COPY test/common/docker-entrypoint.d /docker-entrypoint.d/
22+
COPY test/oss/etc /etc
23+
24+
RUN set -eux \
25+
export DEBIAN_FRONTEND=noninteractive; \
26+
mkdir -p /var/cache/nginx/s3_proxy; \
27+
chown nginx:nginx /var/cache/nginx/s3_proxy; \
28+
chmod -R -v +x /docker-entrypoint.sh /docker-entrypoint.d/*.sh; \
29+
echo "deb https://nginx.org/packages/mainline/debian/ $(echo $PKG_RELEASE | cut -f2 -d~) nginx" >> /etc/apt/sources.list.d/nginx.list; \
30+
apt-get update; \
31+
apt-get install --no-install-recommends --no-install-suggests --yes \
32+
curl nginx-module-njs=${NGINX_VERSION}+${NJS_VERSION}-${PKG_RELEASE}; \
33+
apt-get remove --purge --auto-remove --yes; \
34+
rm -rf /var/lib/apt/lists/* /etc/apt/sources.list.d/nginx.list

test.sh

Lines changed: 326 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,326 @@
1+
#!/usr/bin/env bash
2+
3+
#
4+
# Copyright 2020 F5 Networks
5+
#
6+
# Licensed under the Apache License, Version 2.0 (the "License");
7+
# you may not use this file except in compliance with the License.
8+
# You may obtain a copy of the License at
9+
#
10+
# http://www.apache.org/licenses/LICENSE-2.0
11+
#
12+
# Unless required by applicable law or agreed to in writing, software
13+
# distributed under the License is distributed on an "AS IS" BASIS,
14+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
# See the License for the specific language governing permissions and
16+
# limitations under the License.
17+
#
18+
19+
set -o errexit # abort on nonzero exit status
20+
set -o pipefail # don't hide errors within pipes
21+
22+
nginx_server_proto="http"
23+
nginx_server_host="localhost"
24+
nginx_server_port="8989"
25+
minio_server="http://localhost:9090"
26+
test_server="${nginx_server_proto}://${nginx_server_host}:${nginx_server_port}"
27+
test_fail_exit_code=2
28+
no_dep_exit_code=3
29+
script_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
30+
test_dir="${script_dir}/test"
31+
test_compose_config="${test_dir}/docker-compose.yaml"
32+
test_compose_project="ngt"
33+
34+
p() {
35+
printf "\033[34;1m▶\033[0m "
36+
echo "$1"
37+
}
38+
39+
e() {
40+
>&2 echo "$1"
41+
}
42+
43+
usage() { e "Usage: $0 [--latest-njs <default:false>] [--unprivileged <default:false>] [--type <default:oss|plus>" 1>&2; exit 1; }
44+
45+
for arg in "$@"; do
46+
shift
47+
case "$arg" in
48+
'--help') set -- "$@" '-h' ;;
49+
'--latest-njs') set -- "$@" '-j' ;;
50+
'--unprivileged') set -- "$@" '-u' ;;
51+
'--type') set -- "$@" '-t' ;;
52+
*) set -- "$@" "$arg" ;;
53+
esac
54+
done
55+
56+
while getopts "hjut:" arg; do
57+
case "${arg}" in
58+
j)
59+
njs_latest="1"
60+
;;
61+
u)
62+
unprivileged="1"
63+
;;
64+
t)
65+
nginx_type="${OPTARG}"
66+
;;
67+
*)
68+
usage
69+
;;
70+
esac
71+
done
72+
shift $((OPTIND-1))
73+
74+
startup_message=""
75+
76+
if [ -z "${nginx_type}" ]; then
77+
nginx_type="oss"
78+
startup_message="Starting NGINX ${nginx_type} (default)"
79+
elif ! { [ ${nginx_type} == "oss" ] || [ ${nginx_type} == "plus" ]; }; then
80+
e "Invalid NGINX type: ${nginx_type} - must be either 'oss' or 'plus'"
81+
usage
82+
else
83+
startup_message="Starting NGINX ${nginx_type}"
84+
fi
85+
86+
if [ -z "${njs_latest}" ]; then
87+
njs_latest="0"
88+
startup_message="${startup_message} with the release NJS module (default)"
89+
elif [ ${njs_latest} -eq 1 ]; then
90+
startup_message="${startup_message} with the latest NJS module"
91+
else
92+
startup_message="${startup_message} with the release NJS module"
93+
fi
94+
95+
if [ -z "${unprivileged}" ]; then
96+
unprivileged="0"
97+
startup_message="${startup_message} in privileged mode (default)"
98+
elif [ ${unprivileged} -eq 1 ]; then
99+
startup_message="${startup_message} in unprivileged mode"
100+
else
101+
startup_message="${startup_message} in privileged mode"
102+
fi
103+
104+
e "${startup_message}"
105+
106+
set -o nounset # abort on unbound variable
107+
108+
docker_cmd="$(command -v docker)"
109+
if ! [ -x "${docker_cmd}" ]; then
110+
e "required dependency not found: docker not found in the path or not executable"
111+
exit ${no_dep_exit_code}
112+
fi
113+
114+
docker_compose_cmd="$(command -v docker-compose)"
115+
if ! [ -x "${docker_compose_cmd}" ]; then
116+
e "required dependency not found: docker-compose not found in the path or not executable"
117+
exit ${no_dep_exit_code}
118+
fi
119+
120+
curl_cmd="$(command -v curl)"
121+
if ! [ -x "${curl_cmd}" ]; then
122+
e "required dependency not found: curl not found in the path or not executable"
123+
exit ${no_dep_exit_code}
124+
fi
125+
126+
wait_for_it_cmd="$(command -v wait-for-it || true)"
127+
if [ -x "${wait_for_it_cmd}" ]; then
128+
wait_for_it_installed=1
129+
else
130+
e "wait-for-it command not available, consider installing to prevent race conditions"
131+
wait_for_it_installed=0
132+
fi
133+
134+
if [ "${nginx_type}" = "plus" ]; then
135+
if [ ! -f "./plus/etc/ssl/nginx/nginx-repo.crt" ]; then
136+
e "NGINX Plus certificate file not found: $(pwd)/plus/etc/ssl/nginx/nginx-repo.crt"
137+
exit ${no_dep_exit_code}
138+
fi
139+
140+
if [ ! -f "./plus/etc/ssl/nginx/nginx-repo.key" ]; then
141+
e "NGINX Plus key file not found: $(pwd)/plus/etc/ssl/nginx/nginx-repo.key"
142+
exit ${no_dep_exit_code}
143+
fi
144+
fi
145+
146+
compose() {
147+
# Hint to docker-compose the internal port to map for the container
148+
if [ ${unprivileged} -eq 1 ]; then
149+
export NGINX_INTERNAL_PORT=8080
150+
else
151+
export NGINX_INTERNAL_PORT=80
152+
fi
153+
154+
"${docker_compose_cmd}" -f "${test_compose_config}" -p "${test_compose_project}" "$@"
155+
}
156+
157+
integration_test() {
158+
printf "\033[34;1m▶\033[0m"
159+
printf "\e[1m Integration test suite for v%s signatures\e[22m\n" "$1"
160+
printf "\033[34;1m▶\033[0m"
161+
printf "\e[1m Integration test suite with ALLOW_DIRECTORY_LIST=%s\e[22m\n" "$2"
162+
printf "\033[34;1m▶\033[0m"
163+
printf "\e[1m Integration test suite with PROVIDE_INDEX_PAGE=%s\e[22m\n" "$3"
164+
printf "\033[34;1m▶\033[0m"
165+
printf "\e[1m Integration test suite with APPEND_SLASH_FOR_POSSIBLE_DIRECTORY=%s\e[22m\n" "$4"
166+
167+
# See if Minio is already running, if it isn't then we don't need to build it
168+
# COMPOSE_COMPATIBILITY=true Supports older style compose filenames with _ vs -
169+
170+
if [ -z "$(docker ps -q -f name=${test_compose_project}_minio-_1)" ]; then
171+
p "Building Docker Compose environment"
172+
COMPOSE_COMPATIBILITY=true AWS_SIGS_VERSION=$1 ALLOW_DIRECTORY_LIST=$2 PROVIDE_INDEX_PAGE=$3 APPEND_SLASH_FOR_POSSIBLE_DIRECTORY=$4 compose up --no-start
173+
174+
p "Adding test data to container"
175+
echo "Copying contents of ${test_dir}/data to Docker container ${test_compose_project}_minio_1:/"
176+
"${docker_cmd}" cp "${test_dir}/data" "${test_compose_project}"_minio_1:/
177+
echo "Docker diff output:"
178+
"${docker_cmd}" diff "${test_compose_project}"_minio_1
179+
fi
180+
181+
p "Starting Docker Compose Environment"
182+
COMPOSE_COMPATIBILITY=true AWS_SIGS_VERSION=$1 ALLOW_DIRECTORY_LIST=$2 PROVIDE_INDEX_PAGE=$3 APPEND_SLASH_FOR_POSSIBLE_DIRECTORY=$4 compose up -d
183+
184+
if [ "${wait_for_it_installed}" ]; then
185+
# Hit minio's health check end point to see if it has started up
186+
for (( i=1; i<=3; i++ ))
187+
do
188+
echo "Querying minio server to see if it is ready"
189+
minio_is_up="$(${curl_cmd} -s -o /dev/null -w '%{http_code}' "${minio_server}"/minio/health/cluster)"
190+
if [ "${minio_is_up}" = "200" ]; then
191+
break
192+
else
193+
sleep 2
194+
fi
195+
done
196+
197+
if [ -x "${wait_for_it_cmd}" ]; then
198+
"${wait_for_it_cmd}" -h "${nginx_server_host}" -p "${nginx_server_port}"
199+
fi
200+
fi
201+
202+
p "Starting HTTP API tests (v$1 signatures)"
203+
echo " test/integration/test_api.sh \"$test_server\" \"$test_dir\" $1 $2 $3 $4"
204+
bash "${test_dir}/integration/test_api.sh" "${test_server}" "${test_dir}" "$1" "$2" "$3" "$4";
205+
206+
# We check to see if NGINX is in fact using the correct version of AWS
207+
# signatures as it was configured to do.
208+
sig_versions_found_count=$(compose logs nginx-s3-gateway | grep -c "AWS Signatures Version: v$1\|AWS v$1 Auth")
209+
210+
if [ "${sig_versions_found_count}" -lt 3 ]; then
211+
e "NGINX was not detected as using the correct signatures version - examine logs"
212+
compose logs nginx-s3-gateway
213+
exit "$test_fail_exit_code"
214+
fi
215+
}
216+
217+
finish() {
218+
result=$?
219+
220+
if [ $result -ne 0 ]; then
221+
e "Error running tests - outputting container logs"
222+
compose logs
223+
fi
224+
225+
p "Cleaning up Docker compose environment"
226+
compose stop
227+
compose rm -f
228+
229+
exit ${result}
230+
}
231+
trap finish EXIT ERR SIGTERM SIGINT
232+
233+
### BUILD
234+
235+
p "Building NGINX S3 gateway Docker image"
236+
if [ "${nginx_type}" = "plus" ]; then
237+
if docker buildx > /dev/null 2>&1; then
238+
p "Building using BuildKit"
239+
export DOCKER_BUILDKIT=1
240+
docker build -f Dockerfile.buildkit.${nginx_type} \
241+
--secret id=nginx-crt,src=plus/etc/ssl/nginx/nginx-repo.crt \
242+
--secret id=nginx-key,src=plus/etc/ssl/nginx/nginx-repo.key \
243+
--no-cache --squash \
244+
--tag nginx-s3-gateway --tag nginx-s3-gateway:${nginx_type} .
245+
else
246+
docker build -f Dockerfile.${nginx_type} \
247+
--tag nginx-s3-gateway --tag nginx-s3-gateway:${nginx_type} .
248+
fi
249+
else
250+
docker build -f Dockerfile.${nginx_type} \
251+
--tag nginx-s3-gateway --tag nginx-s3-gateway:${nginx_type} .
252+
fi
253+
254+
if [ ${njs_latest} -eq 1 ]; then
255+
p "Layering in latest NJS build"
256+
docker build -f Dockerfile.latest-njs \
257+
--tag nginx-s3-gateway --tag nginx-s3-gateway:latest-njs-${nginx_type} .
258+
fi
259+
260+
if [ ${unprivileged} -eq 1 ]; then
261+
p "Layering in unprivileged build"
262+
docker build -f Dockerfile.unprivileged \
263+
--tag nginx-s3-gateway --tag nginx-s3-gateway:unprivileged-${nginx_type} .
264+
fi
265+
266+
### UNIT TESTS
267+
268+
runUnitTestWithOutSessionToken() {
269+
test_code="$1"
270+
271+
#MSYS_NO_PATHCONV=1 added to resolve automatic path conversion
272+
# https://github.com/docker/for-win/issues/6754#issuecomment-629702199
273+
MSYS_NO_PATHCONV=1 "${docker_cmd}" run \
274+
--rm \
275+
-v "$(pwd)/test/unit:/var/tmp" \
276+
--workdir /var/tmp \
277+
-e "S3_DEBUG=true" \
278+
-e "S3_STYLE=virtual" \
279+
-e "AWS_ACCESS_KEY_ID=unit_test" \
280+
-e "AWS_SECRET_ACCESS_KEY=unit_test" \
281+
-e "S3_BUCKET_NAME=unit_test" \
282+
-e "S3_SERVER=unit_test" \
283+
-e "S3_SERVER_PROTO=https" \
284+
-e "S3_SERVER_PORT=443" \
285+
-e "S3_REGION=test-1" \
286+
-e "AWS_SIGS_VERSION=4" \
287+
--entrypoint /usr/bin/njs \
288+
nginx-s3-gateway -t module -p '/etc/nginx' /var/tmp/"${test_code}"
289+
}
290+
291+
runUnitTestWithSessionToken() {
292+
test_code="$1"
293+
294+
#MSYS_NO_PATHCONV=1 added to resolve automatic path conversion
295+
# https://github.com/docker/for-win/issues/6754#issuecomment-629702199
296+
MSYS_NO_PATHCONV=1 "${docker_cmd}" run \
297+
--rm \
298+
-v "$(pwd)/test/unit:/var/tmp" \
299+
--workdir /var/tmp \
300+
-e "S3_DEBUG=true" \
301+
-e "S3_STYLE=virtual" \
302+
-e "AWS_ACCESS_KEY_ID=unit_test" \
303+
-e "AWS_SECRET_ACCESS_KEY=unit_test" \
304+
-e "AWS_SESSION_TOKEN=unit_test" \
305+
-e "S3_BUCKET_NAME=unit_test" \
306+
-e "S3_SERVER=unit_test" \
307+
-e "S3_SERVER_PROTO=https" \
308+
-e "S3_SERVER_PORT=443" \
309+
-e "S3_REGION=test-1" \
310+
-e "AWS_SIGS_VERSION=4" \
311+
--entrypoint /usr/bin/njs \
312+
nginx-s3-gateway -t module -p '/etc/nginx' /var/tmp/"${test_code}"
313+
}
314+
315+
p "Running unit tests for utils"
316+
runUnitTestWithSessionToken "utils_test.js"
317+
318+
p "Running unit tests with an access key ID and a secret key in Docker image"
319+
runUnitTestWithOutSessionToken "awscredentials_test.js"
320+
runUnitTestWithOutSessionToken "awssig2_test.js"
321+
runUnitTestWithOutSessionToken "awssig4_test.js"
322+
323+
p "Running unit tests with an session token in Docker image"
324+
runUnitTestWithSessionToken "awscredentials_test.js"
325+
runUnitTestWithSessionToken "awssig2_test.js"
326+
runUnitTestWithSessionToken "awssig4_test.js"

0 commit comments

Comments
 (0)