このガイドでは、互いに自身の給与額を明らかにすることなく、Alex と Bola がどちらの給与がより高額であるかを調べる必要があります。機密データを保持するために Confidential Space を使用することに決め、次のロールを引き受けることに同意します。
Alex: データ共同編集者、ワークロード設定者
Bola: データ共同編集者、ワークロード オペレーター
この配置は、このガイドをできるだけわかりやすくするために設計されています。ただし、ワークロードの作成者とオペレーターが、データ共同編集者から完全に独立した状態にし、必要な数の共同編集者を配置することが可能です。
始める前に
このガイドでは、1 つの組織で複数のプロジェクトにアクセスできる単一のアカウントを使用して、プロセス全体を体験できる Confidential Space のシナリオについて説明します。本番環境デプロイでは、共同編集者、ワークロードの作成者、ワークロードのオペレーターは、それぞれ個別のアカウントと独自のプロジェクトを個別の組織に持ち、互いにアクセスできず、機密データを別々に保持します。
Confidential Space は、 Google Cloudのさまざまなサービスとやり取りして、結果を出すことができます。サービスには以下のものがありますが、これらに限定されません。
このガイドでは、これらの機能のすべてを使用し、基本的な理解があることを前提としています。
必要な API
このガイドを完了するには、指定されたプロジェクトで次の API を有効にする必要があります。
API 名 | API タイトル | これらのプロジェクトで有効にする |
---|---|---|
cloudkms.googleapis.com |
Cloud Key Management Service | データ共同編集者(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
次のコードサンプルの値を関連するリソース名に変更して、次のステップでソースコードを更新します。このガイドの
ALEX_PROJECT_ID
のようなプレースホルダ変数をすでに編集している場合、これらの値は事前入力されています。// Alex's values ALEX_ENCRYPTED_SALARY_FILE // The name of Alex's encrypted salary file ALEX_INPUT_BUCKET_NAME // The name of the storage bucket that contains Alex's encrypted salary file ALEX_RESULTS_BUCKET_NAME // The name of the storage bucket to store Alex's results in ALEX_RESULTS_FILE_PREFIX // A prefix for Alex's results filename. The code adds a timestamp to this prefix. ALEX_KEYRING_NAME // Alex's Key Management Service key ring. ALEX_KEY_NAME // Alex's Key Management Service key. ALEX_PROJECT_ID // Alex's project ID. ALEX_PROJECT_NUMBER // Alex's project number. ALEX_POOL_NAME // Alex's workload identity pool name. // Bola's values BOLA_ENCRYPTED_SALARY_FILE // The name of Bola's encrypted salary file. BOLA_INPUT_BUCKET_NAME // The name of the storage bucket that contains Bola's encrypted salary file. BOLA_RESULTS_BUCKET_NAME // The name of the storage bucket to store Bola's results in. BOLA_RESULTS_FILE_PREFIX // A prefix for Bola's results filename. The code adds a timestamp to this prefix. BOLA_KEYRING_NAME // Bola's Key Management Service key ring. BOLA_KEY_NAME // Bola's Key Management Service key. BOLA_PROJECT_ID // Bola's project ID. BOLA_PROJECT_NUMBER // Bola's project number. BOLA_POOL_NAME // Bola's workload identity pool name.
Alex と Bola のプロジェクト番号を取得するには、関連するプロジェクトで次のコマンドを実行します。
gcloud projects describe ALEX_PROJECT_ID --format="value(projectNumber)"
gcloud projects describe BOLA_PROJECT_ID --format="value(projectNumber)"
Alex のプロジェクトで、[エディタを開く] をクリックして 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 = "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 collaborator1BucketOutputFilePrefix string = "ALEX_RESULTS_FILE_PREFIX" // A prefix for Alex's results filename. The code adds a timestamp to this prefix. 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 collaborator2BucketOutputFilePrefix string = "BOLA_RESULTS_FILE_PREFIX" // A prefix for Bola's results filename. The code adds a timestamp to this prefix. 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. // 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, collaborator1BucketOutputFilePrefix, }, { collaborator2Name, "projects/" + collaborator2ProjectNumber + "/locations/global/workloadIdentityPools/" + collaborator2PoolName + "/providers/attestation-verifier", "projects/" + collaborator2ProjectName + "/locations/global/keyRings/" + collaborator2KMSKeyringName + "/cryptoKeys/" + collaborator2KMSKeyName, collaborator2BucketInputName, collaborator2EncryptedSalaryFileName, collaborator2BucketOutputName, collaborator2BucketOutputFilePrefix, }, } 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 }
すべての関係者がソースコードを読み取り、監査していることを確認します。
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 []
この
Dockerfile
は、マルチステージ ビルドを使用して、まず Go コードをコンパイルし、そのコードのコンパイル済みバージョンを最終的な Docker コンテナにコピーします。[ターミナルを開く] をクリックして Cloud Shell に戻るか、[表示] メニューから Cloud Shell Editor に組み込まれているターミナルを呼び出します。
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 レスポンスには、イメージの 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' \ && '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
次に、リストに表示された最新のファイルを読み取ります。
ALEX_RESULTS_CLOUD_STORAGE_PATH
は、gs://
を含むファイルのパスに置き換えます。gcloud storage cat ALEX_RESULTS_CLOUD_STORAGE_PATH
Bola のプロジェクトに切り替えます。
gcloud config set project BOLA_PROJECT_ID
Bola の場合は、結果バケット内のすべてのファイルを一覧表示します。
gcloud storage ls gs://BOLA_RESULTS_BUCKET_NAME
次に、リストに表示された最新のファイルを読み取ります。
BOLA_RESULTS_CLOUD_STORAGE_PATH
は、gs://
を含むファイルのパスに置き換えます。gcloud storage cat BOLA_RESULTS_CLOUD_STORAGE_PATH
ファイルを読み取ることで、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
省略可: デバッグ VM を作成した場合は、それを削除します。
gcloud compute instances delete WORKLOAD_VM_2_NAME --zone=us-west1-b
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 のプロジェクトをシャットダウンします。