Skip to main content

Minimize Container Registries To 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 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

Remediation

Manual Steps
  1. Identify all container registries currently in use

    • On any machine with access to the project:
      # List all images currently deployed to the cluster and extract registries
      gcloud container clusters get-credentials CLUSTER_NAME --region REGION --project PROJECT_ID

      kubectl get pods --all-namespaces -o jsonpath='{range .items[*]}{.spec.containers[*].image}{"\n"}{.spec.initContainers[*].image}{"\n"}{end}' \
      | tr ' ' '\n' | sed '/^$/d' | sort -u \
      | sed 's#^\([^/]*\)/.*#\1#' | sort -u
    • Compare the resulting list of registries (e.g., gcr.io, us-docker.pkg.dev, docker.io, others) to your organization’s approved registry list.
  2. Determine clusters and projects where Binary Authorization should be enforced

    • On any machine with gcloud configured:
      gcloud projects list
      gcloud container clusters list --project PROJECT_ID --region REGION
    • For each cluster in scope, decide whether all workloads must be restricted to approved registries or whether exceptions are required (e.g., third‑party images that cannot be mirrored).
  3. Review current Binary Authorization configuration and policy (if any)

    • On any machine with gcloud configured:
      # Check if Binary Authorization is enabled on the cluster
      gcloud container clusters describe CLUSTER_NAME \
      --region REGION --project PROJECT_ID \
      --format="value(binaryAuthorization.enabled)"

      # View the current project-level Binary Authorization policy
      gcloud container binauthz policy export \
      --project PROJECT_ID > current-binauthz-policy.yaml
    • Inspect current-binauthz-policy.yaml to see whether it exists and whether any admissionRule or defaultAdmissionRule references constraints on image registries (e.g., via attestor requirements or image pattern constraints).
  4. Design or update the approved-registry policy

    • Using the exported current-binauthz-policy.yaml as a base (or the reference YAML in the Binary Authorization Policy Reference), decide:
      • Which registries (e.g., gcr.io/ORG/*, us-docker.pkg.dev/PROJECT/*) are allowed.
      • Whether images from unapproved registries should be blocked or only warned (for initial rollout).
    • Edit a local policy file, for example:
      nano updated-binauthz-policy.yaml
    • In that file, define or adjust admission rules to require that images match only the allowed registry patterns, and decide what to do with non-matching images (e.g., alwaysDeny for strict enforcement, or attestation-based exceptions).
  5. Enable Binary Authorization on the cluster and apply the policy

    • On any machine with gcloud configured:
      # Enable Binary Authorization on the cluster (if not already enabled)
      gcloud container clusters update CLUSTER_NAME \
      --region REGION --project PROJECT_ID \
      --enable-binauthz

      # Import the updated policy
      gcloud container binauthz policy import updated-binauthz-policy.yaml \
      --project PROJECT_ID
    • Be aware that tightening the policy can cause new pod creations or updates using disallowed registries to be rejected; plan for staged rollout and testing.
  6. Verify that only approved registries are allowed going forward

    • On any machine with gcloud and kubectl configured:
      # Confirm cluster shows Binary Authorization as enabled
      gcloud container clusters describe CLUSTER_NAME \
      --region REGION --project PROJECT_ID \
      --format="value(binaryAuthorization.enabled)"

      # Attempt to deploy a test workload from an unapproved registry (should be denied)
      kubectl run test-unapproved \
      --image=UNAPPROVED_REGISTRY/namespace/image:tag \
      --restart=Never

      # Attempt to deploy a test workload from an approved registry (should be allowed)
      kubectl run test-approved \
      --image=APPROVED_REGISTRY/namespace/image:tag \
      --restart=Never
    • Confirm that the unapproved image is rejected by admission control and that the approved image runs successfully, then remove the test pods.
Using kubectl

kubectl cannot configure which container registries are allowed for image pulls or enable Binary Authorization; this control is managed at the GKE control‑plane / project level via gcloud, the GCP console, or IaC. Refer to the Manual Steps section for the exact gcloud commands and policy configuration needed to restrict registries.

Automation
#!/usr/bin/env bash
#
# Report all unique image registries used by workloads in a GKE cluster.
# Run on: any machine with kubectl access and context set to the target cluster.
#
# This does NOT change anything; it only reports for review.

set -euo pipefail

echo "Collecting images from all namespaces and workload types..." >&2

# Collect images from common workload types
images=$(
{
kubectl get pods --all-namespaces -o json;
kubectl get deployments.apps --all-namespaces -o json;
kubectl get daemonsets.apps --all-namespaces -o json;
kubectl get statefulsets.apps --all-namespaces -o json;
kubectl get jobs.batch --all-namespaces -o json;
kubectl get cronjobs.batch --all-namespaces -o json 2>/dev/null || true;
} \
| jq -r '
.. | .image? // empty
' \
| sort -u
)

if [[ -z "${images}" ]]; then
echo "No images found in the cluster (no running or configured workloads?)" >&2
exit 0
fi

echo
echo "=== Unique images found in the cluster ================================="
printf '%s\n' "${images}"
echo "========================================================================"
echo

# Derive registries from images
# Rules:
# - If image contains '/', take the first path segment as 'registry_or_namespace'
# - If that segment contains a '.', ':' or is 'localhost', treat it as a registry
# - Otherwise, treat image as using the default Docker Hub registry
registries=$(
printf '%s\n' "${images}" \
| awk -F/ '
{
if (NF == 1) {
# No "/" → implicit default registry (Docker Hub)
print "<default-docker-registry>"
} else {
first = $1
if (first ~ /\./ || first ~ /:/ || first == "localhost") {
print first
} else {
# Looks like a namespace on Docker Hub (e.g. library/nginx)
print "<default-docker-registry>"
}
}
}
' \
| sort -u
)

echo "=== Derived image registries in use ====================================="
printf '%s\n' "${registries}"
echo "======================================================================="
echo
echo "Review guidance:"
echo "1) Define your APPROVED registries list (for example):"
echo " - gcr.io"
echo " - us.gcr.io"
echo " - eu.gcr.io"
echo " - asia.gcr.io"
echo " - <your-project>.gcr.io"
echo " - <default-docker-registry> (ONLY if Docker Hub is explicitly approved)"
echo
echo "2) Any registry shown above that is NOT on your approved list is a potential problem."
echo " Examples of suspicious output:"
echo " - docker.io or <default-docker-registry> if public Docker Hub is not approved"
echo " - quay.io, ghcr.io, registry.hub.docker.com, or arbitrary hostnames"
echo " - localhost:5000 or other ad-hoc registries not in policy"
echo
echo "3) For each unapproved registry:"
echo " - Identify which workloads use it:"
echo " kubectl get pods --all-namespaces -o wide | grep '<registry-fragment>'"
echo " kubectl get deploy,sts,ds,job,cronjob --all-namespaces -o yaml | grep '<registry-fragment>' -n"
echo " - Decide whether to:"
echo " * Migrate images to an approved registry, and/or"
echo " * Block them via a Binary Authorization policy as per CISGKE 5.1.4."
echo
echo "This script only surfaces current usage; enforcement must be configured via"
echo "GKE/Binary Authorization policy (cloud provider control plane), not kubectl."

Additional Reading: