Skip to content

Object Lock

Object Lock freezes specific versions of objects so they cannot be deleted or overwritten until a retention period expires. It is used for compliance and audit trails, not for blocking all writes to a key.

Prerequisites

  • A Ceph Object Storage bucket with Object Lock enabled (see below).
  • An S3 user with permissions to create versioned buckets and apply retention policies.

What Object Lock Actually Does

Object Lock works at the version level, not the key level.

When you create a bucket with Object Lock, versioning is automatically enabled. Every upload creates a new version with a unique VersionId. Object Lock attaches a retention policy to that specific version.

Key: contract.pdf
├── Version V1 (locked until 2033) ← CANNOT be deleted
├── Version V2 (no lock)          ← latest, returned by default GET
└── Version V3 (no lock)          ← if you upload again

Key points: - A locked version cannot be deleted by anyone, including administrators. - A locked version cannot be overwritten (it is immutable). - You can still upload new versions of the same key. - GET without a VersionId returns the latest version (which may not be locked). - A DELETE creates a delete marker that hides the latest version, but older locked versions remain.

Regulatory Compliance

Infomaniak Ceph Object Storage supports Object Lock configurations that comply with:

  • SEC Rule 17a-4(f) (financial records retention)
  • FINRA Rule 4511© (broker-dealer records)
  • CFTC Rule 1.31©-(d) (commodity trading records)

When properly configured with COMPLIANCE mode, Ceph Object Lock provides the immutable storage and audit capabilities required by these regulations.

Enabling Object Lock

Object Lock can be enabled at bucket creation or later, but once enabled it cannot be removed.

Enable at bucket creation

aws s3api create-bucket \
  --bucket my-locked-bucket \
  --object-lock-enabled-for-bucket \
  --profile myprofile --region gva2

Versioning is automatically enabled and cannot be disabled.

When created this way, Object Lock is enabled but no default retention is set. Objects uploaded to the bucket are not automatically locked unless you either configure default retention or lock them manually.

Enable on an existing bucket

If the bucket was created without Object Lock, you can enable it later. First ensure versioning is enabled, then apply the Object Lock configuration.

Option A: Enable Object Lock without default retention

Objects are not locked automatically. You must apply retention manually to each object.

# Step 1: Enable versioning
aws s3api put-bucket-versioning \
  --bucket my-locked-bucket \
  --versioning-configuration Status=Enabled \
  --profile myprofile --region gva2

# Step 2: Enable Object Lock (no default retention)
aws s3api put-object-lock-configuration \
  --bucket my-locked-bucket \
  --object-lock-configuration '{"ObjectLockEnabled": "Enabled"}' \
  --profile myprofile --region gva2

Option B: Enable Object Lock with default retention

All objects uploaded after this point are automatically locked for the configured duration.

# Step 1: Enable versioning
aws s3api put-bucket-versioning \
  --bucket my-locked-bucket \
  --versioning-configuration Status=Enabled \
  --profile myprofile --region gva2

# Step 2: Enable Object Lock with default COMPLIANCE retention (7 days)
aws s3api put-object-lock-configuration \
  --bucket my-locked-bucket \
  --object-lock-configuration '{
    "ObjectLockEnabled": "Enabled",
    "Rule": {
      "DefaultRetention": {
        "Mode": "COMPLIANCE",
        "Days": 7
      }
    }
  }' \
  --profile myprofile --region gva2

Important distinction

Enabling Object Lock on a bucket does not automatically lock any objects unless you configure default retention:

Configuration New objects Existing objects
Object Lock enabled, no default retention Not locked Not locked
Object Lock enabled, with default retention Locked automatically Not locked
Manual put-object-retention Locked Locked

Without default retention, objects can be uploaded, overwritten, and deleted normally, just like in a regular versioned bucket. You must explicitly lock each object.

Retention Modes

Mode What it does Who can bypass
COMPLIANCE The version is frozen until RetainUntilDate. No one can delete it early. The retention period cannot be shortened. No one
GOVERNANCE Not supported

How to Lock a Version

Retention Period

Apply a time-based lock to a version:

aws s3api put-object-retention \
  --bucket my-locked-bucket \
  --key contract.pdf \
  --retention '{"Mode":"COMPLIANCE","RetainUntilDate":"2033-12-31T00:00:00Z"}'

This locks the current version of contract.pdf. Future uploads will create new versions without a lock unless you apply one.

Important: In COMPLIANCE mode, once set, the retention period cannot be shortened. It can only be extended.

A legal hold is independent of time and must be manually removed:

# Apply
aws s3api put-object-legal-hold \
  --bucket my-locked-bucket \
  --key contract.pdf \
  --legal-hold Status=ON

# Remove
aws s3api put-object-legal-hold \
  --bucket my-locked-bucket \
  --key contract.pdf \
  --legal-hold Status=OFF

During upload

You can lock an object at upload time:

aws s3api put-object \
  --bucket my-locked-bucket \
  --key contract.pdf \
  --body contract.pdf \
  --object-lock-mode COMPLIANCE \
  --object-lock-retain-until-date "2033-12-31T00:00:00Z"

What Is NOT Protected

1. New uploads to the same key

Uploading a file with the same key always creates a new version:

# First upload creates V1
aws s3api put-object --bucket my-locked-bucket --key contract.pdf --body contract-v1.pdf
aws s3api put-object-retention --bucket my-locked-bucket --key contract.pdf \
  --retention '{"Mode":"COMPLIANCE","RetainUntilDate":"2033-01-01T00:00:00Z"}'

# Second upload creates V2 (NOT locked)
aws s3api put-object --bucket my-locked-bucket --key contract.pdf --body contract-v2.pdf

