-
-
Notifications
You must be signed in to change notification settings - Fork 2.5k
Object locking need to persist the tags and set the headers #6994
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
No logic to include object lock metadata in HEAD/GET response headers No logic to extract object lock metadata from PUT request headers
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Summary of Changes
Hello @chrislusf, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!
This pull request addresses a critical gap in S3 object locking functionality by ensuring that object lock metadata (mode, retention date, legal hold) is correctly persisted when objects are uploaded and subsequently returned in GET
and HEAD
responses. This change enables proper S3 object lock compliance and management within the system. Additionally, I've added extensive tests to validate this new behavior across various scenarios, including versioned objects and error handling.
Highlights
- Object Lock Metadata Persistence: I've implemented logic to extract S3 object lock headers (
X-Amz-Object-Lock-Mode
,X-Amz-Object-Lock-Retain-Until-Date
,X-Amz-Object-Lock-Legal-Hold
) fromPutObject
requests. This metadata is now correctly stored as extended attributes on the object entries in the filer, ensuring it persists with the object. - Object Lock Metadata Retrieval: The
GetObject
andHeadObject
handlers have been enhanced to read the stored object lock metadata from the extended attributes. This ensures that the corresponding S3 object lock headers are correctly included in their responses, providing clients with the object's retention and legal hold status. - New S3 Header Constants: New constants for the S3 object lock headers (
AmzObjectLockMode
,AmzObjectLockRetainUntilDate
,AmzObjectLockLegalHold
) have been added tos3_constants/header.go
for consistency and clarity. - Comprehensive Testing: I've introduced two new test suites (
s3_object_lock_headers_test.go
ands3_versioning_object_lock_test.go
) to thoroughly validate the persistence and retrieval of object lock metadata. These tests cover various scenarios, including different object lock modes (GOVERNANCE, COMPLIANCE), legal holds, retention dates, versioned objects, and error conditions.
Using Gemini Code Assist
The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.
Invoking Gemini
You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command>
or @gemini-code-assist <command>
. Below is a summary of the supported commands.
Feature | Command | Description |
---|---|---|
Code Review | /gemini review |
Performs a code review for the current pull request in its current state. |
Pull Request Summary | /gemini summary |
Provides a summary of the current pull request in its current state. |
Comment | @gemini-code-assist | Responds in comments when explicitly tagged, both in issue comments and review comments. |
Help | /gemini help |
Displays a list of available commands. |
Customization
To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/
folder in the base of the repository. Detailed instructions can be found here.
Limitations & Feedback
Gemini Code Assist is currently in preview and may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments to provide feedback.
You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.
Footnotes
-
Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution. ↩
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
This pull request implements S3 object lock functionality by persisting lock metadata from request headers and adding them to response headers for GET/HEAD requests. The changes are well-supported by a comprehensive set of new integration tests.
I've identified a critical compilation error in one of the new test files and a medium-severity issue in the response handler logic that could be improved for better readability and error logging. Addressing these points will improve the quality and robustness of the new feature.
func createBucketWithObjectLock(t *testing.T, client *s3.Client, bucketName string) { | ||
_, err := client.CreateBucket(context.TODO(), &s3.CreateBucketInput{ | ||
Bucket: aws.String(bucketName), | ||
ObjectLockEnabledForBucket: aws.Bool(true), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
weed/s3api/s3api_object_handlers.go
Outdated
// Add object lock mode header if present | ||
if modeBytes, exists := entry.Extended[s3_constants.ExtObjectLockModeKey]; exists { | ||
mode := string(modeBytes) | ||
if mode != "" { | ||
w.Header().Set(s3_constants.AmzObjectLockMode, mode) | ||
} | ||
} | ||
|
||
// Add retention until date header if present | ||
if dateBytes, exists := entry.Extended[s3_constants.ExtRetentionUntilDateKey]; exists { | ||
dateStr := string(dateBytes) | ||
if dateStr != "" { | ||
// Convert Unix timestamp to ISO8601 format for S3 compatibility | ||
if timestamp, err := strconv.ParseInt(dateStr, 10, 64); err == nil { | ||
retainUntilDate := time.Unix(timestamp, 0).UTC() | ||
w.Header().Set(s3_constants.AmzObjectLockRetainUntilDate, retainUntilDate.Format(time.RFC3339)) | ||
} | ||
} | ||
} | ||
|
||
// Add legal hold header if present | ||
if legalHoldBytes, exists := entry.Extended[s3_constants.ExtLegalHoldKey]; exists { | ||
legalHold := string(legalHoldBytes) | ||
if legalHold != "" { | ||
w.Header().Set(s3_constants.AmzObjectLockLegalHold, legalHold) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function can be improved for readability and robustness:
- The nested
if
checks can be flattened by combining the existence check with a length check on the byte slice. - When parsing the retention date, an error should be logged if
strconv.ParseInt
fails. This would make the behavior consistent withextractObjectLockMetadataFromRequest
and aid in debugging potential data corruption issues.
// Add object lock mode header if present
if modeBytes, exists := entry.Extended[s3_constants.ExtObjectLockModeKey]; exists && len(modeBytes) > 0 {
w.Header().Set(s3_constants.AmzObjectLockMode, string(modeBytes))
}
// Add retention until date header if present
if dateBytes, exists := entry.Extended[s3_constants.ExtRetentionUntilDateKey]; exists && len(dateBytes) > 0 {
dateStr := string(dateBytes)
// Convert Unix timestamp to ISO8601 format for S3 compatibility
if timestamp, err := strconv.ParseInt(dateStr, 10, 64); err == nil {
retainUntilDate := time.Unix(timestamp, 0).UTC()
w.Header().Set(s3_constants.AmzObjectLockRetainUntilDate, retainUntilDate.Format(time.RFC3339))
} else {
glog.Errorf("addObjectLockHeadersToResponse: failed to parse retention until date '%s': %v", dateStr, err)
}
}
// Add legal hold header if present
if legalHoldBytes, exists := entry.Extended[s3_constants.ExtLegalHoldKey]; exists && len(legalHoldBytes) > 0 {
w.Header().Set(s3_constants.AmzObjectLockLegalHold, string(legalHoldBytes))
}
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…t lock-enabled buckets fix --- FAIL: TestAddObjectLockHeadersToResponse/Handle_entry_with_no_object_lock_metadata (0.00s)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR enhances S3 object locking by persisting lock metadata on PUT and exposing it via GET/HEAD responses, and it updates tests to cover these behaviors and adapt to SDK changes.
- Added header validation, extraction into Extended attributes, and error mapping in
PutObjectHandler
- Implemented inclusion of object lock headers in GET/HEAD responses
- Expanded unit and integration tests; updated test code to use
aws.Bool
Reviewed Changes
Copilot reviewed 17 out of 19 changed files in this pull request and generated no comments.
Show a summary per file
File | Description |
---|---|
weed/s3api/s3api_object_retention.go | Removed outdated checkObjectLockPermissionsForPut helper |
weed/s3api/s3api_object_lock_headers_test.go | New unit tests for extracting, validating, and round‐tripping lock headers |
weed/s3api/s3api_object_handlers_put.go | Added validateObjectLockHeaders , extractObjectLockMetadataFromRequest , and error mapping |
weed/s3api/s3api_object_handlers.go | Invoke addObjectLockHeadersToResponse in GET/HEAD |
weed/s3api/s3_constants/header.go | Defined constants for object lock header names |
weed/notification/webhook/webhook_queue.go | Improved logging to handle nil dead‐letter messages |
test/s3/versioning, retention, cors (multiple files) | Updated integration tests to use aws.Bool(...) for boolean parameters |
Comments suppressed due to low confidence (2)
weed/s3api/s3api_object_handlers_put.go:103
- The previous permission check (
checkObjectLockPermissionsForPut
) was removed, which may allow unauthorized overwrites of locked objects. Consider reapplying object lock permission enforcement or integrating governance bypass logic after header validation to ensure locked objects cannot be overwritten.
if err := s3a.validateObjectLockHeaders(r, versioningEnabled); err != nil {
weed/notification/webhook/webhook_queue.go:200
- [nitpick] For static log messages without formatting directives, prefer
glog.Error
overglog.Errorf
to clarify intent and avoid suggesting formatting behavior.
glog.Errorf("received nil message from dead letter channel")
What problem are we solving?
How are we solving the problem?
How is the PR tested?
Checks