This is an automated email from the ASF dual-hosted git repository.

ivandika pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ozone.git


The following commit(s) were added to refs/heads/master by this push:
     new 122ea327d1a HDDS-8511. Enforce strict S3-compliant name for object 
store buckets (#9462)
122ea327d1a is described below

commit 122ea327d1a1bbd1ea5a2c6e050362e1b49d102f
Author: Russole <[email protected]>
AuthorDate: Fri Jan 2 11:29:10 2026 +0800

    HDDS-8511. Enforce strict S3-compliant name for object store buckets (#9462)
---
 .../om/request/bucket/OMBucketCreateRequest.java   | 11 ++++--
 .../request/TestOMClientRequestWithUserInfo.java   |  6 ++++
 .../request/bucket/TestOMBucketCreateRequest.java  | 40 +++++++++++++++++++++-
 .../bucket/TestOMBucketCreateRequestWithFSO.java   | 33 ++++++++++++++++++
 4 files changed, 86 insertions(+), 4 deletions(-)

diff --git 
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/bucket/OMBucketCreateRequest.java
 
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/bucket/OMBucketCreateRequest.java
index d66b5d37081..718f329aaaf 100644
--- 
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/bucket/OMBucketCreateRequest.java
+++ 
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/bucket/OMBucketCreateRequest.java
@@ -92,9 +92,14 @@ public OMRequest preExecute(OzoneManager ozoneManager) 
throws IOException {
     CreateBucketRequest createBucketRequest =
         getOmRequest().getCreateBucketRequest();
     BucketInfo bucketInfo = createBucketRequest.getBucketInfo();
-    // Verify resource name
-    OmUtils.validateBucketName(bucketInfo.getBucketName(),
-        ozoneManager.isStrictS3());
+
+    BucketLayout bucketLayout = 
BucketLayout.fromProto(bucketInfo.getBucketLayout());
+    boolean strict = ozoneManager.isStrictS3()
+        || bucketLayout == BucketLayout.OBJECT_STORE;
+
+    // OBS (Object Store) buckets must follow strict S3 bucket naming rules.
+    // FSO and LEGACY buckets are not strictly bound to S3 naming semantics.
+    OmUtils.validateBucketName(bucketInfo.getBucketName(), strict);
 
     // ACL check during preExecute
     if (ozoneManager.getAclsEnabled()) {
diff --git 
a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/TestOMClientRequestWithUserInfo.java
 
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/TestOMClientRequestWithUserInfo.java
index d8618b8ed8f..145ffe9854f 100644
--- 
a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/TestOMClientRequestWithUserInfo.java
+++ 
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/TestOMClientRequestWithUserInfo.java
@@ -38,6 +38,7 @@
 import org.apache.hadoop.ozone.om.OMConfigKeys;
 import org.apache.hadoop.ozone.om.OMMetadataManager;
 import org.apache.hadoop.ozone.om.OMMetrics;
+import org.apache.hadoop.ozone.om.OmConfig;
 import org.apache.hadoop.ozone.om.OmMetadataManagerImpl;
 import org.apache.hadoop.ozone.om.OzoneManager;
 import org.apache.hadoop.ozone.om.helpers.BucketLayout;
@@ -79,6 +80,11 @@ public void setup() throws Exception {
     when(ozoneManager.getMetadataManager()).thenReturn(omMetadataManager);
     when(ozoneManager.getConfiguration()).thenReturn(ozoneConfiguration);
 
+    // mock OmConfig to avoid NPE in OMBucketCreateRequest.preExecute
+    OmConfig omConfig = mock(OmConfig.class);
+    when(omConfig.isFileSystemPathEnabled()).thenReturn(false);
+    when(ozoneManager.getConfig()).thenReturn(omConfig);
+
     // Mock version manager to avoid NPE in preExecute
     OMLayoutVersionManager versionManager = mock(OMLayoutVersionManager.class);
     when(versionManager.getMetadataLayoutVersion()).thenReturn(0);
diff --git 
a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/bucket/TestOMBucketCreateRequest.java
 
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/bucket/TestOMBucketCreateRequest.java
index 09f3e0b9d60..49bf00b1f8f 100644
--- 
a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/bucket/TestOMBucketCreateRequest.java
+++ 
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/bucket/TestOMBucketCreateRequest.java
@@ -322,10 +322,38 @@ public void 
testAcceptNonS3CompliantBucketNameCreationWithStrictS3False()
         {"bucket_underscore", "_bucket___multi_underscore_", "bucket_"};
     when(ozoneManager.isStrictS3()).thenReturn(false);
     for (String bucketName : nonS3CompliantBucketName) {
-      acceptBucketCreationHelper(volumeName, bucketName);
+      acceptFSOBucketCreationHelper(volumeName, bucketName);
     }
   }
 
+  @Test
+  public void testNonS3BucketNameRejectedForObjectStoreWhenStrictDisabled()
+      throws Exception {
+
+    // strict mode disabled
+    ozoneManager.getConfiguration().setBoolean(
+        OMConfigKeys.OZONE_OM_NAMESPACE_STRICT_S3, false);
+
+    String volumeName = UUID.randomUUID().toString();
+    String bucketName = "bucket_with_underscore"; // non-S3-compliant
+    addCreateVolumeToTable(volumeName, omMetadataManager);
+
+    // Explicitly set bucket layout to OBJECT_STORE so the test doesn't depend 
on
+    // defaults or mocked OM behavior.
+    OzoneManagerProtocolProtos.BucketInfo.Builder bucketInfo =
+        newBucketInfoBuilder(bucketName, volumeName)
+            .setBucketLayout(
+                OzoneManagerProtocolProtos.BucketLayoutProto.OBJECT_STORE);
+
+    OMRequest originalRequest = newCreateBucketRequest(bucketInfo).build();
+    OMBucketCreateRequest req = new OMBucketCreateRequest(originalRequest);
+
+    OMException ex = assertThrows(OMException.class,
+        () -> req.preExecute(ozoneManager));
+
+    assertEquals(OMException.ResultCodes.INVALID_BUCKET_NAME, ex.getResult());
+  }
+
   @ParameterizedTest
   @ValueSource(booleans = {true, false})
   public void testIgnoreClientACL(boolean ignoreClientACLs) throws Exception {
@@ -478,4 +506,14 @@ public static void addCreateVolumeToTable(String 
volumeName,
             .setOwnerName(UUID.randomUUID().toString()).build();
     OMRequestTestUtils.addVolumeToOM(omMetadataManager, omVolumeArgs);
   }
+
+  private void acceptFSOBucketCreationHelper(String volumeName, String 
bucketName)
+      throws Exception {
+    OzoneManagerProtocolProtos.BucketInfo.Builder bucketInfo =
+        newBucketInfoBuilder(bucketName, volumeName)
+            
.setBucketLayout(OzoneManagerProtocolProtos.BucketLayoutProto.FILE_SYSTEM_OPTIMIZED);
+    OMBucketCreateRequest omBucketCreateRequest = doPreExecute(bucketInfo);
+    doValidateAndUpdateCache(volumeName, bucketName,
+        omBucketCreateRequest.getOmRequest());
+  }
 }
diff --git 
a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/bucket/TestOMBucketCreateRequestWithFSO.java
 
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/bucket/TestOMBucketCreateRequestWithFSO.java
index b9bd4029a62..107e697971f 100644
--- 
a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/bucket/TestOMBucketCreateRequestWithFSO.java
+++ 
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/bucket/TestOMBucketCreateRequestWithFSO.java
@@ -20,6 +20,7 @@
 import static 
org.apache.hadoop.ozone.om.request.OMRequestTestUtils.newBucketInfoBuilder;
 import static 
org.apache.hadoop.ozone.om.request.OMRequestTestUtils.newCreateBucketRequest;
 import static 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.BucketLayoutProto.FILE_SYSTEM_OPTIMIZED;
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertNull;
@@ -182,4 +183,36 @@ protected void doValidateAndUpdateCache(String volumeName, 
String bucketName,
     verifySuccessCreateBucketResponse(omClientResponse.getOMResponse());
 
   }
+
+  @Test
+  public void testNonS3BucketNameAllowedForFSOWhenStrictDisabled() throws 
Exception {
+    // Arrange
+    ozoneManager.getConfiguration().setBoolean(
+        OMConfigKeys.OZONE_OM_NAMESPACE_STRICT_S3, false);
+
+    when(ozoneManager.getOMDefaultBucketLayout()).thenReturn(
+        BucketLayout.FILE_SYSTEM_OPTIMIZED);
+
+    String volumeName = UUID.randomUUID().toString();
+    String bucketName = "bucket_with_underscore"; // non-S3-compliant name
+    addCreateVolumeToTable(volumeName, omMetadataManager);
+
+    OzoneManagerProtocolProtos.BucketInfo.Builder bucketInfo =
+        newBucketInfoBuilder(bucketName, volumeName)
+            .setBucketLayout(FILE_SYSTEM_OPTIMIZED)
+            .addMetadata(OMRequestTestUtils.fsoMetadata());
+
+    OMRequest originalRequest = newCreateBucketRequest(bucketInfo).build();
+    OMBucketCreateRequest req = new OMBucketCreateRequest(originalRequest);
+
+    // Act
+    OMRequest modifiedRequest = req.preExecute(ozoneManager);
+
+    // Assert: validateAndUpdateCache should succeed
+    assertDoesNotThrow(() -> {
+      OMBucketCreateRequest omReq = new OMBucketCreateRequest(modifiedRequest);
+      omReq.setUGI(UserGroupInformation.getCurrentUser());
+      omReq.validateAndUpdateCache(ozoneManager, 1);
+    });
+  }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to