> ## 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 an approved set of container registries so that only vetted, trusted registries can supply container images.

### Risk Level

Medium

### Address

Security

### Compliance Standards

* CIS EKS

### Triage and Remediation

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

    <AccordionGroup>
      <Accordion title="Manual Steps" defaultOpen="true">
        1. **Inventory all registries in use by EKS workloads**
           * On any machine with kubectl access:
             ```bash theme={null}
             kubectl get pods -A -o jsonpath='{range .items[*]}{.metadata.namespace}{"\t"}{.metadata.name}{"\t"}{range .spec.containers[*]}{.image}{" "}{end}{"\n"}{end}' | sort -u
             ```
           * Extract the image registry domain (before the first `/`) from each image and build a unique list of registries currently used by the cluster.

        2. **Define and document your approved registry list and criteria**
           * Outside the cluster (in your security/design docs or IaC repo), write down:
             * The approval criteria (security scanning, signing, compliance, network location, etc.).
             * The explicit list of approved registries (for example: `*.dkr.ecr.<region>.amazonaws.com`, `public.ecr.aws/<your-org>`, internal mirror domains).
           * Store this in version control and treat it as policy.

        3. **Compare actual registries vs. approved list and decide disposition**
           * For each registry discovered in step 1:
             * If it is not on the approved list, decide whether to:
               * Add it to the approved list after review against the criteria, or
               * Plan to migrate images away from it and prohibit future use.
           * Record decisions per registry (approved / to-be-phased-out / banned) in your documentation.

        4. **Implement enforcement via AWS IAM and ECR configuration**
           * On any admin machine with AWS CLI configured, restrict ECR access to approved accounts/regions (example for one approved account/region; adjust ARNs/regions as per your policy):
             ```bash theme={null}
             aws ecr put-registry-policy --policy-text '{
               "Version": "2012-10-17",
               "Statement": [
                 {
                   "Sid": "AllowApprovedPull",
                   "Effect": "Allow",
                   "Principal": {"AWS": ["arn:aws:iam::<APPROVED_ACCOUNT_ID>:role/<EKS_NODE_ROLE_NAME>"]},
                   "Action": [
                     "ecr:BatchCheckLayerAvailability",
                     "ecr:GetDownloadUrlForLayer",
                     "ecr:BatchGetImage",
                     "ecr:GetAuthorizationToken"
                   ]
                 }
               ]
             }'
             ```
           * For external registries (Docker Hub, third‑party, etc.), configure AWS VPC endpoints, private connectivity, or organization policies (e.g., AWS Organizations service control policies) to only allow network egress and credentials for approved registries; remove or tighten any IAM policies that grant `ecr:*` or registry logins not aligned with your approval list.

        5. **Update cluster/IaC to reference only approved registries**
           * Search your manifests/IaC (helm charts, kustomize, Terraform, CD pipelines) locally:
             ```bash theme={null}
             grep -RIn "image:" . | grep -v "<your-approved-registry-pattern>"
             ```
           * For each non‑approved image reference, update the image to one hosted in an approved ECR registry (or other approved registry), then redeploy the workloads through your normal CI/CD process.

        6. **Verify only approved registries are currently used**
           * After changes deploy, re-run on any machine with kubectl access:
             ```bash theme={null}
             kubectl get pods -A -o jsonpath='{range .items[*]}{range .spec.containers[*]}{.image}{"\n"}{end}{end}' \
               | sed 's#/.*##' \
               | sort -u
             ```
           * Confirm that the resulting list of registries matches your approved registry list and that IAM/egress controls prevent pulling from any other registries.
      </Accordion>

      <Accordion title="Using kubectl">
        kubectl cannot be used to restrict image pulls to an approved set of ECR registries because this control is implemented at the cloud provider / managed control plane and IAM level, not via Kubernetes API objects. Make these changes in your AWS console/CLI/IaC as described in the Manual Steps section, then use kubectl only to verify workload image sources if needed.
      </Accordion>

      <Accordion title="Automation">
        ```bash theme={null}
        #!/usr/bin/env bash
        # Purpose: Report which container registries are used by workloads in the cluster
        # Scope:   Run from any machine with kubectl access and correct context set

        set -euo pipefail

        # Optional: set a regex of approved registries (edit to match your org policy)
        # Examples:
        #   APPROVED_REGEX='^(123456789012\.dkr\.ecr\.us-west-2\.amazonaws\.com|public\.ecr\.aws/my-team)/'
        #   APPROVED_REGEX='^123456789012\.dkr\.ecr\.(us-west-2|us-east-1)\.amazonaws\.com/'
        APPROVED_REGEX='^$'   # empty (matches nothing) by default so everything is "unapproved" for review

        echo "Collecting images from all namespaces..."
        echo

        # Get all pods and their container images, including initContainers, de-duplicated
        kubectl get pods --all-namespaces -o json \
          | jq -r '
              .items[]
              | .metadata.namespace as $ns
              | .metadata.name as $pod
              | [
                  (.spec.containers[]? | {type:"container", name:.name, image:.image}),
                  (.spec.initContainers[]? | {type:"initContainer", name:.name, image:.image})
                ][]
              | [$ns, $pod, .type, .name, .image]
              | @tsv
            ' | sort -u > /tmp/k8s-images.tsv

        if [ ! -s /tmp/k8s-images.tsv ]; then
          echo "No pods found."
          exit 0
        fi

        echo "Per-pod image usage:"
        echo -e "NAMESPACE\tPOD\tKIND\tCONTAINER\tIMAGE"
        cat /tmp/k8s-images.tsv
        echo

        # Extract just the image field
        cut -f5 /tmp/k8s-images.tsv | sort -u > /tmp/k8s-images-unique.txt

        echo "Unique images in cluster:"
        cat /tmp/k8s-images-unique.txt
        echo

        # Derive the registry domain (or 'docker.io' for images with no explicit registry)
        awk '
        function get_registry(img) {
          split(img, parts, "/")
          if (split(parts[1], hostparts, "\\.") >= 2 || index(parts[1], ":") || parts[1] ~ /localhost/) {
            return parts[1]
          }
          # no explicit registry, default docker.io
          return "docker.io"
        }
        {
          img=$0
          reg=get_registry(img)
          print reg "\t" img
        }' /tmp/k8s-images-unique.txt | sort -u > /tmp/k8s-images-by-registry.tsv

        echo "Registries in use and associated images:"
        echo -e "REGISTRY\tIMAGE"
        cat /tmp/k8s-images-by-registry.tsv
        echo

        echo "Summary: registries in use (count of images per registry):"
        cut -f1 /tmp/k8s-images-by-registry.tsv | sort | uniq -c | sort -nr
        echo

        if [ -n "${APPROVED_REGEX}" ]; then
          echo "Detecting images from registries NOT matching approved regex: ${APPROVED_REGEX}"
          echo -e "REGISTRY\tIMAGE"
          awk -v re="${APPROVED_REGEX}" '
            {
              reg=$1
              img=$2
              # rebuild full image (in case of spaces, though unlikely)
              for (i=3; i<=NF; i++) img=img FS $i
              if (img !~ re) {
                print reg "\t" img
              }
          }' /tmp/k8s-images-by-registry.tsv | sort -u > /tmp/k8s-unapproved.tsv || true

          if [ -s /tmp/k8s-unapproved.tsv ]; then
            cat /tmp/k8s-unapproved.tsv
            echo
            echo "Found images that do NOT match the approved registry pattern."
            echo "Each listed IMAGE should be reviewed against your approval criteria."
          else
            echo "No images found outside the approved registry pattern."
          fi
        else
          echo "APPROVED_REGEX is empty; skipping automatic approved/unapproved classification."
        fi
        ```

        Explanation of what indicates a problem:

        * Any registry in the “Summary: registries in use” section that is not part of your approved ECR list (e.g., `docker.io`, `gcr.io`, other AWS accounts’ ECRs) is a candidate issue.
        * If you set `APPROVED_REGEX` to your allowed ECR registries, any entries printed under “Found images that do NOT match the approved registry pattern” are using unapproved registries and must be reviewed and either:
          * Migrated to an approved ECR registry, or
          * Explicitly granted an exception as part of your policies and procedures.
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>
