Skip to content

06 · Object Storage Lifecycle & Security

Level 1's COS module (Module 4) covered creating buckets and putting objects in them by hand. Production buckets need more than that: rules that age out or archive old objects automatically, retention that stops even an account owner from deleting data too early, encryption keys you control instead of IBM's default, and access scoped to one bucket instead of the whole COS instance. This module covers all four.

Lifecycle rules: let objects age out on their own

A lifecycle configuration is a set of rules, evaluated daily, that transition or expire objects matching a prefix once they reach a certain age — no cron job, no script polling the bucket.

ibmcloud cos bucket-lifecycle-configuration-put \
  --bucket mastery-path-site \
  --lifecycle-configuration '{
    "Rules": [
      {
        "ID": "expire-old-logs",
        "Filter": {"Prefix": "logs/"},
        "Status": "Enabled",
        "Expiration": {"Days": 90}
      },
      {
        "ID": "archive-uploads",
        "Filter": {"Prefix": "uploads/"},
        "Status": "Enabled",
        "Transitions": [
          {"Days": 30, "StorageClass": "GLACIER"}
        ]
      }
    ]
  }'

ibmcloud cos bucket-lifecycle-configuration-get --bucket mastery-path-site

Gotcha: Transitions moves an object to a colder, cheaper storage class (mapped onto COS's Vault/Cold Vault classes) — it does not delete it, and retrieving a transitioned object later can incur a retrieval charge and a delay measured in hours, not milliseconds. Don't transition data your application still reads on a normal request path.

Retention and Object Lock: data even you can't delete early

Retention protects objects from deletion or overwrite until a minimum period has passed, independent of any IAM policy — useful for compliance data (audit logs, financial records) where "an admin account got compromised" should never be a path to destroying evidence.

# Enable Object Lock at bucket creation -- cannot be turned on afterward
ibmcloud cos bucket-create \
  --bucket mastery-path-audit-logs \
  --region us-south \
  --class standard \
  --object-lock

# Set a default retention period for every object added to the bucket
ibmcloud cos object-lock-configuration-put \
  --bucket mastery-path-audit-logs \
  --object-lock-configuration '{
    "ObjectLockEnabled": "Enabled",
    "Rule": {
      "DefaultRetention": {"Mode": "COMPLIANCE", "Days": 365}
    }
  }'

# Or set retention per object, for finer control
ibmcloud cos object-retention-put \
  --bucket mastery-path-audit-logs \
  --key 2026-08-audit.log \
  --retention '{"Mode": "COMPLIANCE", "RetainUntilDate": "2027-08-01T00:00:00Z"}'

Gotcha: --object-lock can only be set at bucket creation time — there is no bucket-update path to add it to an existing bucket. If you forget and need retention later, the fix is create a new Object-Lock-enabled bucket and copy the data across, not a flag change on the old one. COMPLIANCE mode is stricter than GOVERNANCE mode: under COMPLIANCE, nobody — not even the account owner — can shorten or remove the retention period before it expires.

A legal hold blocks deletion indefinitely, independent of any retention period, and is lifted explicitly rather than expiring:

ibmcloud cos object-legal-hold-put \
  --bucket mastery-path-audit-logs \
  --key 2026-08-audit.log \
  --legal-hold '{"Status": "ON"}'

# Lift it once the hold reason (an investigation, a litigation matter) resolves
ibmcloud cos object-legal-hold-put \
  --bucket mastery-path-audit-logs \
  --key 2026-08-audit.log \
  --legal-hold '{"Status": "OFF"}'

Retention and legal hold stack — an object can be past its retention date and still undeletable because a legal hold is still ON.

Encryption: default vs. customer-managed keys

Every COS bucket is encrypted at rest by default with IBM-managed keys — no configuration required. For data where you need to control (and be able to revoke) the encryption key yourself, bring your own via Key Protect or Hyper Protect Crypto Services:

ibmcloud resource service-instance-create mastery-keyprotect \
  kms tiered-pricing us-south \
  --resource-group-name mastery-path

ibmcloud kp key create mastery-cos-root-key \
  --instance-id <keyprotect-instance-id> \
  --standard-key

