diff --git a/tests/commands/get_bucket_acl.sh b/tests/commands/get_bucket_acl.sh index 4c2e28c9..b7f253c8 100644 --- a/tests/commands/get_bucket_acl.sh +++ b/tests/commands/get_bucket_acl.sh @@ -47,4 +47,28 @@ get_bucket_acl_with_user() { return 1 fi return 0 +} + +get_bucket_acl_rest() { + if ! check_param_count_v2 "bucket, env vars, callback fn" 3 $#; then + return 1 + fi + env_vars="BUCKET_NAME=$1 $2" + if ! send_rest_command_expect_success_callback "$env_vars" "./tests/rest_scripts/get_bucket_acl.sh" "200" "$3"; then + log 2 "error getting bucket ACL" + return 1 + fi + return 0 +} + +get_bucket_acl_rest_expect_error() { + if ! check_param_count_v2 "bucket, env vars, expected response code, expected error, expected message" 5 $#; then + return 1 + fi + env_vars="BUCKET_NAME=$1 $2" + if ! send_rest_command_expect_error "$env_vars" "./tests/rest_scripts/get_bucket_acl.sh" "$3" "$4" "$5"; then + log 2 "error checking for get bucket acl error" + return 1 + fi + return 0 } \ No newline at end of file diff --git a/tests/commands/get_object.sh b/tests/commands/get_object.sh index dc74f11a..bae55096 100644 --- a/tests/commands/get_object.sh +++ b/tests/commands/get_object.sh @@ -89,28 +89,53 @@ get_object_with_user() { get_object_rest() { log 6 "get_object_rest" - if [ $# -ne 3 ]; then - log 2 "'get_object_rest' requires bucket name, object name, output file" + if ! check_param_count_v2 "bucket name, object key, output file" 3 $#; then return 1 fi - if ! get_object_rest_with_user "$AWS_ACCESS_KEY_ID" "$AWS_SECRET_ACCESS_KEY" "$1" "$2" "$3"; then - log 2 "error getting REST object with root user" + env_vars="BUCKET_NAME=$1 OBJECT_KEY=$2 OUTPUT_FILE=$3" + if ! send_rest_command_expect_success "$env_vars" "./tests/rest_scripts/get_object.sh" "200"; then + log 2 "error sending REST command and checking error" + return 1 + fi + return 0 +} + +get_object_rest_special_chars() { + if ! check_param_count_v2 "bucket name, key, output file" 3 $#; then + return 1 + fi + # do this in case there are spaces in the name + if ! result=$(COMMAND_LOG="$COMMAND_LOG" OUTPUT_FILE="$TEST_FILE_FOLDER/error.txt" BUCKET_NAME="$1" OBJECT_KEY="$2" OUTPUT_FILE="$3" ./tests/rest_scripts/get_object.sh 2>&1); then + log 2 "error sending put object command: $result" + return 1 + fi + if [ "$result" != "200" ]; then + log 2 "expected '200', was '$result' ($(cat "$3"))" + return 1 + fi + return 0 +} + +get_object_rest_expect_error() { + if ! check_param_count_v2 "bucket name, object key, output file, env vars, response code, error, message" 7 $#; then + return 1 + fi + env_vars="BUCKET_NAME=$1 OBJECT_KEY=$2 OUTPUT_FILE=$3 $4" + log 5 "env vars: $env_vars" + if ! send_rest_command_expect_error "$env_vars" "./tests/rest_scripts/get_object.sh" "$5" "$6" "$7"; then + log 2 "error sending REST command and checking error" return 1 fi return 0 } get_object_rest_with_user() { - if [ $# -ne 5 ]; then - log 2 "'get_object_rest_with_user' requires username, password, bucket name, object name, output file" + if ! check_param_count_v2 "username, password, bucket name, object key, output file" 5 $#; then return 1 fi - if ! result=$(AWS_ACCESS_KEY_ID="$1" AWS_SECRET_ACCESS_KEY="$2" COMMAND_LOG="$COMMAND_LOG" BUCKET_NAME="$3" OBJECT_KEY="$4" OUTPUT_FILE="$5" ./tests/rest_scripts/get_object.sh 2>&1); then - log 2 "error getting object: $result" - return 1 - fi - if [ "$result" != "200" ]; then - log 2 "expected '200', was '$result' ($(cat "$3"))" + env_vars="AWS_ACCESS_KEY_ID=$1 AWS_SECRET_ACCESS_KEY=$2 BUCKET_NAME=$3 OBJECT_KEY=$4 OUTPUT_FILE=$5" + if ! send_rest_command_expect_success "$env_vars" "./tests/rest_scripts/get_object.sh" "200"; then + log 2 "error sending REST command and checking error" return 1 fi return 0 diff --git a/tests/commands/list_objects.sh b/tests/commands/list_objects.sh index 9f616a64..61b9bc5e 100644 --- a/tests/commands/list_objects.sh +++ b/tests/commands/list_objects.sh @@ -131,22 +131,27 @@ list_objects_with_prefix() { } list_objects_rest() { - if ! check_param_count "list_objects_rest" "bucket" 1 $#; then + if ! check_param_count_gt "bucket, callback, params (optional)" 2 $#; then return 1 fi - log 5 "bucket name: $1" - if ! result=$(COMMAND_LOG="$COMMAND_LOG" BUCKET_NAME="$1" OUTPUT_FILE="$TEST_FILE_FOLDER/objects.txt" ./tests/rest_scripts/list_objects.sh); then - log 2 "error listing objects: $result" - return 1 - fi - if [ "$result" != "200" ]; then - log 2 "expected '200', was '$result' ($(cat "$TEST_FILE_FOLDER/objects.txt"))" - return 1 - fi - # shellcheck disable=SC2034 - reply=$(cat "$TEST_FILE_FOLDER/objects.txt") - if ! parse_objects_list_rest; then - log 2 "error parsing list objects" + env_params="BUCKET_NAME=$1 $3" + log 5 "env params: $env_params" + if ! send_rest_command_expect_success_callback "$env_params" "./tests/rest_scripts/list_objects.sh" "200" "$2"; then + log 2 "error sending list objects REST command" return 1 fi + return 0 +} + +list_objects_rest_expect_error() { + if ! check_param_count_v2 "bucket name, env vars, response code, error, message" 5 $#; then + return 1 + fi + env_vars="BUCKET_NAME=$1 $2" + log 5 "env vars: $env_vars" + if ! send_rest_command_expect_error "$env_vars" "./tests/rest_scripts/list_objects.sh" "$3" "$4" "$5"; then + log 2 "error sending REST command and checking error" + return 1 + fi + return 0 } diff --git a/tests/commands/put_bucket_acl.sh b/tests/commands/put_bucket_acl.sh index 0e37e05f..f21415fe 100644 --- a/tests/commands/put_bucket_acl.sh +++ b/tests/commands/put_bucket_acl.sh @@ -116,15 +116,36 @@ put_bucket_canned_acl_with_user() { } put_bucket_acl_rest() { - if ! check_param_count "put_bucket_acl_rest" "bucket, ACL file" 2 $#; then + if ! check_param_count_v2 "bucket, ACL file" 2 $#; then return 1 fi - if ! result=$(COMMAND_LOG="$COMMAND_LOG" BUCKET_NAME="$1" ACL_FILE="$2" OUTPUT_FILE="$TEST_FILE_FOLDER/response.txt" ./tests/rest_scripts/put_bucket_acl.sh); then - log 2 "error attempting to put bucket acl: $result" + local put_bucket_acl_env_vars="BUCKET_NAME=$1 ACL_FILE=$2" + if ! send_rest_command_expect_success "$put_bucket_acl_env_vars" "./tests/rest_scripts/put_bucket_acl.sh" "200"; then + log 2 "error sending REST command and checking error" return 1 fi - if [ "$result" != "200" ]; then - log 5 "response returned code: $result (error: $(cat "$TEST_FILE_FOLDER/response.txt")" + return 0 +} + +put_bucket_acl_rest_expect_error() { + if ! check_param_count_v2 "bucket, ACL file, env params, response code, error code, message" 6 $#; then + return 1 + fi + local put_bucket_acl_env_vars="BUCKET_NAME=$1 ACL_FILE=$2 $3" + if ! send_rest_command_expect_error "$put_bucket_acl_env_vars" "./tests/rest_scripts/put_bucket_acl.sh" "$4" "$5" "$6"; then + log 2 "error sending REST command and checking error" + return 1 + fi + return 0 +} + +put_bucket_acl_rest_with_user() { + if ! check_param_count_v2 "username, password, bucket, ACL file" 4 $#; then + return 1 + fi + local put_bucket_acl_env_vars="AWS_ACCESS_KEY_ID=$1 AWS_SECRET_ACCESS_KEY=$2 BUCKET_NAME=$3 ACL_FILE=$4" + if ! send_rest_command_expect_success "$put_bucket_acl_env_vars" "./tests/rest_scripts/put_bucket_acl.sh" "200"; then + log 2 "error sending REST command and checking error" return 1 fi return 0 diff --git a/tests/commands/put_object.sh b/tests/commands/put_object.sh index d5cef2cc..24d9017c 100644 --- a/tests/commands/put_object.sh +++ b/tests/commands/put_object.sh @@ -70,29 +70,56 @@ put_object_with_user() { } put_object_rest() { - if [ $# -ne 3 ]; then - log 2 "'put_object_rest' requires local file, bucket name, key" + if ! check_param_count_gt "local file, bucket name, key, env vars (optional)" 3 $#; then return 1 fi - if ! put_object_rest_with_user "$AWS_ACCESS_KEY_ID" "$AWS_SECRET_ACCESS_KEY" "$1" "$2" "$3"; then - log 2 "error putting object with REST with root user" + env_vars="DATA_FILE=$1 BUCKET_NAME=$2 OBJECT_KEY=$3 $4" + if ! send_rest_command_expect_success "$env_vars" "./tests/rest_scripts/put_object.sh" "200"; then + log 2 "error sending REST command and checking error" + return 1 + fi + return 0 +} + +put_object_rest_special_chars() { + if ! check_param_count_v2 "local file, bucket name, key" 3 $#; then + return 1 + fi + # do this in case there are spaces in the name + if ! result=$(COMMAND_LOG="$COMMAND_LOG" OUTPUT_FILE="$TEST_FILE_FOLDER/error.txt" DATA_FILE="$1" BUCKET_NAME="$2" OBJECT_KEY="$3" ./tests/rest_scripts/put_object.sh 2>&1); then + log 2 "error sending put object command: $result" + return 1 + fi + if [ "$result" != "200" ]; then + log 2 "expected '200', was '$result' ($(cat "$TEST_FILE_FOLDER/error.txt"))" return 1 fi return 0 } put_object_rest_with_user() { - if [ $# -ne 5 ]; then - log 2 "'put_object_rest_with_user' requires username, password, local file, bucket name, key" + if ! check_param_count_gt "username, password, local file, bucket name, key, env vars (optional)" 5 $#; then return 1 fi - if ! put_object_rest_with_user_and_code "$1" "$2" "$3" "$4" "$5" "200"; then + if ! put_object_rest "$3" "$4" "$5" "AWS_ACCESS_KEY_ID=$1 AWS_SECRET_ACCESS_KEY=$2 $6"; then log 2 "error putting object with user '$1'" return 1 fi return 0 } +put_object_rest_expect_error() { + if ! check_param_count_gt "local file, bucket name, key, env vars, response code, error code, message" 7 $#; then + return 1 + fi + env_vars="DATA_FILE=$1 BUCKET_NAME=$2 OBJECT_KEY=$3 $4" + if ! send_rest_command_expect_error "$env_vars" "./tests/rest_scripts/put_object.sh" "$5" "$6" "$7"; then + log 2 "error sending REST command and checking error" + return 1 + fi + return 0 +} + put_object_rest_with_user_and_code() { if [ $# -ne 6 ]; then log 2 "'put_object_rest_with_user' requires username, password, local file, bucket name, key, expected response code" diff --git a/tests/drivers/create_bucket/create_bucket_rest.sh b/tests/drivers/create_bucket/create_bucket_rest.sh new file mode 100644 index 00000000..312df35e --- /dev/null +++ b/tests/drivers/create_bucket/create_bucket_rest.sh @@ -0,0 +1,113 @@ +#!/usr/bin/env bash + +# Copyright 2024 Versity Software +# This file is licensed under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http:#www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +source ./tests/drivers/get_bucket_acl/get_bucket_acl_rest.sh +source ./tests/drivers/get_object/get_object_rest.sh +source ./tests/drivers/put_bucket_acl/put_bucket_acl_rest.sh +source ./tests/drivers/put_object/put_object_rest.sh + +setup_and_create_bucket_and_check_acl() { + if [ "$RECREATE_BUCKETS" == "false" ]; then + skip "skip bucket create tests for static buckets" + fi + if ! check_param_count_v2 "grant env val" 1 $#; then + return 1 + fi + test_file="$test_file" + if ! bucket_cleanup_if_bucket_exists "$BUCKET_ONE_NAME"; then + log 2 "error cleaning up bucket" + return 1 + fi + + if ! create_versitygw_acl_user_or_get_direct_user "$USERNAME_ONE" "$PASSWORD_ONE"; then + log 2 "error creating user" + return 1 + fi + if [ "$DIRECT" == "true" ]; then + # shellcheck disable=SC2154 + id="id=$user_canonical_id" + else + id="$user_canonical_id" + fi + log 5 "owner: $AWS_ACCESS_KEY_ID" + log 5 "username=$username, password=$password" + envs="$1=$id OBJECT_OWNERSHIP=BucketOwnerPreferred" + log 5 "envs: $envs" + # shellcheck disable=SC2154 + if ! create_bucket_and_check_acl "$BUCKET_ONE_NAME" "$envs" "$username" "$password" "$user_canonical_id" "$owner_canonical_id"; then + log 2 "error creating bucket and checking ACL" + return 1 + fi + return 0 +} + +create_bucket_and_check_acl() { + if ! check_param_count_v2 "bucket name, env vars, username, password, user canonical ID, owner canonical ID" 6 $#; then + return 1 + fi + if ! create_bucket_rest_expect_success "$1" "$2"; then + log 2 "error creating bucket" + return 1 + fi + # cross-account changes take more time to propagate + if [ "$DIRECT" == "true" ]; then + sleep 10 + fi + if ! create_test_file "test_file"; then + log 2 "error creating file" + return 1 + fi + local read_acp=false + local read=false + local write_acp=false + local write=false + if [[ "$2" == *"GRANT_FULL_CONTROL="* ]]; then + read_acp=true + read=true + write_acp=true + write=true + elif [[ "$2" == *"GRANT_READ_ACP="* ]]; then + read_acp=true + elif [[ "$2" == *"GRANT_READ="* ]]; then + read=true + elif [[ "$2" == *"GRANT_WRITE_ACP="* ]]; then + write_acp=true + elif [[ "$2" == *"GRANT_WRITE="* ]]; then + write=true + fi + if ! get_bucket_acl_success_or_access_denied "$1" "$3" "$4" "$read_acp"; then + log 2 "get ACL permissions mismatch" + return 1 + fi + if ! put_object_success_or_access_denied "$3" "$4" "$TEST_FILE_FOLDER/test_file" "$1" "test_file" "$write"; then + log 2 "put object permissions mismatch" + return 1 + fi + if ! list_objects_success_or_access_denied "$3" "$4" "$1" "test_file" "$read"; then + log 2 "list objects permissions mismatch" + return 1 + fi + if ! setup_acl "$TEST_FILE_FOLDER/acl-file.txt" "CanonicalUser" "$5" "READ" "$6"; then + log 2 "error setting up ACL" + return 1 + fi + log 5 "acl file: $(cat "$TEST_FILE_FOLDER/acl-file.txt")" + if ! put_bucket_acl_success_or_access_denied "$1" "$TEST_FILE_FOLDER/acl-file.txt" "$3" "$4" "$write_acp"; then + log 2 "put ACL permissions mismatch" + return 1 + fi + return 0 +} \ No newline at end of file diff --git a/tests/drivers/get_bucket_acl/get_bucket_acl_rest.sh b/tests/drivers/get_bucket_acl/get_bucket_acl_rest.sh new file mode 100644 index 00000000..8e1d9a4a --- /dev/null +++ b/tests/drivers/get_bucket_acl/get_bucket_acl_rest.sh @@ -0,0 +1,75 @@ +#!/usr/bin/env bash + +# Copyright 2024 Versity Software +# This file is licensed under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http:#www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +get_bucket_acl_success_or_access_denied() { + if ! check_param_count_v2 "bucket, username, password, expect success" 4 $#; then + return 1 + fi + if [ "$4" == "true" ]; then + if ! get_bucket_acl_rest "$1" "AWS_ACCESS_KEY_ID=$2 AWS_SECRET_ACCESS_KEY=$3" "get_bucket_acl_data"; then + log 2 "expected GetBucketAcl to succeed, didn't" + return 1 + fi + else + if ! get_bucket_acl_rest_expect_error "$1" "AWS_ACCESS_KEY_ID=$2 AWS_SECRET_ACCESS_KEY=$3" "403" "AccessDenied" "Access Denied"; then + log 2 "expected GetBucketAcl access denied" + return 1 + fi + fi + return 0 +} + +get_bucket_acl_data() { + if ! check_param_count_v2 "data file" 1 $#; then + return 1 + fi + bucket_acl_data="$(cat "$1")" + log 5 "bucket acl data: $bucket_acl_data" + return 0 +} + +check_that_acl_xml_does_not_have_owner_permission() { + if ! check_param_count_v2 "data file" 1 $#; then + return 1 + fi + if [ "$DIRECT" == "true" ]; then + owner_id="$AWS_CANONICAL_ID" + else + owner_id="$AWS_ACCESS_KEY_ID" + fi + if ! grant="$(xmllint --xpath "//*[local-name()='AccessControlPolicy']/*[local-name()='AccessControlList']/*[local-name()='Grant'][*[local-name()='Grantee']/*[local-name()='ID' and text()='${owner_id}']]" "$1" 2>&1)"; then + if [[ "$grant" != *"XPath set is empty"* ]]; then + log 2 "error getting grant: $grant" + return 1 + fi + else + log 2 "root account shouldn't have grant in this case (grant: $grant)" + return 1 + fi + return 0 +} + +check_for_display_name() { + if ! check_param_count_v2 "data file" 1 $#; then + return 1 + fi + log 5 "data: $(cat "$1")" + if ! display_name="$(xmllint --xpath "//*[local-name()='AccessControlPolicy']/*[local-name()='Owner']/*[local-name()='DisplayName']" "$1" 2>&1)"; then + log 2 "error getting display name: $display_name" + return 1 + fi + return 0 +} diff --git a/tests/drivers/get_object/get_object_rest.sh b/tests/drivers/get_object/get_object_rest.sh new file mode 100644 index 00000000..448e21a7 --- /dev/null +++ b/tests/drivers/get_object/get_object_rest.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env bash + +# Copyright 2024 Versity Software +# This file is licensed under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http:#www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +get_object_success_or_access_denied() { + if ! check_param_count_v2 "username, password, bucket, key, output file, expect success" 6 $#; then + return 1 + fi + if [ "$6" == "true" ]; then + if ! get_object_rest_with_user "$1" "$2" "$3" "$4" "$5"; then + log 2 "expected GetObject to succeed, didn't" + return 1 + fi + else + if ! get_object_rest_expect_error "$3" "$4" "$5" "AWS_ACCESS_KEY_ID=$1 AWS_SECRET_ACCESS_KEY=$2" "403" "AccessDenied" "Access Denied"; then + log 2 "expected GetObject access denied" + return 1 + fi + fi + return 0 +} \ No newline at end of file diff --git a/tests/drivers/list_objects/list_objects_rest.sh b/tests/drivers/list_objects/list_objects_rest.sh index 5ff834c1..e106b795 100644 --- a/tests/drivers/list_objects/list_objects_rest.sh +++ b/tests/drivers/list_objects/list_objects_rest.sh @@ -21,7 +21,7 @@ list_and_delete_objects() { if ! check_param_count "list_and_delete_objects" "bucket" 1 $#; then return 1 fi - if ! list_objects 'rest' "$1"; then + if ! list_objects_rest "$1" "parse_objects_list_rest"; then log 2 "error getting object list" return 1 fi @@ -40,3 +40,41 @@ list_and_delete_objects() { fi return 0 } + +list_check_single_object() { + if ! check_param_count_gt "bucket, key, env params (optional)" 2 $#; then + return 1 + fi + if ! list_objects_rest "$1" "parse_objects_list_rest" "$3"; then + log 2 "error listing objects" + return 1 + fi + if [ ${#object_array[@]} -ne "1" ]; then + log 2 "expected one object, found ${#object_array[@]}" + return 1 + fi + if [ "${object_array[0]}" != "$2" ]; then + log 2 "expected '$2', was '${object_array[0]}'" + return 1 + fi + return 0 +} + +list_objects_success_or_access_denied() { + if ! check_param_count_v2 "username, password, bucket, key, expect success" 5 $#; then + return 1 + fi + log 5 "true or false: $5" + if [ "$5" == "true" ]; then + if ! list_check_single_object "$3" "$4" "AWS_ACCESS_KEY_ID=$1 AWS_SECRET_ACCESS_KEY=$2"; then + log 2 "expected ListObjects to succeed, didn't" + return 1 + fi + else + if ! list_objects_rest_expect_error "$3" "AWS_ACCESS_KEY_ID=$1 AWS_SECRET_ACCESS_KEY=$2" "403" "AccessDenied" "Access Denied"; then + log 2 "expected ListObjects access denied" + return 1 + fi + fi + return 0 +} diff --git a/tests/drivers/put_bucket_acl/put_bucket_acl_rest.sh b/tests/drivers/put_bucket_acl/put_bucket_acl_rest.sh new file mode 100644 index 00000000..b9d49ab1 --- /dev/null +++ b/tests/drivers/put_bucket_acl/put_bucket_acl_rest.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env bash + +# Copyright 2024 Versity Software +# This file is licensed under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http:#www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +put_bucket_acl_success_or_access_denied() { + if ! check_param_count_v2 "bucket, acl file, username, password, expect success" 5 $#; then + return 1 + fi + if [ "$5" == "true" ]; then + if ! put_bucket_acl_rest_with_user "$3" "$4" "$1" "$2"; then + log 2 "expected PutBucketAcl to succeed, didn't" + return 1 + fi + else + if ! put_bucket_acl_rest_expect_error "$1" "$2" "AWS_ACCESS_KEY_ID=$3 AWS_SECRET_ACCESS_KEY=$4" "403" "AccessDenied" "Access Denied"; then + log 2 "expected PutBucketAcl access denied" + return 1 + fi + fi + return 0 +} diff --git a/tests/drivers/put_object/put_object_rest.sh b/tests/drivers/put_object/put_object_rest.sh new file mode 100644 index 00000000..e644fe69 --- /dev/null +++ b/tests/drivers/put_object/put_object_rest.sh @@ -0,0 +1,37 @@ +#!/usr/bin/env bash + +# Copyright 2024 Versity Software +# This file is licensed under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http:#www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +put_object_success_or_access_denied() { + if ! check_param_count_v2 "username, password, data file, bucket, key, expect success" 6 $#; then + return 1 + fi + if [ "$6" == "true" ]; then + if ! put_object_rest_with_user "$1" "$2" "$3" "$4" "$5"; then + log 2 "expected PutObject to succeed, didn't" + return 1 + fi + else + if ! put_object_rest_expect_error "$3" "$4" "$5" "AWS_ACCESS_KEY_ID=$1 AWS_SECRET_ACCESS_KEY=$2" "403" "AccessDenied" "Access Denied"; then + log 2 "expected GetBucketAcl access denied" + return 1 + fi + if ! put_object_rest "$3" "$4" "$5"; then + log 2 "error putting object with root account" + return 1 + fi + fi + return 0 +} \ No newline at end of file diff --git a/tests/drivers/rest.sh b/tests/drivers/rest.sh index 291d0ca1..39e20b63 100644 --- a/tests/drivers/rest.sh +++ b/tests/drivers/rest.sh @@ -32,10 +32,18 @@ check_rest_expected_error() { } send_rest_command() { - if ! check_param_count_v2 "env vars, script, output file" 3 $#; then + if ! check_param_count_v2 "env vars, script" 2 $#; then return 1 fi - local env_array=("env" "COMMAND_LOG=$COMMAND_LOG" "OUTPUT_FILE=$3") + if [[ "$1" == *"OUTPUT_FILE"* ]]; then + if ! output_file=$(echo -n "$1" | sed -n 's/^.*OUTPUT_FILE=\([^ ]*\).*$/\1/p' 2>&1); then + log 2 "error getting output file: $output_file" + fi + log 5 "output file: $output_file" + else + output_file="$TEST_FILE_FOLDER/output.txt" + fi + local env_array=("env" "COMMAND_LOG=$COMMAND_LOG" "OUTPUT_FILE=$output_file") if [ "$1" != "" ]; then IFS=' ' read -r -a env_vars <<< "$1" env_array+=("${env_vars[@]}") @@ -51,8 +59,7 @@ send_rest_command_expect_error() { if ! check_param_count_v2 "env vars, script, response code, error, message" 5 $#; then return 1 fi - output_file="$TEST_FILE_FOLDER/error.txt" - if ! send_rest_command "$1" "$2" "$output_file"; then + if ! send_rest_command "$1" "$2"; then log 2 "error sending REST command" return 1 fi @@ -67,13 +74,12 @@ send_rest_command_expect_success() { if ! check_param_count_v2 "env vars, script, response code" 3 $#; then return 1 fi - output_file="$TEST_FILE_FOLDER/error.txt" - if ! send_rest_command "$1" "$2" "$output_file"; then + if ! send_rest_command "$1" "$2"; then log 2 "error sending REST command" return 1 fi if [ "$result" != "$3" ]; then - log 2 "expected '$3', was '$result' ($(cat "$TEST_FILE_FOLDER/error.txt"))" + log 2 "expected '$3', was '$result' ($(cat "$output_file"))" return 1 fi return 0 diff --git a/tests/logger.sh b/tests/logger.sh index 8f043ed1..c23dcffe 100644 --- a/tests/logger.sh +++ b/tests/logger.sh @@ -142,9 +142,9 @@ check_arg_for_mask() { elif [[ "$arg" == --access_key=* ]]; then masked_args+=("${arg:0:17}****") elif [[ "$arg" == *"Credential="* ]]; then - masked_args+=("$(echo "$arg" | sed -E 's/(Credential=[A-Z]{4})[^\/]*/\1****/g')") + masked_args+=("$(echo "$arg" | sed -E 's/(Credential=[A-Z]{5})[^\/]*/\1*****/g')") elif [[ "$arg" == *"AWS_ACCESS_KEY_ID="* ]]; then - masked_args+=("AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID:0:4}****") + masked_args+=("AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID:0:5}****") else if [[ "$arg" == "--secret_key" ]] || [[ "$arg" == "--secret" ]] || [[ "$arg" == "--s3-iam-secret" ]]; then mask_next=true diff --git a/tests/rest_scripts/create_bucket.sh b/tests/rest_scripts/create_bucket.sh index 09e85e15..e154c62f 100755 --- a/tests/rest_scripts/create_bucket.sh +++ b/tests/rest_scripts/create_bucket.sh @@ -25,6 +25,14 @@ acl="$ACL" object_ownership="$OBJECT_OWNERSHIP" # shellcheck disable=SC2153 grant_full_control="$GRANT_FULL_CONTROL" +# shellcheck disable=SC2153 +grant_read="$GRANT_READ" +# shellcheck disable=SC2153 +grant_read_acp="$GRANT_READ_ACP" +# shellcheck disable=SC2153 +grant_write="$GRANT_WRITE" +# shellcheck disable=SC2153 +grant_write_acp="$GRANT_WRITE_ACP" current_date_time=$(date -u +"%Y%m%dT%H%M%SZ") @@ -36,6 +44,18 @@ cr_data+=("x-amz-content-sha256:UNSIGNED-PAYLOAD" "x-amz-date:$current_date_time if [ "$grant_full_control" != "" ]; then cr_data+=("x-amz-grant-full-control:$grant_full_control") fi +if [ "$grant_read" != "" ]; then + cr_data+=("x-amz-grant-read:$grant_read") +fi +if [ "$grant_read_acp" != "" ]; then + cr_data+=("x-amz-grant-read-acp:$grant_read_acp") +fi +if [ "$grant_write" != "" ]; then + cr_data+=("x-amz-grant-write:$grant_write") +fi +if [ "$grant_write_acp" != "" ]; then + cr_data+=("x-amz-grant-write-acp:$grant_write_acp") +fi if [ "$object_ownership" != "" ]; then cr_data+=("x-amz-object-ownership:$object_ownership") fi diff --git a/tests/test_rest.sh b/tests/test_rest.sh index d6f2275b..9579beff 100755 --- a/tests/test_rest.sh +++ b/tests/test_rest.sh @@ -447,13 +447,16 @@ test_file="test_file" run setup_bucket_and_file "$BUCKET_ONE_NAME" "$file_name" assert_success - run put_object_rest "$TEST_FILE_FOLDER/$file_name" "$BUCKET_ONE_NAME" "$file_name/$file_name" + run put_object_rest_special_chars "$TEST_FILE_FOLDER/$file_name" "$BUCKET_ONE_NAME" "$file_name/$file_name" assert_success run list_check_single_object "$BUCKET_ONE_NAME" "$file_name/$file_name" assert_success - run download_and_compare_file "$TEST_FILE_FOLDER/$file_name" "$BUCKET_ONE_NAME" "$file_name/$file_name" "$TEST_FILE_FOLDER/${file_name}-copy" + run get_object_rest_special_chars "$BUCKET_ONE_NAME" "$file_name/$file_name" "$TEST_FILE_FOLDER/${file_name}-copy" + assert_success + + run compare_files "$TEST_FILE_FOLDER/$file_name" "$TEST_FILE_FOLDER/${file_name}-copy" assert_success run delete_object_rest "$BUCKET_ONE_NAME" "$file_name/$file_name" diff --git a/tests/test_rest_acl.sh b/tests/test_rest_acl.sh index 8a620ebf..f217f06d 100755 --- a/tests/test_rest_acl.sh +++ b/tests/test_rest_acl.sh @@ -18,10 +18,13 @@ load ./bats-support/load load ./bats-assert/load source ./tests/commands/put_object.sh +source ./tests/drivers/create_bucket/create_bucket_rest.sh +source ./tests/drivers/get_bucket_acl/get_bucket_acl_rest.sh source ./tests/logger.sh source ./tests/setup.sh source ./tests/util/util_acl.sh source ./tests/util/util_object.sh +source ./tests/util/util_public_access_block.sh source ./tests/util/util_setup.sh export RUN_USERS=true @@ -177,3 +180,41 @@ fi run put_bucket_acl_rest_canned_invalid "$BUCKET_ONE_NAME" "privatee" assert_success } + +@test "REST - FULL_CONTROL permission not returned for owner after CreateBucket with GRANT_READ_ACP" { + if [ "$DIRECT" != "true" ]; then + skip "https://github.com/versity/versitygw/issues/1407" + fi + run create_versitygw_acl_user_or_get_direct_user "$USERNAME_ONE" "$PASSWORD_ONE" + assert_success + canonical_id=${lines[0]} + user_canonical_id=${lines[1]} + username=${lines[2]} + password=${lines[3]} + + run bucket_cleanup_if_bucket_exists "$BUCKET_ONE_NAME" + assert_success + if [ "$DIRECT" == "true" ]; then + id="id=$user_canonical_id" + else + id="$user_canonical_id" + fi + + envs="GRANT_READ_ACP=$id OBJECT_OWNERSHIP=BucketOwnerPreferred" + run create_bucket_rest_expect_success "$BUCKET_ONE_NAME" "$envs" + assert_success + + run get_bucket_acl_rest "$BUCKET_ONE_NAME" "" "check_that_acl_xml_does_not_have_owner_permission" + assert_success +} + +@test "GetBucketAcl - DisplayName" { + if [ "$DIRECT" != "true" ]; then + skip "https://github.com/versity/versitygw/issues/1414" + fi + run setup_bucket "$BUCKET_ONE_NAME" + assert_success + + run get_bucket_acl_rest "$BUCKET_ONE_NAME" "" "check_for_display_name" + assert_success +} \ No newline at end of file diff --git a/tests/test_rest_bucket.sh b/tests/test_rest_bucket.sh index 7bdc72c3..17c06d65 100755 --- a/tests/test_rest_bucket.sh +++ b/tests/test_rest_bucket.sh @@ -20,6 +20,7 @@ load ./bats-assert/load source ./tests/commands/get_object_lock_configuration.sh source ./tests/commands/head_bucket.sh source ./tests/commands/list_buckets.sh +source ./tests/drivers/create_bucket/create_bucket_rest.sh source ./tests/drivers/list_buckets/list_buckets_rest.sh source ./tests/logger.sh source ./tests/setup.sh @@ -314,4 +315,29 @@ export RUN_USERS=true run check_for_buckets_with_multiple_pages "$BUCKET_ONE_NAME" "$BUCKET_TWO_NAME" assert_success -} \ No newline at end of file +} + +@test "REST - CreateBucket - x-amz-grant-full-control - success w/tests" { + run setup_and_create_bucket_and_check_acl "GRANT_FULL_CONTROL" + assert_success +} + +@test "REST - CreateBucket - x-amz-grant-read" { + run setup_and_create_bucket_and_check_acl "GRANT_READ" + assert_success +} + +@test "REST - CreateBucket - x-amz-grant-write" { + run setup_and_create_bucket_and_check_acl "GRANT_WRITE" + assert_success +} + +@test "REST - CreateBucket - x-amz-grant-read-acp" { + run setup_and_create_bucket_and_check_acl "GRANT_READ_ACP" + assert_success +} + +@test "REST - CreateBucket - x-amz-grant-write-acp" { + run setup_and_create_bucket_and_check_acl "GRANT_WRITE_ACP" + assert_success +} diff --git a/tests/test_rest_multipart.sh b/tests/test_rest_multipart.sh index e9448310..90c8fa1a 100755 --- a/tests/test_rest_multipart.sh +++ b/tests/test_rest_multipart.sh @@ -283,9 +283,9 @@ test_file="test_file" } @test "REST - multipart - x-amz-checksum-algorithm is ignored in CompleteMultipartUpload" { - if [ "$DIRECT" != "true" ]; then - skip "https://github.com/versity/versitygw/issues/1345" - fi + #if [ "$DIRECT" != "true" ]; then + # skip "https://github.com/versity/versitygw/issues/1345" + #fi run test_complete_multipart_upload_unneeded_algorithm_parameter "$BUCKET_ONE_NAME" "$test_file" "FULL_OBJECT" "CRC32C" assert_success } diff --git a/tests/util/util_acl.sh b/tests/util/util_acl.sh index 7468f652..501bc063 100644 --- a/tests/util/util_acl.sh +++ b/tests/util/util_acl.sh @@ -234,16 +234,19 @@ get_and_check_acl_rest() { log 2 "'get_and_check_acl_rest' requires bucket name" return 1 fi - if ! result=$(COMMAND_LOG="$COMMAND_LOG" BUCKET_NAME="$1" OUTPUT_FILE="$TEST_FILE_FOLDER/acl.txt" ./tests/rest_scripts/get_bucket_acl.sh); then - log 2 "error attempting to get bucket ACL response: $result" + if ! get_bucket_acl_rest "$1" "" "check_acl_rest"; then + log 2 "error getting and checking acl" return 1 fi - if [ "$result" != "200" ]; then - log 2 "get acl returned code '$result' (message: $(cat "$TEST_FILE_FOLDER/acl.txt"))" + return 0 +} + +check_acl_rest() { + if ! check_param_count_v2 "acl file" 1 $#; then return 1 fi - log 5 "acl: $(cat "$TEST_FILE_FOLDER/acl.txt")" - if ! access_control_policy=$(xmllint --xpath '//*[local-name()="AccessControlPolicy"]' "$TEST_FILE_FOLDER/acl.txt" 2>&1); then + log 5 "acl: $(cat "$1")" + if ! access_control_policy=$(xmllint --xpath '//*[local-name()="AccessControlPolicy"]' "$1" 2>&1); then log 2 "error getting access control policy: $access_control_policy" return 1 fi @@ -323,22 +326,26 @@ create_versitygw_acl_user_or_get_direct_user() { log 2 "direct ACL calls require the following env vars: AWS_CANONICAL_ID, ACL_AWS_CANONICAL_ID, ACL_AWS_ACCESS_KEY_ID, ACL_AWS_SECRET_ACCESS_KEY" return 1 fi - echo "$AWS_CANONICAL_ID" - echo "$ACL_AWS_CANONICAL_ID" - echo "$ACL_AWS_ACCESS_KEY_ID" - echo "$ACL_AWS_SECRET_ACCESS_KEY" + owner_canonical_id="$AWS_CANONICAL_ID" + user_canonical_id="$ACL_AWS_CANONICAL_ID" + username="$ACL_AWS_ACCESS_KEY_ID" + password="$ACL_AWS_SECRET_ACCESS_KEY" else - echo "$AWS_ACCESS_KEY_ID" + owner_canonical_id="$AWS_ACCESS_KEY_ID" if ! create_user_versitygw "$1" "$2" "user"; then log 2 "error creating versitygw user" return 1 fi # shellcheck disable=SC2154 - echo "$1" - echo "$1" + user_canonical_id="$1" + username="$1" # shellcheck disable=SC2154 - echo "$2" + password="$2" fi + echo "$owner_canonical_id" + echo "$user_canonical_id" + echo "$username" + echo "$password" } put_invalid_acl_rest_verify_failure() { diff --git a/tests/util/util_list_objects.sh b/tests/util/util_list_objects.sh index 3b4d39c5..ea787c0a 100644 --- a/tests/util/util_list_objects.sh +++ b/tests/util/util_list_objects.sh @@ -18,10 +18,12 @@ source ./tests/util/util_xml.sh # under the License. parse_objects_list_rest() { + if ! check_param_count_v2 "data file" 1 $#; then + return 1 + fi object_array=() # shellcheck disable=SC2154 - log 5 "reply: $reply" - if ! object_list=$(echo "$reply" | xmllint --xpath '//*[local-name()="Key"]/text()' - 2>&1); then + if ! object_list=$(xmllint --xpath '//*[local-name()="Key"]/text()' "$1" 2>&1); then if [[ "$object_list" == *"XPath set is empty"* ]]; then return 0 fi @@ -37,25 +39,6 @@ parse_objects_list_rest() { return 0 } -list_check_single_object() { - if ! check_param_count "list_check_single_object" "bucket, key" 2 $#; then - return 1 - fi - if ! list_objects "rest" "$1"; then - log 2 "error listing objects" - return 1 - fi - if [ ${#object_array[@]} -ne "1" ]; then - log 2 "expected one object, found ${#object_array[@]}" - return 1 - fi - if [ "${object_array[0]}" != "$2" ]; then - log 2 "expected '$2', was '${object_array[0]}'" - return 1 - fi - return 0 -} - list_check_objects_v1() { if ! check_param_count "list_check_objects_v1" "bucket, expected key one, expected size one, expected key two, expected size two" 5 $#; then return 1 @@ -129,7 +112,7 @@ list_check_objects_rest() { if ! check_param_count "list_check_objects_rest" "bucket" 1 $#; then return 1 fi - list_objects "rest" "$1" + list_objects_rest "$1" "parse_objects_list_rest" object_found=false # shellcheck disable=SC2154 for object in "${object_array[@]}"; do diff --git a/tests/util/util_xml.sh b/tests/util/util_xml.sh index cae5ac50..7a0183f5 100644 --- a/tests/util/util_xml.sh +++ b/tests/util/util_xml.sh @@ -1,14 +1,26 @@ #!/usr/bin/env bash build_xpath_string() { + if ! check_param_count_gt "XML tree" 1 $#; then + return 1 + fi + if ! build_xpath_string_for_element "$@"; then + return 1 + fi + xpath+='/text()' +} + +build_xpath_string_for_element() { if ! check_param_count_gt "XML tree" 1 $#; then return 1 fi xpath='//' - for tree_val in "$@"; do - xpath+='*[local-name()="'$tree_val'"]/' + for ((idx=1;idx<=$#;idx++)); do + xpath+='*[local-name()="'${!idx}'"]' + if [ "$idx" != $# ]; then + xpath+='/' + fi done - xpath+='text()' } check_for_empty_element() { @@ -27,6 +39,22 @@ check_for_empty_element() { return 1 } +get_element() { + if ! check_param_count_gt "data file, XML tree" 2 $#; then + return 1 + fi + + if ! build_xpath_string_for_element "${@:2}"; then + log 2 "error building XPath search string" + return 1 + fi + if ! xml_val=$(grep '<[^/][^ >]*>' "$1" | xmllint --xpath "$xpath" - 2>&1); then + log 2 "error getting XML value matching $xpath: $xml_val (file data: $(cat "$1"))" + return 1 + fi + echo "$xml_val" +} + get_element_text() { if [ $# -lt 2 ]; then log 2 "'get_element_text' requires data file, XML tree" @@ -39,6 +67,7 @@ get_element_text() { fi log 5 "data: $(cat "$1")" + log 5 "xml data: $(grep '<[^/][^ >]*>' "$1")" if ! xml_val=$(grep '<[^/][^ >]*>' "$1" | xmllint --xpath "$xpath" - 2>&1); then log 2 "error getting XML value matching $xpath: $xml_val (file data: $(cat "$1"))" return 1