Minimize Container Registries Only Those Approved
More Info:
Scan images being deployed to Amazon EKS for vulnerabilities.
Risk Level
Low
Address
Security
Compliance Standards
- APRA CPS 234 (Australia)
- BSI C5 (Germany)
- Brazil LGPD
- CCPA / CPRA (California)
- CIS AKS
- CIS Critical Security Controls v8
- 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
- Remediation
Remediation
Manual Steps
-
Inventory current image sources (any machine with kubectl access)
kubectl get pods -A -o jsonpath='{range .items[*]}{.metadata.namespace}{"\t"}{.metadata.name}{"\t"}{range .spec.containers[*]}{.image}{" "}{end}{"\n"}{end}' \| sort -u- Export a clean list of unique registries in use:
kubectl get pods -A -o jsonpath='{range .items[*]}{range .spec.containers[*]}{.image}{"\n"}{end}{end}' \| sed 's#^\([^/]\+\)/.*#\1#' | sort -u > /tmp/current-registries.txt
- Export a clean list of unique registries in use:
-
Define and document the approved registries set (offline / console)
- From security / platform standards, produce a list like:
myorg.azurecr.io(ACR)mcr.microsoft.com(base images)registry.k8s.io(Kubernetes system images, if needed)
- Save as
/tmp/approved-registries.txtfor comparison.
- From security / platform standards, produce a list like:
-
Compare actual vs approved registries (any machine with kubectl access)
echo "=== Unapproved registries in use ==="comm -23 /tmp/current-registries.txt /tmp/approved-registries.txt || true- For each unapproved registry, identify dependent workloads:
UNAPPROVED="<registry-hostname>"kubectl get pods -A -o wide \| awk -v r="$UNAPPROVED" 'NR==1 || $0 ~ r'
- Decide per workload: migrate image to an approved registry or obtain formal exception.
- For each unapproved registry, identify dependent workloads:
-
Lock down Azure Container Registry to AKS (Azure CLI / Portal)
- For each approved ACR, restrict access (run from admin machine with Azure CLI):
ACR_NAME="myregistry" # ACR name, not FQDNAKS_RG="my-aks-rg"AKS_NAME="my-aks-cluster"# Attach ACR to AKS (ensures identity permissions)az aks update -g "$AKS_RG" -n "$AKS_NAME" --attach-acr "$ACR_NAME"# Enable firewall and allow only AKS egress IPs (example: a single egress IP)ACR_RG="$(az acr show -n "$ACR_NAME" --query resourceGroup -o tsv)"ACR_IP="<aks-egress-public-ip>"az acr update -n "$ACR_NAME" --resource-group "$ACR_RG" --public-network-enabled falseaz acr network-rule add -n "$ACR_NAME" -g "$ACR_RG" --ip-address "$ACR_IP"
- Alternatively, use Private Endpoints and ensure only the AKS virtual network/subnets are linked.
- For each approved ACR, restrict access (run from admin machine with Azure CLI):
-
Enforce registry restrictions via Azure Policy / admission control (cloud configuration)
- In the Azure portal or via CLI, assign a built‑in policy (search for):
- “Kubernetes clusters should only allow container images from trusted registries”
- Scope it to the AKS cluster’s resource group or subscription and configure the allowed registries list to match
/tmp/approved-registries.txt. - If using custom admission controllers (e.g., OPA/Gatekeeper), review the constraint templates to ensure they:
- Deny images whose registry host is not in the approved list.
- Are applied to all relevant namespaces (exclude only explicitly approved ones).
- In the Azure portal or via CLI, assign a built‑in policy (search for):
-
Verify enforcement and absence of drift (any machine with kubectl access)
- Attempt to deploy a pod from an unapproved registry and confirm it is blocked:
cat << 'EOF' > /tmp/unapproved-test-pod.yamlapiVersion: v1kind: Podmetadata:name: unapproved-registry-testnamespace: defaultspec:containers:- name: testimage: unapproved.example.com/busybox:latestcommand: ["sh", "-c", "sleep 3600"]EOFkubectl apply -f /tmp/unapproved-test-pod.yamlkubectl describe pod unapproved-registry-test -n default
- Confirm the pod is denied by policy or fails to pull due to ACR firewall/network rules, and re-run step 1’s inventory to ensure only approved registries remain in active workloads.
- Attempt to deploy a pod from an unapproved registry and confirm it is blocked:
Using kubectl
kubectl cannot configure which container registries are approved for AKS workloads; this is controlled via Azure Container Registry firewall rules, Azure Policy/admission control, and network/egress settings in the Azure control plane and surrounding Azure resources. Use kubectl only to inspect current image usage; apply the actual changes using Azure configuration as described in the Manual Steps section.
Automation
#!/usr/bin/env bash
set -euo pipefail
# Run this on any machine with kubectl access and correct context.
# Optional: comma‑separated list of approved registries (prefix match), e.g.:
# APPROVED_REGISTRIES="myregistry.azurecr.io,contoso.azurecr.io"
APPROVED_REGISTRIES="${APPROVED_REGISTRIES:-}"
echo "Collecting image usage from all namespaces..." >&2
# 1) Gather all unique images (including initContainers) across all namespaces
kubectl get pods --all-namespaces -o json \
| jq -r '
.items[]
| {
ns: .metadata.namespace,
pod: .metadata.name,
containers: (
([.spec.containers[], (.spec.initContainers // [])[]]
| {name, image})
)
}
| .ns as $ns
| .pod as $pod
| .containers[]
| [$ns, $pod, .name, .image]
| @tsv
' | sort -u > /tmp/aks_images.tsv
echo "Found the following (namespace, pod, container, image) tuples:" >&2
cat /tmp/aks_images.tsv >&2
echo >&2
# 2) Extract the registry/host portion of each image (text before first '/')
# Note: images without an explicit registry default to Docker Hub
cut -f4 /tmp/aks_images.tsv \
| awk -F/ '
{
if (index($1, ".") || index($1, ":")) {
registry=$1
} else {
# No registry specified -> treat as Docker Hub library or docker.io
registry="docker.io (implicit)"
}
print registry
}
' \
| sort -u > /tmp/aks_registries.txt
echo "Unique registries (or implied registry) in use:" >&2
nl -ba /tmp/aks_registries.txt >&2
echo >&2
if [ -n "$APPROVED_REGISTRIES" ]; then
echo "Approved registries (prefix match): $APPROVED_REGISTRIES" >&2
IFS=',' read -r -a approved <<< "$APPROVED_REGISTRIES"
echo
echo "=== Potentially UNAPPROVED registries in use ==="
echo "(Any registry not matching one of the approved prefixes)"
while read -r reg; do
is_ok=0
for a in "${approved[@]}"; do
# simple prefix match
case "$reg" in
"$a"*) is_ok=1 ;;
esac
done
if [ "$is_ok" -eq 0 ]; then
echo "$reg"
fi
done < /tmp/aks_registries.txt | sort -u
echo
fi
# 3) Detailed report: list pods/containers using each registry
echo "=== Detailed pod/container -> registry mapping ==="
echo -e "NAMESPACE\tPOD\tCONTAINER\tIMAGE\tREGISTRY"
while IFS=$'\t' read -r ns pod cname img; do
reg=$(awk -F/ '
{
if (index($1, ".") || index($1, ":")) {
print $1
} else {
print "docker.io (implicit)"
}
}' <<< "$img")
printf "%s\t%s\t%s\t%s\t%s\n" "$ns" "$pod" "$cname" "$img" "$reg"
done < /tmp/aks_images.tsv | column -t
How to interpret the output:
- Any registry listed under “Unique registries (or implied registry) in use” that is not on your approved list is a review item.
- If
APPROVED_REGISTRIESis set, anything printed under “Potentially UNAPPROVED registries in use” indicates a potential problem. - Pay particular attention to:
docker.io (implicit)or images without a registry (defaulting to Docker Hub) if Docker Hub is not approved.- Public cloud registries (e.g.,
mcr.microsoft.com,docker.io,gcr.io, etc.) if your policy requires only private/ACR registries.
- Use the “Detailed pod/container -> registry mapping” section to identify exactly which workloads are pulling from each non‑approved registry for manual remediation and policy updates.