このガイドでは、互いに自身の給与額を明らかにすることなく、Alex と Bola がどちらの給与がより高額であるかを調べる必要があります。データ機密性を維持するために Confidential Space を使用することに決定し、次のロールを担うことに同意します。
Alex: データ共同編集者、ワークロード作成者
Bola: データ共同編集者、ワークロード オペレーター
この配置は、このガイドをできるだけわかりやすくするために設計されています。ただし、ワークロードの作成者とオペレーターが、データ共同編集者から完全に独立した状態にし、必要な数の共同編集者を配置することが可能です。
始める前に
このガイドでは、1 つの組織で複数のプロジェクトにアクセスできる単一のアカウントを使用して、プロセス全体を体験できる Confidential Space のシナリオについて説明します。本番環境デプロイでは、共同編集者、ワークロードの作成者、ワークロードのオペレーターは、それぞれ個別のアカウントと独自のプロジェクトを個別の組織に持ち、互いにアクセスできず、機密データを別々に保持します。
Confidential Space は、 Google Cloudのさまざまなサービスとやり取りして、結果を出すことができます。サービスには以下のものがありますが、これらに限定されません。
このガイドでは、これらの機能のすべてを使用し、基本的な理解があることを前提としています。
必要な API
このガイドを完了するには、指定されたプロジェクトで次の API を有効にする必要があります。
API 名 | API タイトル | これらのプロジェクトで有効にする |
---|---|---|
cloudkms.googleapis.com |
Cloud KMS | データ共同編集者(Alex と Bola のプロジェクト) |
iamcredentials.googleapis.com |
IAM Service Account Credentials API |
データ共同編集者(Alex と Bola のプロジェクト) |
artifactregistry.googleapis.com |
Artifact Registry | ワークロード作成者(Alex のプロジェクト) |
compute.googleapis.com |
Compute Engine | ワークロード オペレーター(Bola のプロジェクト) |
confidentialcomputing.googleapis.com |
Confidential Computing | ワークロード オペレーター(Bola のプロジェクト) |
必要なロール
このガイドで必要になる権限を取得するには、プロジェクトに対する次の 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 cloudkms.googleapis.com artifactregistry.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_RESULTS_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 iamcredentials.googleapis.com compute.googleapis.com confidentialcomputing.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_RESULTS_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 の暗号化されたデータの読み取り、特定の結果バケットへの結果の書き込みを行う権限を持つサービス アカウントが関連付けられています。
Bola のプロジェクトで次の手順を完了して、サービス アカウントを設定します。
ワークロードを実行するサービス アカウントを作成します。
gcloud iam service-accounts create WORKLOAD_SERVICE_ACCOUNT_NAME
Bola に
iam.serviceAccountUser
ロールを付与します。これにより、後でワークロード VM にサービス アカウントを関連付けることができます。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://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://ALEX_RESULTS_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_RESULTS_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
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.reader
[エディタを開く] をクリックして Cloud Shell エディタを開き、
salary.go
という新しいファイルを作成します。ファイルに次のコードをコピーし、保存します。// READ ME FIRST: Before compiling, customize the details in the USER VARIABLES // SECTION starting at line 30. package main import ( "context" "fmt" "io" "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 outputFile string } // ============================ // START USER VARIABLES SECTION // You need to customize this section, replacing each const's value with your // own. // To get a project number, use the following command, and substitute // <PROJECT_ID> for the data collaborator's project ID. // gcloud projects describe <PROJECT_ID> --format="value(projectNumber)" // Alex's values const collaborator1Name string = "Alex" // Alex's name const collaborator1EncryptedSalaryFileName string = "" // The name of Alex's encrypted salary file const collaborator1BucketInputName string = "" // The name of the storage bucket that contains Alex's encrypted salary file const collaborator1BucketOutputName string = "" // The name of the storage bucket to store Alex's results in const collaborator1BucketOutputFileName string = "" // The name of Alex's output file that contains the results const collaborator1KMSKeyringName string = "" // Alex's Key Management Service key ring const collaborator1KMSKeyName string = "" // Alex's Key Management Service key const collaborator1ProjectName string = "" // Alex's project ID const collaborator1ProjectNumber string = "" // Alex's project number const collaborator1PoolName string = "" // Alex's workload identity pool name // Bola's values const collaborator2Name string = "Bola" // Bola's name const collaborator2EncryptedSalaryFileName string = "" // The name of Bola's encrypted salary file const collaborator2BucketInputName string = "" // The name of the storage bucket that contains Bola's encrypted salary file const collaborator2BucketOutputName string = "" // The name of the storage bucket to store Bola's results in const collaborator2BucketOutputFileName string = "" // The name of Bola's output file that contains the results const collaborator2KMSKeyringName string = "" // Bola's Key Management Service key ring const collaborator2KMSKeyName string = "" // Bola's Key Management Service key const collaborator2ProjectName string = "" // Bola's project ID const collaborator2ProjectNumber string = "" // Bola's project number const collaborator2PoolName string = "" // Bola's workload identity pool name // END USER VARIABLES SECTION // ========================== 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, collaborator1BucketOutputFileName, }, { collaborator2Name, "projects/" + collaborator2ProjectNumber + "/locations/global/workloadIdentityPools/" + collaborator2PoolName + "/providers/attestation-verifier", "projects/" + collaborator2ProjectName + "/locations/global/keyRings/" + collaborator2KMSKeyringName + "/cryptoKeys/" + collaborator2KMSKeyName, collaborator2BucketInputName, collaborator2EncryptedSalaryFileName, collaborator2BucketOutputName, collaborator2BucketOutputFileName, }, } 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 = "earns same\n" } now := time.Now() for _, cw := range collaborators { outputWriter := storageClient.Bucket(cw.outputBucket).Object(fmt.Sprintf("%s-%d", cw.outputFile, 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 }
ソースコードの
USER VARIABLES SECTION
を変更し、コードのコメントで説明されているように、空のconst
値を関連するリソース名に置き換えます。このガイドに示されているALEX_PROJECT_ID
のようなプレースホルダ変数を編集した場合、次のコードサンプルに値が含まれます。このサンプルはコピーして、既存に上書きできます。// Alex's values const collaborator1Name string = "Alex" // Alex's name const collaborator1EncryptedSalaryFileName string = "ALEX_ENCRYPTED_SALARY_FILE" // The name of Alex's encrypted salary file const collaborator1BucketInputName string = "ALEX_INPUT_BUCKET_NAME" // The name of the storage bucket that contains Alex's encrypted salary file const collaborator1BucketOutputName string = "ALEX_RESULTS_BUCKET_NAME" // The name of the storage bucket to store Alex's results in const collaborator1BucketOutputFileName string = "ALEX_RESULTS_FILE_NAME" // The name of Alex's output file that contains the results const collaborator1KMSKeyringName string = "ALEX_KEYRING_NAME" // Alex's Key Management Service key ring const collaborator1KMSKeyName string = "ALEX_KEY_NAME" // Alex's Key Management Service key const collaborator1ProjectName string = "ALEX_PROJECT_ID" // Alex's project ID const collaborator1ProjectNumber string = "ALEX_PROJECT_NUMBER" // Alex's project number const collaborator1PoolName string = "ALEX_POOL_NAME" // Alex's workload identity pool name // Bola's values const collaborator2Name string = "Bola" // Bola's name const collaborator2EncryptedSalaryFileName string = "BOLA_ENCRYPTED_SALARY_FILE" // The name of Bola's encrypted salary file const collaborator2BucketInputName string = "BOLA_INPUT_BUCKET_NAME" // The name of the storage bucket that contains Bola's encrypted salary file const collaborator2BucketOutputName string = "BOLA_RESULTS_BUCKET_NAME" // The name of the storage bucket to store Bola's results in const collaborator2BucketOutputFileName string = "BOLA_RESULTS_FILE_NAME" // The name of Bola's output file that contains the results const collaborator2KMSKeyringName string = "BOLA_KEYRING_NAME" // Bola's Key Management Service key ring const collaborator2KMSKeyName string = "BOLA_KEY_NAME" // Bola's Key Management Service key const collaborator2ProjectName string = "BOLA_PROJECT_ID" // Bola's project ID const collaborator2ProjectNumber string = "BOLA_PROJECT_NUMBER" // Bola's project number const collaborator2PoolName string = "BOLA_POOL_NAME" // Bola's workload identity pool name
Alex と Bola の両方のプロジェクト番号も必ず更新してください。次のコマンドで取得できます。
gcloud projects describe PROJECT_ID --format="value(projectNumber)"
すべての関係者がソースコードを読み取り、監査していることを確認します。
[ターミナル > 新しいターミナル] をクリックして、Cloud Shell エディタ内でターミナルを開きます。
ターミナルで次のコマンドを入力して、Go 環境を設定します。
go mod init salary 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
次のコマンドを入力して、ソースコードを静的リンクされたバイナリにコンパイルします。
CGO_ENABLED=0 go build -trimpath
Cloud Shell エディタで、次の内容を含む
Dockerfile
という名前のファイルを作成します。FROM alpine:latest WORKDIR /test COPY salary /test ENTRYPOINT ["/test/salary"] CMD []
us-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_NAME
Docker の push レスポンスから、安全な場所に Docker イメージのダイジェスト(
sha256:
接頭辞を含む)をコピーします。これは、後でワークロードを承認するために使用されます。すべての関係者が 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' \ && 'STABLE' in assertion.submods.confidential_space.support_attributes"
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.cryptoKeyDecrypter
Bola のプロジェクトに切り替えます。
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' \ && 'STABLE' in assertion.submods.confidential_space.support_attributes"
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 のプロジェクトに作成します。
AMD SEV、インテル TDX、または NVIDIA Confidential Computing を使用したインテル TDX(プレビュー)の Confidential VM インスタンスのサポートされている構成。
Confidential Space イメージに基づく OS。
セキュアブートが有効になっています。
Alex が以前に作成した添付されている Docker イメージ。
ワークロードを実行するサービス アカウントが関連付けられています。
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"
Bola のプロジェクトでワークロードの進行状況を確認するには、ログ エクスプローラに移動します。
[ログ エクスプローラ] に移動
Confidential Space ログを検索するには、次のログフィールドが使用可能な場合は、それらでフィルタします。
リソースタイプ: VM インスタンス
インスタンス ID: VM のインスタンス ID
ログ名: confidential-space-launcher
ログを更新するには、
[現在の位置に移動] をクリックします。ワークロードが完了すると、VM インスタンスが停止します。暗号化された給与ファイルを変更してワークロードを再度デプロイする場合に必要なのは、既存の VM を起動することのみです。
gcloud compute instances start WORKLOAD_VM_NAME --zone=us-west1-b
結果を見る
ワークロードが正常に完了すると、Alex と Bola の両方がそれぞれの結果バケットで結果を表示できます。
Alex のプロジェクトに切り替えます。
gcloud config set project ALEX_PROJECT_ID
結果バケット内のすべてのファイルを一覧表示します。
gcloud storage ls gs://ALEX_RESULTS_BUCKET_NAME
次に、最新のファイルを読み取ります。
gcloud storage cat gs://ALEX_RESULTS_BUCKET_NAME/ALEX_RESULTS_FILE_NAME
Bola のプロジェクトに切り替えます。
gcloud config set project BOLA_PROJECT_ID
Bola の場合は、結果バケット内のすべてのファイルを一覧表示します。
gcloud storage ls gs://BOLA_RESULTS_BUCKET_NAME
次に、最新のファイルを読み取ります。
gcloud storage cat gs://BOLA_RESULTS_BUCKET_NAME/BOLA_RESULTS_FILE_NAME
ファイルを読み取ることで、Alex と Bola は互いに自身の給与について明らかにすることなく、2 人のうちいずれの給与がより高額であるかを調べることができます。
ワークロードをデバッグする
ログ エクスプローラを使用して、リソースが正しく設定されていない、またはプロバイダに Confidential Space ワークロードによって行われたクレームと一致しない属性条件があるなどの問題をトラブルシューティングすることができます。
そのためには、次の変更を行う必要があります。
Alex と Bola の Workload Identity プール プロバイダを更新して、
support_attributes
アサーションを削除します。Confidential Space のデバッグ イメージを使用して詳細なトラブルシューティングを行う必要がありますが、このイメージには検証するサポート属性がありません。Confidential Space デバッグ イメージを使用してワークロード VM を作成し、VM メタデータを設定して
STDOUT
とSTDERR
を Cloud Logging にリダイレクトし、ワークロードからのすべての出力をキャプチャします。
変更を行う手順は次のとおりです。
Alex のプロジェクトに切り替えます。
gcloud config set project ALEX_PROJECT_ID
Alex のプロバイダを更新して、
support_attributes
アサーションを削除します。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'"
Bola のプロジェクトに切り替えます。
gcloud config set project BOLA_PROJECT_ID
Bola のプロバイダを更新して、
support_attributes
アサーションを削除します。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'"
Confidential Space デバッグ イメージを使用して新しい VM を作成し、メタデータで
tee-container-log-redirect
をtrue
に設定します。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"
本番環境イメージとは異なり、デバッグ イメージはワークロードの完了後も VM を実行し続けます。つまり、SSH を使用して VM に接続し、デバッグを続行できます。
クリーンアップ
このガイドで作成したリソースを削除する手順は次のとおりです。
健太のリソースをクリーンアップする
Alex のプロジェクトに切り替えます。
gcloud config set project ALEX_PROJECT_ID
Alex の Workload Identity プールを削除します。
gcloud iam workload-identity-pools delete ALEX_POOL_NAME \ --location=global
Alex の Cloud Storage バケットを削除します。
gcloud storage rm gs://ALEX_INPUT_BUCKET_NAME \ gs://ALEX_RESULTS_BUCKET_NAME --recursive
Alex の給与ファイルと Go コードを削除します。
rm ALEX_SALARY.txt \ ALEX_ENCRYPTED_SALARY_FILE \ salary.go salary \ go.mod go.sum
省略可: Alex のプロジェクトをシャットダウンします。
Bola のリソースをクリーンアップする
Bola のプロジェクトに切り替えます。
gcloud config set project BOLA_PROJECT_ID
ワークロード 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.com
Bola の Workload Identity プールを削除します。
gcloud iam workload-identity-pools delete BOLA_POOL_NAME \ --location=global
Bola の Cloud Storage バケットを削除します。
gcloud storage rm gs://BOLA_INPUT_BUCKET_NAME \ gs://BOLA_RESULTS_BUCKET_NAME --recursive
Bola の給与ファイルを削除します。
rm BOLA_SALARY.txt \ BOLA_ENCRYPTED_SALARY_FILE
省略可: Bola のプロジェクトをシャットダウンします。