> ## Documentation Index
> Fetch the complete documentation index at: https://cloudanix.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# 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

<Tabs>
  <Tab title="Remediation">
    ### Remediation

    <AccordionGroup>
      <Accordion title="Using Console" defaultOpen="true">
        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

        1. **Sign in to OCI Console**
           * Go to: [https://cloud.oracle.com](https://cloud.oracle.com)
           * Log in with your tenancy and user credentials.

        2. **Navigate to Object Storage**
           * In the left-side **Navigation menu**, click **Storage**.
           * Select **Buckets**.

        3. **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).

        4. **Open the bucket details**
           * From the list of buckets, click the name of the bucket that needs a retention rule.

        5. **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).

        6. **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., `365` days).
           * **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.

        7. **Create the rule**
           * Review the configuration.
           * Click **Create** (or **Save**) to add the retention rule to the bucket.

        8. **Repeat for all non-compliant buckets**
           * Return to **Buckets** list.
           * Repeat steps 4–7 for each bucket flagged by your OCI Security/Monitoring tool.

        9. **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.
      </Accordion>

      <Accordion title="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 config` done)
        * Proper permissions: ability to manage Object Storage buckets/retention rules in the target compartments

        ***

        ### 1. Get your Object Storage namespace

        ```bash theme={null}
        oci os ns get
        ```

        Save the value of `data` as `NAMESPACE`.

        ***

        ### 2. List buckets (optionally filter by compartment)

        ```bash theme={null}
        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

        ```bash theme={null}
        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

        ```bash theme={null}
        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:

        * `--duration` is in days.
        * `--time-rule-locked null` means the rule is not yet locked; you can later set a lock time to make it immutable.

        ***

        ### 5. Verify the rule

        ```bash theme={null}
        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.

        1. Find the `retention-rule-id`:

        ```bash theme={null}
        oci os retention-rule list \
          --namespace-name "$NAMESPACE" \
          --bucket-name "$BUCKET_NAME" \
          --query "data[0].id" \
          --raw-output
        ```

        2. Set a lock time (ISO 8601). Example: lock now + 1 day:

        ```bash theme={null}
        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:

        ```bash theme={null}
        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.
      </Accordion>

      <Accordion title="Using Python">
        Below are step‑by‑step instructions to:

        1. Detect OCI Object Storage buckets without retention rules
        2. Apply a default retention rule using Python (OCI SDK)

        ***

        ## 1. Prerequisites

        1. **Install OCI Python SDK**
           ```bash theme={null}
           pip install oci
           ```

        2. **Configure OCI CLI config file** (SDK reuses it):\
           `~/.oci/config` should have at least:
           ```ini theme={null}
           [DEFAULT]
           user=ocid1.user.oc1..aaaa...
           fingerprint=...
           key_file=~/.oci/oci_api_key.pem
           tenancy=ocid1.tenancy.oc1..aaaa...
           region=us-ashburn-1
           ```

        3. Ensure the user has permissions like:
           ```text theme={null}
           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.

        ```python theme={null}
        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*:

        1. Wrap the script into a function.
        2. 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.
        3. 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:

        ```python theme={null}
        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.
      </Accordion>

      <Accordion title="Using Terraform">
        ```hcl theme={null}
        # 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`.
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>
