Skip to content

Commit 122ea32

Browse files
authored
HDDS-8511. Enforce strict S3-compliant name for object store buckets (#9462)
1 parent d8c574b commit 122ea32

4 files changed

Lines changed: 86 additions & 4 deletions

File tree

hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/bucket/OMBucketCreateRequest.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,9 +92,14 @@ public OMRequest preExecute(OzoneManager ozoneManager) throws IOException {
9292
CreateBucketRequest createBucketRequest =
9393
getOmRequest().getCreateBucketRequest();
9494
BucketInfo bucketInfo = createBucketRequest.getBucketInfo();
95-
// Verify resource name
96-
OmUtils.validateBucketName(bucketInfo.getBucketName(),
97-
ozoneManager.isStrictS3());
95+
96+
BucketLayout bucketLayout = BucketLayout.fromProto(bucketInfo.getBucketLayout());
97+
boolean strict = ozoneManager.isStrictS3()
98+
|| bucketLayout == BucketLayout.OBJECT_STORE;
99+
100+
// OBS (Object Store) buckets must follow strict S3 bucket naming rules.
101+
// FSO and LEGACY buckets are not strictly bound to S3 naming semantics.
102+
OmUtils.validateBucketName(bucketInfo.getBucketName(), strict);
98103

99104
// ACL check during preExecute
100105
if (ozoneManager.getAclsEnabled()) {

hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/TestOMClientRequestWithUserInfo.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import org.apache.hadoop.ozone.om.OMConfigKeys;
3939
import org.apache.hadoop.ozone.om.OMMetadataManager;
4040
import org.apache.hadoop.ozone.om.OMMetrics;
41+
import org.apache.hadoop.ozone.om.OmConfig;
4142
import org.apache.hadoop.ozone.om.OmMetadataManagerImpl;
4243
import org.apache.hadoop.ozone.om.OzoneManager;
4344
import org.apache.hadoop.ozone.om.helpers.BucketLayout;
@@ -79,6 +80,11 @@ public void setup() throws Exception {
7980
when(ozoneManager.getMetadataManager()).thenReturn(omMetadataManager);
8081
when(ozoneManager.getConfiguration()).thenReturn(ozoneConfiguration);
8182

83+
// mock OmConfig to avoid NPE in OMBucketCreateRequest.preExecute
84+
OmConfig omConfig = mock(OmConfig.class);
85+
when(omConfig.isFileSystemPathEnabled()).thenReturn(false);
86+
when(ozoneManager.getConfig()).thenReturn(omConfig);
87+
8288
// Mock version manager to avoid NPE in preExecute
8389
OMLayoutVersionManager versionManager = mock(OMLayoutVersionManager.class);
8490
when(versionManager.getMetadataLayoutVersion()).thenReturn(0);

hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/bucket/TestOMBucketCreateRequest.java

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -322,10 +322,38 @@ public void testAcceptNonS3CompliantBucketNameCreationWithStrictS3False()
322322
{"bucket_underscore", "_bucket___multi_underscore_", "bucket_"};
323323
when(ozoneManager.isStrictS3()).thenReturn(false);
324324
for (String bucketName : nonS3CompliantBucketName) {
325-
acceptBucketCreationHelper(volumeName, bucketName);
325+
acceptFSOBucketCreationHelper(volumeName, bucketName);
326326
}
327327
}
328328

329+
@Test
330+
public void testNonS3BucketNameRejectedForObjectStoreWhenStrictDisabled()
331+
throws Exception {
332+
333+
// strict mode disabled
334+
ozoneManager.getConfiguration().setBoolean(
335+
OMConfigKeys.OZONE_OM_NAMESPACE_STRICT_S3, false);
336+
337+
String volumeName = UUID.randomUUID().toString();
338+
String bucketName = "bucket_with_underscore"; // non-S3-compliant
339+
addCreateVolumeToTable(volumeName, omMetadataManager);
340+
341+
// Explicitly set bucket layout to OBJECT_STORE so the test doesn't depend on
342+
// defaults or mocked OM behavior.
343+
OzoneManagerProtocolProtos.BucketInfo.Builder bucketInfo =
344+
newBucketInfoBuilder(bucketName, volumeName)
345+
.setBucketLayout(
346+
OzoneManagerProtocolProtos.BucketLayoutProto.OBJECT_STORE);
347+
348+
OMRequest originalRequest = newCreateBucketRequest(bucketInfo).build();
349+
OMBucketCreateRequest req = new OMBucketCreateRequest(originalRequest);
350+
351+
OMException ex = assertThrows(OMException.class,
352+
() -> req.preExecute(ozoneManager));
353+
354+
assertEquals(OMException.ResultCodes.INVALID_BUCKET_NAME, ex.getResult());
355+
}
356+
329357
@ParameterizedTest
330358
@ValueSource(booleans = {true, false})
331359
public void testIgnoreClientACL(boolean ignoreClientACLs) throws Exception {
@@ -478,4 +506,14 @@ public static void addCreateVolumeToTable(String volumeName,
478506
.setOwnerName(UUID.randomUUID().toString()).build();
479507
OMRequestTestUtils.addVolumeToOM(omMetadataManager, omVolumeArgs);
480508
}
509+
510+
private void acceptFSOBucketCreationHelper(String volumeName, String bucketName)
511+
throws Exception {
512+
OzoneManagerProtocolProtos.BucketInfo.Builder bucketInfo =
513+
newBucketInfoBuilder(bucketName, volumeName)
514+
.setBucketLayout(OzoneManagerProtocolProtos.BucketLayoutProto.FILE_SYSTEM_OPTIMIZED);
515+
OMBucketCreateRequest omBucketCreateRequest = doPreExecute(bucketInfo);
516+
doValidateAndUpdateCache(volumeName, bucketName,
517+
omBucketCreateRequest.getOmRequest());
518+
}
481519
}

hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/bucket/TestOMBucketCreateRequestWithFSO.java

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import static org.apache.hadoop.ozone.om.request.OMRequestTestUtils.newBucketInfoBuilder;
2121
import static org.apache.hadoop.ozone.om.request.OMRequestTestUtils.newCreateBucketRequest;
2222
import static org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.BucketLayoutProto.FILE_SYSTEM_OPTIMIZED;
23+
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
2324
import static org.junit.jupiter.api.Assertions.assertEquals;
2425
import static org.junit.jupiter.api.Assertions.assertNotNull;
2526
import static org.junit.jupiter.api.Assertions.assertNull;
@@ -182,4 +183,36 @@ protected void doValidateAndUpdateCache(String volumeName, String bucketName,
182183
verifySuccessCreateBucketResponse(omClientResponse.getOMResponse());
183184

184185
}
186+
187+
@Test
188+
public void testNonS3BucketNameAllowedForFSOWhenStrictDisabled() throws Exception {
189+
// Arrange
190+
ozoneManager.getConfiguration().setBoolean(
191+
OMConfigKeys.OZONE_OM_NAMESPACE_STRICT_S3, false);
192+
193+
when(ozoneManager.getOMDefaultBucketLayout()).thenReturn(
194+
BucketLayout.FILE_SYSTEM_OPTIMIZED);
195+
196+
String volumeName = UUID.randomUUID().toString();
197+
String bucketName = "bucket_with_underscore"; // non-S3-compliant name
198+
addCreateVolumeToTable(volumeName, omMetadataManager);
199+
200+
OzoneManagerProtocolProtos.BucketInfo.Builder bucketInfo =
201+
newBucketInfoBuilder(bucketName, volumeName)
202+
.setBucketLayout(FILE_SYSTEM_OPTIMIZED)
203+
.addMetadata(OMRequestTestUtils.fsoMetadata());
204+
205+
OMRequest originalRequest = newCreateBucketRequest(bucketInfo).build();
206+
OMBucketCreateRequest req = new OMBucketCreateRequest(originalRequest);
207+
208+
// Act
209+
OMRequest modifiedRequest = req.preExecute(ozoneManager);
210+
211+
// Assert: validateAndUpdateCache should succeed
212+
assertDoesNotThrow(() -> {
213+
OMBucketCreateRequest omReq = new OMBucketCreateRequest(modifiedRequest);
214+
omReq.setUGI(UserGroupInformation.getCurrentUser());
215+
omReq.validateAndUpdateCache(ozoneManager, 1);
216+
});
217+
}
185218
}

0 commit comments

Comments
 (0)