Google cloud 的 Binary Authorization 可以帮助用户在部署 container 时采用信任的 image。可以通过配置信任的 repository,也可以通过 Key 认证的方式实现 image 的认证。
本文将介绍,如何采用 Binary Authorization 实现容器的 Image 的安全部署。
一 创建相关服务
1、开启相关的 API
首先打开 cloud shell,在 cloud shell 中检查相关的配置:
hengwei@cloudshell:~ (wh-service01)$ gcloud config list[component_manager]disable_update_check = True[compute]gce_metadata_read_timeout_sec = 5[core]account = hengwei@google.comdisable_usage_reporting = Falseproject = wh-service01[metrics]environment = devshell
复制代码
定义参数:
PROJECT_ID=wh-service01echo $PROJECT_IDWh-service01ZONE=us-central1-aecho $ZONEus-central1-a
复制代码
开启 API:
gcloud services enable > container.googleapis.com> containeranalysis.googleapis.com> binaryauthorization.googleapis.comOperation "operations/acf.0587658c-ebed-42a4-ac53-5f68b3b3bb3f" finished successfully.
复制代码
可以看到,此时 Binary Authorization 的 API 已经 enable 了:
2、创建 GKE cluster
采用命令行模式创建 GKE Cluster:
gcloud container clusters create --enable-binauthz --zone $ZONE gkecluster01NAME LOCATION MASTER_VERSION MASTER_IPgkecluster01 us-central1-a 1.13.11-gke.23 35.222.79.234 MACHINE_TYPE NODE_VERSION NUM_NODES STATUSn1-standard-1 1.13.11-gke.23 3 RUNNINGgcloud container clusters get-credentials --zone $ZONE gkecluster01Fetching cluster endpoint and auth data.kubeconfig entry generated for gkecluster01.kubectl get nodeNAME STATUS ROLES AGE VERSIONgke-gkecluster01-default-pool-5ecb124a-520n Ready <none> 15m v1.13.11-gke.23gke-gkecluster01-default-pool-5ecb124a-b314 Ready <none> 16m v1.13.11-gke.23gke-gkecluster01-default-pool-5ecb124a-vn7p Ready <none> 15m v1.13.11-gke.23
复制代码
3、创建 Container Image
查看 Binauthz 的策略:
gcloud container binauthz policy exportadmissionWhitelistPatterns:- namePattern: gcr.io/google_containers/*- namePattern: gcr.io/google-containers/*- namePattern: k8s.gcr.io/*- namePattern: gke.gcr.io/*- namePattern: gcr.io/stackdriver-agents/*defaultAdmissionRule:enforcementMode: ENFORCED_BLOCK_AND_AUDIT_LOGevaluationMode: ALWAYS_ALLOWname: projects/wh-service01/policy
复制代码
Console 中的配置:
创建 docker image,并 push 到 Google Container Registry(GCR)中。
image 的 Dockerfile:
cat << EOF > DockerfileFROM alpineCMD tail -f /dev/nullEOF
复制代码
Build 和 push:
export CONTAINER_PATH=us.gcr.io/$PROJECT_ID/hello-worlddocker build -t $CONTAINER_PATH ./gcloud auth configure-docker --quietdocker push $CONTAINER_PATH
复制代码
此时可以看到 GCR 中已经有 image 上传上来:
使用这个 image 创建 deployment:
kubectl create deployment hello-world --image=$CONTAINER_PATH
复制代码
可以看到已经创建成功:
kubectl get podNAME READY STATUS RESTARTS AGEhello-world-55b45c79cd-bwvgl 1/1 Running 0 13s
复制代码
二 配置 Binary Authorization 策略
根据前文的描述,Binary Authorization 的策略有三种:
我们在第一节中,测试 Allow all image 和 Disallow all image 两个策略,在第二节中,测试 attestor 相关的策略。
1、Binary Authorization Policy
创建 policy.yaml 文件:
cat > ./policy.yaml << EOFglobalPolicyEvaluationMode: ENABLEdefaultAdmissionRule:evaluationMode: ALWAYS_DENYenforcementMode: ENFORCED_BLOCK_AND_AUDIT_LOGEOF
复制代码
可以看到,这里把 Adminission Rule 改成了 Always Deny,除白名单内的 image,是不能创建 pod 的。
部署此策略:
gcloud container binauthz policy import policy.yaml
复制代码
此时中 console 中可以看到策略如下:
重新部署 deployment:
kubectl delete deployment --allkubectl delete event --allkubectl create deployment hello-world --image=$CONTAINER_PATH
复制代码
可以看到,pod 因为 image policy,不能创建:
手工添加白名单:
保存后,deployment 部署成功:
2、Attestor 策略
GKE 的 Binary Authorization 功能通过调用 Container Analysis 功能中的 container image 的 metadata,来确定是否是认证过的 image。具体实现方式如下:
在 Container Analysis 中定义 Note,通过手工或自动的方式在创建 image 时,metadata 中加入数字签名。
Binary Authorization 中设置 Attestor,调用 Note,确认 image 的 metadata 中的数字签名。如果数字签名通过,可以把 image 部署到container 中,否则不允许。从而实现对 container Image 的授权。
如下是 container build的pipline:
在 Build/Test 以及 Artifact 阶段实现 Attest:
在部署阶段,实现 enforce:
A 创建 Container Analysis Note
创建 note 配置文件:
cat > ./create_note_request.json << EOM{"attestation": {"hint": {"human_readable_name": "This note represents an attestation authority"}}}EOM
复制代码
创建 note-01:
export NOTE_ID=attestor-note-01curl -vvv -X POST-H "Content-Type: application/json" -H "Authorization: Bearer $(gcloud auth print-access-token)" --data-binary @./create_note_request.json "https://containeranalysis.googleapis.com/v1/projects/${PROJECT_ID}/notes/?noteId=${NOTE_ID}"
复制代码
查看 note:
B 创建 Attestor
用命令行:
export ATTESTOR_ID=binauthz-attestor-01gcloud container binauthz attestors create $ATTESTOR_ID --attestation-authority-note=$NOTE_ID --attestation-authority-note-project=${PROJECT_ID}
复制代码
查看 Attestor:
gcloud container binauthz attestors list
复制代码
C 添加 key
Enable KMS 服务:
gcloud services enable cloudkms.googleapis.com
复制代码
采用 Google Cloud KMS 创建 Key,并添加到 attestor 中。
创建 Key-ring、Key:
export KEY_LOCATION=globalexport KEYRING=key-ring-01export KEY_NAME=key-01export KEY_VERSION=1gcloud kms keyrings create "${KEYRING}" --location="${KEY_LOCATION}"gcloud kms keys create "${KEY_NAME}" --keyring="${KEYRING}" --location="${KEY_LOCATION}" --purpose asymmetric-signing --default-algorithm="ec-sign-p256-sha256"
复制代码
查看 key 的情况:
Attestor 中添加 Key:
gcloud beta container binauthz attestors public-keys add --attestor="${ATTESTOR_ID}" --keyversion-project="${PROJECT_ID}" --keyversion-location="${KEY_LOCATION}" --keyversion-keyring="${KEYRING}" --keyversion-key="${KEY_NAME}" --keyversion="${KEY_VERSION}"
复制代码
此时,Attestor 中添加了 Public Key:
D 对 container Image 进行签名
先获取 Image 对 Digest:
export DIGEST=$(gcloud container images describe ${CONTAINER_PATH}:latest --format='get(image_summary.digest)')
复制代码
是一串 hash 值:
echo $DIGESTsha256:e4551a5ded95740f0be38b37dbcebac081a9f5c717d223e1998c871d6a8a79dd
复制代码
手工对 Image 进行签名:
gcloud beta container binauthz attestations sign-and-create --artifact-url="${CONTAINER_PATH}@${DIGEST}" --attestor="${ATTESTOR_ID}" --attestor-project="${PROJECT_ID}" --keyversion-project="${PROJECT_ID}" --keyversion-location="${KEY_LOCATION}" --keyversion-keyring="${KEYRING}" --keyversion-key="${KEY_NAME}" --keyversion="${KEY_VERSION}"
复制代码
可以查看签名对情况:
gcloud container binauthz attestations list> --attestor=$ATTESTOR_ID --attestor-project=${PROJECT_ID}---attestation:attestation:genericSignedAttestation:contentType: SIMPLE_SIGNING_JSONserializedPayload: ewogICJjc……=signatures:- publicKeyId: //cloudkms.googleapis.com/v1/projects/wh-service01/locations/global/keyRings/key-ring-01/cryptoKeys/key-01/cryptoKeyVersions/1signature: MEUCIQCh_SIeuAoAzuGl7dymtgrFFclJk6EJ-u5Jeg_x3xU2gQIgKFyG__OGBdMVgVC21iIqBIa_ETeHHKJ7MrM0tB7LICo=createTime: '2020-02-04T08:01:19.206181Z'kind: ATTESTATIONname: projects/wh-service01/occurrences/9b462272-33bb-46de-ad6a-61312223cf05noteName: projects/wh-service01/notes/attestor-note-01resource:uri: https://us.gcr.io/wh-service01/hello-world@sha256:e4551a5ded95740f0be38b37dbcebac081a9f5c717d223e1998c871d6a8a79ddupdateTime: '2020-02-04T08:01:19.206181Z'
复制代码
E 更新 Binary Authorization 的策略
将策略改成,只允许 Attestor 方式的 Image。此时 Binary Authorization 的策略如下:
两张模式的 Image 都可以部署到 Container 中。
F 部署 Container
kubectl create deployment hello-world-signed--image="${CONTAINER_PATH}@${DIGEST}"
复制代码
查看部署情况:
三 总结
通过 Google Cloud 的 Binary Authorization,可以方便的对 Container 的 Image 进行管理。可以通过简单的镜像源进行粗略的管理,也可以通过 Attestor的方式对镜像签名进行验证,从而实现相对严格的验证和授权。