> ## 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 container image pulls to an approved set of registries using firewall rules, admission controllers, or Azure Policy, and limit egress traffic to those registries.

### Risk Level

Medium

### Address

Security

### Compliance Standards

* CIS AKS

### Triage and Remediation

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

    <AccordionGroup>
      <Accordion title="Manual Steps" defaultOpen="true">
        1. **Inventory current image registries in use**
           * Run 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 registry hostnames (first path segment before `/`) and compile a list of all registries currently used by workloads (including system namespaces like `kube-system` and `azure-*`).

        2. **Define and document the approved registry list**
           * Using your organization’s security policy, decide which registries are approved (for example, specific Azure Container Registries and any required Microsoft/AKS system registries).
           * Document them as explicit FQDNs, e.g.:
             * `mycorpprod.azurecr.io`
             * `mycorptest.azurecr.io`
             * Required Microsoft endpoints as per AKS / egress docs.

        3. **Restrict access at the registry and network level (Azure side)**
           * For each Azure Container Registry:
             * In the Azure Portal: ACR → **Networking** → enable **Selected networks** and add only approved VNets/subnets or private endpoints as per:\
               [https://learn.microsoft.com/azure/container-registry/container-registry-firewall-access-rules](https://learn.microsoft.com/azure/container-registry/container-registry-firewall-access-rules)
             * Or via Azure CLI, run on any admin machine:
               ```bash theme={null}
               az acr update \
                 --name mycorpprod \
                 --resource-group <RG-NAME> \
                 --public-network-enabled false
               ```
           * For cluster egress control:
             * If you use a firewall/NVA/Azure Firewall: restrict outbound rules from AKS subnets to only the approved registry FQDNs/IPs according to:\
               [https://learn.microsoft.com/azure/aks/limit-egress-traffic](https://learn.microsoft.com/azure/aks/limit-egress-traffic)

        4. **Enforce registry usage with Azure Policy / admission control**
           * In Azure Portal: **Policy** → **Definitions** and locate policies such as:
             * `Kubernetes cluster containers should only use allowed images`
           * Assign to the AKS cluster’s scope and configure the list of allowed registries (FQDNs from step 2).
           * If using Gatekeeper/another admission controller (via IaC), create/update a policy that rejects images whose registry host is not in the approved list. Example (conceptual) for Gatekeeper ConstraintTemplate/Constraint; apply via your existing GitOps/IaC pipeline.

        5. **Verify enforcement and impact**
           * Attempt to deploy a pod pulling from an unapproved registry, on any machine with kubectl access:
             ```bash theme={null}
             cat <<'EOF' | kubectl apply -f -
             apiVersion: v1
             kind: Pod
             metadata:
               name: test-unapproved-registry
             spec:
               containers:
               - name: c
                 image: unapproved.example.com/namespace/image:tag
             EOF
             ```
           * Confirm that:
             * The admission policy rejects the pod (check events):
               ```bash theme={null}
               kubectl describe pod test-unapproved-registry
               ```
             * Or, if admitted, that image pull fails due to network/egress restrictions (image pull errors in events).

        6. **Re-audit running workloads and system behavior**
           * Re-run the inventory command (step 1) to confirm that all *new* pods only use approved registries.
           * Review AKS egress logs/firewall logs (Azure Firewall, NSG flow logs, etc.) to ensure no successful outbound connections from AKS subnets to non-approved registries.
      </Accordion>

      <Accordion title="Using kubectl">
        kubectl cannot be used to restrict container image pulls to approved registries because this control is enforced at the cloud/provider configuration level (Azure Container Registry firewall rules, Azure Policy, and egress controls), not via Kubernetes API objects. Apply the remediation in the cloud console or IaC as described in the Manual Steps section.
      </Accordion>

      <Accordion title="Automation">
        ```bash theme={null}
        #!/usr/bin/env bash
        # Purpose: Report container registries in use across the cluster for review
        # Requirements: kubectl configured with access to the target AKS cluster

        set -euo pipefail

        echo "==[ 1/4 ] Cluster-scoped image usage (Pods, Deployments, etc.)=="
        # List all images referenced by core workload types in all namespaces
        kubectl get pods,deployments,daemonsets,statefulsets,replicasets,cronjobs,jobs \
          -A -o jsonpath='{range ..image}{.}{"\n"}{end}' 2>/dev/null \
          | sort -u \
          | awk 'NF' \
          | tee /tmp/aks-images-all.txt

        echo
        echo "==[ 2/4 ] Unique image registries/domains in use (derived from above)=="
        # Extract registry portion (text before first /); if no /, mark as "dockerhub_implicit"
        awk '
          {
            img=$0
            split(img,parts,"/")
            if (NF==1 || img !~ /\./ && img !~ /:/) {
              # Images like "nginx:1.21" => implicit Docker Hub
              print "dockerhub_implicit"
            } else {
              print parts[1]
            }
          }' /tmp/aks-images-all.txt \
          | sort -u \
          | tee /tmp/aks-registries-all.txt

        echo
        echo "==[ 3/4 ] Report by namespace and workload=="
        # Show each pod, its namespace, workload owner (if any), and images
        kubectl get pods -A -o json \
          | jq -r '
            .items[]
            | {
                ns: .metadata.namespace,
                pod: .metadata.name,
                owner: ( .metadata.ownerReferences[0].kind + "/" + .metadata.ownerReferences[0].name ) // "POD/standalone",
                images: ([.spec.containers[]?.image] + [.spec.initContainers[]?.image]) | unique
              }
            | .ns + "\t" + .owner + "\t" + .pod + "\t" + ( .images | join(",") )
          ' \
          | column -t -s $'\t' \
          | tee /tmp/aks-image-usage-by-pod.txt

        echo
        echo "==[ 4/4 ] OPTIONAL: Compare against an approved registry list (if provided)=="
        APPROVED_FILE="./approved-registries.txt"
        if [[ -f "${APPROVED_FILE}" ]]; then
          echo "Using approved registry list from: ${APPROVED_FILE}"
          echo "Approved registries:"
          cat "${APPROVED_FILE}"
          echo

          echo "Non-approved registries in use:"
          # Show any registry not present in approved-registries.txt
          grep -Fvx -f "${APPROVED_FILE}" /tmp/aks-registries-all.txt || true
        else
          cat <<'EOF'
        No ./approved-registries.txt found.
        To enable automatic comparison, create a file named approved-registries.txt in the current directory
        with one approved registry/hostname per line, for example:

        myteam.azurecr.io
        another-approved-registry.io
        dockerhub_implicit

        Then re-run this script to see which registries are outside the approved set.
        EOF
        fi

        echo
        echo "==[ SUMMARY ]=="
        echo "All unique images:        /tmp/aks-images-all.txt"
        echo "All unique registries:    /tmp/aks-registries-all.txt"
        echo "Per-pod image usage:      /tmp/aks-image-usage-by-pod.txt"
        if [[ -f "${APPROVED_FILE}" ]]; then
          echo "Compare non-approved registries above with your policies, ACR firewall rules,"
          echo "Azure Policy / admission controller configurations, and egress controls."
        fi
        ```

        **How to run (any machine with kubectl access)**

        ```bash theme={null}
        chmod +x report-registries.sh
        ./report-registries.sh
        ```

        **Interpreting the output (what indicates a problem)**

        * `/tmp/aks-registries-all.txt` lists every registry/domain in use.
          * Any entry that is **not** on your formally approved list (for example, your ACR FQDNs) is a potential problem.
          * `dockerhub_implicit` indicates images like `nginx:latest` with no explicit registry, typically Docker Hub. Treat this as unapproved unless your policy explicitly allows it.
        * The “Non-approved registries in use:” section (when `approved-registries.txt` is present) shows registries that:
          * Must be blocked via ACR firewall rules, Azure Policy/admission controls, or
          * Must be reviewed and either added to the approved list or removed/migrated.
        * `/tmp/aks-image-usage-by-pod.txt` lets you trace unapproved registries back to the exact namespaces/workloads to drive remediation decisions.
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>
