Cómo decodificar un pull secret
- Pega en la entrada una de estas cosas:
- la salida de
kubectl get secret regcred -o yaml - solo el valor Base64 de
.dockerconfigjson - el propio JSON, por ejemplo tu
~/.docker/config.json
- la salida de
- Las credenciales del registro aparecen primero: registro, usuario, contraseña y el valor
authseparado en usuario y contraseña. - Para crear un Secret, abre Crear pull secret y rellena Registro, Usuario, Contraseña y, si quieres, Correo (opcional). El resultado es el mismo Secret que escribe
kubectl create secret docker-registry.
El doble Base64 de un pull secret
Un pull secret envuelve Base64 dentro de Base64, y por eso decodificarlo a mano lleva dos pasos.
apiVersion: v1
kind: Secret
metadata:
name: regcred
type: kubernetes.io/dockerconfigjson
data:
.dockerconfigjson: eyJhdXRocyI6eyJyZWdpc3RyeS5leGFtcGxlLmNvbSI6eyJ1c2VybmFtZSI6ImNpLWJvdCIsInBhc3N3b3JkIjoicHVsbC1vbmx5LXRva2VuIiwiYXV0aCI6Ilkya3RZbTkwT25CMWJHd3RiMjVzZVMxMGIydGxiZz09In19fQ==
La primera capa, el valor del Secret, se decodifica como el JSON de configuración de Docker:
{"auths":{"registry.example.com":{"username":"ci-bot","password":"pull-only-token","auth":"Y2ktYm90OnB1bGwtb25seS10b2tlbg=="}}}
La segunda capa, auth, se decodifica como ci-bot:pull-only-token. Un valor .dockerconfigjson creado con kubectl create secret docker-registry empieza por eyJhdXRocyI6, el Base64 de {"auths":, lo que hace que estas cadenas sean fáciles de reconocer en logs y manifiestos.
Formatos con los que te puedes encontrar
| Forma | De dónde sale |
|---|---|
{"auths": {"host": {...}}} | .dockerconfigjson, el ~/.docker/config.json actual |
{"host": {"auth": "...", "email": "..."}} | Secrets .dockercfg heredados (kubernetes.io/dockercfg) |
"https://index.docker.io/v1/" como host | Docker Hub |
identitytoken en lugar de una contraseña | registros que entregan tokens de actualización OAuth tras docker login |
Aquí se decodifican los dos tipos de Secret. Un .dockercfg heredado no tiene el envoltorio auths, así que un script escrito para un formato no encuentra nada en el otro, y sin avisar.
Decodificar en la shell
kubectl get secret regcred -o jsonpath='{.data.\.dockerconfigjson}' | base64 --decode | jq .
kubectl get secret regcred -o jsonpath='{.data.\.dockerconfigjson}' | base64 --decode \
| jq -r '.auths | to_entries[] | "\(.key) \(.value.auth | @base64d)"'
El segundo comando imprime una línea registry user:password por registro. El valor auth tiene el mismo formato que un encabezado Basic Auth, así que el decodificador de Basic Auth también lo lee.
Por qué falla un pull secret
- Clave de registro equivocada. El host de
authsdebe coincidir con la referencia de la imagen:ghcr.io/org/appnecesitaghcr.io, y las imágenes de Docker Hub necesitanhttps://index.docker.io/v1/. - Secret en otro namespace.
imagePullSecretssolo encuentra Secrets en el namespace del propio Pod. - Token caducado. Algunos registros emiten contraseñas de corta duración; los tokens de Amazon ECR, por ejemplo, valen 12 horas. Un Secret que ayer funcionaba da hoy
ImagePullBackOff. - JSON construido a mano. Una contraseña copiada con un salto de línea o un espacio al final, o un valor
authcodificado a partir de la cadena equivocada, falla sin avisar. Compara elauthdecodificado con los campos de usuario y contraseña, o vuelve a crear el Secret conkubectl create secret docker-registry.
Cualquiera que pueda leer el Secret puede usar la cuenta, porque Base64 no oculta nada. Usa tokens de registro de solo lectura en los pull secrets.
Preguntas frecuentes
¿Cómo decodifico un imagePullSecret?
Pega arriba la salida de kubectl get secret regcred -o yaml. En una shell, kubectl get secret regcred -o jsonpath='{.data.\.dockerconfigjson}' | base64 --decode imprime el JSON, y su campo auth vuelve a estar en Base64.
¿Qué es el campo auth de config.json?
Es username:password en Base64, el mismo formato que un encabezado HTTP Basic Authorization. Y2ktYm90OnB1bGwtb25seS10b2tlbg== se decodifica como ci-bot:pull-only-token.
¿Por qué la entrada auths de mi ~/.docker/config.json está vacía?
Docker guarda la contraseña en un credential helper cuando está definido credsStore o credHelpers, por ejemplo el llavero del sistema. El archivo solo tiene entonces {} por cada registro y no hay nada que decodificar.