プルシークレットをデコードする手順
- 次のいずれかを入力欄に貼り付けます。
kubectl get secret regcred -o yamlの出力.dockerconfigjsonの Base64 の値だけ- JSON そのもの、たとえば
~/.docker/config.json
- 最初にレジストリの認証情報が一覧表示されます。レジストリ、ユーザー名、パスワード、そしてユーザー名とパスワードに分解した
authの値です。 - 逆に Secret を作るには、プルシークレットを作成 を開き、レジストリ、ユーザー名、パスワード、必要なら メールアドレス(任意) を入力します。結果は
kubectl create secret docker-registryが書き出すものと同じ Secret です。
プルシークレットの中の二重の Base64
プルシークレットは Base64 の中に Base64 を包んでいます。手作業でデコードすると 2 段階かかるのはそのためです。
apiVersion: v1
kind: Secret
metadata:
name: regcred
type: kubernetes.io/dockerconfigjson
data:
.dockerconfigjson: eyJhdXRocyI6eyJyZWdpc3RyeS5leGFtcGxlLmNvbSI6eyJ1c2VybmFtZSI6ImNpLWJvdCIsInBhc3N3b3JkIjoicHVsbC1vbmx5LXRva2VuIiwiYXV0aCI6Ilkya3RZbTkwT25CMWJHd3RiMjVzZVMxMGIydGxiZz09In19fQ==
1 層目の Secret の値は、Docker の設定 JSON にデコードされます。
{"auths":{"registry.example.com":{"username":"ci-bot","password":"pull-only-token","auth":"Y2ktYm90OnB1bGwtb25seS10b2tlbg=="}}}
2 層目の auth は ci-bot:pull-only-token にデコードされます。kubectl create secret docker-registry で作った .dockerconfigjson の値は {"auths": の Base64 である eyJhdXRocyI6 で始まるので、ログやマニフェストの中でもこうした文字列は簡単に見つけられます。
出会う可能性のある形式
| 形 | 出どころ |
|---|---|
{"auths": {"host": {...}}} | .dockerconfigjson、現在の ~/.docker/config.json |
{"host": {"auth": "...", "email": "..."}} | 旧形式の .dockercfg Secret(kubernetes.io/dockercfg) |
ホストが "https://index.docker.io/v1/" | Docker Hub |
パスワードの代わりに identitytoken | docker login の後に OAuth のリフレッシュトークンを発行するレジストリ |
ここではどちらの Secret タイプもデコードできます。旧形式の .dockercfg には auths の外枠がないため、一方の形式向けに書いたスクリプトはもう一方では何も見つけられず、しかもエラーになりません。
シェルでデコードする
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)"'
2 つ目のコマンドは、レジストリごとに registry user:password の行を 1 行ずつ出力します。auth の値は Basic 認証ヘッダーと同じ形式なので、Basic 認証デコーダー でも読めます。
プルシークレットが失敗する理由
- レジストリのキーが違う。
authsのホストはイメージの参照と一致していなければなりません。ghcr.io/org/appにはghcr.ioが必要で、Docker Hub のイメージにはhttps://index.docker.io/v1/が必要です。 - Secret が別の Namespace にある。
imagePullSecretsが見つけられるのは、Pod と同じ Namespace の Secret だけです。 - トークンの期限切れ。 有効期間の短いパスワードを発行するレジストリもあります。たとえば Amazon ECR のトークンは 12 時間有効です。昨日は動いていた Secret が、今日は
ImagePullBackOffになります。 - 手作りの JSON。 末尾の改行や空白ごとコピーしたパスワードや、間違った文字列からエンコードした
authの値は、何も言わずに失敗します。デコードしたauthをユーザー名とパスワードのフィールドと比べるか、kubectl create secret docker-registryで Secret を作り直してください。
Base64 は何も隠さないので、Secret を読める人なら誰でもそのアカウントを使えます。プルシークレットには、読み取り専用のレジストリトークンを使ってください。
よくある質問
imagePullSecret をデコードするには?
kubectl get secret regcred -o yaml の出力を上に貼り付けてください。シェルなら、kubectl get secret regcred -o jsonpath='{.data.\.dockerconfigjson}' | base64 --decode で JSON が出力され、その auth フィールドはさらにもう一度 Base64 になっています。
config.json の auth フィールドとは何ですか?
username:password を Base64 にしたもので、HTTP の Basic 認証の Authorization ヘッダーと同じ形式です。Y2ktYm90OnB1bGwtb25seS10b2tlbg== は ci-bot:pull-only-token にデコードされます。
~/.docker/config.json の auths のエントリが空なのはなぜですか?
credsStore や credHelpers が設定されていると、Docker はパスワードをシステムのキーチェーンなどの認証情報ヘルパーに保存します。その場合、ファイルにはレジストリごとに {} しかなく、デコードするものはありません。