CLI で使ってみる

このチュートリアルでは、証明書を要求する Binary Authorization ポリシーの構成とテストの方法を説明します。このタイプのポリシーは、Google Kubernetes Engine(GKE)にコンテナ イメージをデプロイできる対象と、GKE へのデプロイを許可するコンテナ イメージを定義し、コンテナベースのソフトウェア サプライ チェーンを保護します。

デプロイ時に、Binary Authorization は認証者を使用して証明書のデジタル署名を検証します。証明書は、継続的インテグレーション(CI)パイプラインの一部として署名者によって作成されています。

このチュートリアルでは、GKE クラスタ、証明書、認証者はすべて 1 つのプロジェクトに存在します。単一プロジェクト構成はサービスのテストや試験運用に非常に役立ちます。より現実的な例については、マルチプロジェクト構成をご覧ください。

以下では、コマンドラインで実行するタスクについて説明します。これらの手順を Google Cloud Console で行うには、Console で使ってみるをご覧ください。

目標

このチュートリアルでは、以下の方法について学習します。

  • Binary Authorization を有効にして Google Kubernetes Engine(GKE)クラスタを作成する
  • Binary Authorization 施行者が証明書の署名を検証するために使用する認証者を作成する
  • 証明書を要求するポリシーを構成する
  • 証明書に署名して後で検証するための暗号鍵ペアを作成する
  • 署名を作成してコンテナ イメージ ダイジェストに署名する
  • 署名を使用して証明書を作成する
  • コンテナ イメージを GKE にデプロイしてポリシーをテストする

費用

このチュートリアルでは、Google Cloud の課金対象となる以下のコンポーネントを使用します。

  • Container Registry
  • GKE

料金計算ツールを使うと、予想使用量に基づいて費用の見積もりを出すことができます。Cloud Platform を初めて使用する方は、無料トライアルをご利用いただけます。

始める前に

  1. Google アカウントにログインします。

    Google アカウントをまだお持ちでない場合は、新しいアカウントを登録します。

  2. Cloud Console のプロジェクト セレクタページで、Cloud プロジェクトを選択または作成します。

    プロジェクト セレクタのページに移動

  3. Google Cloud プロジェクトに対して課金が有効になっていることを確認します。プロジェクトに対して課金が有効になっていることを確認する方法を学習する

  4. Cloud SDK をインストールして初期化します。
  5. GKE を操作するために kubectl をインストールします。

Binary Authorization を有効にする

デフォルト プロジェクトを設定する

まず、gcloud コマンドでデフォルトの Google Cloud プロジェクトを設定します。

PROJECT_ID=PROJECT_ID
gcloud config set project ${PROJECT_ID}

ここで PROJECT_ID はプロジェクトの名前です。

必要な API を有効にする

次に、GKE、Container Analysis、Binary Authorization で Google Cloud APIs を有効にします。

gcloud services enable \
    container.googleapis.com \
    containeranalysis.googleapis.com \
    binaryauthorization.googleapis.com

Binary Authorization を有効にしたクラスタを作成する

クラスタを作成する

これで、Binary Authorization を有効にして GKE クラスタを作成できるようになりました。このクラスタで、デプロイしたコンテナ イメージを実行します。クラスタを作成するときに、--enable-binauthz フラグを gcloud container clusters create コマンドに渡します。

クラスタの作成手順は次のとおりです。

gcloud container clusters create \
    --enable-binauthz \
    --zone us-central1-a \
    test-cluster

ここでは、GKE ゾーン us-central1-atest-cluster というクラスタを作成します。

kubectl を構成する

kubectl のインストール用にローカルの kubeconfig ファイルも更新する必要があります。これにより、GKE でクラスタにアクセスするために必要な認証情報とエンドポイント情報が提供されます。

ローカル kubeconfig ファイルを更新するには:

gcloud container clusters get-credentials \
    --zone us-central1-a \
    test-cluster

デフォルトのポリシーを表示する

Binary Authorization ポリシーは、コンテナ イメージのデプロイを制御する一連のルールです。プロジェクトごとに 1 つのポリシーを作成できます。デフォルトでは、すべてのコンテナ イメージをデプロイできるポリシーが構成されています。

Binary Authorization を使用すると、YAML 形式のポリシー ファイルをエクスポートまたはインポートできます。この形式は、サービスによって保存されたポリシーの構造を反映しています。gcloud コマンドでポリシーを構成する場合は、このファイルを編集します。

