diff --git a/.github/workflows/system.yml b/.github/workflows/system.yml index aa3343f8..38f6563f 100644 --- a/.github/workflows/system.yml +++ b/.github/workflows/system.yml @@ -33,6 +33,12 @@ jobs: RECREATE_BUCKETS: "true" DELETE_BUCKETS_AFTER_TEST: "true" BACKEND: "posix" + - set: "REST, posix, non-static, not implemented, folder IAM" + IAM_TYPE: folder + RUN_SET: "rest-not-implemented" + RECREATE_BUCKETS: "true" + DELETE_BUCKETS_AFTER_TEST: "true" + BACKEND: "posix" - set: "s3, posix, non-file count, non-static, folder IAM" IAM_TYPE: folder RUN_SET: "s3-non-file-count" diff --git a/tests/commands/get_bucket_ownership_controls.sh b/tests/commands/get_bucket_ownership_controls.sh index 5accae2b..4d3f2bc8 100644 --- a/tests/commands/get_bucket_ownership_controls.sh +++ b/tests/commands/get_bucket_ownership_controls.sh @@ -46,6 +46,10 @@ get_bucket_ownership_controls_rest() { return 1 fi if [ "$result" != "200" ]; then + if check_xml_element_contains "$TEST_FILE_FOLDER/ownershipControls.txt" "OwnershipControlsNotFoundError" "Error" "Code"; then + echo "" + return 0 + fi log 2 "GetBucketOwnershipControls returned response code: $result, reply: $(cat "$TEST_FILE_FOLDER/ownershipControls.txt")" return 1 fi diff --git a/tests/drivers/not_implemented/not_implemented_rest.sh b/tests/drivers/not_implemented/not_implemented_rest.sh new file mode 100644 index 00000000..e901016c --- /dev/null +++ b/tests/drivers/not_implemented/not_implemented_rest.sh @@ -0,0 +1,56 @@ +#!/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 + +send_not_implemented_expect_failure() { + if [ $(($# % 2)) -ne 0 ]; then + log 2 "'send_not_implemented_expect_failure' param count must be multiple of 2 (key/value pairs)" + return 1 + fi + if ! curl_command=$(go run ./tests/rest_scripts/generate_command.go -awsAccessKeyId "$AWS_ACCESS_KEY_ID" -awsSecretAccessKey "$AWS_SECRET_ACCESS_KEY" -url "$AWS_ENDPOINT_URL" "$@" 2>&1); then + log 2 "error: $curl_command" + return 1 + fi + local full_command="send_command $curl_command" + log 5 "full command: $full_command" + if ! result=$(eval "${full_command[*]}" 2>&1); then + log 3 "error sending command: $result" + return 1 + fi + log 5 "result: $result" + echo -n "$result" > "$TEST_FILE_FOLDER/result.txt" + if ! check_rest_expected_header_error "$TEST_FILE_FOLDER/result.txt" "501" "NotImplemented"; then + log 2 "error checking expected header error" + return 1 + fi + return 0 +} + +test_not_implemented_expect_failure() { + if ! check_param_count_v2 "bucket, query, method" 3 $#; then + return 1 + fi + if ! setup_bucket "$1"; then + log 2 "error setting up bucket" + return 1 + fi + if ! send_not_implemented_expect_failure "-bucketName" "$1" "-query" "$2" "-method" "$3"; then + log 2 "error with command that should be \"not implemented\"" + return 1 + fi + return 0 +} \ No newline at end of file diff --git a/tests/drivers/rest.sh b/tests/drivers/rest.sh index cad697e0..0bcaf442 100644 --- a/tests/drivers/rest.sh +++ b/tests/drivers/rest.sh @@ -71,25 +71,21 @@ send_rest_command_expect_error() { } check_rest_expected_header_error() { - if ! check_param_count_v2 "response code, file, expected response, expected error" 4 $#; then + if ! check_param_count_v2 "file, expected response, expected error" 3 $#; then return 1 fi - status_line=$(head -n 1 "$2") + status_line=$(head -n 1 "$1") # Parse the status code and message status_code=$(echo "$status_line" | awk '{print $2}') status_message=$(echo "$status_line" | cut -d' ' -f3- | tr -d '\r') log 5 "status code: $status_code, status message: $status_message" - if [ "$1" != "$3" ]; then - log 2 "expected curl response '$3', was '$1" + if [ "$2" != "$status_code" ]; then + log 2 "expected curl response '$2', was '$status_code'" return 1 fi - if [ "$status_code" != "$3" ]; then - log 2 "expected HTTP response '$3', was '$status_code" - return 1 - fi - if [ "$status_message" != "$4" ]; then - log 2 "expected message '$4', was '$status_message'" + if [ "$status_message" != "$3" ]; then + log 2 "expected message '$3', was '$status_message'" return 1 fi return 0 @@ -103,7 +99,7 @@ send_rest_command_expect_header_error() { log 2 "error sending REST command" return 1 fi - if ! check_rest_expected_header_error "$result" "$output_file" "$3" "$4"; then + if ! check_rest_expected_header_error "$output_file" "$3" "$4"; then log 2 "error checking REST error" return 1 fi diff --git a/tests/rest_scripts/generate_command.go b/tests/rest_scripts/generate_command.go new file mode 100644 index 00000000..0928aac4 --- /dev/null +++ b/tests/rest_scripts/generate_command.go @@ -0,0 +1,196 @@ +package main + +import ( + "crypto/hmac" + "crypto/sha256" + "encoding/hex" + "flag" + "fmt" + "log" + "strings" + "time" +) + +var method *string +var url *string +var bucketName *string +var objectKey *string +var query *string +var awsRegion *string +var awsAccessKeyId *string +var awsSecretAccessKey *string +var serviceName *string +var debug *bool + +type S3Command struct { + Method string + Url string + BucketName string + ObjectKey string + Query string + AwsRegion string + AwsAccessKeyId string + AwsSecretAccessKey string + ServiceName string + + currentDateTime string + host string + payloadHash string + headerValues [][]string + canonicalRequestHash string + path string + signedParamString string + yearMonthDay string + signature string +} + +func main() { + if err := checkFlags(); err != nil { + log.Fatalf("Error checking flags: %v", err) + } + + s3Command := &S3Command{ + Method: *method, + Url: *url, + BucketName: *bucketName, + ObjectKey: *objectKey, + Query: *query, + AwsRegion: *awsRegion, + AwsAccessKeyId: *awsAccessKeyId, + AwsSecretAccessKey: *awsSecretAccessKey, + ServiceName: *serviceName, + } + curlShellCommand, err := s3Command.CurlShellCommand() + if err != nil { + log.Fatalf("Error generating curl command: %v", err) + } + fmt.Println(curlShellCommand) +} + +func checkFlags() error { + method = flag.String("method", "GET", "HTTP method to use") + url = flag.String("url", "https://localhost:7070", "S3 server URL") + bucketName = flag.String("bucketName", "", "Bucket name") + objectKey = flag.String("objectKey", "", "Object key") + query = flag.String("query", "", "S3 query") + awsAccessKeyId = flag.String("awsAccessKeyId", "", "AWS access key ID") + awsSecretAccessKey = flag.String("awsSecretAccessKey", "", "AWS secret access key") + awsRegion = flag.String("awsRegion", "us-east-1", "AWS region") + serviceName = flag.String("serviceName", "s3", "Service name") + debug = flag.Bool("debug", false, "Print debug statements") + // Parse the flags + flag.Parse() + + if flag.Lookup("awsAccessKeyId").Value.String() == "" { + return fmt.Errorf("the 'awsAccessKeyId' value must be set") + } + if flag.Lookup("awsSecretAccessKey").Value.String() == "" { + return fmt.Errorf("the 'awsSecretAccessKey' value must be set") + } + return nil +} + +func printDebug(format string, args ...any) { + if *debug { + log.Printf(format, args...) + } +} + +func hmacSHA256(key []byte, data string) []byte { + h := hmac.New(sha256.New, key) + h.Write([]byte(data)) + return h.Sum(nil) +} + +func (s *S3Command) CurlShellCommand() (string, error) { + s.currentDateTime = time.Now().UTC().Format("20060102T150405Z") + protocolAndHost := strings.Split(s.Url, "://") + if len(protocolAndHost) != 2 { + return "", fmt.Errorf("invalid URL value: %s", s.Url) + } + s.host = protocolAndHost[1] + s.payloadHash = "UNSIGNED-PAYLOAD" + s.headerValues = [][]string{ + {"x-amz-content-sha256", s.payloadHash}, + {"x-amz-date", s.currentDateTime}, + } + s.path = "/" + s.BucketName + if s.ObjectKey != "" { + s.path += "/" + s.ObjectKey + } + s.generateCanonicalRequestString() + + s.yearMonthDay = strings.Split(s.currentDateTime, "T")[0] + s.getStsSignature() + + return s.buildCurlShellCommand(), nil +} + +func (s *S3Command) generateCanonicalRequestString() { + canonicalRequestLines := []string{*method} + + canonicalRequestLines = append(canonicalRequestLines, s.path) + canonicalRequestLines = append(canonicalRequestLines, s.Query) + canonicalRequestLines = append(canonicalRequestLines, "host:"+s.host) + + signedParams := []string{"host"} + for _, headerValue := range s.headerValues { + key := headerValue[0] + canonicalRequestLines = append(canonicalRequestLines, key+":"+headerValue[1]) + signedParams = append(signedParams, key) + } + + canonicalRequestLines = append(canonicalRequestLines, "") + s.signedParamString = strings.Join(signedParams, ";") + canonicalRequestLines = append(canonicalRequestLines, s.signedParamString, s.payloadHash) + + canonicalRequestString := strings.Join(canonicalRequestLines, "\n") + printDebug("Canonical request string: %s\n", canonicalRequestString) + + canonicalRequestHashBytes := sha256.Sum256([]byte(canonicalRequestString)) + s.canonicalRequestHash = hex.EncodeToString(canonicalRequestHashBytes[:]) +} + +func (s *S3Command) getStsSignature() { + thirdLine := fmt.Sprintf("%s/%s/%s/aws4_request", s.yearMonthDay, s.AwsRegion, s.ServiceName) + stsDataLines := []string{ + "AWS4-HMAC-SHA256", + s.currentDateTime, + thirdLine, + s.canonicalRequestHash, + } + stsDataString := strings.Join(stsDataLines, "\n") + + // Derive signing key step by step + dateKey := hmacSHA256([]byte("AWS4"+s.AwsSecretAccessKey), s.yearMonthDay) + dateRegionKey := hmacSHA256(dateKey, s.AwsRegion) + dateRegionServiceKey := hmacSHA256(dateRegionKey, s.ServiceName) + signingKey := hmacSHA256(dateRegionServiceKey, "aws4_request") + + // Generate signature + signatureBytes := hmacSHA256(signingKey, stsDataString) + + // Print hex-encoded signature + s.signature = hex.EncodeToString(signatureBytes) +} + +func (s *S3Command) buildCurlShellCommand() string { + curlCommand := []string{"curl", "-iks"} + if s.Method != "GET" { + curlCommand = append(curlCommand, fmt.Sprintf("-X %s ", s.Method)) + } + fullPath := "\"" + *url + s.path + if *query != "" { + fullPath += "?" + *query + } + fullPath += "\"" + curlCommand = append(curlCommand, fullPath) + authorizationString := fmt.Sprintf("\"Authorization: AWS4-HMAC-SHA256 Credential=%s/%s/%s/%s/aws4_request,SignedHeaders=%s,Signature=%s\"", + s.AwsAccessKeyId, s.yearMonthDay, s.AwsRegion, s.ServiceName, s.signedParamString, s.signature) + curlCommand = append(curlCommand, "-H", authorizationString) + for _, headerValue := range s.headerValues { + headerString := fmt.Sprintf("\"%s: %s\"", headerValue[0], headerValue[1]) + curlCommand = append(curlCommand, "-H", headerString) + } + return strings.Join(curlCommand, " ") +} diff --git a/tests/rest_scripts/put_bucket_analytics_configuration.sh b/tests/rest_scripts/put_bucket_analytics_configuration.sh new file mode 100755 index 00000000..83afdb0c --- /dev/null +++ b/tests/rest_scripts/put_bucket_analytics_configuration.sh @@ -0,0 +1,59 @@ +#!/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 +analytics_file="$ANALYTICS_FILE" + +if [ -n "$ANALYTICS_FILE" ]; then + payload="$(cat "$analytics_file")" +else + payload="" +fi + +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 +analytics= +host:$host +" +canonical_request+="x-amz-content-sha256:$payload_hash +x-amz-date:$current_date_time + +" +canonical_request+="host;x-amz-content-sha256;x-amz-date +$payload_hash" + +# shellcheck disable=SC2119 +create_canonical_hash_sts_and_signature + +curl_command+=(curl -ks -w "\"%{http_code}\"" -X PUT "$AWS_ENDPOINT_URL/$bucket_name?analytics=") +curl_command+=(-H "\"Authorization: AWS4-HMAC-SHA256 Credential=$aws_access_key_id/$year_month_day/$aws_region/s3/aws4_request,SignedHeaders=host;${acl_header}x-amz-content-sha256;x-amz-date,Signature=$signature\"") +curl_command+=(-H "\"x-amz-content-sha256: $payload_hash\"" +-H "\"x-amz-date: $current_date_time\"") +if [ -n "$ANALYTICS_FILE" ]; then + curl_command+=(-d "\"${payload//\"/\\\"}\"") +fi +curl_command+=(-o "$OUTPUT_FILE") + +# shellcheck disable=SC2154 +eval "${curl_command[*]}" 2>&1 \ No newline at end of file diff --git a/tests/rest_scripts/upload_part.go b/tests/rest_scripts/upload_part.go deleted file mode 100644 index 41e7f16e..00000000 --- a/tests/rest_scripts/upload_part.go +++ /dev/null @@ -1,7 +0,0 @@ -package main - -import "fmt" - -func main() { - fmt.Println("main") -} diff --git a/tests/run.sh b/tests/run.sh index 8d0e7115..fe4c477e 100755 --- a/tests/run.sh +++ b/tests/run.sh @@ -17,33 +17,34 @@ # Function to display help information show_help() { echo "Usage: $0 [option...]" - echo " -h, --help Display this help message and exit" - echo " Separate the below by comma" - echo " s3api Run all tests with s3api cli" - echo " s3api-multipart Run multipart tests with s3api cli" - echo " s3api-bucket Run bucket tests with s3api cli" - echo " s3api-object Run object tests with s3api cli" - echo " s3api-policy Run policy tests with s3api cli" - echo " s3api-user Run user tests with s3api cli" - echo " s3 Run tests with s3 cli" - echo " s3cmd Run tests with s3cmd utility" - echo " s3cmd-user Run user tests with s3cmd utility" - echo " s3cmd-non-user Run non-user tests with s3cmd utility" - echo " s3cmd-file-count Run file count test with s3cmd utility" - echo " mc Run tests with mc utility" - echo " mc-non-file-count Run non-file count tests with mc utility" - echo " mc-file-count Run file count test with mc utility" - echo " rest Run tests with rest cli" - echo " rest-base Run REST base tests" - echo " rest-acl Run REST ACL tests" - echo " rest-chunked Run REST chunked upload tests" - echo " rest-checksum Run REST checksum tests" - echo " rest-create-bucket Run REST create bucket tests" - echo " rest-head-bucket Run REST head bucket tests" - echo " rest-list-buckets Run REST list-buckets tests" - echo " rest-multipart Run REST multipart tests" - echo " rest-versioning Run REST versioning tests" - echo " rest-bucket Run REST bucket tests" + echo " -h, --help Display this help message and exit" + echo " Separate the below by comma" + echo " s3api Run all tests with s3api cli" + echo " s3api-multipart Run multipart tests with s3api cli" + echo " s3api-bucket Run bucket tests with s3api cli" + echo " s3api-object Run object tests with s3api cli" + echo " s3api-policy Run policy tests with s3api cli" + echo " s3api-user Run user tests with s3api cli" + echo " s3 Run tests with s3 cli" + echo " s3cmd Run tests with s3cmd utility" + echo " s3cmd-user Run user tests with s3cmd utility" + echo " s3cmd-non-user Run non-user tests with s3cmd utility" + echo " s3cmd-file-count Run file count test with s3cmd utility" + echo " mc Run tests with mc utility" + echo " mc-non-file-count Run non-file count tests with mc utility" + echo " mc-file-count Run file count test with mc utility" + echo " rest Run tests with rest cli" + echo " rest-base Run REST base tests" + echo " rest-acl Run REST ACL tests" + echo " rest-chunked Run REST chunked upload tests" + echo " rest-checksum Run REST checksum tests" + echo " rest-create-bucket Run REST create bucket tests" + echo " rest-head-bucket Run REST head bucket tests" + echo " rest-list-buckets Run REST list-buckets tests" + echo " rest-multipart Run REST multipart tests" + echo " rest-not-implemented Run REST multipart tests" + echo " rest-versioning Run REST versioning tests" + echo " rest-bucket Run REST bucket tests" } handle_param() { @@ -55,7 +56,8 @@ handle_param() { s3|s3-file-count|s3-non-file-count|s3api|s3cmd|s3cmd-user|s3cmd-non-user|\ s3cmd-file-count|mc|mc-non-file-count|mc-file-count|s3api-user|rest|s3api-policy|\ s3api-bucket|s3api-object|s3api-multipart|rest-base|rest-acl|rest-chunked|rest-checksum|\ - rest-create-bucket|rest-head-bucket|rest-list-buckets|rest-versioning|rest-bucket|rest-multipart) + rest-create-bucket|rest-head-bucket|rest-list-buckets|rest-not-implemented|\ + rest-versioning|rest-bucket|rest-multipart) run_suite "$1" ;; *) # Handle unrecognized options or positional arguments @@ -170,6 +172,8 @@ run_suite() { exit_code=1 elif ! "$HOME"/bin/bats ./tests/test_rest_multipart.sh; then exit_code=1 + elif ! "$HOME"/bin/bats ./tests/test_rest_not_implemented.sh; then + exit_code=1 elif ! "$HOME"/bin/bats ./tests/test_rest_versioning.sh; then exit_code=1 elif ! "$HOME"/bin/bats ./tests/test_rest_bucket.sh; then @@ -208,6 +212,10 @@ run_suite() { echo "Running REST list-buckets tests ..." "$HOME"/bin/bats ./tests/test_rest_list_buckets.sh || exit_code=$? ;; + rest-not-implemented) + echo "Running REST not-implemented tests ..." + "$HOME"/bin/bats ./tests/test_rest_not_implemented.sh || exit_code=$? + ;; rest-multipart) echo "Running REST multipart tests ..." "$HOME"/bin/bats ./tests/test_rest_multipart.sh || exit_code=$? diff --git a/tests/test_rest_not_implemented.sh b/tests/test_rest_not_implemented.sh new file mode 100755 index 00000000..94ae32f4 --- /dev/null +++ b/tests/test_rest_not_implemented.sh @@ -0,0 +1,237 @@ +#!/usr/bin/env bats + +# 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. + +load ./bats-support/load +load ./bats-assert/load + +source ./tests/drivers/not_implemented/not_implemented_rest.sh +source ./tests/setup.sh + +@test "REST - PutBucketAnalyticsConfiguration" { + skip "https://github.com/versity/versitygw/issues/1433" + run test_not_implemented_expect_failure "$BUCKET_ONE_NAME" "analytics=" "PUT" + assert_success +} + +@test "REST - Get/ListBucketAnalyticsConfiguration(s)" { + skip "https://github.com/versity/versitygw/issues/1437" + run test_not_implemented_expect_failure "$BUCKET_ONE_NAME" "analytics=" "GET" + assert_success +} + +@test "REST - DeleteBucketAnalyticsConfiguration" { + skip "https://github.com/versity/versitygw/issues/1438" + run test_not_implemented_expect_failure "$BUCKET_ONE_NAME" "analytics=" "DELETE" + assert_success +} + +@test "REST - GetBucketEncryption" { + skip "https://github.com/versity/versitygw/issues/1439" + run test_not_implemented_expect_failure "$BUCKET_ONE_NAME" "encryption=" "GET" + assert_success +} + +@test "REST - PutBucketEncryption" { + skip "https://github.com/versity/versitygw/issues/1439" + run test_not_implemented_expect_failure "$BUCKET_ONE_NAME" "encryption=" "PUT" + assert_success +} + +@test "REST - DeleteBucketEncryption" { + skip "https://github.com/versity/versitygw/issues/1439" + run test_not_implemented_expect_failure "$BUCKET_ONE_NAME" "encryption=" "DELETE" + assert_success +} + +@test "REST - ListBucketIntelligentTieringConfigurations" { + skip "https://github.com/versity/versitygw/issues/1440" + run test_not_implemented_expect_failure "$BUCKET_ONE_NAME" "intelligent-tiering=" "GET" + assert_success +} + +@test "REST - PutBucketIntelligentTieringConfiguration" { + skip "https://github.com/versity/versitygw/issues/1440" + run test_not_implemented_expect_failure "$BUCKET_ONE_NAME" "intelligent-tiering=" "PUT" + assert_success +} + +@test "REST - DeleteBucketIntelligentTieringConfiguration" { + skip "https://github.com/versity/versitygw/issues/1440" + run test_not_implemented_expect_failure "$BUCKET_ONE_NAME" "intelligent-tiering=" "DELETE" + assert_success +} + +@test "REST - ListBucketInventoryConfigurations" { + skip "https://github.com/versity/versitygw/issues/1441" + run test_not_implemented_expect_failure "$BUCKET_ONE_NAME" "inventory=" "GET" + assert_success +} + +@test "REST - PutBucketInventoryConfigurations" { + skip "https://github.com/versity/versitygw/issues/1441" + run test_not_implemented_expect_failure "$BUCKET_ONE_NAME" "inventory=" "PUT" + assert_success +} + +@test "REST - DeleteBucketInventoryConfigurations" { + skip "https://github.com/versity/versitygw/issues/1441" + run test_not_implemented_expect_failure "$BUCKET_ONE_NAME" "inventory=" "DELETE" + assert_success +} + +@test "REST - GetBucketLifecycleConfiguration" { + skip "https://github.com/versity/versitygw/issues/1443" + run test_not_implemented_expect_failure "$BUCKET_ONE_NAME" "lifecycle=" "GET" + assert_success +} + +@test "REST - PutBucketLifecycleConfiguration" { + skip "https://github.com/versity/versitygw/issues/1443" + run test_not_implemented_expect_failure "$BUCKET_ONE_NAME" "lifecycle=" "PUT" + assert_success +} + +@test "REST - DeleteBucketLifecycleConfiguration" { + skip "https://github.com/versity/versitygw/issues/1443" + run test_not_implemented_expect_failure "$BUCKET_ONE_NAME" "lifecycle=" "DELETE" + assert_success +} + +@test "REST - GetBucketLogging" { + skip "https://github.com/versity/versitygw/issues/1444" + run test_not_implemented_expect_failure "$BUCKET_ONE_NAME" "logging=" "GET" + assert_success +} + +@test "REST - PutBucketLogging" { + skip "https://github.com/versity/versitygw/issues/1444" + run test_not_implemented_expect_failure "$BUCKET_ONE_NAME" "logging=" "PUT" + assert_success +} + +@test "REST - ListBucketMetricsConfigurations" { + skip "https://github.com/versity/versitygw/issues/1445" + run test_not_implemented_expect_failure "$BUCKET_ONE_NAME" "metrics=" "GET" + assert_success +} + +@test "REST - PutBucketMetricsConfigurations" { + skip "https://github.com/versity/versitygw/issues/1445" + run test_not_implemented_expect_failure "$BUCKET_ONE_NAME" "metrics=" "PUT" + assert_success +} + +@test "REST - DeleteBucketMetricsConfigurations" { + skip "https://github.com/versity/versitygw/issues/1445" + run test_not_implemented_expect_failure "$BUCKET_ONE_NAME" "metrics=" "DELETE" + assert_success +} + +@test "REST - GetBucketReplication" { + skip "https://github.com/versity/versitygw/issues/1449" + run test_not_implemented_expect_failure "$BUCKET_ONE_NAME" "replication=" "GET" + assert_success +} + +@test "REST - PutBucketReplication" { + skip "https://github.com/versity/versitygw/issues/1449" + run test_not_implemented_expect_failure "$BUCKET_ONE_NAME" "replication=" "PUT" + assert_success +} + +@test "REST - DeleteBucketReplication" { + skip "https://github.com/versity/versitygw/issues/1449" + run test_not_implemented_expect_failure "$BUCKET_ONE_NAME" "replication=" "DELETE" + assert_success +} + +@test "REST - GetBucketWebsite" { + skip "https://github.com/versity/versitygw/issues/1450" + run test_not_implemented_expect_failure "$BUCKET_ONE_NAME" "website=" "GET" + assert_success +} + +@test "REST - PutBucketWebsite" { + skip "https://github.com/versity/versitygw/issues/1450" + run test_not_implemented_expect_failure "$BUCKET_ONE_NAME" "website=" "PUT" + assert_success +} + +@test "REST - DeleteBucketWebsite" { + skip "https://github.com/versity/versitygw/issues/1450" + run test_not_implemented_expect_failure "$BUCKET_ONE_NAME" "website=" "DELETE" + assert_success +} + +@test "REST - GetPublicAccessBlock" { + skip "https://github.com/versity/versitygw/issues/1451" + run test_not_implemented_expect_failure "$BUCKET_ONE_NAME" "publicAccessBlock=" "GET" + assert_success +} + +@test "REST - PutPublicAccessBlock" { + skip "https://github.com/versity/versitygw/issues/1451" + run test_not_implemented_expect_failure "$BUCKET_ONE_NAME" "publicAccessBlock=" "PUT" + assert_success +} + +@test "REST - DeletePublicAccessBlock" { + skip "https://github.com/versity/versitygw/issues/1451" + run test_not_implemented_expect_failure "$BUCKET_ONE_NAME" "publicAccessBlock=" "DELETE" + assert_success +} + +@test "REST - GetBucketAccelerateConfiguration" { + skip "https://github.com/versity/versitygw/issues/1452" + run test_not_implemented_expect_failure "$BUCKET_ONE_NAME" "accelerate=" "GET" + assert_success +} + +@test "REST - PutBucketAccelerateConfiguration" { + skip "https://github.com/versity/versitygw/issues/1452" + run test_not_implemented_expect_failure "$BUCKET_ONE_NAME" "accelerate=" "PUT" + assert_success +} + +@test "REST - GetBucketNotificationConfiguration" { + skip "https://github.com/versity/versitygw/issues/1453" + run test_not_implemented_expect_failure "$BUCKET_ONE_NAME" "notification=" "GET" + assert_success +} + +@test "REST - PutBucketNotificationConfiguration" { + skip "https://github.com/versity/versitygw/issues/1453" + run test_not_implemented_expect_failure "$BUCKET_ONE_NAME" "notification=" "PUT" + assert_success +} + +@test "REST - GetBucketPolicyStatus" { + skip "https://github.com/versity/versitygw/issues/1454" + run test_not_implemented_expect_failure "$BUCKET_ONE_NAME" "policyStatus=" "GET" + assert_success +} + +@test "REST - GetBucketRequestPayment" { + skip "https://github.com/versity/versitygw/issues/1455" + run test_not_implemented_expect_failure "$BUCKET_ONE_NAME" "requestPayment=" "GET" + assert_success +} + +@test "REST - PutBucketRequestPayment" { + skip "https://github.com/versity/versitygw/issues/1455" + run test_not_implemented_expect_failure "$BUCKET_ONE_NAME" "requestPayment=" "PUT" + assert_success +}