# GET returns V2 by default
aws s3api get-object --bucket my-locked-bucket --key contract.pdf /tmp/downloaded.pdf
# Contents: contract-v2.pdf

To retrieve V1 (the locked version):

aws s3api get-object \
  --bucket my-locked-bucket \
  --key contract.pdf \
  --version-id abc123 \
  /tmp/locked-version.pdf

2. Delete markers

aws s3 rm and similar high-level commands do not fail. They create a delete marker that hides the latest version:

aws s3 rm s3://my-locked-bucket/contract.pdf
# Result: success, but it just created a delete marker.
# The locked version is still there.

The locked versions remain accessible via their VersionId:

aws s3api list-object-versions --bucket my-locked-bucket --prefix contract.pdf
# Shows: Versions[] and DeleteMarkers[]

What IS Protected

A locked version cannot be physically deleted, even with the VersionId:

aws s3api delete-object --bucket my-locked-bucket --key contract.pdf --version-id abc123
# Result: AccessDenied - forbidden by object lock

This is the real protection. The version is preserved for the retention period and can be retrieved at any time.

Check If a Version Is Locked

# Check the current (latest) version
aws s3api get-object-retention --bucket my-locked-bucket --key contract.pdf

# Check a specific version
aws s3api get-object-retention --bucket my-locked-bucket --key contract.pdf --version-id abc123

# List all versions with their lock status
aws s3api list-object-versions --bucket my-locked-bucket --prefix contract.pdf

Important: list-object-versions does NOT show lock status

list-object-versions returns the list of versions and delete markers, but does not include retention information. You must call get-object-retention for each specific VersionId to know if it is locked.

Example:

aws s3api list-object-versions --bucket my-locked-bucket

Output:

{
  "Versions": [
    {
      "Key": "dummy",
      "VersionId": "Fg71q9EEUIvMLC26tbAiDnh1DJNnjhO",
      "IsLatest": false,
      ...
    }
  ],
  "DeleteMarkers": [
    {
      "Key": "dummy",
      "VersionId": "1vNoFu32B5vKGDI1h9ox29hhqTG3.7Z",
      "IsLatest": true,
      ...
    }
  ]
}

Notice there is no lock information in this output. To check whether Fg71q9EEUIvMLC26tbAiDnh1DJNnjhO is locked:

aws s3api get-object-retention \
  --bucket my-locked-bucket \
  --key dummy \
  --version-id Fg71q9EEUIvMLC26tbAiDnh1DJNnjhO

Output:

{
  "Retention": {
    "Mode": "COMPLIANCE",
    "RetainUntilDate": "2026-07-14T20:10:00+00:00"
  }
}

Locked versions hidden behind delete markers

When you DELETE an object in a versioned bucket, S3 creates a delete marker that hides the version. The locked version still exists underneath, but it is no longer returned by default GET or ListObjectsV2.

In the example above, the latest version of dummy is a delete marker (IsLatest: true). The actual object with content is VersionId: Fg71q9EEUIvMLC26tbAiDnh1DJNnjhO, which is still locked until 2026-07-14T20:10:00+00:00.

Not all versions are locked

Because Object Lock is only a capability at the bucket level, versions may or may not have retention applied. In the same bucket:

aws s3api get-object-retention \
  --bucket my-locked-bucket \
  --key dummy1.txt \
  --version-id mHTPPAV4S248f0Yz7kB5CMLGO9hvGwN
# Returns: COMPLIANCE lock

aws s3api get-object-retention \
  --bucket my-locked-bucket \
  --key dummy1.txt \
  --version-id qnJDaRn-lOn1ZAnCHbl9m2IiQs6MgYA
# Returns error (no lock set)

Rule of thumb: if get-object-retention returns an error or empty response, that specific version is not locked.

Auditing an entire bucket

To audit all locked versions in a bucket, you must iterate over all versions:

for version in $(aws s3api list-object-versions --bucket my-locked-bucket \
  --query 'Versions[*].VersionId' --output text); do
  key=$(aws s3api list-object-versions --bucket my-locked-bucket \
    --query "Versions[?VersionId=='$version'].Key" --output text)
  echo "=== $key ($version) ==="
  aws s3api get-object-retention --bucket my-locked-bucket --key "$key" --version-id "$version" || echo "No lock"
done

Note: This is slow for buckets with many versions. There is no single API call that lists versions with their lock status.

Default Bucket Retention

You can configure a default retention so new objects are automatically locked:

aws s3api put-object-lock-configuration \
  --bucket my-locked-bucket \
  --object-lock-configuration '{
    "ObjectLockEnabled": "Enabled",
    "Rule": {
      "DefaultRetention": {
        "Mode": "COMPLIANCE",
        "Days": 365
      }
    }
  }'

Objects uploaded after this will automatically have a retention policy applied.

Limits

  • Object Lock can be enabled at bucket creation or later.
  • Once enabled, it cannot be disabled.
  • Object Lock requires versioning.
  • A locked version cannot be deleted until the retention period expires .
  • In COMPLIANCE mode, the retention period cannot be shortened.

Comparison with Legacy Storage

Feature Ceph Object Storage Legacy Swift Legacy S3-over-Swift
Object Lock Yes No No
Legal Hold Yes No No
Retention Period Yes No No

Common Use Cases

  • Financial records: Lock monthly statements so they cannot be tampered with. Complies with SEC 17a-4, FINRA 4511©.
  • Healthcare: Retain patient data for a legally required period. Complies with HIPAA.
  • Legal discovery: Preserve documents under litigation hold.
  • Audit logs: Ensure log files cannot be deleted after a breach. Complies with CFTC 1.31.
  • Commodity trading: Lock trade records for regulatory examination.