# Create a bucket that encrypts with that root key instead of IBM's default
ibmcloud cos bucket-create \
  --bucket mastery-path-secure \
  --region us-south \
  --class standard \
  --ibm-sse-kp-customer-root-key-crn crn:v1:bluemix:public:kms:us-south:a/...:key:...

Gotcha: if you ever delete the Key Protect root key backing a bucket, every object in that bucket becomes permanently unreadable — COS cannot decrypt data whose key no longer exists, and there's no recovery path short of a key backup taken beforehand. Treat root key deletion with the same care as deleting the data itself.

IAM access scoped to one bucket, not the whole instance

Level 1's IAM module scoped policies to a resource group. For COS you can go one level tighter — scope a policy to a single bucket by CRN, so a service ID that only needs to write to mastery-path-site can't touch mastery-path-audit-logs in the same instance:

ibmcloud iam service-policy-create mastery-path-app \
  --roles Writer \
  --service-name cloud-object-storage \
  --service-instance <cos-instance-id> \
  --resource-type bucket \
  --resource mastery-path-site

How It Actually Works

  • COS durability comes from erasure coding, not simple replication — an object is split into data shards plus parity shards and spread across multiple storage nodes (and, for cross-region/regional resiliency plans, multiple facilities). Reading it back reconstructs the object from any sufficient subset of those shards, which is why COS tolerates the loss of several nodes or an entire facility without losing the object and without ever storing three or more full copies the way simple mirroring would — it's the same efficiency-vs-redundancy tradeoff RAID 6 makes, just distributed across a data center-scale storage cluster instead of disks in one machine.
  • Lifecycle rules are evaluated by a background daily sweep against object metadata, not enforced at write time. Setting a 90-day expiration on logs/ doesn't touch objects already in the bucket instantly — the next daily rule evaluation compares each object's stored creation timestamp against the rule and only then marks matching, now-overdue objects for deletion. That lag (up to ~24h) is why a rule change never produces an immediate, visible cleanup.
  • Object Lock and retention are stored as immutable metadata attached to the specific object version, enforced by the storage layer itself before any IAM check runs. A delete request that would otherwise succeed under IAM is rejected by COS's own retention check first — this is the mechanism that makes COMPLIANCE mode resistant even to a fully privileged, compromised admin credential: there's no IAM policy or role that COS will honor to override an active compliance-mode lock.
  • Customer-managed encryption works by envelope encryption, not by encrypting every object directly with your Key Protect root key. COS generates a unique data-encryption key (DEK) per object, encrypts the object with it, then asks Key Protect to wrap that DEK with your root key and stores only the wrapped DEK alongside the object. Reading the object means COS asks Key Protect to unwrap the DEK (an operation Key Protect logs and can refuse) before decrypting — which is exactly why deleting the root key breaks every object's DEK unwrap in one action instead of requiring a slow re-encryption sweep.

Cheat sheet

Command Purpose
ibmcloud cos bucket-lifecycle-configuration-put --bucket <b> --lifecycle-configuration <json> Set expiration/transition rules
ibmcloud cos bucket-lifecycle-configuration-get --bucket <b> View current lifecycle rules
ibmcloud cos bucket-create --bucket <b> --object-lock Create a bucket with Object Lock enabled (creation-time only)
ibmcloud cos object-lock-configuration-put --bucket <b> --object-lock-configuration <json> Set a default retention mode/period
ibmcloud cos object-retention-put --bucket <b> --key <k> --retention <json> Set retention on one object
ibmcloud cos object-legal-hold-put --bucket <b> --key <k> --legal-hold <json> Toggle a legal hold on/off
ibmcloud cos bucket-create --bucket <b> --ibm-sse-kp-customer-root-key-crn <crn> Encrypt a bucket with your own Key Protect key
ibmcloud iam service-policy-create <id> --service-name cloud-object-storage --resource-type bucket --resource <bucket> Scope IAM access to one bucket

Exercise

Create a bucket with Object Lock enabled, set a COMPLIANCE default retention of a few minutes (for testing — real audit data would use months or years), upload an object, and confirm ibmcloud cos object-delete fails while the retention window is still open. Separately, set a lifecycle rule on mastery-path-site from Module 4 (Level 1) that expires anything under tmp/ after 1 day, and issue a service ID a policy scoped to that one bucket rather than the whole COS instance.