デフォルト ポリシーを表示するには、ポリシーの YAML ファイルをエクスポートします。

gcloud container binauthz policy export

デフォルトでは、このファイルの内容は次のようになっています。

admissionWhitelistPatterns:
- namePattern: gcr.io/google_containers/*
- namePattern: gcr.io/google-containers/*
- namePattern: k8s.gcr.io/*
- namePattern: gke.gcr.io/*
- namePattern: gcr.io/stackdriver-agents/*
globalPolicyEvaluationMode: ENABLE
defaultAdmissionRule:
  evaluationMode: ALWAYS_ALLOW
  enforcementMode: ENFORCED_BLOCK_AND_AUDIT_LOG
name: projects/${PROJECT_ID}/policy

デフォルト ルールは defaultAdmissionRule ノードに定義されています。evaluationMode は、イメージのデプロイ時にすべての試行を許可することを指定します。

ポリシーの構造については、ポリシー YAML リファレンスをご覧ください。

認証者を作成する

認証者は、デプロイ時に Binary Authorization 施行者が GKE で対応する署名付きコンテナ イメージのデプロイを許可するかどうかを決定する際に使用する検証機関です。認証者には公開鍵が含まれ、通常は、ソフトウェア サプライ チェーンのセキュリティを担当する組織の担当者が管理します。

認証者を作成するには、次のことを行います。

  • Container Analysisメモを作成して、認証プロセスで使用される信頼できるメタデータを保存する
  • Binary Authorization で認証者を作成し、作成したメモを関連付ける

このチュートリアルでは、test-attestor という認証者と test-attestor-note という Container Analysis メモを使用しています。実際のシナリオでは、任意の数の認証者を指定できます。各認証者は、コンテナ イメージの認証プロセスに参加する当事者を表します。

Container Analysis メモを作成する

  1. 認証者の名前と Container Analysis メモを格納する変数を設定します。

    ATTESTOR=test-attestor
    NOTE_ID=test-attestor-note
    
  2. Container Analysis メモを記述する JSON ファイルを /tmp/note_payload.json に作成します。

    cat > /tmp/note_payload.json << EOM
    {
      "name": "projects/${PROJECT_ID}/notes/${NOTE_ID}",
      "attestation": {
        "hint": {
          "human_readable_name": "Attestor Note"
        }
      }
    }
    EOM
    
  3. HTTP リクエストを Container Analysis REST API に送信して、メモを作成します。

    curl -X POST \
        -H "Content-Type: application/json" \
        -H "Authorization: Bearer $(gcloud auth print-access-token)"  \
        --data-binary @/tmp/note_payload.json  \
        "https://containeranalysis.googleapis.com/v1/projects/${PROJECT_ID}/notes/?noteId=${NOTE_ID}"
    
  4. メモが作成されたことを確認します。

    curl \
    -H "Authorization: Bearer $(gcloud auth print-access-token)" \
    "https://containeranalysis.googleapis.com/v1/projects/${PROJECT_ID}/notes/${NOTE_ID}"
    

認証者を作成する

これで認証者を作成できます。

  1. Binary Authorization で認証者を作成します。

    gcloud container binauthz attestors create ${ATTESTOR} \
    --attestation-authority-note=${NOTE_ID} \
    --attestation-authority-note-project=${PROJECT_ID}
    
  2. 認証者が作成されたことを確認します。

    gcloud container binauthz attestors list
    

作成した認証者は、以下で作成する PKIX 鍵ペアが関連付けられていないため、まだ使用できません。

鍵ペアを生成する

Binary Authorization は、暗号鍵を使用して署名者の ID を安全に確認します。これにより、承認済みのコンテナ イメージのみをデプロイできます。鍵ペアは秘密鍵と公開鍵で構成されます。署名者は、署名を生成して証明書に保存し、秘密鍵を使用してコンテナ イメージのダイジェストに署名します。公開鍵は認証者に保存されます。コンテナのデプロイを許可する前に、Binary Authorization の施行者が認証者の公開鍵を使用して、証明書の署名を検証します。

このチュートリアルでは、暗号鍵に公開鍵基盤(X.509)(PKIX)形式を使用します。このチュートリアルでは、PKIX 鍵ペアの生成に推奨の 楕円曲線デジタル署名アルゴリズム(ECDSA)を使用していますが、RSA 鍵または PGP 鍵で署名することもできます。

署名アルゴリズムの詳細については、鍵の目的とアルゴリズムをご覧ください。

Cloud Key Management Service(Cloud KMS)によって生成され、保存された鍵は PKIX に準拠しています。PKIX 鍵と Cloud KMS の使用方法については、CLI を使用した認証者の作成をご覧ください。

PKIX 鍵ペアの生成手順は次のとおりです。

  1. 秘密鍵を作成します。

    PRIVATE_KEY_FILE="/tmp/ec_private.pem"
    openssl ecparam -genkey -name prime256v1 -noout -out ${PRIVATE_KEY_FILE}
    
  2. 秘密鍵から公開鍵を抽出します。

    PUBLIC_KEY_FILE="/tmp/ec_public.pem"
    openssl ec -in ${PRIVATE_KEY_FILE} -pubout -out ${PUBLIC_KEY_FILE}
    
  3. 認証者に ECDSA 公開鍵を追加します。

    次に、エクスポートした公開鍵を認証者に追加して、Binary Authorization で本人確認に使用できるようにします。

    gcloud --project="${PROJECT_ID}" \
        beta container binauthz attestors public-keys add \
        --attestor="${ATTESTOR}" \
        --pkix-public-key-file=${PUBLIC_KEY_FILE} \
        --pkix-public-key-algorithm=ecdsa-p256-sha256
    
  4. 公開鍵 ID を保存します。

    公開鍵 ID を保存するには、上記の public-keys add の出力から ID をコピーします。認証者に追加した公開鍵 ID を表示するには、gcloud container binauthz attestors describe ${ATTESTOR} を使用します。

    PUBLIC_KEY_ID=$(gcloud container binauthz attestors describe ${ATTESTOR} \
      --format='value(userOwnedGrafeasNote.publicKeys[0].id)')
    

ポリシーを構成する

これで、ポリシーを構成できます。この手順では、ポリシー YAML ファイルをローカル システムにエクスポートし、上記で定義した認証者による証明書を要求するようにデフォルト ルールを変更します。

ポリシーの構成手順は次のとおりです。

  1. Google 管理のシステム イメージを許可する新しいポリシー ファイルを作成します。evaluationModeREQUIRE_ATTESTATION を設定し、作成した認証者を参照するノードを requireAttestationsBy という名前で追加します。

    cat > /tmp/policy.yaml << EOM
        globalPolicyEvaluationMode: ENABLE
        defaultAdmissionRule:
          evaluationMode: REQUIRE_ATTESTATION
          enforcementMode: ENFORCED_BLOCK_AND_AUDIT_LOG
          requireAttestationsBy:
            - projects/${PROJECT_ID}/attestors/${ATTESTOR}
        name: projects/${PROJECT_ID}/policy
    EOM
    
  2. ポリシー YAML ファイルを Binary Authorization にインポートします。

    gcloud container binauthz policy import /tmp/policy.yaml
    

ポリシーの構成の詳細については、CLI を使用したポリシーの構成をご覧ください。

ポリシーをテストする

上記で構成したポリシーをテストするには、サンプル コンテナ イメージをクラスタにデプロイします。必要な証明書が作成されていないため、ポリシーによってデプロイがブロックされます。

このチュートリアルでは、Container Registry のパス gcr.io/google-samples/hello-app にあるサンプル イメージを使用できます。これは Google が作成した公開コンテナ イメージで、Hello, World! サンプル アプリケーションが含まれています。

まず、イメージをデプロイします。

kubectl run hello-server --image gcr.io/google-samples/hello-app:1.0 --port 8080

次に、Binary Authorization でデプロイがブロックされたことを確認します。

kubectl get pods

このコマンドを実行すると、イメージがデプロイされなかったことを示す次のメッセージが出力されます。

No resources found.

次のコマンドによってデプロイの詳細を確認できます。

kubectl get event --template \
'{{range.items}}{{"\033[0;36m"}}{{.reason}}:{{"\033[0m"}}\{{.message}}{{"\n"}}{{end}}'

ポリシーによってデプロイが拒否されたことがわかります。

FailedCreate: Error creating: pods "hello-server-579859fb5b-hjvnr" is forbidden: image policy webhook backend denied one or more images: Denied by default admission rule. Denied by Attestation Authority. Image gcr.io/google-samples/hello-app:1.0 denied by projects/example-project/attestors/test-attestor: No attestations found

デプロイを削除して次の手順に進みます。

kubectl delete deployment hello-server

証明書を作成する

証明書は、GKE が関連するコンテナ イメージのデプロイを許可したことを証明する署名者によって作成されるデジタル ドキュメントです。証明書を作成するプロセスを「イメージに署名する」という場合があります。署名者は人の場合もあれば、コンテナ イメージのビルド時に実行される自動プロセスである場合もあります。署名は、鍵ペアの秘密鍵を使用して作成されます。デプロイ時に、Binary Authorization 施行者は認証者の公開鍵を使用して証明書の署名を検証します。

このチュートリアルでは、イメージのデプロイが承認されていることのみを証明します。

証明書の作成手順は次のとおりです。

  1. イメージのレジストリパスとダイジェストを格納する変数を設定します。

    IMAGE_PATH="gcr.io/google-samples/hello-app"
    IMAGE_DIGEST="sha256:c62ead5b8c15c231f9e786250b07909daf6c266d0fcddd93fea882eb722c3be4"
    
  2. 証明書ペイロードを生成します。

    gcloud container binauthz create-signature-payload \
    --artifact-url=${IMAGE_PATH}@${IMAGE_DIGEST} > /tmp/generated_payload.json
    

    ペイロード JSON ファイルの内容は次のとおりです。

    {
      "critical": {
        "identity": {
          "docker-reference": "gcr.io/google-samples/hello-app"
        },
        "image": {
          "docker-manifest-digest": "sha256:c62ead5b8c15c231f9e786250b07909daf6c266d0fcddd93fea
    882eb722c3be4"
        },
        "type": "Google cloud binauthz container signature"
      }
    }
    
  3. PKIX 秘密鍵でペイロードに署名し、署名ファイルを出力します。

    openssl dgst -sha256 -sign ${PRIVATE_KEY_FILE} /tmp/generated_payload.json > /tmp/ec_signature
    

    署名ファイルは、上記で作成したペイロード JSON ファイルのデジタル署名バージョンです。

  4. 証明書を作成します。

    gcloud container binauthz attestations create \
        --artifact-url="${IMAGE_PATH}@${IMAGE_DIGEST}" \
        --attestor="projects/${PROJECT_ID}/attestors/${ATTESTOR}" \
        --signature-file=/tmp/ec_signature \
        --public-key-id="${PUBLIC_KEY_ID}"
    

    または、次のように入力して、指定された認証者が証明書を検証できることを検証します。

    gcloud alpha container binauthz attestations create \
        --artifact-url="${IMAGE_PATH}@${IMAGE_DIGEST}" \
        --attestor="projects/${PROJECT_ID}/attestors/${ATTESTOR}" \
        --signature-file=/tmp/ec_signature \
        --public-key-id="${PUBLIC_KEY_ID}" \
        --validate
    

    PUBLIC_KEY_ID は、上記の PKIX 鍵ペアを生成するにある公開鍵 ID です。

  5. 証明書が作成されたことを確認します。

    gcloud container binauthz attestations list \
        --attestor=$ATTESTOR --attestor-project=$PROJECT_ID
    

証明書の作成の詳細については、証明書の作成をご覧ください。

ポリシーを再テストする

クラスタにサンプル コンテナ イメージをデプロイして、ポリシーを再度テストします。今回は、Binary Authorization はイメージパスとダイジェストの両方を使用して証明書を検索するため、1.0latest などのタグではなく、ダイジェストを使用してイメージをデプロイする必要があります。ここでは、必要な証明書が作成されたため、Binary Authorization はイメージのデプロイを許可します。

イメージのデプロイ手順は次のとおりです。

kubectl run hello-server --image ${IMAGE_PATH}@${IMAGE_DIGEST} --port 8080

イメージがデプロイされたことを確認するには:

kubectl get pods

このコマンドを実行すると、デプロイが成功したことを示す次のようなメッセージが出力されます。

NAME                            READY     STATUS    RESTARTS   AGE
hello-server-579859fb5b-h2k8s   1/1       Running   0          1m

クリーンアップ

このチュートリアルで使用したリソースについて、Google Cloud Platform アカウントに課金されないようにする手順は次のとおりです。

GKE で作成したクラスタを削除します。

gcloud container clusters delete \
    --zone=us-central1-a \
    test-cluster

次のステップ