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

# Minimize User Access To Gcr

### More Info:

Scan images being deployed to Amazon EKS for vulnerabilities.

### Risk Level

High

### Address

Security

### Compliance Standards

* APRA CPS 234 (Australia)
* BSI C5 (Germany)
* Brazil LGPD
* CCPA / CPRA (California)
* CIS Critical Security Controls v8
* CIS GKE
* CMMC 2.0
* CSA Cloud Controls Matrix v4
* DPDPA
* Digital Operational Resilience Act (EU)
* Essential 8
* 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
* 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="Manual Steps" defaultOpen="true">
        1. **List who can access Container/Artifact Registry at the project level**
           * Run on any machine with `gcloud` and `gsutil` configured:
             ```bash theme={null}
             PROJECT_ID="your-project-id"

             # View project-level IAM
             gcloud projects get-iam-policy "$PROJECT_ID" \
               --format="table(bindings.role, bindings.members)"
             ```
           * Review members with broad roles that can affect images, such as:
             * `roles/storage.admin`, `roles/storage.objectAdmin`, `roles/storage.objectCreator`
             * `roles/artifactregistry.admin`, `roles/artifactregistry.repoAdmin`, `roles/artifactregistry.writer`
             * `roles/owner`, `roles/editor`
           * Decide which identities truly need publish (write) or pull (read) access for container images.

        2. **Inspect IAM on GCR storage bucket(s)**
           * For legacy GCR, list buckets and view IAM:
             ```bash theme={null}
             # List buckets; identify artifacts.<PROJECT_ID>.appspot.com
             gsutil ls

             BUCKET="gs://artifacts.your-project-id.appspot.com"

             # Show IAM policy for the GCR bucket
             gsutil iam get "$BUCKET"
             ```
           * Look for members with:
             * `roles/storage.admin`, `roles/storage.objectAdmin`, `roles/storage.objectCreator`
           * Determine which should be reduced to read-only (`objectViewer`) or removed entirely.

        3. **Inspect IAM on Artifact Registry repositories**
           * List repositories and their IAM:
             ```bash theme={null}
             gcloud artifacts repositories list \
               --project="$PROJECT_ID" \
               --format="table(name,format,location)"

             REPO="projects/your-project-id/locations/your-location/repositories/your-repo"

             gcloud artifacts repositories get-iam-policy "$REPO" \
               --project="$PROJECT_ID"
             ```
           * Identify users/groups/service accounts with admin or write roles that do not strictly need them.

        4. **Right-size access on the GCR bucket (if used)**
           * For each identity that only needs to pull images from GCR, grant read and remove excessive roles:
             ```bash theme={null}
             BUCKET="gs://artifacts.your-project-id.appspot.com"

             # Example: grant read-only (objectViewer)
             gsutil iam ch serviceAccount:sa-name@your-project-id.iam.gserviceaccount.com:objectViewer "$BUCKET"

             # Example: remove overly broad role (e.g., objectAdmin, storage.admin, objectCreator)
             gsutil iam ch -d serviceAccount:sa-name@your-project-id.iam.gserviceaccount.com:roles/storage.objectAdmin "$BUCKET"
             ```
           * For project-level roles that grant excessive storage or registry permissions, edit a policy file:
             ```bash theme={null}
             gcloud projects get-iam-policy "$PROJECT_ID" > /tmp/policy.yaml
             # Edit /tmp/policy.yaml to remove or downgrade roles for identities that do not need them
             gcloud projects set-iam-policy "$PROJECT_ID" /tmp/policy.yaml
             ```

        5. **Right-size access on Artifact Registry repositories**
           * For each principal that only needs to pull images:
             * Prefer `roles/artifactregistry.reader` on the specific repository.
           * For each that needs to push images but not administer IAM:
             * Prefer `roles/artifactregistry.writer` on the specific repository.
           * Example to set a minimal policy for one repository (edit as needed):
             ```bash theme={null}
             REPO="projects/your-project-id/locations/your-location/repositories/your-repo"

             cat > /tmp/repo-policy.yaml << 'EOF'
             bindings:
             - role: roles/artifactregistry.reader
               members:
               - serviceAccount:sa-pull@your-project-id.iam.gserviceaccount.com
             - role: roles/artifactregistry.writer
               members:
               - serviceAccount:sa-push@your-project-id.iam.gserviceaccount.com
             EOF

             gcloud artifacts repositories set-iam-policy "$REPO" /tmp/repo-policy.yaml \
               --project="$PROJECT_ID"
             ```

        6. **Verify that only least-privilege access remains**
           * Re-check project and resource-level IAM to ensure no unnecessary broad roles remain:
             ```bash theme={null}
             gcloud projects get-iam-policy "$PROJECT_ID" \
               --format="table(bindings.role, bindings.members)"

             gsutil iam get "gs://artifacts.your-project-id.appspot.com"

             gcloud artifacts repositories get-iam-policy "$REPO" \
               --project="$PROJECT_ID"
             ```
           * Confirm that:
             * Only identities that must publish images have writer roles on specific repos/buckets.
             * Identities that only pull images have read-only roles.
             * Broad roles (e.g., `owner`, `editor`, `storage.admin`, `artifactregistry.admin`) are not granted where unnecessary for registry use.
      </Accordion>

      <Accordion title="Using kubectl">
        kubectl cannot be used to change Container Registry or Artifact Registry IAM permissions; those are managed at the GCP project, registry, or underlying storage bucket level via gcloud/gsutil, the GCP console, or IaC. To address this finding, make the changes described in the Manual Steps section using those cloud‑provider tools.
      </Accordion>

      <Accordion title="Automation">
        ```bash theme={null}
        #!/usr/bin/env bash
        #
        # Audit GCR/Artifact Registry access relevant to this GKE cluster.
        # Runs with: any machine that has:
        #   - kubectl access to the cluster
        #   - gcloud, gsutil, and jq installed
        #
        # REQUIRED INPUTS (set these explicitly before running)
        PROJECT_ID="my-gcp-project-id"
        CLUSTER_LOCATION="us-central1"   # zone or region where the cluster runs
        CLUSTER_NAME="my-gke-cluster"

        set -euo pipefail

        if ! command -v kubectl >/dev/null 2>&1 \
          || ! command -v gcloud >/dev/null 2>&1 \
          || ! command -v gsutil >/dev/null 2>&1 \
          || ! command -v jq >/dev/null 2>&1; then
          echo "ERROR: kubectl, gcloud, gsutil, and jq are required on this machine." >&2
          exit 1
        fi

        echo "=== 1. Discover identities used to pull images in this cluster ==="

        # 1a. Get all service account emails used by Kubernetes service accounts backing GKE workloads
        echo
        echo "--- Kubernetes service accounts and their GCP service accounts (GKE Workload Identity) ---"
        kubectl get sa --all-namespaces -o json \
          | jq -r '
            .items[]
            | {
                ns: .metadata.namespace,
                sa: .metadata.name,
                gsa: (
                  .metadata.annotations["iam.gke.io/gcp-service-account"]
                  // .metadata.annotations["iam.gke.io/gcp-serviceaccount"]
                  // ""
                )
              }
            | select(.gsa != "")
            | "\(.ns)/\(.sa) -> \(.gsa)"' \
          | sort || echo "No Kubernetes service accounts with Workload Identity annotation found."

        # 1b. Get node service accounts (for node image pulls when using node SA)
        echo
        echo "--- Node pool service accounts (used by kubelet / image pulls) ---"
        gcloud container clusters describe "$CLUSTER_NAME" \
          --location "$CLUSTER_LOCATION" \
          --project "$PROJECT_ID" \
          --format='table(nodePools.name, nodeConfig.serviceAccount)'

        echo
        echo "=== 2. List all IAM members with roles that can write to GCR / Artifact Registry at PROJECT level ==="
        # Roles to inspect (expand as needed)
        WRITE_ROLES=(
          "roles/storage.admin"
          "roles/storage.objectAdmin"
          "roles/storage.objectCreator"
          "roles/artifactregistry.admin"
          "roles/artifactregistry.repoAdmin"
          "roles/artifactregistry.writer"
        )

        gcloud projects get-iam-policy "$PROJECT_ID" \
          --format=json > /tmp/"$PROJECT_ID"-iam.json

        for ROLE in "${WRITE_ROLES[@]}"; do
          echo
          echo "--- Members with $ROLE on project $PROJECT_ID ---"
          jq -r --arg ROLE "$ROLE" '
            .bindings[]
            | select(.role == $ROLE)
            | .members[]
          ' /tmp/"$PROJECT_ID"-iam.json || true
        done

        echo
        echo "=== 3. Inspect IAM on the GCR/Artifact Registry bucket ==="
        BUCKET="gs://artifacts.${PROJECT_ID}.appspot.com"

        echo
        echo "--- IAM policy for bucket: $BUCKET ---"
        gsutil iam get "$BUCKET" | jq '.' || {
          echo "WARNING: Could not fetch IAM for $BUCKET (bucket may not exist or account lacks permission)." >&2
        }

        echo
        echo "--- Members with broad Storage roles on the bucket (possible risk) ---"
        gsutil iam get "$BUCKET" 2>/dev/null \
          | jq -r '
              .bindings[]
              | select(.role
                  | IN(
                    "roles/storage.admin",
                    "roles/storage.objectAdmin",
                    "roles/storage.objectCreator"
                  ))
              | "ROLE: \(.role)\nMEMBERS:\n  - " + (.members | join("\n  - ")) + "\n"
            ' || echo "No broad Storage roles detected on bucket or unable to read bucket IAM."

        echo
        echo "=== 4. Correlate pulling identities with high-privilege roles ==="

        echo
        echo "--- High-privilege members that are also used by this cluster (Workload Identity or nodes) ---"

        # Collect cluster-related identities (Workload Identity GSAs + node SAs)
        CLUSTER_IDENTITIES_FILE=/tmp/"$PROJECT_ID"-cluster-identities.txt
        : > "$CLUSTER_IDENTITIES_FILE"

        kubectl get sa --all-namespaces -o json \
          | jq -r '
              .items[]
              | .metadata.annotations["iam.gke.io/gcp-service-account"]
              // .metadata.annotations["iam.gke.io/gcp-serviceaccount"]
              // empty
            ' | sort -u >> "$CLUSTER_IDENTITIES_FILE" || true

        gcloud container clusters describe "$CLUSTER_NAME" \
          --location "$CLUSTER_LOCATION" \
          --project "$PROJECT_ID" \
          --format='value(nodePools[].nodeConfig.serviceAccount)' \
          | tr ';' '\n' | sort -u >> "$CLUSTER_IDENTITIES_FILE" || true

        sort -u -o "$CLUSTER_IDENTITIES_FILE" "$CLUSTER_IDENTITIES_FILE"

        # Now intersect with high-privilege members from project and bucket IAM
        HIGH_PRIV_FILE=/tmp/"$PROJECT_ID"-high-priv-members.txt
        : > "$HIGH_PRIV_FILE"

        jq -r '
          .bindings[]
          | select(.role
              | IN(
                "roles/storage.admin",
                "roles/storage.objectAdmin",
                "roles/storage.objectCreator",
                "roles/artifactregistry.admin",
                "roles/artifactregistry.repoAdmin",
                "roles/artifactregistry.writer"
              ))
          | .members[]
        ' /tmp/"$PROJECT_ID"-iam.json >> "$HIGH_PRIV_FILE" || true

        gsutil iam get "$BUCKET" 2>/dev/null \
          | jq -r '
              .bindings[]
              | select(.role
                  | IN(
                    "roles/storage.admin",
                    "roles/storage.objectAdmin",
                    "roles/storage.objectCreator"
                  ))
              | .members[]
            ' >> "$HIGH_PRIV_FILE" || true

        sort -u -o "$HIGH_PRIV_FILE" "$HIGH_PRIV_FILE"

        echo "Cluster identities with high-privilege GCR/Artifact Registry roles:"
        grep -Ff "$CLUSTER_IDENTITIES_FILE" "$HIGH_PRIV_FILE" || echo "None found."

        echo
        echo "=== 5. Interpretation guidance ==="
        cat <<'EOF'
        Potential PROBLEMS indicated by the output above:

        1) Any of the following in the bucket IAM (gsutil iam get):
           - role: roles/storage.admin
           - role: roles/storage.objectAdmin
           - role: roles/storage.objectCreator
           especially when the members are:
           - allUsers or allAuthenticatedUsers (anonymous/broad access)
           - user:* emails that do not need to push images
           - serviceAccount:* that are not CI/CD or dedicated image-publisher accounts

        2) At the project level (gcloud projects get-iam-policy):
           - Bindings for Storage or Artifact Registry write/admin roles granted to:
             - broad groups (e.g. group:devs@example.com) that don't all need image push rights
             - generic service accounts shared by many workloads
             - individual users instead of central CI/CD identities

        3) In the correlation section:
           - Any service account that your cluster uses (Workload Identity GSA or node SA)
             also appearing as a member with:
               - roles/storage.admin
               - roles/storage.objectAdmin
               - roles/storage.objectCreator
               - roles/artifactregistry.admin
               - roles/artifactregistry.repoAdmin
               - roles/artifactregistry.writer
             should be reviewed. Many workloads only need read (objectViewer / artifactregistry.reader).

        This script does NOT automatically fix anything.
        Use the benchmark remediation to:
          - Replace broad write/admin roles with least-privilege roles (e.g. objectViewer/reader),
          - Then gsutil iam ch -d ... or update project IAM to remove excess roles.
        EOF
        ```
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>

### Additional Reading:

* [https://docs.aws.amazon.com/AmazonECR/latest/userguide/image-scanning.html](https://docs.aws.amazon.com/AmazonECR/latest/userguide/image-scanning.html)
