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]