Object locking prevents object versions from being deleted or overwritten – for a fixed amount of time or indefinitely. Use an object lock to help meet regulatory requirements requiring WORM storage, or to add another layer of protection against object changes and deletion.
Objects are not actually locked. Object locking is used to lock individual object versions.
Object locking does not prevent the creation of new versions of an object while the object is locked – it makes it impossible to delete or otherwise change the version(s) of the object with locking enabled.
Object locking does not prevent overwriting or deleting objects
Since the locked versions remain present and protected it is still possible to overwrite or even delete objects with locking enabled.
A new version is created when overwriting or modifying an object.
A delete request creates a delete marker. The object appears deleted, but Swarm preserves history including the locked version.
There are two types of object locking used simultaneously and independent of each other:
Retention – Specifies a fixed period of time ("retention period") during which the object remains locked. During this period, the object is WORM-protected and cannot be overwritten or deleted. The lock goes away automatically after the period expires.
Legal hold – An object stays locked indefinitely when a legal hold is applied. A legal hold does not expire; it must be explicitly removed.
Retention
Retention Periods
A retention period is used to set the fixed amount of time the object needs to remain locked. The object version cannot be changed or deleted until the time expires.
There is more than one way to set a retention period on an object version:
Newly created objects can inherit a default retention period configured on the bucket level.
Explicitly setting a retention period when creating a new object overrides the default retention period configured for the bucket if present.
Explicitly set a retention period on an existing object version.
A bucket default retention period specifies a duration (in days or years) for which every object version placed in the bucket is locked. Gateway calculates a retention period for the object version by adding the specified duration to the object version's creation timestamp when placing an object in the bucket.
How to Extend a Retention Period
A retention period can always be extended after it has been set with the following steps:
Submit a new lock request for the object version with a retention period longer than the current one.
Gateway replaces the existing retention period with the new, longer period.
Any user with permissions to set an object retention period can also extend a retention period.
Retention Modes
A retention mode must always be specified when locking an object or setting a bucket default retention period.
Retention mode applies to individual objects
Retention mode always applies to the individual objects carrying it, not to the bucket or cluster as a whole.
There are two retention modes impacting actions with objects under retention:
In governance mode, grant some users the permission to shorten or remove a retention period or delete object versions under retention if necessary.
In compliance mode, a locked object version cannot be overwritten or deleted by any user, even the admin user. The retention mode cannot be changed, and the retention period cannot be shortened when an object is locked in compliance mode.
Compliance mode is irreversible
Compliance mode is irreversible for the entire retention period once an object is locked.
In a deviation from S3, Gateway always uses the maximum of either the bucket default retention duration, or the duration specified in a per-object request.
Legal Hold
A legal hold prevents an object version from being overwritten or deleted until the legal hold is removed.
Legal holds do not have an associated retention period and are independent from retention periods and retention modes. As long as the bucket containing the object has object locking enabled adding and removing legal holds are available. It does not matter if the specified object version has a retention period set or not.
Legal hold does not affect retention
Setting a legal hold on an object version does not affect the retention mode or retention period for the object version.
Prerequisites
Swarm Storage 12.0 or above must be running in order to use this feature because it relies on the Swarm lifepoints feature to prevent deletion of locked objects until a certain date has passed. Object locking is fully implemented starting with Gateway 7.6.
Whenever an object gets locked until a certain date, it gets a deletable=no
lifepoint protecting it from deletion until the date.
Applications can impose user defined lifepoints together with object locks
Even though Gateway relies on lifepoints, it remains possible for applications to impose user defined lifepoints on objects together with object locks. Gateway verifies correct semantics in all cases without any additional behavior needed from the application side. In case of any conflicts between user defined lifepoints and object locks, the object lock always wins.
In order for object locking to work, versioning needs to be enabled.
Gateway refuses to enable object locking when versioning is not enabled. Gateway refuses to disable versioning once object locking is enabled. In both cases an error message is displayed.
Administrators are advised against disabling versioning once object locking has been enabled anywhere in the cluster
The ability to disable versioning at the cluster level via SNMP does not pass via Gateway so it cannot protect against disabling object locking in the cluster.
Administrators are advised against disabling versioning at the cluster level to avoid the risk of auto-deleting locked object versions after object locking has been enabled in individual domains or buckets.
Metadata Headers related to Object Locking
Object versions in Swarm are immutable and the metadata cannot be changed unlike Amazon S3.
Object locking uses the following headers:
on buckets:
x-object-lock-meta-status: ENABLED
(empty means DISABLED)x-object-lock-meta-default: <GOVERNANCE|COMPLIANCE>[:<duration>]
Bucket default retention period duration is expressed as <integer>y for number of years or<integer>d
for number of days.
on objects:
x-object-lock-meta-mode: <GOVERNANCE|COMPLIANCE>
x-object-lock-meta-retain-until-date: <date>
x-object-lock-meta-legal-hold: ON
(empty means OFF)x-object-lock-meta-original-lifepoints:
<original lifepoints>lifepoint: [<date>] deletable=no
(for retention period)lifepoint: [] deletable=no
(for legal hold)
The above headers are listed using the SCSP names. The corresponding S3 names start with x-amz-*. The SCSP headers are effectively stored with the objects. The S3 names are mapped onto the SCSP counterparts and back on-the-fly.
Assumptions and Limitations
Internal to Gateway, all header values are treated as case-insensitive.
Dates are in the
rfc1123
format, e.g. "Wed, 12 Dec 2016 15:59:02 GMT
". For S3 these are translated in to theISO8601
format.The
x-object-lock-meta-retain-until-date
header applies to retention periods and specifies the end date of the retention period. Thex-object-lock-meta-legal-hold
header applies to legal hold. Both a retention period and a legal hold can both be set on the same object version.The
x-object-lock-meta-original-lifepoints
header stores the complete set of user defined delete/deletable lifepoint headers found on the object at the time the retention period/legal hold was applied. The original delete/deletable lifepoint headers are removed. Swarm no longer considers these lifepoints.
Gateway manipulates delete/deletable type lifepoints, all other lifepoints are unaffected and continue functioning normally.
An object lock in effect takes precedence over any user-defined delete/deletable lifepoints, blockingdelete
. The user-defined lifepoints take effect again when an object lock expires (or gets removed).Object locking works for tenanted objects. Object locking cannot be set on untenanted and unnamed objects in a cluster.
Lifepoint Headers
Gateway now adds a single deletable=no
lifepoint header (the lock lifepoint), to go along with the object lock. This lock lifepoint is what actually protects the object against deletion in Swarm, both through user requests and through built-in functionalities like HP or bucket policies.
The lock lifepoint is computed as follows;
The lock lifepoint end date matches the end date of the retention period if the object is locked with a retention period. For legal hold, the lock lifepoint has no end date.
Next review the list of original lifepoints, and append those whose end date is later than the one from the lock lifepoint. In case of legal hold, there is no end date so none of the original lifepoints get appended.
The purpose of storing the set of original lifepoints is to allow later modifications/removal of the object lock to recompute/reinstate the original lifepoints as they were before the object lock.
The purpose of appending the "later lifepoints" to the lock lifepoint is to allow Swarm to act on them as it normally does once the lock lifepoint has expired naturally, without any intervention from Gateway. For legal hold there must always be a Gateway intervention to remove the lock, so the original lifepoints get reinstated at the time.
How to Enable Object Locking
Object locking is set using API calls. It is not yet available in the user interface.
Enabling Object Locking on a Bucket
Object locking must be enabled on the bucket before locking any objects.
S3 normally allows enabling object locking on new buckets without any objects. Gateway does not impose this restriction.
The user must have the PutBucketObjectLocking
permission to enable/disable object locking on a bucket. A user must have the GetBucketObjectLocking
permission to query current object locking status.
Object Locking and Versioning Inheritance Rules
Versioning can be disabled for another bucket or domain in the cluster unrelated if a bucket in one domain has object locking (and therefore versioning) enabled.
Cannot be disabled at the bucket, domain or cluster level if object locking (and versioning) is enabled at a bucket level.
Can be disabled for individual buckets if enabled at a domain level.
Can be disabled for individual domains and/or buckets if enabled at the cluster level.
It does not matter if versioning was enabled on the bucket itself, or whether it was inherited from cluster or domain level. Gateway refuses to disable versioning at the domain or bucket level if object locking is in effect anywhere within it.
Errors When Attempting to Enable Object Locking
The request to enable object locking can fail with the following errors:
412 Precondition Failed
is displayed if the Swarm cluster does not yet support all the features necessary to perform the operation.412 Precondition Failed
is displayed if the bucket does not have versioning enabled.403 Forbidden
if the user does not have thePutBucketObjectLocking
permission.
Enabling object locking on a bucket comes down to storing the x-object-lock-meta-status
and optionally x-object-lock-meta-default
headers on the bucket context object. This immediately caches the bucket’s object locking configuration in memory so it is readily available during object requests.
Enabling Object Locking using S3
Enable or inspect the object locking configuration on a bucket using the following calls;
https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObjectLockConfiguration.html
https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObjectLockConfiguration.html
Enabling Object Locking using SCSP
Enable object locking on a bucket:
PUT /<bucket>?objectlock=<defaultmode> [ :<defaultperiod> ]
defaultmode
can be either "governance" or "compliance"defaultperiod
is optional; it is a number of years (y) or days (d), eg.1y
or20d
.
In this call omit either defaultmode
, defaultperiod
, or both.
The bucket allows object locking (it is enabled), but no locking happens by default if both are omitted. Objects written to the bucket without any locking directives remain unlocked.
The defaults can be modified or removed at any time via additional PUT
commands. This does not affect the object locking status of the bucket – once it is enabled, it stays enabled.
Object Locking Cannot be Disabled After it has been Enabled
Object locking cannot be disabled
Object locking cannot be disabled once enabled on a bucket.
It does not matter if versioning was enabled on the bucket itself, or whether it was inherited from cluster or domain level. Gateway refuses to disable versioning at the domain or bucket level if object locking is in effect anywhere within it.
Remove the lock defaults and write new objects without any object locking headers to allow writing unlocked objects into a bucket with object locking enabled.
Remove the lock defaults:
PUT /<bucket>?objectlock=
(use an empty query argument)
The "=" is optional.
How to Check Object Locking Status
Query the object locking status of a bucket:
GET /<bucket>?objectlock
This returns the following response headers:x-object-lock-meta-status: ENABLED
x-object-lock-meta-default: <GOVERNANCE|COMPLIANCE>[:<duration>]
And the response body says:Object locking is enabled on bucket <bucket> with default mode <mode> [ and default duration <duration> ]
No response headers are present and the response body displays as below if the bucket does not have object locking enabled:Object locking disabled
REST API Changes
Object locking introduces the following new REST calls:
PUT
with?objectlock
query argumentsGET
with?objectlock
query argumentsDELETE
with?objectlock
query arguments (DELETE
is an object-only call)
Object locking also introduces changes to existing REST calls:
PUT
can now take object locking headers to create locks as a side effectPOST
can now take object locking headers to create locks as a side effectCOPY
can now take object locking headers to create locks as a side effectGET
can return object locking headers if the user has the appropriate permissionsHEAD
can return object locking headers if the user has the appropriate permissions
For S3, see the Amazon documentation website.
How to Lock an Object at Creation Time
Creating a New Object with a Retention Period
The client adds the following headers in the S3 PutObject
/ SCSP POST
request to create a new object or object version with an immediate retention period in effect:
x-object-lock-meta-mode: <GOVERNANCE|COMPLIANCE>
x-object-lock-meta-retain-until-date: <date>
This takes precedence over the default bucket retention mode and duration, if present.
In a deviation from S3, Gateway always uses the maximum of either the bucket default retention duration, or the duration specified in a per-object request.
Gateway looks for corresponding defaults at the bucket level if any one of these two headers is omitted from the request and if found, takes the corresponding values from there.
The request fails with a 400 Bad Request
error because both are needed for a successful retention lock if either mode or retain-until-date is then still missing.
Creating a New Object with a Legal Hold
The client adds the following header in the S3 PutObject
/ SCSP POST
request to create a new object or object version with an immediate legal hold in effect:
x-object-lock-legal-hold: ON
The user needs to have the PutObjectRetention
and, respectively, PutObjectLegalHold
permission to use these headers, or the request fails with a 403 Forbidden
error.
The request fails with a 412 Precondition Failed
error if the bucket does not have object locking enabled.
Gateway forwards these headers when creating the new object on Swarm, and also creates a lock lifepoint instructing Swarm to not delete the object before the retention period expires. For retention periods, the lock lifepoint also includes the subset of the original lifepoints with a later end date than the retention period.
lifepoint: [<date>] deletable=no, <later lifepoints>
Or in case of legal hold;
lifepoint: [] deletable=no
The original lifepoint headers are preserved in:
x-object-lock-meta-original-lifepoints: <original lifepoints>
Writing an Object as a Normal Unlocked Object in a Bucket with Object Locking Enabled
Objects are written as a normal unlocked object, despite being written to a bucket with object locking enabled if both headers are omitted from the request, and there are no defaults at the bucket level.
Managing Retention on an Existing Object
Enabling and disabling retention on an object requires the user have the PutObjectRetention
permission.
The user must have the GetObjectRetention
permission to query current retention status.
The client must explicitly specify the versionId
of the object version to lock.
Gateway then applies the extra object locking headers to the version, thus applying object locking protection for the length of the retention period.
The following headers are added or changed;
x-object-lock-meta-mode: <GOVERNANCE|COMPLIANCE>
x-object-lock-meta-retain-until-date: <date>x-object-lock-meta-original-lifepoints: <original lifepoints>
lifepoint: [<date>] deletable=no, <later lifepoints>
Gateway must recompute the lock lifepoint when changing the retention period, starting from the preserved set of original lifepoints and appending those with later end dates to the lock lifepoint. This is the main purpose of preserving the original lifepoints.
In a deviation from S3, Gateway always uses the maximum of either the bucket default retention duration, or the duration specified in a per-object request.
Introducing or extending a retention period is always possible, but there are restrictions to shortening or removing a retention period on an object already under retention:
In compliance mode this is never permitted
In governance mode, the user needs to have the special
BypassGovernanceRetention
permission.
Also, an S3 request must explicitly includex-amz-bypass-governance-retention:true
as a request header with any request requiring overriding governance mode.
Using S3, enable or inspect the retention period on an object using the following calls;
https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObjectRetention.html
https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObjectRetention.html
Using SCSP, enable or inspect the retention period on an object using the following calls:
Set a governance lock onto an object, specifying both lock mode and duration (this overrides any defaults configured on the bucket):
PUT /<bucket>/<object>?version=<uuid>&objectlock=governance:<untildate>
Set a compliance lock onto an object and inherit the default duration from the bucket:
PUT /<bucket>/<object>?version=<uuid>&objectlock=compliance
Completely inherit the default object lock mode and duration on the bucket:
PUT /<bucket>/<object>?version=<uuid>&objectlock
Remove a (governance) object lock from an object:
DELETE /<bucket>/<object>?version=<uuid>&objectlock=<mode>
The mode is always "governance". A compliance mode object lock cannot be removed. The BypassGovernanceRetention permission is required to carry out this action and the request must carry the x-object-lock-meta-bypass-governance:true header.Query current object lock status:
GET /<bucket>/<object>?version=<uuid>&objectlock
The response carries the following headers:x-object-lock-meta-mode: <GOVERNANCE|COMPLIANCE>
x-object-lock-meta-retain-until: <date>
And the response body says:Object is locked in <mode> mode until <date>
None of the headers are present when called on an object not under retention, and the response body says:Object is not locked
Both S3 and SCSP also allow retrieving object lock information using regular object HEAD
and GET
requests.
Assuming the user has the GetObjectRetention
permission, the information is returned in the form of the above response headers. The response body is not affected.
Managing Legal Hold on an Existing Object
Enabling/disabling legal hold requires the user have the PutObjectLegalHold
permission. The GetObjectLegalHold
permission is required to check the current legal hold status.
As with retention periods, Gateway stores this as a metadata header.
x-object-lock-meta-legal-hold: ON
(empty means OFF)
x-object-lock-meta-original-lifepoints: <original lifepoints>
lifepoint: [] deletable=no
Using S3, enable or inspect the legal hold using the following calls:
https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObjectLegalHold.html
https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObjectLegalHold.html
Using SCSP, enable or inspect the legal hold on an object using the following calls:
Set a legal hold onto an object:
PUT /<bucket>/<object>?version=<uuid>&objectlock=legal-hold
Remove a legal hold from an object:
DELETE /<bucket>/<object>?version=<uuid>&objectlock=legal-hold
This reinstates any original lifepoints by moving them from thex-object-lock-meta-original-lifepoints
header back in to the properlifepoint
headers.Query an object's legal hold status:
GET /<bucket>/<object>?version=<uuid>&objectlock
The response carries the following headers:x-object-lock-meta-legal-hold: on
And the response body says:Object is locked in legal hold
The header is not present when called on an object not under legal hold nor retention, and the response body says:Object is not locked
Both S3 and SCSP also allow retrieving legal hold information using regular object HEAD
and GET
requests. Assuming the user has the GetObjectLegalHold
permission, the information is returned in the form of the above response headers. The response body is not affected.
Combined Retention and Legal Hold
An object can be both under one of the retention modes AND legal hold at the same time.
In the SCSP protocol, querying and deleting such combined locks is handled via a uniform GET
and DELETE
API (as opposed to S3 which has separate APIs for querying/deleting retention and legal hold).
Query:
GET /<bucket>/<object>?version=<uuid>&objectlock[=<locktype>]
Response headers for both retention and the legal hold display when querying the object lock status without specifying the lock type, and the response body contains both status texts, separated by a new line.
The user needs both theGetObjectRetention
and theGetObjectLegalHold
permissions for this request.
Query the lock status for one specific lock type, either "legal-hold" or "retention". The corresponding permission is required.Delete:
DELETE /<bucket>/<object>?version=<uuid>&objectlock=<locktype>
Using SCSP remove either the retention or legal hold using DELETE and specifying the appropriate query argumentobjectlock=<locktype>
, locktype being "legal-hold" or "retention". The locktype of "retention" is used exclusively for locks in governance mode.
Differences Between S3 and Swarm's Implementation of Object Locking
In S3, a DELETE request results in a delete marker, shadowing the locked object version. Swarm's implementation deviates from this logic – it rejects any DELETE
requests for indelible objects with an HTTP 403 Forbidden
error.
Gateway checks if the object is locked when it gets a HTTP 403 Forbidden
error from Swarm. Gateway simulates the S3 behavior creating a new (unlocked) object version, immediately followed by a DELETE
, thus creating a delete marker.
For SCSP, use a configuration flag to pick the desired behavior:
fail deletes of locked objects with a
403 Forbidden
error, ormimic the S3 behavior
[object_locking]
scspDeleteUsesS3Logic=true
New Policy Actions Related to Object Locking
The following new policy actions related to object locking have been introduced:
PutBucketObjectLocking
: to enable/disable object locking on a bucketGetBucketObjectLocking
: to query bucket object locking statusPutObjectRetention
: to set or extend object retentionGetObjectRetention
: to query object retentionBypassGovernanceRetention
: to shorten/remove a retention in governance modePutObjectLegalHold
: to set/remove a legal holdGetObjectLegalHold
: to query legal hold
Interactions with Existing Swarm Functionality
Recursive Deletes
Clients can request recursive deletes of entire domains/buckets using DELETE <uri>?recursive=yes
requests. Swarm implements this by synchronously deleting the domain/bucket object, and asynchronously deleting the objects in it. This has potential for conflicting with object retention/legal hold. Gateway first checks if there are any objects under retention/legal hold and refuse the recursive delete if so.
The recursive delete request fails with a 412 Precondition Failed
error if any buckets with object locks are found.
APPEND
SCSP APPEND does create a new version when versioning is enabled; it does not allow an object's metadata to be modified. The "retain-until" header value can not be changed on an APPEND
. Gateway does not impose any restrictions on the use of APPEND
in combination with object locking.
Max Retention Configuration
S3 allows defining a max-retention-duration
limit in the policy. Gateway currently approximates this functionality using a new configuration flag:
[object_locking]
retentionMaxYears=100
The default limit value is 100 years (input type int) if unspecified.
A year is assumed to be 365 days when performing conversions between numbers of days and years.
In the SCSP/S3 APIs, any user-specified value exceeding the limit is capped to the limit.
Audit Logging
Object Locking operations are audit logged. Since object locks can also be requested as part of the object PUT/POST/COPY
requests, Gateway tag the request's audit log line with additional object lock information, rather than inserting new log lines.
The tags are appended to the audit log line, enclosed in []
brackets. Multiple tags (for example, both legal hold and retention were requested) are comma separated.
Object locking tags are always prefixed with OBJLCK
.
Enabling retention on a bucket and setting defaults if provided:
<audit log line> [OBJLCK:ENABLE:<mode>:<duration>]
Setting/removing retention on an object:
<audit log line> [OBJLCK:RETENTION:<mode>:<retainUntil>]
<audit log line> [OBJLCK:RETENTION:NONE]
Setting/removing legal hold on an object:
<audit log line> [OBJLCK:LEGALHOLD:ON]
<audit log line> [OBJLCK:LEGALHOLD:OFF]