From 83fbc2744ac9c62b33abd3d0f398031c01479ae4 Mon Sep 17 00:00:00 2001 From: f64116045 Date: Sun, 13 Sep 2026 22:54:30 +0800 Subject: [PATCH 1/3] HDDS-16408. Prevent DeletePublicAccessBlock from deleting buckets --- .../ozone/s3/awssdk/v1/AbstractS3SDKV1Tests.java | 16 ++++++++++++++++ .../ozone/s3/awssdk/v2/AbstractS3SDKV2Tests.java | 15 +++++++++++++++ .../ozone/s3/endpoint/BucketCrudHandler.java | 7 +++---- .../apache/hadoop/ozone/s3/util/S3Consts.java | 1 + .../ozone/s3/endpoint/TestBucketDelete.java | 12 ++++++++++++ 5 files changed, 47 insertions(+), 4 deletions(-) diff --git a/hadoop-ozone/integration-test-s3/src/test/java/org/apache/hadoop/ozone/s3/awssdk/v1/AbstractS3SDKV1Tests.java b/hadoop-ozone/integration-test-s3/src/test/java/org/apache/hadoop/ozone/s3/awssdk/v1/AbstractS3SDKV1Tests.java index 42e8140dcb87..17a001c3711d 100644 --- a/hadoop-ozone/integration-test-s3/src/test/java/org/apache/hadoop/ozone/s3/awssdk/v1/AbstractS3SDKV1Tests.java +++ b/hadoop-ozone/integration-test-s3/src/test/java/org/apache/hadoop/ozone/s3/awssdk/v1/AbstractS3SDKV1Tests.java @@ -53,6 +53,7 @@ import com.amazonaws.services.s3.model.CopyPartResult; import com.amazonaws.services.s3.model.CreateBucketRequest; import com.amazonaws.services.s3.model.DeleteBucketTaggingConfigurationRequest; +import com.amazonaws.services.s3.model.DeletePublicAccessBlockRequest; import com.amazonaws.services.s3.model.GeneratePresignedUrlRequest; import com.amazonaws.services.s3.model.GetBucketLifecycleConfigurationRequest; import com.amazonaws.services.s3.model.GetBucketTaggingConfigurationRequest; @@ -485,6 +486,21 @@ public void testDeleteBucket() { assertFalse(s3Client.doesBucketExistV2(bucketName)); } + @Test + public void testDeletePublicAccessBlockDoesNotDeleteBucket() { + final String bucketName = getBucketName(); + s3Client.createBucket(bucketName); + + AmazonServiceException exception = assertThrows(AmazonServiceException.class, + () -> s3Client.deletePublicAccessBlock( + new DeletePublicAccessBlockRequest().withBucketName(bucketName))); + assertEquals(HttpURLConnection.HTTP_NOT_IMPLEMENTED, exception.getStatusCode()); + assertEquals(S3ErrorTable.NOT_IMPLEMENTED.getCode(), exception.getErrorCode()); + assertTrue(s3Client.doesBucketExistV2(bucketName)); + + s3Client.deleteBucket(bucketName); + } + @Test public void testDeleteBucketNotExist() { final String bucketName = getBucketName(); diff --git a/hadoop-ozone/integration-test-s3/src/test/java/org/apache/hadoop/ozone/s3/awssdk/v2/AbstractS3SDKV2Tests.java b/hadoop-ozone/integration-test-s3/src/test/java/org/apache/hadoop/ozone/s3/awssdk/v2/AbstractS3SDKV2Tests.java index bfcf5b741bc3..94b163bf73c7 100644 --- a/hadoop-ozone/integration-test-s3/src/test/java/org/apache/hadoop/ozone/s3/awssdk/v2/AbstractS3SDKV2Tests.java +++ b/hadoop-ozone/integration-test-s3/src/test/java/org/apache/hadoop/ozone/s3/awssdk/v2/AbstractS3SDKV2Tests.java @@ -277,6 +277,21 @@ public void testCreateBucketAlreadyExistsDifferentOwner() throws IOException { exception.awsErrorDetails().errorCode()); } + @Test + public void testDeletePublicAccessBlockDoesNotDeleteBucket() { + final String bucketName = getBucketName(); + s3Client.createBucket(b -> b.bucket(bucketName)); + + S3Exception exception = assertThrows(S3Exception.class, + () -> s3Client.deletePublicAccessBlock(b -> b.bucket(bucketName))); + assertEquals(HttpURLConnection.HTTP_NOT_IMPLEMENTED, exception.statusCode()); + assertEquals(S3ErrorTable.NOT_IMPLEMENTED.getCode(), + exception.awsErrorDetails().errorCode()); + assertDoesNotThrow(() -> s3Client.headBucket(b -> b.bucket(bucketName))); + + s3Client.deleteBucket(b -> b.bucket(bucketName)); + } + @Test public void testPutObject() { final String bucketName = getBucketName(); diff --git a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/BucketCrudHandler.java b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/BucketCrudHandler.java index 3d4cc4d6ad5a..a64b2b7a8f36 100644 --- a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/BucketCrudHandler.java +++ b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/BucketCrudHandler.java @@ -41,15 +41,14 @@ */ public class BucketCrudHandler extends BucketOperationHandler { - /** - * Handle only plain PUT bucket (create bucket), not subresources. - */ + /** Handle only plain bucket creation and deletion, not subresources. */ private boolean shouldHandle() { return queryParams().get(QueryParams.ACL) == null && queryParams().get(QueryParams.UPLOADS) == null && queryParams().get(QueryParams.DELETE) == null && queryParams().get(QueryParams.TAGGING) == null - && queryParams().get(QueryParams.LIFECYCLE) == null; + && queryParams().get(QueryParams.LIFECYCLE) == null + && queryParams().get(QueryParams.PUBLIC_ACCESS_BLOCK) == null; } /** diff --git a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/util/S3Consts.java b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/util/S3Consts.java index f75653ad098b..5488fc154b2d 100644 --- a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/util/S3Consts.java +++ b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/util/S3Consts.java @@ -172,6 +172,7 @@ public static final class QueryParams { public static final String PART_NUMBER = "partNumber"; public static final String PART_NUMBER_MARKER = "part-number-marker"; public static final String PREFIX = "prefix"; + public static final String PUBLIC_ACCESS_BLOCK = "publicAccessBlock"; public static final String START_AFTER = "start-after"; public static final String TAGGING = "tagging"; // GetObjectTorrent is not implemented diff --git a/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/TestBucketDelete.java b/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/TestBucketDelete.java index d576a7dedece..2494c27c53eb 100644 --- a/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/TestBucketDelete.java +++ b/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/TestBucketDelete.java @@ -17,6 +17,8 @@ package org.apache.hadoop.ozone.s3.endpoint; +import static org.apache.hadoop.ozone.s3.endpoint.EndpointTestUtils.assertErrorResponse; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.fail; @@ -27,6 +29,7 @@ import org.apache.hadoop.ozone.client.OzoneClientStub; import org.apache.hadoop.ozone.s3.exception.OS3Exception; import org.apache.hadoop.ozone.s3.exception.S3ErrorTable; +import org.apache.hadoop.ozone.s3.util.S3Consts.QueryParams; import org.apache.http.HttpStatus; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -88,4 +91,13 @@ public void testDeleteWithBucketNotEmpty() throws Exception { } fail("testDeleteWithBucketNotEmpty failed"); } + + @Test + public void testDeletePublicAccessBlockDoesNotDeleteBucket() { + bucketEndpoint.queryParamsForTest().set(QueryParams.PUBLIC_ACCESS_BLOCK, ""); + + assertErrorResponse(S3ErrorTable.NOT_IMPLEMENTED, + () -> bucketEndpoint.delete(bucketName)); + assertDoesNotThrow(() -> objectStoreStub.getS3Bucket(bucketName)); + } } From ace6b952672573fd3063deda441c1828f3c68100 Mon Sep 17 00:00:00 2001 From: f64116045 Date: Wed, 16 Sep 2026 23:46:21 +0800 Subject: [PATCH 2/3] HDDS-16408. Route unsupported bucket subresources before CRUD --- .../s3/awssdk/v1/AbstractS3SDKV1Tests.java | 27 ++++++- .../s3/awssdk/v2/AbstractS3SDKV2Tests.java | 22 ++++- .../apache/hadoop/ozone/audit/S3GAction.java | 3 + .../ozone/s3/endpoint/BucketCrudHandler.java | 8 +- .../ozone/s3/endpoint/BucketEndpoint.java | 1 + .../UnsupportedBucketSubresourceHandler.java | 81 +++++++++++++++++++ .../ozone/s3/endpoint/TestBucketDelete.java | 12 --- .../TestUnsupportedBucketSubresource.java | 76 +++++++++++++++++ 8 files changed, 205 insertions(+), 25 deletions(-) create mode 100644 hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/UnsupportedBucketSubresourceHandler.java create mode 100644 hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/TestUnsupportedBucketSubresource.java diff --git a/hadoop-ozone/integration-test-s3/src/test/java/org/apache/hadoop/ozone/s3/awssdk/v1/AbstractS3SDKV1Tests.java b/hadoop-ozone/integration-test-s3/src/test/java/org/apache/hadoop/ozone/s3/awssdk/v1/AbstractS3SDKV1Tests.java index 17a001c3711d..ec2cc5c59e8e 100644 --- a/hadoop-ozone/integration-test-s3/src/test/java/org/apache/hadoop/ozone/s3/awssdk/v1/AbstractS3SDKV1Tests.java +++ b/hadoop-ozone/integration-test-s3/src/test/java/org/apache/hadoop/ozone/s3/awssdk/v1/AbstractS3SDKV1Tests.java @@ -57,6 +57,7 @@ import com.amazonaws.services.s3.model.GeneratePresignedUrlRequest; import com.amazonaws.services.s3.model.GetBucketLifecycleConfigurationRequest; import com.amazonaws.services.s3.model.GetBucketTaggingConfigurationRequest; +import com.amazonaws.services.s3.model.GetPublicAccessBlockRequest; import com.amazonaws.services.s3.model.GetObjectRequest; import com.amazonaws.services.s3.model.GetObjectTaggingRequest; import com.amazonaws.services.s3.model.GetObjectTaggingResult; @@ -72,6 +73,8 @@ import com.amazonaws.services.s3.model.ListPartsRequest; import com.amazonaws.services.s3.model.MultipartUpload; import com.amazonaws.services.s3.model.MultipartUploadListing; +import com.amazonaws.services.s3.model.PublicAccessBlockConfiguration; +import com.amazonaws.services.s3.model.SetPublicAccessBlockRequest; import com.amazonaws.services.s3.model.ObjectListing; import com.amazonaws.services.s3.model.ObjectMetadata; import com.amazonaws.services.s3.model.ObjectTagging; @@ -487,15 +490,31 @@ public void testDeleteBucket() { } @Test - public void testDeletePublicAccessBlockDoesNotDeleteBucket() { + public void testPublicAccessBlockIsNotImplemented() { final String bucketName = getBucketName(); s3Client.createBucket(bucketName); - AmazonServiceException exception = assertThrows(AmazonServiceException.class, + AmazonServiceException getException = assertThrows(AmazonServiceException.class, + () -> s3Client.getPublicAccessBlock( + new GetPublicAccessBlockRequest().withBucketName(bucketName))); + assertEquals(HttpURLConnection.HTTP_NOT_IMPLEMENTED, getException.getStatusCode()); + assertEquals(S3ErrorTable.NOT_IMPLEMENTED.getCode(), getException.getErrorCode()); + + AmazonServiceException putException = assertThrows(AmazonServiceException.class, + () -> s3Client.setPublicAccessBlock( + new SetPublicAccessBlockRequest() + .withBucketName(bucketName) + .withPublicAccessBlockConfiguration( + new PublicAccessBlockConfiguration() + .withBlockPublicAcls(true)))); + assertEquals(HttpURLConnection.HTTP_NOT_IMPLEMENTED, putException.getStatusCode()); + assertEquals(S3ErrorTable.NOT_IMPLEMENTED.getCode(), putException.getErrorCode()); + + AmazonServiceException deleteException = assertThrows(AmazonServiceException.class, () -> s3Client.deletePublicAccessBlock( new DeletePublicAccessBlockRequest().withBucketName(bucketName))); - assertEquals(HttpURLConnection.HTTP_NOT_IMPLEMENTED, exception.getStatusCode()); - assertEquals(S3ErrorTable.NOT_IMPLEMENTED.getCode(), exception.getErrorCode()); + assertEquals(HttpURLConnection.HTTP_NOT_IMPLEMENTED, deleteException.getStatusCode()); + assertEquals(S3ErrorTable.NOT_IMPLEMENTED.getCode(), deleteException.getErrorCode()); assertTrue(s3Client.doesBucketExistV2(bucketName)); s3Client.deleteBucket(bucketName); diff --git a/hadoop-ozone/integration-test-s3/src/test/java/org/apache/hadoop/ozone/s3/awssdk/v2/AbstractS3SDKV2Tests.java b/hadoop-ozone/integration-test-s3/src/test/java/org/apache/hadoop/ozone/s3/awssdk/v2/AbstractS3SDKV2Tests.java index 94b163bf73c7..e17b6cf52471 100644 --- a/hadoop-ozone/integration-test-s3/src/test/java/org/apache/hadoop/ozone/s3/awssdk/v2/AbstractS3SDKV2Tests.java +++ b/hadoop-ozone/integration-test-s3/src/test/java/org/apache/hadoop/ozone/s3/awssdk/v2/AbstractS3SDKV2Tests.java @@ -278,15 +278,29 @@ public void testCreateBucketAlreadyExistsDifferentOwner() throws IOException { } @Test - public void testDeletePublicAccessBlockDoesNotDeleteBucket() { + public void testPublicAccessBlockIsNotImplemented() { final String bucketName = getBucketName(); s3Client.createBucket(b -> b.bucket(bucketName)); - S3Exception exception = assertThrows(S3Exception.class, + S3Exception getException = assertThrows(S3Exception.class, + () -> s3Client.getPublicAccessBlock(b -> b.bucket(bucketName))); + assertEquals(HttpURLConnection.HTTP_NOT_IMPLEMENTED, getException.statusCode()); + assertEquals(S3ErrorTable.NOT_IMPLEMENTED.getCode(), + getException.awsErrorDetails().errorCode()); + + S3Exception putException = assertThrows(S3Exception.class, + () -> s3Client.putPublicAccessBlock(b -> b + .bucket(bucketName) + .publicAccessBlockConfiguration(c -> c.blockPublicAcls(true)))); + assertEquals(HttpURLConnection.HTTP_NOT_IMPLEMENTED, putException.statusCode()); + assertEquals(S3ErrorTable.NOT_IMPLEMENTED.getCode(), + putException.awsErrorDetails().errorCode()); + + S3Exception deleteException = assertThrows(S3Exception.class, () -> s3Client.deletePublicAccessBlock(b -> b.bucket(bucketName))); - assertEquals(HttpURLConnection.HTTP_NOT_IMPLEMENTED, exception.statusCode()); + assertEquals(HttpURLConnection.HTTP_NOT_IMPLEMENTED, deleteException.statusCode()); assertEquals(S3ErrorTable.NOT_IMPLEMENTED.getCode(), - exception.awsErrorDetails().errorCode()); + deleteException.awsErrorDetails().errorCode()); assertDoesNotThrow(() -> s3Client.headBucket(b -> b.bucket(bucketName))); s3Client.deleteBucket(b -> b.bucket(bucketName)); diff --git a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/audit/S3GAction.java b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/audit/S3GAction.java index f215cd6cb0ff..5243afba3bf0 100644 --- a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/audit/S3GAction.java +++ b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/audit/S3GAction.java @@ -35,6 +35,9 @@ public enum S3GAction implements AuditAction { GET_BUCKET_LIFECYCLE, PUT_BUCKET_LIFECYCLE, DELETE_BUCKET_LIFECYCLE, + GET_UNSUPPORTED_BUCKET_SUBRESOURCE, + PUT_UNSUPPORTED_BUCKET_SUBRESOURCE, + DELETE_UNSUPPORTED_BUCKET_SUBRESOURCE, //RootEndpoint LIST_S3_BUCKETS, diff --git a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/BucketCrudHandler.java b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/BucketCrudHandler.java index a64b2b7a8f36..9db79b2b3d20 100644 --- a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/BucketCrudHandler.java +++ b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/BucketCrudHandler.java @@ -32,9 +32,8 @@ * Implements PUT (create bucket) and DELETE operations when no * subresource query parameters are present. * - * This handler processes bucket-level requests that do not target - * specific subresources (such as {@code ?acl}, {@code ?uploads}, - * {@code ?delete} or {@code ?tagging}), which are handled by dedicated handlers. + * This handler processes bucket-level requests that do not target a + * subresource handled by another handler. * * This handler extends EndpointBase to inherit all required functionality * (configuration, headers, request context, audit logging, metrics, etc.). @@ -47,8 +46,7 @@ private boolean shouldHandle() { && queryParams().get(QueryParams.UPLOADS) == null && queryParams().get(QueryParams.DELETE) == null && queryParams().get(QueryParams.TAGGING) == null - && queryParams().get(QueryParams.LIFECYCLE) == null - && queryParams().get(QueryParams.PUBLIC_ACCESS_BLOCK) == null; + && queryParams().get(QueryParams.LIFECYCLE) == null; } /** diff --git a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/BucketEndpoint.java b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/BucketEndpoint.java index c833d5f22f43..99b6036b119d 100644 --- a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/BucketEndpoint.java +++ b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/BucketEndpoint.java @@ -453,6 +453,7 @@ protected void init() { .add(new ListMultipartUploadsHandler()) .add(new BucketTaggingHandler()) .add(new BucketLifecycleHandler()) + .add(new UnsupportedBucketSubresourceHandler()) .add(new BucketCrudHandler()) .add(this) .build(); diff --git a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/UnsupportedBucketSubresourceHandler.java b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/UnsupportedBucketSubresourceHandler.java new file mode 100644 index 000000000000..92ddc2aeb618 --- /dev/null +++ b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/UnsupportedBucketSubresourceHandler.java @@ -0,0 +1,81 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you 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. + */ + +package org.apache.hadoop.ozone.s3.endpoint; + +import static org.apache.hadoop.ozone.s3.exception.S3ErrorTable.NOT_IMPLEMENTED; +import static org.apache.hadoop.ozone.s3.exception.S3ErrorTable.newError; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Set; +import javax.ws.rs.core.Response; +import org.apache.hadoop.ozone.audit.S3GAction; +import org.apache.hadoop.ozone.s3.exception.OS3Exception; +import org.apache.hadoop.ozone.s3.util.S3Consts.QueryParams; + +/** Rejects unsupported bucket subresource operations. */ +class UnsupportedBucketSubresourceHandler extends BucketOperationHandler { + + private static final Set UNSUPPORTED_SUBRESOURCES = Set.of( + QueryParams.PUBLIC_ACCESS_BLOCK); + + private String findUnsupportedSubresource() { + for (String subresource : UNSUPPORTED_SUBRESOURCES) { + if (queryParams().get(subresource) != null) { + return subresource; + } + } + return null; + } + + @Override + Response handleGetRequest(S3RequestContext context, String bucketName) + throws IOException, OS3Exception { + String subresource = findUnsupportedSubresource(); + if (subresource == null) { + return null; + } + + context.setAction(S3GAction.GET_UNSUPPORTED_BUCKET_SUBRESOURCE); + throw newError(NOT_IMPLEMENTED, subresource); + } + + @Override + Response handlePutRequest(S3RequestContext context, String bucketName, + InputStream body) throws IOException, OS3Exception { + String subresource = findUnsupportedSubresource(); + if (subresource == null) { + return null; + } + + context.setAction(S3GAction.PUT_UNSUPPORTED_BUCKET_SUBRESOURCE); + throw newError(NOT_IMPLEMENTED, subresource); + } + + @Override + Response handleDeleteRequest(S3RequestContext context, String bucketName) + throws IOException, OS3Exception { + String subresource = findUnsupportedSubresource(); + if (subresource == null) { + return null; + } + + context.setAction(S3GAction.DELETE_UNSUPPORTED_BUCKET_SUBRESOURCE); + throw newError(NOT_IMPLEMENTED, subresource); + } +} diff --git a/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/TestBucketDelete.java b/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/TestBucketDelete.java index 2494c27c53eb..d576a7dedece 100644 --- a/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/TestBucketDelete.java +++ b/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/TestBucketDelete.java @@ -17,8 +17,6 @@ package org.apache.hadoop.ozone.s3.endpoint; -import static org.apache.hadoop.ozone.s3.endpoint.EndpointTestUtils.assertErrorResponse; -import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.fail; @@ -29,7 +27,6 @@ import org.apache.hadoop.ozone.client.OzoneClientStub; import org.apache.hadoop.ozone.s3.exception.OS3Exception; import org.apache.hadoop.ozone.s3.exception.S3ErrorTable; -import org.apache.hadoop.ozone.s3.util.S3Consts.QueryParams; import org.apache.http.HttpStatus; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -91,13 +88,4 @@ public void testDeleteWithBucketNotEmpty() throws Exception { } fail("testDeleteWithBucketNotEmpty failed"); } - - @Test - public void testDeletePublicAccessBlockDoesNotDeleteBucket() { - bucketEndpoint.queryParamsForTest().set(QueryParams.PUBLIC_ACCESS_BLOCK, ""); - - assertErrorResponse(S3ErrorTable.NOT_IMPLEMENTED, - () -> bucketEndpoint.delete(bucketName)); - assertDoesNotThrow(() -> objectStoreStub.getS3Bucket(bucketName)); - } } diff --git a/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/TestUnsupportedBucketSubresource.java b/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/TestUnsupportedBucketSubresource.java new file mode 100644 index 000000000000..632fc4669d93 --- /dev/null +++ b/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/TestUnsupportedBucketSubresource.java @@ -0,0 +1,76 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you 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. + */ + +package org.apache.hadoop.ozone.s3.endpoint; + +import static org.apache.hadoop.ozone.s3.endpoint.EndpointTestUtils.assertErrorResponse; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; + +import java.io.IOException; +import org.apache.hadoop.ozone.OzoneConsts; +import org.apache.hadoop.ozone.client.ObjectStore; +import org.apache.hadoop.ozone.client.OzoneClient; +import org.apache.hadoop.ozone.client.OzoneClientStub; +import org.apache.hadoop.ozone.s3.exception.S3ErrorTable; +import org.apache.hadoop.ozone.s3.util.S3Consts.QueryParams; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +/** Tests for unsupported bucket subresource operations. */ +public class TestUnsupportedBucketSubresource { + + private static final String BUCKET_NAME = OzoneConsts.BUCKET; + private ObjectStore objectStore; + private BucketEndpoint bucketEndpoint; + + @BeforeEach + public void setup() throws IOException { + OzoneClient client = new OzoneClientStub(); + objectStore = client.getObjectStore(); + objectStore.createS3Bucket(BUCKET_NAME); + + bucketEndpoint = EndpointBuilder.newBucketEndpointBuilder() + .setClient(client) + .build(); + bucketEndpoint.queryParamsForTest().set(QueryParams.PUBLIC_ACCESS_BLOCK, ""); + } + + @Test + public void getPublicAccessBlockIsNotImplemented() { + assertErrorResponse(S3ErrorTable.NOT_IMPLEMENTED, + () -> bucketEndpoint.get(BUCKET_NAME)); + assertBucketExists(); + } + + @Test + public void putPublicAccessBlockIsNotImplemented() { + assertErrorResponse(S3ErrorTable.NOT_IMPLEMENTED, + () -> bucketEndpoint.put(BUCKET_NAME, null)); + assertBucketExists(); + } + + @Test + public void deletePublicAccessBlockIsNotImplemented() { + assertErrorResponse(S3ErrorTable.NOT_IMPLEMENTED, + () -> bucketEndpoint.delete(BUCKET_NAME)); + assertBucketExists(); + } + + private void assertBucketExists() { + assertDoesNotThrow(() -> objectStore.getS3Bucket(BUCKET_NAME)); + } +} From ebb3bf6460b6df58f825adff11eaa3e42a83ea48 Mon Sep 17 00:00:00 2001 From: f64116045 Date: Thu, 17 Sep 2026 00:42:18 +0800 Subject: [PATCH 3/3] HDDS-16408. Fix checkstyle violations --- .../hadoop/ozone/s3/awssdk/v1/AbstractS3SDKV1Tests.java | 6 +++--- .../s3/endpoint/UnsupportedBucketSubresourceHandler.java | 2 +- .../ozone/s3/endpoint/TestUnsupportedBucketSubresource.java | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/hadoop-ozone/integration-test-s3/src/test/java/org/apache/hadoop/ozone/s3/awssdk/v1/AbstractS3SDKV1Tests.java b/hadoop-ozone/integration-test-s3/src/test/java/org/apache/hadoop/ozone/s3/awssdk/v1/AbstractS3SDKV1Tests.java index ec2cc5c59e8e..1218b78d1dc2 100644 --- a/hadoop-ozone/integration-test-s3/src/test/java/org/apache/hadoop/ozone/s3/awssdk/v1/AbstractS3SDKV1Tests.java +++ b/hadoop-ozone/integration-test-s3/src/test/java/org/apache/hadoop/ozone/s3/awssdk/v1/AbstractS3SDKV1Tests.java @@ -57,10 +57,10 @@ import com.amazonaws.services.s3.model.GeneratePresignedUrlRequest; import com.amazonaws.services.s3.model.GetBucketLifecycleConfigurationRequest; import com.amazonaws.services.s3.model.GetBucketTaggingConfigurationRequest; -import com.amazonaws.services.s3.model.GetPublicAccessBlockRequest; import com.amazonaws.services.s3.model.GetObjectRequest; import com.amazonaws.services.s3.model.GetObjectTaggingRequest; import com.amazonaws.services.s3.model.GetObjectTaggingResult; +import com.amazonaws.services.s3.model.GetPublicAccessBlockRequest; import com.amazonaws.services.s3.model.Grantee; import com.amazonaws.services.s3.model.InitiateMultipartUploadRequest; import com.amazonaws.services.s3.model.InitiateMultipartUploadResult; @@ -73,8 +73,6 @@ import com.amazonaws.services.s3.model.ListPartsRequest; import com.amazonaws.services.s3.model.MultipartUpload; import com.amazonaws.services.s3.model.MultipartUploadListing; -import com.amazonaws.services.s3.model.PublicAccessBlockConfiguration; -import com.amazonaws.services.s3.model.SetPublicAccessBlockRequest; import com.amazonaws.services.s3.model.ObjectListing; import com.amazonaws.services.s3.model.ObjectMetadata; import com.amazonaws.services.s3.model.ObjectTagging; @@ -83,6 +81,7 @@ import com.amazonaws.services.s3.model.PartListing; import com.amazonaws.services.s3.model.PartSummary; import com.amazonaws.services.s3.model.Permission; +import com.amazonaws.services.s3.model.PublicAccessBlockConfiguration; import com.amazonaws.services.s3.model.PutObjectRequest; import com.amazonaws.services.s3.model.PutObjectResult; import com.amazonaws.services.s3.model.S3Object; @@ -92,6 +91,7 @@ import com.amazonaws.services.s3.model.SetBucketTaggingConfigurationRequest; import com.amazonaws.services.s3.model.SetObjectAclRequest; import com.amazonaws.services.s3.model.SetObjectTaggingRequest; +import com.amazonaws.services.s3.model.SetPublicAccessBlockRequest; import com.amazonaws.services.s3.model.Tag; import com.amazonaws.services.s3.model.TagSet; import com.amazonaws.services.s3.model.UploadPartRequest; diff --git a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/UnsupportedBucketSubresourceHandler.java b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/UnsupportedBucketSubresourceHandler.java index 92ddc2aeb618..800cc656b642 100644 --- a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/UnsupportedBucketSubresourceHandler.java +++ b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/UnsupportedBucketSubresourceHandler.java @@ -2,7 +2,7 @@ * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. - * The ASF licenses this file to you under the Apache License, Version 2.0 + * The ASF licenses this file to You 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 * diff --git a/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/TestUnsupportedBucketSubresource.java b/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/TestUnsupportedBucketSubresource.java index 632fc4669d93..d444acd2cee2 100644 --- a/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/TestUnsupportedBucketSubresource.java +++ b/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/TestUnsupportedBucketSubresource.java @@ -2,7 +2,7 @@ * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. - * The ASF licenses this file to you under the Apache License, Version 2.0 + * The ASF licenses this file to You 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 *