> ## 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.

# Storage permissions logging remediation

### Triage and Remediation

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

    <AccordionGroup>
      <Accordion title="Using Console" defaultOpen="true">
        To fix “Storage Permissions Logging” for Google Cloud Storage using the GCP Console, you essentially need to ensure that Cloud Audit Logs (especially **Data Access** logs) are enabled for Google Cloud Storage and that they are being routed to a log destination you retain.

        Below are the step‑by‑step instructions in the Console.

        ***

        ### 1. Enable Audit Logs for Google Cloud Storage

        1. Sign in to the **Google Cloud Console**.
        2. Make sure you have selected the **correct project** (top-left project selector).
        3. In the left navigation menu, go to:\
           **IAM & Admin → Audit Logs**.
        4. In the “Audit Logs” page:
           * In the **Service** list, locate and select:\
             **“Cloud Storage”** (sometimes listed as **“Storage”** or **“storage.googleapis.com”**).
        5. You will see log types for this service:
           * **Admin Read**
           * **Admin Write**
           * **Data Read**
           * **Data Write**
        6. For comprehensive permissions logging:
           * Check **Admin Read** and **Admin Write** (if not already enabled).
           * Check **Data Read** and **Data Write** (these are typically off by default and are crucial for object/permission access logging).
        7. Click **Save** at the bottom of the page.

        > This ensures that actions on buckets/objects and permission changes are written to Cloud Audit Logs.

        ***

        ### 2. Verify Logs Are Being Stored (Log Router / Sinks)

        Audit logs automatically go to **Cloud Logging**, but compliance often requires storing them longer (e.g., in a bucket, BigQuery, or Pub/Sub). To route them properly:

        1. In the left navigation menu, go to:\
           **Logging → Logs Router**.
        2. Look for an existing **sink** that captures audit logs (especially from `cloudaudit.googleapis.com`).
           * If one exists and routes to a storage bucket/BigQuery with sufficient retention for your requirements, you may not need to change anything.
        3. To create a dedicated sink (if needed):
           * Click **Create sink**.
           * **Sink name**: e.g., `gcs-audit-logs-sink`.
           * **Sink destination**: choose one, commonly:
             * **Cloud Storage bucket** (recommended for archive),
             * or **BigQuery** (for querying),
             * or **Pub/Sub** (for streaming/forwarding).
           * Click **Next**.
        4. **Choose logs to include**:
           * Under “Choose logs to include in the sink”, set a filter such as:
             ```text theme={null}
             logName:"cloudaudit.googleapis.com" 
             protoPayload.serviceName="storage.googleapis.com"
             ```
           * This captures Storage audit logs (including permission changes and access).
        5. Click **Create sink**.

        ***

        ### 3. Confirm Logs for Storage Permissions Are Appearing

        1. Go to **Logging → Logs Explorer**.
        2. In the query box, use a filter like:
           ```text theme={null}
           resource.type="gcs_bucket"
           logName:"cloudaudit.googleapis.com"
           ```
        3. Click **Run query**.
        4. Inspect entries:
           * Look for `protoPayload.methodName` values related to IAM or ACL changes (e.g., `storage.setIamPermissions`, `storage.objects.get`, `storage.buckets.update`, etc.).
           * Confirm that these actions on your buckets are being logged.

        ***

        ### 4. (Optional) Narrow to a Specific Bucket / Project

        If the misconfiguration is flagged for a specific bucket:

        1. In the **Logs Explorer** query, further filter:
           ```text theme={null}
           resource.type="gcs_bucket"
           resource.labels.bucket_name="YOUR_BUCKET_NAME"
           logName:"cloudaudit.googleapis.com"
           ```
        2. Confirm that both:
           * Permission changes (`setIamPolicy`, `update`), and
           * Access operations (`get`, `list`, `insert`, etc.)\
             are present.

        ***

        Once you have:

        * Enabled **Admin** and **Data Access** audit logs for **Cloud Storage** in IAM & Admin → Audit Logs, and
        * Ensured they are routed and stored via a **Logs Router sink**,

        the “Storage Permissions Logging” finding for GCP Storage should be remediated.
      </Accordion>

      <Accordion title="Using CLI">
        Below are concise, CLI‑only steps to enable Storage permissions logging (audit logging for Cloud Storage IAM & access) in GCP.

        ### 1. Set project ID

        ```bash theme={null}
        PROJECT_ID="your-project-id"
        gcloud config set project "$PROJECT_ID"
        ```

        ### 2. Export current IAM policy

        ```bash theme={null}
        gcloud projects get-iam-policy "$PROJECT_ID" \
          --format=json > iam-policy.json
        ```

        ### 3. Edit IAM policy to add audit logging for Cloud Storage

        Open `iam-policy.json` in an editor and add / merge this `auditConfigs` block at the top level (alongside `bindings`):

        ```json theme={null}
        "auditConfigs": [
          {
            "service": "storage.googleapis.com",
            "auditLogConfigs": [
              {
                "logType": "ADMIN_READ"
              },
              {
                "logType": "DATA_READ"
              },
              {
                "logType": "DATA_WRITE"
              }
            ]
          }
        ]
        ```

        Notes:

        * If `auditConfigs` already exists, just append or merge the `storage.googleapis.com` entry into the array.
        * Keep the rest of the file unchanged.

        ### 4. Apply the updated IAM policy

        ```bash theme={null}
        gcloud projects set-iam-policy "$PROJECT_ID" iam-policy.json
        ```

        This enables:

        * ADMIN\_READ logs: IAM / permission changes on Cloud Storage.
        * DATA\_READ logs: reads of bucket/objects.
        * DATA\_WRITE logs: writes/deletes of bucket/objects.

        ### 5. (Optional) Verify audit logs

        Use Cloud Logging to confirm logs are being generated:

        ```bash theme={null}
        gcloud logging read \
          'logName:"cloudaudit.googleapis.com" AND resource.type="gcs_bucket"' \
          --limit=10 --format="table(timestamp, protoPayload.methodName, resource.labels.bucket_name)"
        ```

        This remediates the “Storage Permissions Logging” gap by ensuring Cloud Storage access and permission changes are captured via Cloud Audit Logs.
      </Accordion>

      <Accordion title="Using Python">
        Below is how to remediate “Storage Permissions Logging” for a Google Cloud Storage bucket using Python, assuming the finding means “bucket access logging is not enabled”.

        ### 1. Prerequisites

        1. Install the client library:
           ```bash theme={null}
           pip install google-cloud-storage
           ```
        2. Authenticate:
           ```bash theme={null}
           gcloud auth application-default login
           ```
        3. Ensure your service account / ADC has `storage.buckets.update` on the target bucket and `storage.buckets.get` on the log bucket.

        ***

        ### 2. Create (or choose) a logging bucket

        You need a separate bucket to receive access logs.

        ```python theme={null}
        from google.cloud import storage

        def create_bucket_if_not_exists(project_id: str, bucket_name: str, location: str = "US"):
            storage_client = storage.Client(project=project_id)
            bucket = storage_client.bucket(bucket_name)
            if not bucket.exists():
                bucket.storage_class = "STANDARD"
                bucket.location = location
                bucket = storage_client.create_bucket(bucket)
                print(f"Created log bucket {bucket.name}")
            else:
                print(f"Log bucket {bucket.name} already exists")
            return bucket

        project_id = "YOUR_PROJECT_ID"
        log_bucket_name = "my-project-storage-logs"

        create_bucket_if_not_exists(project_id, log_bucket_name)
        ```

        ***

        ### 3. Grant write permission for logging

        GCS uses a special writer identity to store logs: `cloud-storage-analytics@google.com`\
        Grant it `roles/storage.objectCreator` on the log bucket.

        ```python theme={null}
        from google.cloud import storage

        def allow_logging_writer_on_log_bucket(log_bucket_name: str):
            storage_client = storage.Client()
            bucket = storage_client.bucket(log_bucket_name)
            bucket.iam_configuration.uniform_bucket_level_access_enabled = True
            bucket.patch()

            policy = bucket.get_iam_policy(requested_policy_version=3)
            role = "roles/storage.objectCreator"
            member = "group:cloud-storage-analytics@google.com"
            if member not in policy.get(role, []):
                policy[role].add(member)
                bucket.set_iam_policy(policy)
                print(f"Granted {role} to {member} on {log_bucket_name}")
            else:
                print(f"{member} already has {role} on {log_bucket_name}")

        log_bucket_name = "my-project-storage-logs"
        allow_logging_writer_on_log_bucket(log_bucket_name)
        ```

        ***

        ### 4. Enable logging on the source bucket

        This sets the log destination bucket and an optional log object prefix.

        ```python theme={null}
        from google.cloud import storage

        def enable_bucket_access_logging(
            source_bucket_name: str,
            log_bucket_name: str,
            log_object_prefix: str = "access_logs/"
        ):
            storage_client = storage.Client()
            bucket = storage_client.bucket(source_bucket_name)

            bucket.logging = {
                "logBucket": log_bucket_name,
                "logObjectPrefix": log_object_prefix,
            }
            bucket.patch()
            print(
                f"Enabled access logging for {source_bucket_name} "
                f"to {log_bucket_name} with prefix '{log_object_prefix}'"
            )

        source_bucket_name = "my-app-data-bucket"
        log_bucket_name = "my-project-storage-logs"

        enable_bucket_access_logging(source_bucket_name, log_bucket_name)
        ```

        ***

        ### 5. Verify configuration

        ```python theme={null}
        from google.cloud import storage

        def show_logging_config(bucket_name: str):
            storage_client = storage.Client()
            bucket = storage_client.bucket(bucket_name)
            bucket.reload()
            print("Logging configuration:", bucket.logging)

        show_logging_config("my-app-data-bucket")
        ```

        You should see something like:

        ```python theme={null}
        {'logBucket': 'my-project-storage-logs', 'logObjectPrefix': 'access_logs/'}
        ```

        If your tool checks multiple buckets, loop over all non-logging buckets and call `enable_bucket_access_logging` for each.
      </Accordion>

      <Accordion title="Using Terraform">
        ```hcl theme={null}
        resource "google_storage_bucket" "app_data" {
          name          = "APP_DATA_BUCKET_NAME"          # replace with your data bucket name
          location      = "BUCKET_LOCATION"               # e.g. "US"
          storage_class = "STANDARD"

          # ...other settings...

          # Enable access logging for this bucket
          logging {
            log_bucket        = google_storage_bucket.app_data_logs.name
            log_object_prefix = "ACCESS_LOG_PREFIX"       # e.g. "gcs-access/"
          }
        }

        # Dedicated bucket to receive access logs
        resource "google_storage_bucket" "app_data_logs" {
          name          = "APP_DATA_LOG_BUCKET_NAME"      # replace with your log bucket name
          location      = "BUCKET_LOCATION"               # usually same region
          storage_class = "STANDARD"

          uniform_bucket_level_access = true

          # Optionally restrict public access, add lifecycle rules, etc.
        }
        ```

        Enabling the `logging` block does not force replacement of the existing bucket; Terraform will show an in-place update on `google_storage_bucket.app_data` adding `logging.log_bucket` and `logging.log_object_prefix`, and creation of `google_storage_bucket.app_data_logs` if it does not yet exist.
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>
