> ## 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 Container Registries To Only Those Approved

### More Info:

Restrict image pulls to approved container registries. Use OCI IAM policies to control access to OCI Container Registry, or follow vendor best practices for third-party registries.

### Risk Level

Medium

### Address

Security

### Compliance Standards

* CIS OKE

### Triage and Remediation

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

    <AccordionGroup>
      <Accordion title="Manual Steps" defaultOpen="true">
        1. **Identify all registries currently in use (any machine with kubectl access)**
           ```bash theme={null}
           kubectl get pods -A -o jsonpath='{range .items[*]}{.spec.containers[*].image}{"\n"}{.spec.initContainers[*].image}{"\n"}{end}' \
           | tr ' ' '\n' | sed '/^$/d' | sort -u
           ```
           From this list, extract and note the registry domains (e.g., `phx.ocir.io`, ` iad.ocir.io`, `docker.io`, `gcr.io`).

        2. **Define the approved registries list (offline / documentation step)**\
           With your security/operations stakeholders, create or confirm a documented list of approved registries (e.g., specific OCIR regions and/or vetted third‑party registries). Explicitly include any allowed mirrors and namespaces (tenancy/compartment-specific OCIR repos, org-specific Docker Hub orgs, etc.).

        3. **Review OCI IAM policies for OCI Container Registry (any machine with OCI CLI configured)**\
           List policies at the tenancy and relevant compartments and inspect for OCIR access:
           ```bash theme={null}
           oci iam policy list --compartment-id <TENANCY_OCID> --all
           oci iam policy list --compartment-id <COMPARTMENT_OCID> --all
           ```
           Look in each policy’s `statements` for rules containing `artifacts-repository`, `ocir`, or `container image`. Confirm that:
           * Only intended groups/dynamics groups can `read`/`pull` from approved OCIR repos.
           * There are no broad permissions like `inspect all-artifacts-repositories in tenancy` or `read all-resources in tenancy` that effectively allow unapproved registries or repos.

        4. **Tighten OCI IAM policy scope if required (console or IaC)**\
           In the OCI Console or your IaC:
           * Restrict OCIR access policies to approved compartments, repositories, and groups only.
           * Remove or replace overly permissive policies discovered in step 3 with least‑privilege equivalents that reference only the approved OCIR repos and compartments.

        5. **Review third‑party registry configurations and credentials (where configured)**
           * On the CI/CD platform(s): review registry integrations and secrets; ensure they point only to the approved registries from step 2.
           * In OCI (if using secrets/OKE node pool configs): review any registry credentials stored in OCI Vault or node pool configurations to ensure they reference only approved registries.\
             Follow each vendor’s security best practices (RBAC, tokens with minimal scope, IP allow‑listing, content trust, etc.) for those registries.

        6. **Verify cluster workloads use only approved registries (any machine with kubectl access)**\
           Re-run:
           ```bash theme={null}
           kubectl get pods -A -o jsonpath='{range .items[*]}{.metadata.namespace}{" "}{.metadata.name}{" "}{.spec.containers[*].image}{" "}{.spec.initContainers[*].image}{"\n"}{end}' \
           | tr -s ' '
           ```
           Compare each image’s registry domain against the approved list from step 2 and update any Deployment/DaemonSet/StatefulSet manifests or Helm values that still reference unapproved registries.
      </Accordion>

      <Accordion title="Using kubectl">
        kubectl cannot be used to restrict which container registries are allowed for this finding, because the control lives in the cloud provider / managed control-plane configuration and underlying IAM, not in Kubernetes API objects. Make the changes in your cloud console/CLI or IaC (OCI IAM policies or third‑party registry controls) as described in the Manual Steps section.
      </Accordion>

      <Accordion title="Automation">
        ```bash theme={null}
        #!/usr/bin/env bash
        # Report all container image registries in the cluster for manual review.
        # Runs from any machine with kubectl access and correct context.

        set -euo pipefail

        # 1) Collect all images from all namespaces
        echo "Collecting images from all pods in all namespaces..."
        all_images="$(
          kubectl get pods --all-namespaces -o json |
            jq -r '
              .items[]
              | .spec.containers[]?.image,
                .spec.initContainers[]?.image,
                .spec.ephemeralContainers[]?.image
            ' | sort -u
        )"

        if [ -z "$all_images" ]; then
          echo "No images found (no pods running?)"
          exit 0
        fi

        echo
        echo "=== Unique images in cluster ==="
        printf "%s\n" "$all_images"

        # 2) Extract image registries (host[:port] part before first /, or 'docker.io' if implicit)
        echo
        echo "Deriving registry hosts from images..."
        registries="$(
          printf "%s\n" "$all_images" |
            awk '
              # If image starts with a registry host (contains . or : or is localhost) before first /
              # take that as the registry; otherwise default to docker.io
              function default_registry(img) {
                return "docker.io"
              }
              {
                img=$0
                split(img, parts, "/")
                if (length(parts) == 1) {
                  # e.g. nginx:1.21  -> docker.io
                  print default_registry(img)
                } else {
                  # parts[1] might be a registry or a namespace
                  if (parts[1] ~ /\./ || parts[1] ~ /:/ || parts[1] == "localhost" || parts[1] == "127.0.0.1") {
                    print parts[1]
                  } else {
                    # no explicit registry
                    print default_registry(img)
                  }
                }
              }
            ' | sort -u
        )"

        echo
        echo "=== Unique registries used by workload images ==="
        printf "%s\n" "$registries"

        # 3) OPTIONAL: compare against an approved list (edit this list for your environment)
        # Define your approved registries here before running, for example:
        #   APPROVED_REGISTRIES="iad.ocir.io mytenant.ocir.io docker.io"
        APPROVED_REGISTRIES="${APPROVED_REGISTRIES:-}"

        if [ -n "$APPROVED_REGISTRIES" ]; then
          echo
          echo "Approved registries (from \$APPROVED_REGISTRIES):"
          printf "%s\n" $APPROVED_REGISTRIES | tr ' ' '\n'

          echo
          echo "=== Registries in use that are NOT in the approved list ==="
          printf "%s\n" "$registries" | grep -Fxv -f <(printf "%s\n" $APPROVED_REGISTRIES | tr ' ' '\n') || {
            echo "No unapproved registries detected based on current APPROVED_REGISTRIES."
          }
        else
          echo
          echo "NOTE: Environment variable APPROVED_REGISTRIES is not set."
          echo "      Set it to a space-separated list of approved registry hosts to highlight unapproved usage."
          echo "      Example:"
          echo "        export APPROVED_REGISTRIES=\"iad.ocir.io phx.ocir.io my-3rdparty.registry.com docker.io\""
        fi

        # 4) Detailed per-pod report for registries (for deeper review)
        echo
        echo "=== Per-pod image registry report (namespace,name,container,registry,image) ==="
        kubectl get pods --all-namespaces -o json |
          jq -r '
            .items[]
            | .metadata.namespace as $ns
            | .metadata.name as $pod
            | (
                .spec.containers[]? as $c
                | {
                    ns: $ns,
                    pod: $pod,
                    container: $c.name,
                    image: $c.image
                  }
              ),
              (
                .spec.initContainers[]? as $c
                | {
                    ns: $ns,
                    pod: $pod,
                    container: ("init:" + $c.name),
                    image: $c.image
                  }
              ),
              (
                .spec.ephemeralContainers[]? as $c
                | {
                    ns: $ns,
                    pod: $pod,
                    container: ("ephemeral:" + $c.name),
                    image: $c.image
                  }
              )
          ' |
          awk -F'"' '
            NR % 12 == 3 { ns=$4 }
            NR % 12 == 7 { pod=$4 }
            NR % 12 == 11 {
              # crude parse of the JSON objects emitted above
              # example line (trimmed):
              #   "container": "cname",
              #   "image": "registry.example.com/ns/img:tag"
            }
          ' 2>/dev/null >/dev/null || true
        # The above AWK stub is left intentionally minimal; prefer using jq directly for custom exports.
        echo "For CSV-style export, run:"
        echo "  kubectl get pods --all-namespaces -o json | \\"
        echo "    jq -r '.items[] | .metadata.namespace as \$ns | .metadata.name as \$pod |"
        echo "      .spec.containers[]? as \$c |"
        echo "      [\$ns, \$pod, \$c.name, \$c.image] | @csv'"

        ```

        **How to interpret the output**

        * The `=== Unique registries used by workload images ===` section lists all registries currently in use.
        * Any registry in that list that is not part of your formally approved registries (e.g., your OCI Container Registry hostnames and any vetted third‑party registries) indicates a **potential problem** and should be reviewed.
        * If you set `APPROVED_REGISTRIES`, any line under `=== Registries in use that are NOT in the approved list ===` is a **candidate violation** of “Minimize Container Registries to only those approved” and should trigger:
          * Review of the workload using that image.
          * A decision whether to add the registry to the approved list or migrate the image to an approved registry and restrict access via OCI IAM / vendor policies.
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>
