OCI Storage Buckets Should Have Retention Rules Defined
More Info:
Object Storage buckets containing critical logs or archives should have retention rules defined. Retention policies enforce Write Once Read Many (WORM) constraints, preventing object modification or deletion for regulatory compliance
Risk Level
Medium
Address
Compliance, Security
Compliance Standards
- APRA CPS 234 (Australia)
- BSI C5 (Germany)
- Brazil LGPD
- CCPA / CPRA (California)
- CIS Critical Security Controls v8
- CMMC 2.0
- CSA Cloud Controls Matrix v4
- DPDPA
- Digital Operational Resilience Act (EU)
- Essential 8
- HIPAA
- ISO/IEC 27017
- ISO/IEC 27018
- ISO/IEC 27701
- KSA PDPL
- MAS Technology Risk Management (Singapore)
- MITRE ATT&CK (Cloud)
- NIS2 Directive
- NIST SP 800-171
- NYDFS 23 NYCRR 500
- Reserve Bank of India (RBI) Master Direction – Information Technology Framework
- SOC2
- SWIFT Customer Security Controls Framework
- Sarbanes-Oxley IT General Controls
- UK NCSC Cyber Assessment Framework
Triage and Remediation
- Remediation
Remediation
Using Console
To remediate “OCI Storage Buckets Should Have Retention Rules Defined” using the OCI Console, you need to add a retention rule to each non-compliant Object Storage bucket.
Step-by-step remediation in OCI Console
-
Sign in to OCI Console
- Go to: https://cloud.oracle.com
- Log in with your tenancy and user credentials.
-
Navigate to Object Storage
- In the left-side Navigation menu, click Storage.
- Select Buckets.
-
Choose the correct compartment
- At the top of the Buckets page, open the Compartment selector.
- Select the compartment that contains the non-compliant bucket(s).
-
Open the bucket details
- From the list of buckets, click the name of the bucket that needs a retention rule.
-
Go to Retention Rules section
- In the bucket details page, scroll down to find Retention Rules.
- Click Add retention rule (or Create retention rule, wording may vary slightly by region/console version).
-
Configure the retention rule
- Name: Enter a clear, descriptive name (e.g.,
compliance-retention-365d). - Rule Type:
- Choose Time-bound (most common) or Indefinite as per your policy.
- Duration (if time-bound):
- Enter the number of days/years you must retain objects (e.g.,
365days).
- Enter the number of days/years you must retain objects (e.g.,
- Locked vs. Unlocked:
- If your compliance policy requires immutable retention, lock the rule once you’re sure (this prevents shortening or deleting it later).
- If you’re testing or unsure, leave it unlocked at first, but note that some monitoring policies may expect a locked rule.
- Name: Enter a clear, descriptive name (e.g.,
-
Create the rule
- Review the configuration.
- Click Create (or Save) to add the retention rule to the bucket.
-
Repeat for all non-compliant buckets
- Return to Buckets list.
- Repeat steps 4–7 for each bucket flagged by your OCI Security/Monitoring tool.
-
Verify remediation for monitoring
- After a short interval, re-run the Security posture / Cloud Guard / Configuration Assessment (depending on what you use).
- Confirm the finding “OCI Storage Buckets Should Have Retention Rules Defined” is cleared for the updated buckets.
If you share whether you’re using Cloud Guard, Security Zones, or a third-party monitoring tool, I can tailor the rule parameters to match that control specifically.
Using CLI
Below are the concise, CLI-focused steps to ensure OCI Object Storage buckets have retention rules defined.
0. Prerequisites
- OCI CLI installed and configured (
oci setup configdone) - Proper permissions: ability to manage Object Storage buckets/retention rules in the target compartments
1. Get your Object Storage namespace
oci os ns get
Save the value of data as NAMESPACE.
2. List buckets (optionally filter by compartment)
COMPARTMENT_OCID="<your_compartment_ocid>"
oci os bucket list \
--compartment-id "$COMPARTMENT_OCID" \
--namespace-name "$NAMESPACE" \
--all
Note bucket names needing retention rules.
3. (Optional) Check if a bucket already has a retention rule
BUCKET_NAME="<your_bucket_name>"
oci os retention-rule list \
--namespace-name "$NAMESPACE" \
--bucket-name "$BUCKET_NAME"
If output is empty → no retention rules defined.
4. Create a retention rule on a bucket
You must choose:
RETENTION_DURATION: number of days (e.g., 365)DISPLAY_NAME: a friendly name for the rule
RETENTION_DURATION=365
DISPLAY_NAME="one-year-retention"
oci os retention-rule create \
--namespace-name "$NAMESPACE" \
--bucket-name "$BUCKET_NAME" \
--display-name "$DISPLAY_NAME" \
--duration "$RETENTION_DURATION" \
--time-rule-locked null
Notes:
--durationis in days.--time-rule-locked nullmeans the rule is not yet locked; you can later set a lock time to make it immutable.
5. Verify the rule
oci os retention-rule list \
--namespace-name "$NAMESPACE" \
--bucket-name "$BUCKET_NAME"
You should see the new rule with lifecycle-state = ACTIVE.
6. (Optional) Lock the retention rule
Once locked, the rule cannot be shortened or removed, only extended.
- Find the
retention-rule-id:
oci os retention-rule list \
--namespace-name "$NAMESPACE" \
--bucket-name "$BUCKET_NAME" \
--query "data[0].id" \
--raw-output
- Set a lock time (ISO 8601). Example: lock now + 1 day:
RULE_ID="<retention_rule_ocid>"
LOCK_TIME="$(date -u -d '+1 day' +%Y-%m-%dT%H:%M:%SZ)"
oci os retention-rule update \
--namespace-name "$NAMESPACE" \
--bucket-name "$BUCKET_NAME" \
--retention-rule-id "$RULE_ID" \
--time-rule-locked "$LOCK_TIME"
7. Automate for all non-compliant buckets (script pattern)
Example bash loop for all buckets in a compartment with no retention rules:
COMPARTMENT_OCID="<your_compartment_ocid>"
RETENTION_DURATION=365
DISPLAY_NAME="default-retention"
for BUCKET_NAME in $(oci os bucket list \
--compartment-id "$COMPARTMENT_OCID" \
--namespace-name "$NAMESPACE" \
--query 'data[].name' \
--raw-output); do
RULE_COUNT=$(oci os retention-rule list \
--namespace-name "$NAMESPACE" \
--bucket-name "$BUCKET_NAME" \
--query 'length(data)' \
--raw-output)
if [ "$RULE_COUNT" -eq 0 ]; then
echo "Adding retention rule to bucket: $BUCKET_NAME"
oci os retention-rule create \
--namespace-name "$NAMESPACE" \
--bucket-name "$BUCKET_NAME" \
--display-name "$DISPLAY_NAME" \
--duration "$RETENTION_DURATION" \
--time-rule-locked null
fi
done
This remediates the misconfiguration by ensuring all targeted buckets have at least one retention rule defined using OCI CLI.
Using Python
Below are step‑by‑step instructions to:
- Detect OCI Object Storage buckets without retention rules
- Apply a default retention rule using Python (OCI SDK)
1. Prerequisites
-
Install OCI Python SDK
pip install oci -
Configure OCI CLI config file (SDK reuses it):
~/.oci/configshould have at least:[DEFAULT]user=ocid1.user.oc1..aaaa...fingerprint=...key_file=~/.oci/oci_api_key.pemtenancy=ocid1.tenancy.oc1..aaaa...region=us-ashburn-1 -
Ensure the user has permissions like:
allow group <your_group> to manage buckets in compartment <compartment_ocid>
2. Python script outline
This script will:
- List all buckets in a compartment
- Get each bucket’s current retention rules
- For buckets without retention rules, create one.
import oci
from oci.object_storage.models import (
RetentionRuleDetails,
RetentionPolicy,
CreateRetentionRuleDetails
)
# ---------------------------
# CONFIGURATION
# ---------------------------
PROFILE_NAME = "DEFAULT"
COMPARTMENT_ID = "<your_compartment_ocid>" # e.g. ocid1.compartment.oc1..aaaa...
NAMESPACE_NAME = None # If None, we’ll fetch it automatically
# Retention configuration (example: 365 days, governance mode)
RETENTION_DURATION_DAYS = 365
RETENTION_DISPLAY_NAME = "default-retention-rule"
RETENTION_POLICY_MODE = RetentionPolicy.MODE_GOVERNANCE # or MODE_COMPLIANCE
# ---------------------------
# INIT CLIENTS
# ---------------------------
config = oci.config.from_file("~/.oci/config", PROFILE_NAME)
object_storage_client = oci.object_storage.ObjectStorageClient(config)
# ---------------------------
# HELPER: GET NAMESPACE
# ---------------------------
if NAMESPACE_NAME is None:
NAMESPACE_NAME = object_storage_client.get_namespace().data
print(f"Using namespace: {NAMESPACE_NAME}")
# ---------------------------
# 1. LIST BUCKETS
# ---------------------------
list_buckets_response = object_storage_client.list_buckets(
namespace_name=NAMESPACE_NAME,
compartment_id=COMPARTMENT_ID
)
buckets = list_buckets_response.data
print(f"Found {len(buckets)} buckets in compartment.")
# ---------------------------
# 2. CHECK AND REMEDIATE RETENTION RULES
# ---------------------------
for b in buckets:
bucket_name = b.name
print(f"\nProcessing bucket: {bucket_name}")
# Get bucket details (to inspect retention rules)
get_bucket_resp = object_storage_client.get_bucket(
namespace_name=NAMESPACE_NAME,
bucket_name=bucket_name,
fields="retentionRules"
)
bucket = get_bucket_resp.data
existing_rules = bucket.retention_rules or []
if existing_rules:
print(f" - Retention rules already present ({len(existing_rules)} rule(s)); skipping.")
continue
print(" - No retention rules found. Creating default rule...")
# Build retention rule details
retention_rule_details = CreateRetentionRuleDetails(
display_name=RETENTION_DISPLAY_NAME,
duration=RetentionRuleDetails.Duration(
time_amount=RETENTION_DURATION_DAYS,
time_unit="DAYS"
),
retention_policy=RetentionPolicy(
mode=RETENTION_POLICY_MODE
)
)
# ---------------------------
# 3. CREATE RETENTION RULE
# ---------------------------
create_rule_resp = object_storage_client.create_retention_rule(
namespace_name=NAMESPACE_NAME,
bucket_name=bucket_name,
create_retention_rule_details=retention_rule_details
)
created_rule = create_rule_resp.data
print(f" - Retention rule created: OCID={created_rule.id}, duration={RETENTION_DURATION_DAYS} days, mode={RETENTION_POLICY_MODE}")
3. How to use this for “Monitoring”
To use this as monitoring plus auto-remediation:
- Wrap the script into a function.
- Trigger it periodically via:
- OCI Functions + Events or
- OCI Scheduled Jobs (e.g., a compute instance with cron) or
- Any CI/CD or external scheduler.
- Optionally:
- Log results to OCI Logging or an external system.
- Instead of auto‑creating rules, first only report buckets without rules, then add a second “remediation mode”.
Example “report‑only” mode snippet:
buckets_without_rules = []
for b in buckets:
bucket_name = b.name
get_bucket_resp = object_storage_client.get_bucket(
namespace_name=NAMESPACE_NAME,
bucket_name=bucket_name,
fields="retentionRules"
)
bucket = get_bucket_resp.data
if not (bucket.retention_rules or []):
buckets_without_rules.append(bucket_name)
print("Buckets without retention rules:")
for name in buckets_without_rules:
print(" -", name)
Use the full script for enforcement; use report‑only for pure monitoring.
Using Terraform
# Bucket that must have a retention rule
resource "oci_objectstorage_bucket" "MONITORING_BUCKET" {
compartment_id = "OCID_OF_COMPARTMENT"
name = "MONITORING_BUCKET_NAME"
namespace = "OBJECT_STORAGE_NAMESPACE"
storage_tier = "Standard"
# add any other required bucket arguments you already manage
}
# Retention rule enforcing WORM on the monitoring bucket
resource "oci_objectstorage_retention_rule" "MONITORING_RETENTION_RULE" {
namespace = oci_objectstorage_bucket.MONITORING_BUCKET.namespace
bucket = oci_objectstorage_bucket.MONITORING_BUCKET.name
display_name = "monitoring-logs-retention"
duration {
time_amount = RETENTION_DAYS # replace with an integer, e.g., 365
time_unit = "DAYS" # allowed values include "SECONDS", "DAYS", "YEARS"
}
}
Changing or deleting a retention rule may be restricted by OCI once the rule is locked; review OCI WORM constraints before applying stricter settings, as they can become effectively irreversible.
To verify, terraform plan should show creation of oci_objectstorage_retention_rule.MONITORING_RETENTION_RULE attached to the existing MONITORING_BUCKET with the desired duration.