Skip to content

Instantly share code, notes, and snippets.

@JonTheNiceGuy
Last active December 4, 2025 13:57
Show Gist options
  • Select an option

  • Save JonTheNiceGuy/ead664eddaaf87aa5c6a1743984397c9 to your computer and use it in GitHub Desktop.

Select an option

Save JonTheNiceGuy/ead664eddaaf87aa5c6a1743984397c9 to your computer and use it in GitHub Desktop.
crictl pull image using ecr-credential-provider

pullImage Functions

A while back I wrote a blog post about using Credential Providers to automate getting secrets for pulling images for Kubernetes.

Today I had cause to go back to look at that when my cluster was failing to pull images (because they didn't exist, foolishly) and I decided I needed a way to automatically check whether I could actually pull the images. Unlike with the docker credential helpers, you can't just "pull" an image, you need to tell crictl what credentials to use (as this is usually handled by kubelet), so I wrote the first script - ecr_pullImage.function.sh. After a short while I realised it would be more useful to be able to pull from several image sources, and asked Claude to enhance the script to figure out what the kubelet would likely do (without access to the pullSecrets from the cluster). And thus, generic_pullImage.function.sh was born.

Enjoy!

These functions by Jon Spriggs is released under the "Public Domain", CC0 1.0

#!/bin/bash
pullImage() {
registry="$(cut -d/ -f1 <<<"$1")"
image="$1"
password="$(echo "{\"apiVersion\": \"credentialprovider.kubelet.k8s.io/v1\", \"kind\": \"CredentialProviderRequest\", \"image\": \"$image\"} | /usr/local/bin/image-credential-provider/ecr-credential-provider | jq ".auth[\"$registry\"].password -r)"
crictl pull --creds "AWS:${password}" "$image"
}
#!/bin/bash
pullImage() {
local image="$1"
local registry="$(cut -d/ -f1 <<<"$image")"
# Get paths from kubelet process
local kubelet_cmd="$(ps aux | grep '/usr/bin/kubelet' | grep -v 'grep')"
local config_path="$(echo "$kubelet_cmd" | grep -oP '(?<=--image-credential-provider-config )[^ ]+')"
local bin_dir="$(echo "$kubelet_cmd" | grep -oP '(?<=--image-credential-provider-bin-dir )[^ ]+')"
# Default paths if not found
config_path="${config_path:-/etc/kubernetes/image-credential-provider-config.json}"
bin_dir="${bin_dir:-/usr/local/bin/image-credential-provider}"
# Find matching provider
local provider_name=""
local num_providers=$(jq '.providers | length' "$config_path")
for ((i=0; i<num_providers; i++)); do
local num_patterns=$(jq ".providers[$i].matchImages | length" "$config_path")
for ((j=0; j<num_patterns; j++)); do
local pattern=$(jq -r ".providers[$i].matchImages[$j]" "$config_path")
# Use bash pattern matching against both registry and full image
if [[ "$registry" == $pattern ]] || [[ "$image" == $pattern ]]; then
provider_name=$(jq -r ".providers[$i].name" "$config_path")
break 2
fi
done
done
# If no provider matched, pull without credentials (for public images)
if [[ -z "$provider_name" ]]; then
echo "No credential provider matched for image: $image, pulling without credentials" >&2
crictl pull "$image"
return $?
fi
# Get credentials using the matched provider
local provider_path="${bin_dir}/${provider_name}"
if [[ ! -x "$provider_path" ]]; then
echo "Error: Credential provider not found or not executable: $provider_path" >&2
return 1
fi
local creds="$(echo "{\"apiVersion\": \"credentialprovider.kubelet.k8s.io/v1\", \"kind\": \"CredentialProviderRequest\", \"image\": \"$image\"}" | "$provider_path")"
local username="$(jq -r ".auth[\"$registry\"].username" <<<"$creds")"
local password="$(jq -r ".auth[\"$registry\"].password" <<<"$creds")"
if [[ "$username" == "null" ]] || [[ "$password" == "null" ]]; then
echo "Error: Failed to get credentials for image: $image" >&2
return 1
fi
crictl pull --creds "${username}:${password}" "$image"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment