このガイドでは、互いに自身の給与額を明らかにすることなく、Alex と Bola がどちらの給与がより高額であるかを調べる必要があります。機密データを保護するために Confidential Space を使用することに決め、次の ロールを担当することにしました。
Alex: データ共同編集者、ワークロード作成者
Bola: データ共同編集者、ワークロード オペレーター
このガイドでは、できるだけわかりやすくするために、このような配置にしています。ただし、ワークロードの作成者とオペレーターが、データ共同編集者から完全に独立した状態にし、必要な数の共同編集者を配置することが可能です。
始める前に
このガイドでは、1 つの組織で複数のプロジェクトにアクセスできる単一のアカウントを使用して、プロセス全体を体験できる Confidential Space のシナリオについて説明します。本番環境デプロイでは、共同編集者、ワークロードの作成者、ワークロードのオペレーターは、それぞれ個別のアカウントと独自のプロジェクトを個別の組織に持ち、互いにアクセスできず、機密データを別々に保持します。
Confidential Space は Google Cloudのさまざまなサービスとやり取りして、結果を出すことができます。サービスには以下のものがありますが、これらに限定されません。
このガイドでは、これらの機能の基本的な知識があることを前提としています。
必要なロール
このガイドで必要になる権限を取得するには、プロジェクトに対する次の IAM ロールを付与するよう管理者に依頼してください。
- データ共同編集者(Alex と Bola)の Cloud KMS 管理者(
roles/cloudkms.admin)。 - データ共同編集者(Alex と Bola)の IAM Workload Identity プール管理者(
roles/iam.workloadIdentityPoolAdmin)。 - データ共同編集者(Alex と Bola)の Service Usage 管理者(
roles/serviceusage.serviceUsageAdmin)。 - データ共同編集者(Alex と Bola)とワークロード オペレーター(Bola)のストレージ管理者(
roles/storage.admin)。 - ワークロード オペレーター(Bola)のサービス アカウント管理者(
roles/iam.serviceAccountAdmin)。 - ワークロード オペレーター(Bola)の Compute 管理者(
roles/compute.admin)。 - ワークロード オペレーター(Bola)のセキュリティ管理者(
roles/securityAdmin)。 - ワークロード作成者(Alex)の Artifact Registry 管理者(
roles/artifactregistry.admin)。
ロールの付与の詳細については、プロジェクト、フォルダ、組織へのアクセスを管理するをご覧ください。
必要な権限は、カスタム ロールや他の事前定義 ロールから取得することもできます。
データ共同編集者のリソースを設定する
Alex と Bola の両方に、次のリソースを含む独立したプロジェクトが必要です。
機密データ自体。
データを暗号化して機密性を保持するための暗号鍵。
暗号化されたデータを保存する Cloud Storage バケット。
Workload Identity プール。機密データを処理するワークロードは、このプールを使用してプライベート データにアクセスして復号します。
開始するには、 Google Cloud コンソールに移動します。
Alex のリソースを設定する
Alex のリソースを設定するには、次の手順を完了します。
- [Cloud Shell をアクティブにする] をクリックします。
-
Cloud Shell で次のコマンドを入力して、Alex のプロジェクトを作成します。ALEX_PROJECT_ID は任意の名前に置き換えます。
gcloud projects create ALEX_PROJECT_ID -
新しく作成したプロジェクトに切り替えます。
gcloud config set project ALEX_PROJECT_ID -
データ 共同編集者およびワークロード作成者として、Alex が必要とする API を有効にします。
gcloud services enable \ artifactregistry.googleapis.com \ cloudkms.googleapis.com \ iamcredentials.googleapis.com -
Cloud Key Management Service でキーリングと暗号鍵を作成します。
gcloud kms keyrings create ALEX_KEYRING_NAME \ --location=global gcloud kms keys create ALEX_KEY_NAME \ --location=global \ --keyring=ALEX_KEYRING_NAME \ --purpose=encryption -
新しく 作成された暗号鍵を使用してデータを暗号化できるように、Alex に
cloudkms.cryptoKeyEncrypterロールを付与します。gcloud kms keys add-iam-policy-binding \ "projects/ALEX_PROJECT_ID/locations/global/\ keyRings/ALEX_KEYRING_NAME/\ cryptoKeys/ALEX_KEY_NAME" \ --member=user:$(gcloud config get-value account) \ --role=roles/cloudkms.cryptoKeyEncrypter -
Alex の Workload Identity プールを作成します。
gcloud iam workload-identity-pools create ALEX_POOL_NAME \ --location=global -
入力データ用の Cloud Storage バケットと、結果を保存するためのバケットを 作成します。
gcloud storage buckets create gs://ALEX_INPUT_BUCKET_NAME \ gs://ALEX_OUTPUT_BUCKET_NAME -
Alex の給与のみを数値として含むファイルを作成します。
echo 123456 > ALEX_SALARY.txt -
ファイルを暗号化して、Alex の バケットにアップロードします。
gcloud kms encrypt \ --ciphertext-file="ALEX_ENCRYPTED_SALARY_FILE" \ --plaintext-file="ALEX_SALARY.txt" \ --key="projects/ALEX_PROJECT_ID/locations/global/\ keyRings/ALEX_KEYRING_NAME/\ cryptoKeys/ALEX_KEY_NAME"gcloud storage cp ALEX_ENCRYPTED_SALARY_FILE gs://ALEX_INPUT_BUCKET_NAME
Bola のリソースを設定する
Bola のリソースを設定するには、次の手順を完了します。
-
Cloud Shell で次のコマンドを入力して、Bola のプロジェクトを作成します。BOLA_PROJECT_ID は任意の名前に置き換えます。
gcloud projects create BOLA_PROJECT_ID -
新しく作成したプロジェクトに切り替えます。
gcloud config set project BOLA_PROJECT_ID -
データ共同編集者およびワークロード オペレーターとして、Bola が必要とする API を有効にします。
gcloud services enable \ cloudkms.googleapis.com \ compute.googleapis.com \ confidentialcomputing.googleapis.com \ iamcredentials.googleapis.com -
Cloud Key Management Service でキーリングと暗号鍵を作成します。
gcloud kms keyrings create BOLA_KEYRING_NAME \ --location=global gcloud kms keys create BOLA_KEY_NAME \ --location=global \ --keyring=BOLA_KEYRING_NAME \ --purpose=encryption -
新しく作成された暗号鍵を使用してデータを暗号化できるように、Bola に
cloudkms.cryptoKeyEncrypterロールを付与します。gcloud kms keys add-iam-policy-binding \ "projects/BOLA_PROJECT_ID/locations/global/\ keyRings/BOLA_KEYRING_NAME/\ cryptoKeys/BOLA_KEY_NAME" \ --member=user:$(gcloud config get-value account) \ --role=roles/cloudkms.cryptoKeyEncrypter -
Bola の Workload Identity プールを作成します。
gcloud iam workload-identity-pools create BOLA_POOL_NAME \ --location=global -
入力データ用の Cloud Storage バケットと、結果を保存するためのバケットを 作成します。
gcloud storage buckets create gs://BOLA_INPUT_BUCKET_NAME \ gs://BOLA_OUTPUT_BUCKET_NAME -
Bola の給与のみを数値として含むファイルを作成します。
echo 111111 > BOLA_SALARY.txt -
ファイルを暗号化して、Bola の バケットにアップロードします。
gcloud kms encrypt \ --ciphertext-file="BOLA_ENCRYPTED_SALARY_FILE" \ --plaintext-file="BOLA_SALARY.txt" \ --key="projects/BOLA_PROJECT_ID/locations/global/\ keyRings/BOLA_KEYRING_NAME/\ cryptoKeys/BOLA_KEY_NAME"gcloud storage cp BOLA_ENCRYPTED_SALARY_FILE gs://BOLA_INPUT_BUCKET_NAME
ワークロードのサービス アカウントを作成する
このガイドでは、Bola がワークロードを操作して実行しますが、サードパーティを含む誰でもこれらのロールを引き継ぐことができます。ワークロードを実行するために Bola が作成する VM インスタンスには、証明トークンを生成し、ログを書き込み、Alex と Bola の暗号化されたデータを読み取り、特定の結果を Cloud Storage バケットに書き込む権限を持つサービス アカウントが接続されています。
Bola のプロジェクトで次の手順を完了して、サービス アカウントを設定します。
ワークロードを実行するサービス アカウントを作成します。
gcloud iam service-accounts create WORKLOAD_SERVICE_ACCOUNT_NAME後でサービス アカウントをワークロード VM に接続できるように、Bola に
iam.serviceAccountUserロールを付与します。gcloud iam service-accounts add-iam-policy-binding \ WORKLOAD_SERVICE_ACCOUNT_NAME@BOLA_PROJECT_ID.iam.gserviceaccount.com \ --member=user:$(gcloud config get-value account) \ --role=roles/iam.serviceAccountUser証明トークンをリクエストできるように、サービス アカウントに
confidentialcomputing.workloadUserロールを付与します。gcloud projects add-iam-policy-binding BOLA_PROJECT_ID \ --member=serviceAccount:WORKLOAD_SERVICE_ACCOUNT_NAME@BOLA_PROJECT_ID.iam.gserviceaccount.com \ --role=roles/confidentialcomputing.workloadUserサービス アカウントに Cloud Logging にログを書き込むための
logging.logWriterロールを付与して、ワークロードの進捗状況を確認できるようにします。gcloud projects add-iam-policy-binding BOLA_PROJECT_ID \ --member=serviceAccount:WORKLOAD_SERVICE_ACCOUNT_NAME@BOLA_PROJECT_ID.iam.gserviceaccount.com \ --role=roles/logging.logWriterサービス アカウントに、暗号化されたデータを含む Alex と Bola のバケットに対する読み取りアクセス権と、各結果バケットへの書き込みアクセス権を付与します。
gcloud storage buckets add-iam-policy-binding gs://ALEX_INPUT_BUCKET_NAME \ --member=serviceAccount:WORKLOAD_SERVICE_ACCOUNT_NAME@BOLA_PROJECT_ID.iam.gserviceaccount.com \ --role=roles/storage.objectViewer gcloud storage buckets add-iam-policy-binding gs://ALEX_OUTPUT_BUCKET_NAME \ --member=serviceAccount:WORKLOAD_SERVICE_ACCOUNT_NAME@BOLA_PROJECT_ID.iam.gserviceaccount.com \ --role=roles/storage.objectAdmin gcloud storage buckets add-iam-policy-binding gs://BOLA_INPUT_BUCKET_NAME \ --member=serviceAccount:WORKLOAD_SERVICE_ACCOUNT_NAME@BOLA_PROJECT_ID.iam.gserviceaccount.com \ --role=roles/storage.objectViewer gcloud storage buckets add-iam-policy-binding gs://BOLA_OUTPUT_BUCKET_NAME \ --member=serviceAccount:WORKLOAD_SERVICE_ACCOUNT_NAME@BOLA_PROJECT_ID.iam.gserviceaccount.com \ --role=roles/storage.objectAdminこれは、アクセス権を付与するユーザーが、操作対象の Cloud Storage バケットを含むプロジェクトのストレージ管理者(
roles/storage.admin)ロールを持っていることを前提としています。
ワークロードを作成する
このガイドでは、Alex はワークロードのコードを指定し、コードを格納する Docker イメージをビルドしていますが、サードパーティを含む誰でもこれらのロールを引き継ぐことができます。
Alex は、ワークロード用に次のリソースを作成する必要があります。
ワークロードを実行するコード。
ワークロードを実行するサービス アカウントがアクセスできる Artifact Registry の Docker リポジトリ。
ワークロード コードを格納して実行する Docker イメージ。
リソースを作成して設定するには、Alex のプロジェクトで次の手順を完了します。
Alex のプロジェクトに切り替えます。
gcloud config set project ALEX_PROJECT_ID[エディタを開く] をクリックして Cloud Shell エディタを開き、
salary.goという名前の新しいファイルを作成します。次のコードをファイルにコピーして保存します。package main import ( "context" "fmt" "io" "os" "strconv" "strings" "time" kms "cloud.google.com/go/kms/apiv1" kmspb "cloud.google.com/go/kms/apiv1/kmspb" "cloud.google.com/go/storage" "google.golang.org/api/option" ) type collaborator struct { name string wipName string keyName string inputBucket string inputFile string outputBucket string } // The following values are pulled from environment variables // Alex's values var collaborator1Name string = os.Getenv("COLLAB_1_NAME") // Alex's name var collaborator1EncryptedSalaryFileName string = os.Getenv("COLLAB_1_ENCRYPTED_SALARY") // The name of Alex's encrypted salary file. var collaborator1BucketInputName string = os.Getenv("COLLAB_1_INPUT_BUCKET") // The name of the storage bucket that contains Alex's encrypted salary file. var collaborator1BucketOutputName string = os.Getenv("COLLAB_1_OUTPUT_BUCKET") // The name of the storage bucket to store Alex's results in. var collaborator1KMSKeyringName string = os.Getenv("COLLAB_1_KEYRING_NAME") // Alex's Key Management Service key ring. var collaborator1KMSKeyName string = os.Getenv("COLLAB_1_KEY_NAME") // Alex's Key Management Service key. var collaborator1ProjectName string = os.Getenv("COLLAB_1_PROJECT_ID") // Alex's project ID. var collaborator1ProjectNumber string = os.Getenv("COLLAB_1_PROJECT_NUMBER") // Alex's project number. var collaborator1PoolName string = os.Getenv("COLLAB_1_POOL_NAME") // Alex's workload identity pool name. // Bola's values var collaborator2Name string = os.Getenv("COLLAB_2_NAME") // Bola's name var collaborator2EncryptedSalaryFileName string = os.Getenv("COLLAB_2_ENCRYPTED_SALARY") // The name of Bola's encrypted salary file. var collaborator2BucketInputName string = os.Getenv("COLLAB_2_INPUT_BUCKET") // The name of the storage bucket that contains Bola's encrypted salary file. var collaborator2BucketOutputName string = os.Getenv("COLLAB_2_OUTPUT_BUCKET") // The name of the storage bucket to store Bola's results in. var collaborator2KMSKeyringName string = os.Getenv("COLLAB_2_KEYRING_NAME") // Bola's Key Management Service key ring. var collaborator2KMSKeyName string = os.Getenv("COLLAB_2_KEY_NAME") // Bola's Key Management Service key. var collaborator2ProjectName string = os.Getenv("COLLAB_2_PROJECT_ID") // Bola's project ID. var collaborator2ProjectNumber string = os.Getenv("COLLAB_2_PROJECT_NUMBER") // Bola's project number. var collaborator2PoolName string = os.Getenv("COLLAB_2_POOL_NAME") // Bola's workload identity pool name. var collaborators = [2]collaborator{ { collaborator1Name, "projects/" + collaborator1ProjectNumber + "/locations/global/workloadIdentityPools/" + collaborator1PoolName + "/providers/attestation-verifier", "projects/" + collaborator1ProjectName + "/locations/global/keyRings/" + collaborator1KMSKeyringName + "/cryptoKeys/" + collaborator1KMSKeyName, collaborator1BucketInputName, collaborator1EncryptedSalaryFileName, collaborator1BucketOutputName, }, { collaborator2Name, "projects/" + collaborator2ProjectNumber + "/locations/global/workloadIdentityPools/" + collaborator2PoolName + "/providers/attestation-verifier", "projects/" + collaborator2ProjectName + "/locations/global/keyRings/" + collaborator2KMSKeyringName + "/cryptoKeys/" + collaborator2KMSKeyName, collaborator2BucketInputName, collaborator2EncryptedSalaryFileName, collaborator2BucketOutputName, }, } const credentialConfig = `{ "type": "external_account", "audience": "//iam.googleapis.com/%s", "subject_token_type": "urn:ietf:params:oauth:token-type:jwt", "token_url": "https://sts.googleapis.com/v1/token", "credential_source": { "file": "/run/container_launcher/attestation_verifier_claims_token" } }` func main() { fmt.Println("workload started") ctx := context.Background() storageClient, err := storage.NewClient(ctx) // Using the default credential on the Compute Engine VM if err != nil { panic(err) } // Get and decrypt s0, err := getSalary(ctx, storageClient, collaborators[0]) if err != nil { panic(err) } s1, err := getSalary(ctx, storageClient, collaborators[1]) if err != nil { panic(err) } res := "" if s0 > s1 { res = fmt.Sprintf("%s earns more!\n", collaborators[0].name) } else if s1 > s0 { res = fmt.Sprintf("%s earns more!\n", collaborators[1].name) } else { res = "You earn the same!\n" } now := time.Now() for _, cw := range collaborators { outputWriter := storageClient.Bucket(cw.outputBucket).Object(fmt.Sprintf("comparison-result-%d", now.Unix())).NewWriter(ctx) _, err = outputWriter.Write([]byte(res)) if err != nil { fmt.Printf("Could not write: %v", err) panic(err) } if err = outputWriter.Close(); err != nil { fmt.Printf("Could not close: %v", err) panic(err) } } } func getSalary(ctx context.Context, storageClient *storage.Client, cw collaborator) (float64, error) { encryptedBytes, err := getFile(ctx, storageClient, cw.inputBucket, cw.inputFile) if err != nil { return 0.0, err } decryptedByte, err := decryptByte(ctx, cw.keyName, cw.wipName, encryptedBytes) if err != nil { return 0.0, err } decryptedNumber := strings.TrimSpace(string(decryptedByte)) num, err := strconv.ParseFloat(decryptedNumber, 64) if err != nil { return 0.0, err } return num, nil } func decryptByte(ctx context.Context, keyName, wippro string, encryptedData []byte) ([]byte, error) { cc := fmt.Sprintf(credentialConfig, wippro) kmsClient, err := kms.NewKeyManagementClient(ctx, option.WithCredentialsJSON([]byte(cc))) if err != nil { return nil, fmt.Errorf("creating a new KMS client with federated credentials: %w", err) } decryptRequest := &kmspb.DecryptRequest{ Name: keyName, Ciphertext: encryptedData, } decryptResponse, err := kmsClient.Decrypt(ctx, decryptRequest) if err != nil { return nil, fmt.Errorf("could not decrypt ciphertext: %w", err) } return decryptResponse.Plaintext, nil } func getFile(ctx context.Context, c *storage.Client, bucketName string, objPath string) ([]byte, error) { bucketHandle := c.Bucket(bucketName) objectHandle := bucketHandle.Object(objPath) objectReader, err := objectHandle.NewReader(ctx) if err != nil { return nil, err } defer objectReader.Close() s, err := io.ReadAll(objectReader) if err != nil { return nil, err } return s, nil }すべての関係者がソースコードを読み取り、監査していることを確認します。
Cloud Shell エディタで、次の内容を含む
Dockerfileという名前のファイルを作成します。# Compile the provided Go code to a statically linked binary FROM golang:latest AS build WORKDIR /build COPY salary.go . RUN go mod init salary RUN go get cloud.google.com/go/kms/apiv1 cloud.google.com/go/storage google.golang.org/api/option google.golang.org/genproto/googleapis/cloud/kms/v1 RUN CGO_ENABLED=0 go build -trimpath # Build the workload container image FROM alpine:latest AS run WORKDIR /test COPY --from=build /build/salary /test/salary ENTRYPOINT ["/test/salary"] CMD [] # Allow the workload to access the following environment variables LABEL "tee.launch_policy.allow_env_override"="\ COLLAB_1_NAME,\ COLLAB_2_NAME,\ COLLAB_1_ENCRYPTED_SALARY,\ COLLAB_2_ENCRYPTED_SALARY,\ COLLAB_1_INPUT_BUCKET,\ COLLAB_2_INPUT_BUCKET,\ COLLAB_1_OUTPUT_BUCKET,\ COLLAB_2_OUTPUT_BUCKET,\ COLLAB_1_KEYRING_NAME,\ COLLAB_2_KEYRING_NAME,\ COLLAB_1_KEY_NAME,\ COLLAB_2_KEY_NAME,\ COLLAB_1_PROJECT_ID,\ COLLAB_2_PROJECT_ID,\ COLLAB_1_PROJECT_NUMBER,\ COLLAB_2_PROJECT_NUMBER,\ COLLAB_1_POOL_NAME,\ COLLAB_2_POOL_NAME"この
Dockerfileは、マルチステージ ビルドを使用して、まず Go コードをコンパイルし、そのコードのコンパイル済みバージョンを最終的なワークロード コンテナにコピーします。また、そのワークロード コンテナで特定の環境変数を使用することもできます。これらの環境変数の値は、後でワークロードの実行に必要な特定のリソースにマッピングされます。[ターミナルを開く] をクリックして Cloud Shell に戻るか、[表示] メニューから Cloud Shell エディタに組み込まれているターミナルを呼び出します。
Artifact Registry で Docker リポジトリを作成します。
gcloud artifacts repositories create REPOSITORY_NAME \ --repository-format=docker \ --location=usワークロードを実行するサービス アカウントに Artifact Registry の読み取り(
roles/artifactregistry.reader)ロールを付与し、リポジトリから読み取れるようにします。gcloud artifacts repositories add-iam-policy-binding REPOSITORY_NAME \ --location=us \ --member=serviceAccount:WORKLOAD_SERVICE_ACCOUNT_NAME@BOLA_PROJECT_ID.iam.gserviceaccount.com \ --role=roles/artifactregistry.readerus-docker.pkg.devドメイン名を含めるように Docker 認証情報を更新します。gcloud auth configure-docker us-docker.pkg.devターミナルで次のコマンドを入力して、
Dockerfileから Docker イメージを作成します。docker build -t \ "us-docker.pkg.dev/ALEX_PROJECT_ID/\ REPOSITORY_NAME/WORKLOAD_CONTAINER_NAME:latest" .Docker イメージを Artifact Registry に push します。
docker push \ us-docker.pkg.dev/ALEX_PROJECT_ID/REPOSITORY_NAME/WORKLOAD_CONTAINER_NAMEDocker の push レスポンスには、イメージの SHA256 ダイジェストが一覧表示されます。これは、後でワークロードを承認するために必要になります。ダイジェストは次の例のようになります。
sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855イメージ ダイジェスト(
sha256:接頭辞を含む)を、参照できる場所にコピーします。次のコードサンプルにダイジェストを入力して、このガイドの残りのコードサンプルに必要な値を事前入力することもできます。WORKLOAD_CONTAINER_IMAGE_DIGESTすべての関係者が Docker イメージを監査し、使用を許可する前に信頼できることを確認するようにしてください。
ワークロードを承認する
両当事者がワークロードを承認したら、Alex と Bola は Google Cloud Attestation を プロバイダとして Workload Identity プールに追加する必要があります。プロバイダは、使用する証明サービスと、Alex または Bola のデータを操作できるようにするためにワークロードが一致する必要があるプロパティを指定します。悪意のある行為者が Docker イメージを変更したり、別の測定プロパティを変更したりすると、ワークロードはアクセスを拒否されます。
このガイドでは、 属性マッピング を使用して、イメージ ダイジェストに基づいてワークロードに直接リソース アクセスを提供します。 ただし、状況によっては、サービス アカウントの権限借用を使用してリソースにアクセスすることをおすすめします。詳細については、 外部ワークロードのアクセス をご覧ください。
必要な条件で Alex と Bola のプロバイダを設定するには、次の手順を完了します。
次のコマンドを入力して、Alex のプロバイダを作成します。
gcloud iam workload-identity-pools providers create-oidc attestation-verifier \ --location=global \ --workload-identity-pool=ALEX_POOL_NAME \ --issuer-uri="https://confidentialcomputing.googleapis.com/" \ --allowed-audiences="https://sts.googleapis.com" \ --attribute-mapping="google.subject=\"gcpcs\ ::\"+assertion.submods.container.image_digest+\"\ ::\"+assertion.submods.gce.project_number+\"\ ::\"+assertion.submods.gce.instance_id,\ attribute.image_digest=assertion.submods.container.image_digest" \ --attribute-condition="assertion.swname == 'CONFIDENTIAL_SPACE'"次のコマンドで Alex のプロジェクト番号を取得します。
gcloud projects describe ALEX_PROJECT_ID --format="value(projectNumber)"Alex のプロバイダで定義されたフェデレーション ID に
cloudkms.cryptoKeyDecrypterロールを付与し、image_digest属性を指定して、指定されたダイジェストを持つワークロード コンテナのみが KMS 鍵を復号できるようにします。gcloud kms keys add-iam-policy-binding \ "projects/ALEX_PROJECT_ID/locations/global/\ keyRings/ALEX_KEYRING_NAME/\ cryptoKeys/ALEX_KEY_NAME" \ --member="principalSet://iam.googleapis.com/\ projects/ALEX_PROJECT_NUMBER/locations/global/\ workloadIdentityPools/ALEX_POOL_NAME/\ attribute.image_digest/WORKLOAD_CONTAINER_IMAGE_DIGEST" \ --role=roles/cloudkms.cryptoKeyDecrypterBola のプロジェクトに切り替えます。
gcloud config set project BOLA_PROJECT_ID次のコマンドを入力して、Bola のプロバイダを作成します。
gcloud iam workload-identity-pools providers create-oidc attestation-verifier \ --location=global \ --workload-identity-pool=BOLA_POOL_NAME \ --issuer-uri="https://confidentialcomputing.googleapis.com/" \ --allowed-audiences="https://sts.googleapis.com" \ --attribute-mapping="google.subject=\"gcpcs\ ::\"+assertion.submods.container.image_digest+\"\ ::\"+assertion.submods.gce.project_number+\"\ ::\"+assertion.submods.gce.instance_id,\ attribute.image_digest=assertion.submods.container.image_digest" \ --attribute-condition="assertion.swname == 'CONFIDENTIAL_SPACE'"次のコマンドで Bola のプロジェクト番号を取得します。
gcloud projects describe BOLA_PROJECT_ID --format="value(projectNumber)"Bola のプロバイダで定義されたフェデレーション ID に
cloudkms.cryptoKeyDecrypterロールを付与し、image_digest属性を指定して、指定されたダイジェストを持つワークロード コンテナのみが KMS 鍵を復号できるようにします。gcloud kms keys add-iam-policy-binding \ "projects/BOLA_PROJECT_ID/locations/global/\ keyRings/BOLA_KEYRING_NAME/\ cryptoKeys/BOLA_KEY_NAME" \ --member="principalSet://iam.googleapis.com/\ projects/BOLA_PROJECT_NUMBER/locations/global/\ workloadIdentityPools/BOLA_POOL_NAME/\ attribute.image_digest/WORKLOAD_CONTAINER_IMAGE_DIGEST" \ --role=roles/cloudkms.cryptoKeyDecrypter
ワークロードをテストする
プロバイダが Alex と Bola の Workload Identity プールと必要なリソースの両方に追加されたら、ワークロード オペレーターがワークロードをテストします。
ワークロードをテストするには、次のプロパティを持つ新しい Confidential VM インスタンスを Bola のプロジェクトに作成します。
A サポート対象の構成 with AMD SEV、Intel TDX、または NVIDIA Confidential Computing を使用した Intel TDX を使用する。
セキュアブートが有効になっています。
トラブルシューティングを容易にするために、 Confidential Space デバッグ イメージに基づく OS 。
Alex が以前に作成した Docker イメージへの参照 。これは Confidential Space イメージの上に読み込まれます。
STDOUTとSTDERRは Cloud Logging とシリアル コンソールの両方にリダイレクトされます。ワークロードに必要なリソースの詳細が環境変数として設定されます。
Bola の Cloud Shell で次のコマンドを入力して、ワークロードをテストします。
gcloud compute instances create WORKLOAD_VM_2_NAME \
--confidential-compute-type=SEV \
--shielded-secure-boot \
--scopes=cloud-platform \
--zone=us-west1-b \
--maintenance-policy=MIGRATE \
--min-cpu-platform="AMD Milan" \
--image-project=confidential-space-images \
--image-family=confidential-space-debug \
--service-account=WORKLOAD_SERVICE_ACCOUNT_NAME@BOLA_PROJECT_ID.iam.gserviceaccount.com \
--metadata="^~^tee-image-reference=us-docker.pkg.dev/\
ALEX_PROJECT_ID/REPOSITORY_NAME/WORKLOAD_CONTAINER_NAME:latest\
~tee-container-log-redirect=true\
~tee-env-COLLAB_1_NAME=Alex\
~tee-env-COLLAB_2_NAME=Bola\
~tee-env-COLLAB_1_ENCRYPTED_SALARY=ALEX_ENCRYPTED_SALARY_FILE\
~tee-env-COLLAB_2_ENCRYPTED_SALARY=BOLA_ENCRYPTED_SALARY_FILE\
~tee-env-COLLAB_1_INPUT_BUCKET=ALEX_INPUT_BUCKET_NAME\
~tee-env-COLLAB_2_INPUT_BUCKET=BOLA_INPUT_BUCKET_NAME\
~tee-env-COLLAB_1_OUTPUT_BUCKET=ALEX_OUTPUT_BUCKET_NAME\
~tee-env-COLLAB_2_OUTPUT_BUCKET=BOLA_OUTPUT_BUCKET_NAME\
~tee-env-COLLAB_1_KEYRING_NAME=ALEX_KEYRING_NAME\
~tee-env-COLLAB_2_KEYRING_NAME=BOLA_KEYRING_NAME\
~tee-env-COLLAB_1_KEY_NAME=ALEX_KEY_NAME\
~tee-env-COLLAB_2_KEY_NAME=BOLA_KEY_NAME\
~tee-env-COLLAB_1_PROJECT_ID=ALEX_PROJECT_ID\
~tee-env-COLLAB_2_PROJECT_ID=BOLA_PROJECT_ID\
~tee-env-COLLAB_1_PROJECT_NUMBER=ALEX_PROJECT_NUMBER\
~tee-env-COLLAB_2_PROJECT_NUMBER=BOLA_PROJECT_NUMBER\
~tee-env-COLLAB_1_POOL_NAME=ALEX_POOL_NAME\
~tee-env-COLLAB_2_POOL_NAME=BOLA_POOL_NAME"
進行状況を表示
Bola のプロジェクトでワークロードの進行状況を確認するには、[ログ エクスプローラ] に移動します。
Confidential Space のログエントリのみを表示するには、次の ログのフィールドでフィルタします(使用可能な場合)。
リソースタイプ: VM インスタンス
インスタンス ID: VM のインスタンス ID
ログ名: confidential-space-launcher
ログを更新するには、 [現在の位置に移動] をクリックします。以前の結果までスクロールしてから、ログの末尾まで再度スクロールして、最新のエントリを読み込むこともできます。
結果を見る
ワークロード タスクが終了して 0 が返された場合、エラーが発生していないため、Alex と Bola の出力バケットで出力を確認します。
Alex のプロジェクトに切り替えます。
gcloud config set project ALEX_PROJECT_ID結果バケット内のすべてのファイルを一覧表示します。
gcloud storage ls gs://ALEX_OUTPUT_BUCKET_NAME一覧表示された最新のファイルを読み取ります。
ALEX_OUTPUT_CLOUD_STORAGE_PATHは、gs://を含むファイルのパスに置き換えます。gcloud storage cat ALEX_OUTPUT_CLOUD_STORAGE_PATHファイルが存在しない場合は、ワークロードをデバッグする必要があります。
Bola のプロジェクトに切り替えます。
gcloud config set project BOLA_PROJECT_ID結果バケット内のすべてのファイルを一覧表示します。
gcloud storage ls gs://BOLA_OUTPUT_BUCKET_NAME一覧表示された最新のファイルを読み取ります。
BOLA_RESULTS_CLOUD_STORAGE_PATHは、gs://を含むファイルのパスに置き換えます。gcloud storage cat BOLA_RESULTS_CLOUD_STORAGE_PATHファイルが存在しない場合は、ワークロードをデバッグする必要があります。
結果を正常に読み取ったら、VM インスタンスを停止します。
gcloud compute instances stop WORKLOAD_VM_2_NAME --zone=us-west1-b
ファイルを読み取ることで、Alex と Bola は互いに自身の給与について明らかにすることなく、2 人のうちいずれの給与がより高額であるかを調べることができます。
ワークロードをデバッグして再起動する
Confidential Space 環境には多くの部分があり、ワークロードが失敗する原因となる構成が誤っている可能性があります。
本番環境の Confidential Space イメージとは異なり、デバッグ イメージでは、ワークロードが完了した後も VM インスタンスが実行されたままになります。つまり、ログで問題の解決に十分な情報が得られない場合は、次のステップとして SSH 経由で VM インスタンスに接続してデバッグを続行します。
デバッグが完了したら、VM インスタンスを停止します。
gcloud compute instances stop WORKLOAD_VM_2_NAME --zone=us-west1-b
デバッグした環境に対してワークロードを実行するには、VM を再起動します。
gcloud compute instances start WORKLOAD_VM_2_NAME --zone=us-west1-b
本番環境用に環境を強化する
ワークロードのテストが正常に完了したら、本番環境デプロイ用に Confidential Space 環境を
強化します。Alex と Bola
は、プロバイダに
support_attributesアサーション
を追加して、本番環境の Confidential Space イメージがワークロードに使用されていることを確認する必要があります。
Alex のプロジェクトに切り替えます。
gcloud config set project ALEX_PROJECT_ID次のコマンドを入力して、Alex のプロバイダを更新します。
gcloud iam workload-identity-pools providers update-oidc attestation-verifier \ --location=global \ --workload-identity-pool=ALEX_POOL_NAME \ --issuer-uri="https://confidentialcomputing.googleapis.com/" \ --allowed-audiences="https://sts.googleapis.com" \ --attribute-mapping="google.subject=\"gcpcs\ ::\"+assertion.submods.container.image_digest+\"\ ::\"+assertion.submods.gce.project_number+\"\ ::\"+assertion.submods.gce.instance_id,\ attribute.image_digest=assertion.submods.container.image_digest" \ --attribute-condition="assertion.swname == 'CONFIDENTIAL_SPACE' \ && 'STABLE' in assertion.submods.confidential_space.support_attributes"Bola のプロジェクトに切り替えます。
gcloud config set project BOLA_PROJECT_ID次のコマンドを入力して、Bola のプロバイダを更新します。
gcloud iam workload-identity-pools providers update-oidc attestation-verifier \ --location=global \ --workload-identity-pool=BOLA_POOL_NAME \ --issuer-uri="https://confidentialcomputing.googleapis.com/" \ --allowed-audiences="https://sts.googleapis.com" \ --attribute-mapping="google.subject=\"gcpcs\ ::\"+assertion.submods.container.image_digest+\"\ ::\"+assertion.submods.gce.project_number+\"\ ::\"+assertion.submods.gce.instance_id,\ attribute.image_digest=assertion.submods.container.image_digest" \ --attribute-condition="assertion.swname == 'CONFIDENTIAL_SPACE' \ && 'STABLE' in assertion.submods.confidential_space.support_attributes"
本番環境ワークロードをデプロイする
Bola は、本番環境ワークロードを実行するために別の VM インスタンスを作成する必要があります。テスト ワークロードと比較して、次の点が異なります。
OS は本番環境の Confidential Space イメージに基づいています。SSH は無効になっており、ワークロードが完了すると VM インスタンスが停止します。
ロギングのリダイレクトが削除されます。機密情報が公開されない基本的なログのみが Cloud Logging に表示されます。
Bola の Cloud Shell で次のコマンドを入力して、本番環境ワークロードをデプロイします。
gcloud compute instances create WORKLOAD_VM_NAME \
--confidential-compute-type=SEV \
--shielded-secure-boot \
--scopes=cloud-platform \
--zone=us-west1-b \
--maintenance-policy=MIGRATE \
--image-project=confidential-space-images \
--image-family=confidential-space \
--service-account=WORKLOAD_SERVICE_ACCOUNT_NAME@BOLA_PROJECT_ID.iam.gserviceaccount.com \
--metadata="^~^tee-image-reference=us-docker.pkg.dev/\
ALEX_PROJECT_ID/REPOSITORY_NAME/WORKLOAD_CONTAINER_NAME:latest\
~tee-env-COLLAB_1_NAME=Alex\
~tee-env-COLLAB_2_NAME=Bola\
~tee-env-COLLAB_1_ENCRYPTED_SALARY=ALEX_ENCRYPTED_SALARY_FILE\
~tee-env-COLLAB_2_ENCRYPTED_SALARY=BOLA_ENCRYPTED_SALARY_FILE\
~tee-env-COLLAB_1_INPUT_BUCKET=ALEX_INPUT_BUCKET_NAME\
~tee-env-COLLAB_2_INPUT_BUCKET=BOLA_INPUT_BUCKET_NAME\
~tee-env-COLLAB_1_OUTPUT_BUCKET=ALEX_OUTPUT_BUCKET_NAME\
~tee-env-COLLAB_2_OUTPUT_BUCKET=BOLA_OUTPUT_BUCKET_NAME\
~tee-env-COLLAB_1_KEYRING_NAME=ALEX_KEYRING_NAME\
~tee-env-COLLAB_2_KEYRING_NAME=BOLA_KEYRING_NAME\
~tee-env-COLLAB_1_KEY_NAME=ALEX_KEY_NAME\
~tee-env-COLLAB_2_KEY_NAME=BOLA_KEY_NAME\
~tee-env-COLLAB_1_PROJECT_ID=ALEX_PROJECT_ID\
~tee-env-COLLAB_2_PROJECT_ID=BOLA_PROJECT_ID\
~tee-env-COLLAB_1_PROJECT_NUMBER=ALEX_PROJECT_NUMBER\
~tee-env-COLLAB_2_PROJECT_NUMBER=BOLA_PROJECT_NUMBER\
~tee-env-COLLAB_1_POOL_NAME=ALEX_POOL_NAME\
~tee-env-COLLAB_2_POOL_NAME=BOLA_POOL_NAME"
進行状況の確認方法と 結果の表示方法は、ワークロードをテストしたときと同じです。
本番環境ワークロードが完了すると、VM インスタンスが停止します。異なる結果を確認するには、給与を変更して再暗号化し、それぞれの Cloud Storage バケットに再アップロードしてから、VM インスタンスを再起動してワークロードを再度実行します。
gcloud compute instances start WORKLOAD_VM_NAME --zone=us-west1-b
クリーンアップ
このガイドで作成したリソースを削除するには、次の手順を完了します。
Alex のリソースをクリーンアップする
Alex のプロジェクトに切り替えます。
gcloud config set project ALEX_PROJECT_IDAlex の Workload Identity プールを削除します。
gcloud iam workload-identity-pools delete ALEX_POOL_NAME \ --location=globalAlex の Cloud Storage バケットを削除します。
gcloud storage rm gs://ALEX_INPUT_BUCKET_NAME \ gs://ALEX_OUTPUT_BUCKET_NAME --recursiveAlex の給与ファイル、Go コード、
Dockerfileを削除します。rm ALEX_SALARY.txt \ ALEX_ENCRYPTED_SALARY_FILE \ salary.go \ Dockerfile(省略可) Alex のプロジェクトをシャットダウンします。
Bola のリソースをクリーンアップする
Bola のプロジェクトに切り替えます。
gcloud config set project BOLA_PROJECT_IDテスト ワークフローを実行した VM を削除します。
gcloud compute instances delete WORKLOAD_VM_2_NAME --zone=us-west1-b本番環境ワークフローを実行した VM を削除します。
gcloud compute instances delete WORKLOAD_VM_NAME --zone=us-west1-bワークロードを実行したサービス アカウントを削除します。
gcloud iam service-accounts delete \ WORKLOAD_SERVICE_ACCOUNT_NAME@BOLA_PROJECT_ID.iam.gserviceaccount.comBola の Workload Identity プールを削除します。
gcloud iam workload-identity-pools delete BOLA_POOL_NAME \ --location=globalBola の Cloud Storage バケットを削除します。
gcloud storage rm gs://BOLA_INPUT_BUCKET_NAME \ gs://BOLA_OUTPUT_BUCKET_NAME --recursiveBola の給与ファイルを削除します。
rm BOLA_SALARY.txt \ BOLA_ENCRYPTED_SALARY_FILE(省略可)Bola の Cloud Key Management Service 鍵を無効化 または破棄します。
(省略可) Bola のプロジェクトをシャットダウンします。