Skip to content

Conversation

@Russole
Copy link
Contributor

@Russole Russole commented Dec 8, 2025

What changes were proposed in this pull request?

This patch limits the non-strict naming behavior only to FSO buckets, which do not rely on S3 naming semantics.
Legacy/ObjectStore buckets—which represent the S3 bucket layout in Ozone—continue to enforce strict, S3-compliant naming rules, even when strict mode is disabled.

In summary, this PR ensures that only FSO buckets may use non-strict bucket names when
ozone.om.namespace.s3.strict=false; S3 buckets (Legacy/ObjectStore) must remain strict.

Appoach

  • Updated OMBucketCreateRequest to apply non-strict bucket name validation only when strict mode is disabled and the bucket layout is FSO.
  • Ensured that S3 buckets (Legacy/ObjectStore layout) always enforce strict, S3-compliant naming rules, regardless of the strict-mode setting.

What is the link to the Apache JIRA

https://issues.apache.org/jira/browse/HDDS-8511

How was this patch tested?

I relied on existing unit and integration tests, and verified that the full CI passed on my fork.
Please let me know if additional tests are needed.

…me including non-S3 compliant charaters when the om server side config 'ozone.om.namespace.s3.strict' is set false
@sreejasahithi
Copy link
Contributor

sreejasahithi commented Dec 8, 2025

Thanks @Russole for working on this,
According to me volume based S3 bucket detection does not look completely right because what I understand is that in multi-tenancy S3 requests route to respective tenant volumes (not always s3v) as each tenant has its own designated volume. I think its better to do by bucket layout and not by volume name.

@jojochuang jojochuang added the s3 S3 Gateway label Dec 8, 2025
Copy link
Contributor

@Tejaskriya Tejaskriya left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @Russole for picking this up.
There are tests: TestOMBucketCreateRequestWithFSO and TestOMBucketCreateRequest.
Could you please add a test for this case in the FSO file?

Also, there is a method of creating linked buckets through the ozone sh bucket link (LinkBucketHandler code) command.
This also might need a check. You can choose to handle this in this PR, or create a different jira too.

@adoroszlai adoroszlai changed the title Hdds 8511. Allow only FSO type of bucket to be created with bucket name including non-S3 compliant charaters when the om server side config 'ozone.om.namespace.s3.strict' is set false Hdds 8511. Enforce strict S3-compliant name for OBJECT_STORE buckets Dec 10, 2025
@adoroszlai adoroszlai changed the title Hdds 8511. Enforce strict S3-compliant name for OBJECT_STORE buckets HDDS-8511. Enforce strict S3-compliant name for OBJECT_STORE buckets Dec 10, 2025
Copy link
Contributor

@adoroszlai adoroszlai left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @Russole for working on this.

Please also update:

  • test cases in TestOMBucketCreateRequest (search for isStrictS3)
  • description of config property in hadoop-hdds/common/src/main/resources/ozone-default.xml

Comment on lines 97 to 131

// Convert BucketLayoutProto -> BucketLayout enum.
BucketLayout bucketLayout =
BucketLayout.valueOf(bucketInfo.getBucketLayout().name());

// Determine if this bucket belongs to the S3 namespace.
String s3VolumeName = ozoneManager.getConfiguration().get(
OzoneConfigKeys.OZONE_S3_VOLUME_NAME,
OzoneConfigKeys.OZONE_S3_VOLUME_NAME_DEFAULT);
boolean isS3Bucket =
s3VolumeName != null && s3VolumeName.equals(bucketInfo.getVolumeName());

// Compute effectiveStrict based on global strict flag, S3 namespace,
// and bucket layout.
boolean globalStrict = ozoneManager.isStrictS3();
boolean effectiveStrict = globalStrict;


// When strict=false, only S3 buckets with FSO layout should allow
// non-S3-compliant characters (e.g. underscore).
// All other S3 bucket layouts must still enforce strict naming rules.
if (!globalStrict && isS3Bucket) {
if (bucketLayout == BucketLayout.FILE_SYSTEM_OPTIMIZED) {
// S3 + FSO + strict=false → bypass strict S3 validation (allow '_' and other non-S3 characters)
effectiveStrict = false;
} else {
// S3 + non-FSO + strict=false → strict S3 validation still applies
// '_' and other non-S3 characters are not permitted
effectiveStrict = true;
}
}

// Verify resource name
OmUtils.validateBucketName(bucketInfo.getBucketName(),
ozoneManager.isStrictS3());
effectiveStrict);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Considering bucket links, multitenancy, and that S3 volume name can be updated in the config, I don't think this should be restricted to buckets in the S3 volume.
  2. Check eligibility using bucketLayout#isObjectStore to handle LEGACY, too.
  3. Use existing conversion logic BucketLayout#fromProto.
