diff --git a/tests/commands/put_bucket_acl.sh b/tests/commands/put_bucket_acl.sh index d26ecbf8..fa3ff2aa 100644 --- a/tests/commands/put_bucket_acl.sh +++ b/tests/commands/put_bucket_acl.sh @@ -58,22 +58,15 @@ reset_bucket_acl() { return 1 fi # shellcheck disable=SC2154 - cat < "$TEST_FILE_FOLDER/$acl_file" -{ - "Grants": [ - { - "Grantee": { - "ID": "$AWS_ACCESS_KEY_ID", - "Type": "CanonicalUser" - }, - "Permission": "FULL_CONTROL" - } - ], - "Owner": { - "ID": "$AWS_ACCESS_KEY_ID" - } -} -EOF + if [ "$DIRECT" != "true" ]; then + if ! setup_acl_json "$TEST_FILE_FOLDER/$acl_file" "ID" "$AWS_ACCESS_KEY_ID" "FULL_CONTROL" "$AWS_ACCESS_KEY_ID"; then + log 2 "error resetting versitygw ACL" + return 1 + fi + elif ! setup_acl_json "$TEST_FILE_FOLDER/$acl_file" "ID" "$AWS_CANONICAL_ID" "FULL_CONTROL" "$AWS_CANONICAL_ID"; then + log 2 "error resetting direct ACL" + return 1 + fi if ! put_bucket_acl_s3api "$BUCKET_ONE_NAME" "$TEST_FILE_FOLDER/$acl_file"; then log 2 "error putting bucket acl (s3api)" return 1 diff --git a/tests/env.sh b/tests/env.sh index df378b44..03f9fa2f 100644 --- a/tests/env.sh +++ b/tests/env.sh @@ -123,6 +123,14 @@ check_universal_vars() { log 1 "RECREATE_BUCKETS must be 'true' or 'false'" exit 1 fi + if [ "$RECREATE_BUCKETS" != "true" ] && [ "$RECREATE_BUCKETS" != "false" ]; then + log 1 "RECREATE_BUCKETS must be 'true' or 'false'" + exit 1 + fi + if [ "$RECREATE_BUCKETS" == "false" ] && [ "$DELETE_BUCKETS_AFTER_TEST" == "true" ]; then + log 1 "cannot set DELETE_BUCKETS_AFTER_TEST to 'true' if RECREATE_BUCKETS is 'false'" + return 1 + fi if [ -z "$TEST_FILE_FOLDER" ]; then log 1 "TEST_FILE_FOLDER missing" exit 1 @@ -135,6 +143,10 @@ check_universal_vars() { fi # exporting these since they're needed for subshells export AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_REGION AWS_PROFILE AWS_ENDPOINT_URL + if [ -n "$AWS_CANONICAL_ID" ]; then + log 5 "canonical ID: $AWS_CANONICAL_ID" + export AWS_CANONICAL_ID + fi } delete_command_log() { diff --git a/tests/rest_scripts/get_object.sh b/tests/rest_scripts/get_object.sh new file mode 100755 index 00000000..8ce678ca --- /dev/null +++ b/tests/rest_scripts/get_object.sh @@ -0,0 +1,47 @@ +#!/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/rest_scripts/rest.sh + +# Fields + +# shellcheck disable=SC2153 +bucket_name="$BUCKET_NAME" +# shellcheck disable=SC2154 +key="$OBJECT_KEY" + +current_date_time=$(date -u +"%Y%m%dT%H%M%SZ") + +#x-amz-object-attributes:ETag +canonical_request="GET +/$bucket_name/$key + +host:$host +x-amz-content-sha256:UNSIGNED-PAYLOAD +x-amz-date:$current_date_time + +host;x-amz-content-sha256;x-amz-date +UNSIGNED-PAYLOAD" + +create_canonical_hash_sts_and_signature + +curl_command+=(curl -ks -w "\"%{http_code}\"" "$AWS_ENDPOINT_URL/$bucket_name/$key" +-H "\"Authorization: AWS4-HMAC-SHA256 Credential=$aws_access_key_id/$year_month_day/$aws_region/s3/aws4_request,SignedHeaders=host;x-amz-content-sha256;x-amz-date,Signature=$signature\"" +-H "\"x-amz-content-sha256: UNSIGNED-PAYLOAD\"" +-H "\"x-amz-date: $current_date_time\"" +-o "$OUTPUT_FILE") +# shellcheck disable=SC2154 +eval "${curl_command[*]}" 2>&1 \ No newline at end of file diff --git a/tests/rest_scripts/list_objects.sh b/tests/rest_scripts/list_objects.sh new file mode 100755 index 00000000..d39743e2 --- /dev/null +++ b/tests/rest_scripts/list_objects.sh @@ -0,0 +1,45 @@ +#!/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/rest_scripts/rest.sh + +# Fields + +# shellcheck disable=SC2153 +bucket_name="$BUCKET_NAME" + +current_date_time=$(date -u +"%Y%m%dT%H%M%SZ") + +#x-amz-object-attributes:ETag +canonical_request="GET +/$bucket_name + +host:$host +x-amz-content-sha256:UNSIGNED-PAYLOAD +x-amz-date:$current_date_time + +host;x-amz-content-sha256;x-amz-date +UNSIGNED-PAYLOAD" + +create_canonical_hash_sts_and_signature + +curl_command+=(curl -ks -w "\"%{http_code}\"" "$AWS_ENDPOINT_URL/$bucket_name" +-H "\"Authorization: AWS4-HMAC-SHA256 Credential=$aws_access_key_id/$year_month_day/$aws_region/s3/aws4_request,SignedHeaders=host;x-amz-content-sha256;x-amz-date,Signature=$signature\"" +-H "\"x-amz-content-sha256: UNSIGNED-PAYLOAD\"" +-H "\"x-amz-date: $current_date_time\"" +-o "$OUTPUT_FILE") +# shellcheck disable=SC2154 +eval "${curl_command[*]}" 2>&1 diff --git a/tests/rest_scripts/put_bucket_acl.sh b/tests/rest_scripts/put_bucket_acl.sh new file mode 100755 index 00000000..112ba9bb --- /dev/null +++ b/tests/rest_scripts/put_bucket_acl.sh @@ -0,0 +1,51 @@ +#!/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/rest_scripts/rest.sh + +# Fields + +# shellcheck disable=SC2153 +bucket_name="$BUCKET_NAME" +# shellcheck disable=SC2153 +acl_file="$ACL_FILE" + +payload="$(cat "$acl_file")" + +payload_hash="$(echo -n "$payload" | sha256sum | awk '{print $1}')" +current_date_time=$(date -u +"%Y%m%dT%H%M%SZ") + +canonical_request="PUT +/$bucket_name +acl= +host:$host +x-amz-content-sha256:$payload_hash +x-amz-date:$current_date_time + +host;x-amz-content-sha256;x-amz-date +$payload_hash" + +create_canonical_hash_sts_and_signature + +curl_command+=(curl -ks -w "\"%{http_code}\"" -X PUT "$AWS_ENDPOINT_URL/$bucket_name?acl=" +-H "\"Authorization: AWS4-HMAC-SHA256 Credential=$aws_access_key_id/$year_month_day/$aws_region/s3/aws4_request,SignedHeaders=host;x-amz-content-sha256;x-amz-date,Signature=$signature\"" +-H "\"x-amz-content-sha256: $payload_hash\"" +-H "\"x-amz-date: $current_date_time\"" +-d "\"${payload//\"/\\\"}\"" +-o "$OUTPUT_FILE") + +# shellcheck disable=SC2154 +eval "${curl_command[*]}" 2>&1 diff --git a/tests/test_common_acl.sh b/tests/test_common_acl.sh index cb5ea145..8af4697b 100644 --- a/tests/test_common_acl.sh +++ b/tests/test_common_acl.sh @@ -52,8 +52,7 @@ test_common_put_bucket_acl() { run put_bucket_ownership_controls "$BUCKET_ONE_NAME" "BucketOwnerPreferred" assert_success - username=$USERNAME_ONE - run setup_user "$username" "HIJKLMN" "user" + run setup_user "$USERNAME_ONE" "$PASSWORD_ONE" "user" assert_success run get_check_acl_id "$1" "$BUCKET_ONE_NAME" @@ -64,24 +63,14 @@ test_common_put_bucket_acl() { assert_success if [[ $DIRECT == "true" ]]; then - grantee="{\"Type\": \"Group\", \"URI\": \"http://acs.amazonaws.com/groups/global/AllUsers\"}" + grantee_type="Group" + grantee_id="http://acs.amazonaws.com/groups/global/AllUsers" else - grantee="{\"ID\": \"$username\", \"Type\": \"CanonicalUser\"}" + grantee_type="ID" + grantee_id="$USERNAME_ONE" fi - -cat < "$TEST_FILE_FOLDER"/"$acl_file" - { - "Grants": [ - { - "Grantee": $grantee, - "Permission": "READ" - } - ], - "Owner": { - "ID": "$AWS_ACCESS_KEY_ID" - } - } -EOF + run setup_acl_json "$TEST_FILE_FOLDER/$acl_file" "$grantee_type" "$grantee_id" "READ" "$AWS_ACCESS_KEY_ID" + assert_success run put_bucket_acl_s3api "$BUCKET_ONE_NAME" "$TEST_FILE_FOLDER"/"$acl_file" assert_success @@ -89,22 +78,8 @@ EOF run get_check_acl_after_first_put "$1" "$BUCKET_ONE_NAME" assert_success -cat < "$TEST_FILE_FOLDER"/"$acl_file" - { - "Grants": [ - { - "Grantee": { - "ID": "$username", - "Type": "CanonicalUser" - }, - "Permission": "FULL_CONTROL" - } - ], - "Owner": { - "ID": "$AWS_ACCESS_KEY_ID" - } - } -EOF + run setup_acl_json "$TEST_FILE_FOLDER/$acl_file" "ID" "$USERNAME_ONE" "FULL_CONTROL" "$AWS_ACCESS_KEY_ID" + assert_success run put_bucket_acl_s3api "$BUCKET_ONE_NAME" "$TEST_FILE_FOLDER"/"$acl_file" assert_success diff --git a/tests/test_rest.sh b/tests/test_rest.sh index 0c312e38..76403393 100755 --- a/tests/test_rest.sh +++ b/tests/test_rest.sh @@ -452,4 +452,42 @@ export RUN_USERS=true run get_and_check_acl_rest "$BUCKET_ONE_NAME" assert_success +} + +@test "REST - put ACL" { + run setup_bucket "s3api" "$BUCKET_ONE_NAME" + assert_success + + test_file="test_file" + run create_test_files "$test_file" + assert_success + + run put_bucket_ownership_controls "$BUCKET_ONE_NAME" "BucketOwnerPreferred" + assert_success + + run put_object "s3api" "$TEST_FILE_FOLDER/$test_file" "$BUCKET_ONE_NAME" "$test_file" + assert_success + + 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 setup_acl "$TEST_FILE_FOLDER/acl-file.txt" "$user_canonical_id" "READ" "$canonical_id" + assert_success + + run list_objects_with_user_rest_verify_access_denied "$BUCKET_ONE_NAME" "$username" "$password" + assert_success + + run put_acl_rest "$BUCKET_ONE_NAME" "$TEST_FILE_FOLDER/acl-file.txt" + assert_success + + if [ "$DIRECT" == "true" ]; then + sleep 5 + fi + + run list_objects_with_user_rest_verify_success "$BUCKET_ONE_NAME" "$username" "$password" "$test_file" + assert_success } \ No newline at end of file diff --git a/tests/test_s3api_policy_object.sh b/tests/test_s3api_policy_object.sh index eebd7cec..84120297 100644 --- a/tests/test_s3api_policy_object.sh +++ b/tests/test_s3api_policy_object.sh @@ -323,15 +323,10 @@ test_s3api_policy_put_wildcard() { username=${lines[0]} password=${lines[1]} - effect="Allow" - principal="$username" - action="s3:PutObject" - resource="arn:aws:s3:::$BUCKET_ONE_NAME/$test_folder/*" - run setup_bucket "s3api" "$BUCKET_ONE_NAME" assert_success - run setup_policy_with_single_statement "$TEST_FILE_FOLDER/$policy_file" "dummy" "$effect" "$principal" "$action" "$resource" + run setup_policy_with_single_statement "$TEST_FILE_FOLDER/$policy_file" "dummy" "Allow" "$username" "s3:PutObject" "arn:aws:s3:::$BUCKET_ONE_NAME/$test_folder/*" assert_success run put_bucket_policy "s3api" "$BUCKET_ONE_NAME" "$TEST_FILE_FOLDER/$policy_file" diff --git a/tests/util/util_acl.sh b/tests/util/util_acl.sh index 40090572..bcc72c47 100644 --- a/tests/util/util_acl.sh +++ b/tests/util/util_acl.sh @@ -1,5 +1,21 @@ #!/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/util/util_users.sh + get_check_default_acl_s3cmd() { if [ $# -ne 1 ]; then log 2 "'get_check_acl_s3cmd' requires bucket name" @@ -243,3 +259,92 @@ get_and_check_acl_rest() { fi return 0 } + +setup_acl() { + if [ $# -ne 4 ]; then + log 2 "'setup_acl' requires acl file, grantee, permission, owner ID" + return 1 + fi + cat < "$1" + + + $4 + + + + + $2 + + $3 + + + +EOF +} + +setup_acl_json() { + if [ $# -ne 5 ]; then + log 2 "'setup_acl_json' requires acl file, grantee type, grantee ID, permission, owner ID" + return 1 + fi + cat < "$1" +{ + "Grants": [ + { + "Grantee": { + "Type": "$2", + "ID": "$3" + }, + "Permission": "$4" + } + ], + "Owner": { + "ID": "$5" + } +} +EOF +} + +create_versitygw_acl_user_or_get_direct_user() { + if [ $# -ne 2 ]; then + log 2 "'create_versitygw_acl_user_or_get_direct_user' requires username, password" + return 1 + fi + if [ "$DIRECT" == "true" ]; then + if [ -z "$AWS_CANONICAL_ID" ] || [ -z "$ACL_AWS_CANONICAL_ID" ] || [ -z "$ACL_AWS_ACCESS_KEY_ID" ] || [ -z "$ACL_AWS_SECRET_ACCESS_KEY" ]; then + log 2 "direct ACL calls require the following env vars: ACL_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" + else + echo "$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" + # shellcheck disable=SC2154 + echo "$2" + fi +} + +put_acl_rest() { + if [ $# -ne 2 ]; then + log 2 "'put_acl_rest' requires bucket name, ACL file" + 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" + return 1 + fi + if [ "$result" != "200" ]; then + log 5 "response returned code: $result (error: $(cat "$TEST_FILE_FOLDER/response.txt")" + return 1 + fi + return 0 +} diff --git a/tests/util/util_bucket.sh b/tests/util/util_bucket.sh index c183dbf9..efbc8ed7 100644 --- a/tests/util/util_bucket.sh +++ b/tests/util/util_bucket.sh @@ -74,23 +74,21 @@ clear_bucket_s3api() { return 1 fi - #run check_ownership_rule_and_reset_acl "$1" - #assert_success "error checking ownership rule and resetting acl" + if ! check_ownership_rule_and_reset_acl "$1"; then + log 2 "error checking ownership rule and resetting acl" + return 1 + fi # shellcheck disable=SC2154 if [[ $lock_config_exists == true ]] && ! put_object_lock_configuration_disabled "$1"; then log 2 "error disabling object lock config" return 1 fi - #if ! put_bucket_versioning "s3api" "$1" "Suspended"; then - # log 2 "error suspending bucket versioning" - # return 1 - #fi - #if ! change_bucket_owner "$AWS_ACCESS_KEY_ID" "$AWS_SECRET_ACCESS_KEY" "$1" "$AWS_ACCESS_KEY_ID"; then - # log 2 "error changing bucket owner back to root" - # return 1 - #fi + if [ "$RUN_USERS" == "true" ] && ! change_bucket_owner "$AWS_ACCESS_KEY_ID" "$AWS_SECRET_ACCESS_KEY" "$1" "$AWS_ACCESS_KEY_ID"; then + log 2 "error changing bucket owner back to root" + return 1 + fi } # params: bucket name @@ -219,6 +217,10 @@ bucket_cleanup_if_bucket_exists() { fi if bucket_exists "$1" "$2"; then + if [ "$DELETE_BUCKETS_AFTER_TEST" == "false" ]; then + log 2 "skipping bucket cleanup/deletion" + return 0 + fi if ! bucket_cleanup "$1" "$2"; then log 2 "error deleting bucket and/or contents" return 1 diff --git a/tests/util/util_list_objects.sh b/tests/util/util_list_objects.sh index eeed367f..08cb7b05 100644 --- a/tests/util/util_list_objects.sh +++ b/tests/util/util_list_objects.sh @@ -198,3 +198,48 @@ check_object_listing_with_prefixes() { fi return 0 } + +list_objects_with_user_rest_verify_access_denied() { + if [ $# -ne 3 ]; then + log 2 "list_objects_with_user_rest_verify_access_denied' requires bucket, username, password" + return 1 + fi + if ! result=$(AWS_ACCESS_KEY_ID="$2" AWS_SECRET_ACCESS_KEY="$3" COMMAND_LOG="$COMMAND_LOG" BUCKET_NAME="$1" OUTPUT_FILE="$TEST_FILE_FOLDER/objects.txt" ./tests/rest_scripts/list_objects.sh); then + log 2 "error attempting to list objects: $result" + return 1 + fi + if [ "$result" != "403" ]; then + log 2 "expected response code of '403', was '$result'" + return 1 + fi + error_message="$(cat "$TEST_FILE_FOLDER/objects.txt")" + if [[ "$error_message" != *"Access Denied"* ]]; then + log 2 "unexpected error message: $error_message" + return 1 + fi + return 0 +} + +list_objects_with_user_rest_verify_success() { + if [ $# -ne 4 ]; then + log 2 "list_objects_with_user_rest_verify_access_denied' requires bucket, username, password, expected object" + return 1 + fi + if ! result=$(AWS_ACCESS_KEY_ID="$2" AWS_SECRET_ACCESS_KEY="$3" COMMAND_LOG="$COMMAND_LOG" BUCKET_NAME="$1" OUTPUT_FILE="$TEST_FILE_FOLDER/objects.txt" ./tests/rest_scripts/list_objects.sh); then + log 2 "error attempting to list objects: $result" + return 1 + fi + if [ "$result" != "200" ]; then + log 2 "expected response code of '200', was '$result' (error: $(cat "$TEST_FILE_FOLDER/objects.txt"))" + return 1 + fi + if ! key=$(xmllint --xpath '//*[local-name()="Key"]/text()' "$TEST_FILE_FOLDER/objects.txt" 2>&1); then + log 2 "error getting object key: $key" + return 1 + fi + if [ "$key" != "$4" ]; then + log 2 "expected '$4', was '$key'" + return 1 + fi + return 0 +} \ No newline at end of file