チュートリアルベースでの評価メモ。
- GCP (Google Cloud Platform)が提供するBinary Authorizationのうち、Attestor(証人 / 署名者)によるContainer Image署名の検証機能を確認。
- GKE上でのContainer Deploy(
kubectl run
)において、署名を登録したImageが許可され、署名されていないImageは拒否されることを確認。
概要
- Binary Authorizationは、GKE上で実行するContainer Imageを、信頼されたものに限定するための仕掛け。以下の2種類の制限機能がサポートされている(本記事は、Attestorについて記載)。
- Policy
- 特定のレジストリ(Domainに対するパターンマッチング)から取得したContainer Imageに限定する。
- Attestors
- AttestorによるPGP署名が事前登録されたContainer Imageに限定する。
- Policy
環境
- OS
- Debian GNU/Linux 9 (GCP Cloud Shell)
- GKE Version
- v1.13.11-gke.14
特記事項
- 本評価時点で
Beta
のため、以下で言及している機能は今後変更される可能性あり。 - Attestor機能を有効にするためには、GKE Clusterを、
--enable-binauthz
オプションを指定して作成する必要がある。 - ポリシーの制限は、デフォルトルール(Project単位)、と除外ルール(Cluster単位)の2種類で指定できる。
- Attestorに関連付けて登録したImage署名の削除コマンドが見当たらない。
-
gcloud beta container binauthz attestations create
で署名を登録できるが、delete
操作が見当たらない (Attestor自体を再作成する必要がある?)。
-
手順
APの有効化
前提となるCloud APIの有効化。
gcloud services enable \
container.googleapis.com \
containeranalysis.googleapis.com \
binaryauthorization.googleapis.com
前提設定(環境変数の設定)
PROJECT_ID="$(gcloud config get-value project)"
NOTE_ID="Sample-Attestor-Note"
ATTESTOR="Sample-Attestor"
ATTESTOR_EMAIL="$(gcloud config get-value core/account)"
PGP_PUB_KEY="key.pgp"
Attestor Noteの作成
まずは、Attestor情報を関連付けるためのNoteを作成する必要がある。
cat > note.json << EOF
{
"name": "projects/${PROJECT_ID}/notes/${NOTE_ID}",
"attestation_authority": {
"hint": {
"human_readable_name": "SampleName"
}
}
}
EOF
curl -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
--data-binary @note.json \
"https://containeranalysis.googleapis.com/v1beta1/projects/${PROJECT_ID}/notes/?noteId=${NOTE_ID}"
署名用PGP Keyの作成
(十分なエントロピーを確保するための)乱数生成用パッケージをインストール。
sudo apt install rng-tools -y
sudo rngd -r /dev/urandom
署名用のPGP鍵を生成し、ファイルにエクスポートする(パスワードを求められるが、今回は空のパスワードを指定)。
gpg --quick-generate-key --yes ${ATTESTOR_EMAIL}
gpg --armor --export "${ATTESTOR_EMAIL}" > ${PGP_PUB_KEY}
Attestorの作成&PGP鍵登録
上記で作成したAttestor Noteを指定して、Attestor情報を登録。
gcloud --project="${PROJECT_ID}" \
beta container binauthz attestors create "${ATTESTOR}" \
--attestation-authority-note="${NOTE_ID}" \
--attestation-authority-note-project="${PROJECT_ID}"
登録したAttestorに対して、PGP鍵を登録。
gcloud --project="${PROJECT_ID}" \
beta container binauthz attestors public-keys add \
--attestor="${ATTESTOR}" \
--pgp-public-key-file="${PGP_PUB_KEY}"
GKE Clusterの設定
クラスタを作成。--enable-binauthz
オプションを有効にする必要がある。
gcloud container clusters create sample-cluster --zone us-central1-a --enable-binauthz
Attestationを有効にするポリシーを定義(Attestorによる署名が存在しないイメージを拒否するように設定する)。
cat > policy.yaml << EOF
defaultAdmissionRule:
evaluationMode: REQUIRE_ATTESTATION
enforcementMode: ENFORCED_BLOCK_AND_AUDIT_LOG
requireAttestationsBy:
- projects/${PROJECT_ID}/attestors/${ATTESTOR}
name: projects/${PROJECT_ID}/policy
EOF
gcloud container binauthz policy import policy.yaml
対象のContainer ImageのDigestの情報を取得。
IMAGE_PATH="gcr.io/google-samples/hello-app"
IMAGE_DIGEST="$(gcloud container images list-tags --format='get(digest)' $IMAGE_PATH | head -1)"
デプロイ確認(失敗)
このコンテナの署名は未登録のため、この段階で実行するとエラー終了する(上記で設定したPolicyにより拒否される)。
kubectl run hello-server --generator=run-pod/v1 --image ${IMAGE_PATH}@${IMAGE_DIGEST} --port 8080
Error from server (Forbidden): pods "hello-server" is forbidden: image policy webhook backend denied one or more images: Denied by default admission rule. Denied by Attestor. Image gcr.io/google-samples/hello-app denied by projects/qwiklabs-gcp-01-351cba835b68/attestors/Sample-Attestor: Attestor cannot attest to an image deployed by tag
署名済みイメージの作成
署名用のPGP鍵のFinger Printを取得。
PGP_FINGERPRINT="$(gpg --list-keys ${ATTESTOR_EMAIL} | head -2 | tail -1 | awk '{print $1}')"
署名を作成。
gcloud beta container binauthz create-signature-payload \
--artifact-url="${IMAGE_PATH}@${IMAGE_DIGEST}" > payload.json
gpg --local-user "${ATTESTOR_EMAIL}" \
--armor \
--output signature.json \
--sign payload.json
署名情報をAttestationとして登録。
gcloud beta container binauthz attestations create \
--artifact-url="${IMAGE_PATH}@${IMAGE_DIGEST}" \
--attestor="projects/${PROJECT_ID}/attestors/${ATTESTOR}" \
--signature-file=signature.json \
--public-key-id="${PGP_FINGERPRINT}"
デプロイ確認(成功)
署名したイメージを指定してデプロイすると正常終了する。
kubectl run hello-server --generator=run-pod/v1 --image ${IMAGE_PATH}@${IMAGE_DIGEST} --port 8080