Suggested change
// Convert BucketLayoutProto -> BucketLayout enum.
BucketLayout bucketLayout =
BucketLayout.valueOf(bucketInfo.getBucketLayout().name());
// Determine if this bucket belongs to the S3 namespace.
String s3VolumeName = ozoneManager.getConfiguration().get(
OzoneConfigKeys.OZONE_S3_VOLUME_NAME,
OzoneConfigKeys.OZONE_S3_VOLUME_NAME_DEFAULT);
boolean isS3Bucket =
s3VolumeName != null && s3VolumeName.equals(bucketInfo.getVolumeName());
// Compute effectiveStrict based on global strict flag, S3 namespace,
// and bucket layout.
boolean globalStrict = ozoneManager.isStrictS3();
boolean effectiveStrict = globalStrict;
// When strict=false, only S3 buckets with FSO layout should allow
// non-S3-compliant characters (e.g. underscore).
// All other S3 bucket layouts must still enforce strict naming rules.
if (!globalStrict && isS3Bucket) {
if (bucketLayout == BucketLayout.FILE_SYSTEM_OPTIMIZED) {
// S3 + FSO + strict=false → bypass strict S3 validation (allow '_' and other non-S3 characters)
effectiveStrict = false;
} else {
// S3 + non-FSO + strict=false → strict S3 validation still applies
// '_' and other non-S3 characters are not permitted
effectiveStrict = true;
}
}
// Verify resource name
OmUtils.validateBucketName(bucketInfo.getBucketName(),
ozoneManager.isStrictS3());
effectiveStrict);
BucketLayout bucketLayout = BucketLayout.fromProto(bucketInfo.getBucketLayout());
boolean strict = ozoneManager.isStrictS3()
|| bucketLayout.isObjectStore(ozoneManager.getConfig().isFileSystemPathEnabled());
OmUtils.validateBucketName(bucketInfo.getBucketName(), strict);

@adoroszlai adoroszlai changed the title HDDS-8511. Enforce strict S3-compliant name for OBJECT_STORE buckets HDDS-8511. Enforce strict S3-compliant name for object store buckets Dec 14, 2025
@Russole
Copy link
Contributor Author

Russole commented Dec 16, 2025

Thanks @sreejasahithi, @adoroszlai, and @Tejaskriya for the detailed reviews.
I’ll start updating the patch based on your comments.

Copy link
Contributor

@adoroszlai adoroszlai left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @Russole for updating the patch.

Comment on lines 99 to 103
OmConfig omConfig = ozoneManager.getConfig();
boolean fsPathEnabled = false;
if (omConfig != null) {
fsPathEnabled = omConfig.isFileSystemPathEnabled();
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of adding this logic, please mock ozoneManager.getConfig() in TestOMClientRequestWithUserInfo:

when(ozoneManager.getConfiguration()).thenReturn(ozoneConfiguration);

like:

when(ozoneManager.getConfiguration()).thenReturn(ozoneConfiguration);
when(ozoneManager.getConfig()).thenReturn(ozoneConfiguration.getObject(OmConfig.class));

Comment on lines 482 to 484
protected OMBucketCreateRequest doPreExecute(String volumeName,
String bucketName,
OzoneManagerProtocolProtos.BucketLayoutProto layout) throws Exception {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Please do not format method signature like this. Whenever visibility / return type / method name / other modifiers are changed, we would have to reindent all parameters.

Comment on lines 57 to 62
// 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);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then we don't need this new test class, test case can be added in TestOMBucketCreateRequest.

@Russole
Copy link
Contributor Author

Russole commented Dec 22, 2025

I re-ran the job on my fork and it passed.
I don’t have permission to rerun the upstream CI,
so I’d appreciate it if someone could help rerun the failed job.

@adoroszlai adoroszlai requested a review from ivandika3 December 23, 2025 09:03
Copy link
Contributor

@ivandika3 ivandika3 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the patch. Left some comments.

Comment on lines 189 to 191
// Arrange
ozoneManager.getConfiguration().setBoolean(
OMConfigKeys.OZONE_OM_NAMESPACE_STRICT_S3, false); // 如果常數名稱不同,改成實際的 key
Copy link
Contributor

@ivandika3 ivandika3 Dec 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Please remove the zh comment (since some community members may not understand it) and the "Arrange" comment also can be removed.

Comment on lines 98 to 99
boolean strict = ozoneManager.isStrictS3()
|| bucketLayout.isObjectStore(ozoneManager.getConfig().isFileSystemPathEnabled());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's only check for OBS bucket (i.e. not use BucketLayout#isObjectStore which also takes into account LEGACY buckets) since it provides a stronger guarantee than LEGACY bucket which can become "object store" if we change the configuration ("ozone.om.enable.filesystem.paths").

Also let's add a small comment that OBS bucket needs to have strictly S3 name bucket unlikes FSO and LEGACY bucket.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes I think let's keep this s3 strict compliant name only for OBS buckets.

Comment on lines 510 to 520
protected OMBucketCreateRequest doPreExecute(String volumeName,
String bucketName,
OzoneManagerProtocolProtos.BucketLayoutProto layout) throws Exception {
OzoneManagerProtocolProtos.BucketInfo.Builder bucketInfo =
newBucketInfoBuilder(bucketName, volumeName)
.setBucketLayout(layout);
if (layout == OzoneManagerProtocolProtos.BucketLayoutProto.FILE_SYSTEM_OPTIMIZED) {
bucketInfo.addMetadata(OMRequestTestUtils.fsoMetadata());
}
return doPreExecute(bucketInfo);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this extra doPreExecute is not necessary. How about we simply use the current newBucketInfoBuilder#setBucketLayout(FILE_SYSTEM_OPTIMIZED)? Also the addMetadata is also not necessary.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

s3 S3 Gateway

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants