Membuat lingkungan Confidential Space pertama Anda


Dalam panduan ini, Alex dan Bola ingin mengetahui siapa yang memiliki gaji tertinggi tanpa mengungkapkan angka kepada satu sama lain. Mereka memutuskan untuk menggunakan Confidential Space untuk menjaga data mereka tetap rahasia, dan setuju untuk mengambil peran berikut:

  • Alex: Kolaborator data, penulis beban kerja

  • Bola: Kolaborator data, operator beban kerja

Pengaturan ini dirancang agar semuanya tetap semudah mungkin untuk panduan ini. Namun, penulis dan operator workload dapat sepenuhnya independen dari kolaborator data, dan Anda dapat memiliki kolaborator sebanyak yang Anda inginkan.

Sebelum memulai

Panduan ini menunjukkan skenario Ruang Rahasia menggunakan satu akun di satu organisasi dengan akses ke beberapa project, sehingga Anda dapat merasakan seluruh prosesnya. Dalam deployment produksi, kolaborator, penulis beban kerja, dan operator beban kerja memiliki akun terpisah dan project mereka sendiri yang terdapat dalam organisasi terpisah, yang tidak dapat diakses satu sama lain dan menjaga data rahasia mereka tetap terpisah.

Ruang Rahasia dapat berinteraksi dengan banyak layanan Google Clouduntuk menghasilkan hasilnya, termasuk, tetapi tidak terbatas pada:

Panduan ini menggunakan dan mengasumsikan pemahaman dasar tentang semua fitur ini.

API yang diperlukan

Anda harus mengaktifkan API berikut di project yang ditentukan agar dapat menyelesaikan panduan ini.

Nama API Judul API Aktifkan di project ini
cloudkms.googleapis.com Cloud KMS Kolaborator data (project Alex dan Bola)
iamcredentials.googleapis.com IAM Service Account Credentials API

Kolaborator data (project Alex)

Dalam panduan ini, hanya Alex yang perlu mengaktifkan API ini. Namun, jika lebih dari dua pihak terlibat, IAM Service Account Credentials API perlu diaktifkan di setiap project kolaborator data yang tidak menghosting akun layanan beban kerja.

artifactregistry.googleapis.com Artifact Registry Penulis beban kerja (project Alex)
compute.googleapis.com Compute Engine Operator workload (project Bola)
confidentialcomputing.googleapis.com Confidential Computing Operator workload (project Bola)

Peran yang diperlukan

Untuk mendapatkan izin yang Anda perlukan untuk menyelesaikan panduan ini, minta administrator untuk memberi Anda peran IAM berikut pada project:

  • Cloud KMS Admin (roles/cloudkms.admin) untuk kolaborator data (Alex dan Bola).
  • IAM Workload Identity Pool Admin (roles/iam.workloadIdentityPoolAdmin) untuk kolaborator data (Alex dan Bola).
  • Service Usage Admin (roles/serviceusage.serviceUsageAdmin) untuk kolaborator data (Alex dan Bola).
  • Admin Akun Layanan (roles/iam.serviceAccountAdmin) untuk kolaborator data (Alex dan Bola).
  • Storage Admin (roles/storage.admin) untuk kolaborator data (Alex dan Bola) dan operator beban kerja (Bola).
  • Compute Admin (roles/compute.admin) untuk operator beban kerja (Bola).
  • Security Admin (roles/securityAdmin) untuk operator beban kerja (Bola).
  • Administrator Artifact Registry (roles/artifactregistry.admin) untuk penulis workload (Alex).

Untuk mengetahui informasi selengkapnya tentang cara memberikan peran, lihat Mengelola akses ke project, folder, dan organisasi.

Anda mungkin juga bisa mendapatkan izin yang diperlukan melalui peran khusus atau peran bawaan lainnya.

Menyiapkan resource kolaborator data

Alex dan Bola memerlukan project independen yang berisi resource berikut:

  • Data rahasia itu sendiri.

  • Kunci enkripsi untuk mengenkripsi data tersebut dan menjaga kerahasiaannya.

  • Bucket Cloud Storage untuk menyimpan data terenkripsi.

  • Akun layanan yang memiliki akses ke kunci enkripsi, sehingga dapat mendekripsi data rahasia.

  • Identitas kumpulan beban kerja dengan akun layanan yang terhubung ke akun tersebut. Workload yang memproses data rahasia menggunakan kumpulan untuk meniru akun layanan dan mengambil data yang tidak dienkripsi.

Untuk memulai, buka konsol Google Cloud:

Buka konsol Google Cloud

Menyiapkan resource Alex

Untuk menyiapkan resource bagi Alex, selesaikan petunjuk berikut.

  1. Klik Aktifkan Cloud Shell.
  2. Di Cloud Shell, masukkan perintah berikut untuk membuat project untuk Alex, dengan mengganti ALEX_PROJECT_ID dengan nama pilihan Anda:

    gcloud projects create ALEX_PROJECT_ID
  3. Beralih ke project yang baru dibuat:

    gcloud config set project ALEX_PROJECT_ID
  4. Jika Anda belum melakukannya, aktifkan API yang diperlukan Alex sebagai collaborator data dan penulis workload:

    gcloud services enable cloudkms.googleapis.com artifactregistry.googleapis.com iamcredentials.googleapis.com
  5. Buat key ring dan kunci enkripsi dengan 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
  6. Berikan peran cloudkms.cryptoKeyEncrypter kepada Alex agar ia dapat menggunakan kunci enkripsi yang baru dibuat untuk mengenkripsi data:

    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
  7. Buat akun layanan yang nantinya akan digunakan oleh workload untuk mendekripsi data:

    gcloud iam service-accounts create ALEX_SERVICE_ACCOUNT_NAME
  8. Berikan peran cloudkms.cryptoKeyDecrypter kepada akun layanan agar dapat menggunakan kunci enkripsi yang baru saja Anda buat untuk mendekripsi data:

    gcloud kms keys add-iam-policy-binding \
        projects/ALEX_PROJECT_ID/locations/global/keyRings/ALEX_KEYRING_NAME/cryptoKeys/ALEX_KEY_NAME \
        --member=serviceAccount:ALEX_SERVICE_ACCOUNT_NAME@ALEX_PROJECT_ID.iam.gserviceaccount.com \
        --role=roles/cloudkms.cryptoKeyDecrypter
  9. Buat workload identity pool, lalu hubungkan akun layanan ke workload identity pool tersebut dengan peran iam.workloadIdentityUser:

    gcloud iam workload-identity-pools create ALEX_POOL_NAME \
        --location=global
    gcloud iam service-accounts add-iam-policy-binding \
        ALEX_SERVICE_ACCOUNT_NAME@ALEX_PROJECT_ID.iam.gserviceaccount.com \
        --member="principalSet://iam.googleapis.com/projects/"$(gcloud projects describe ALEX_PROJECT_ID \
            --format="value(projectNumber)")"/locations/global/workloadIdentityPools/ALEX_POOL_NAME/*" \
        --role=roles/iam.workloadIdentityUser
  10. Buat bucket Cloud Storage untuk data input, dan bucket lain untuk menyimpan hasilnya:

    gcloud storage buckets create gs://ALEX_INPUT_BUCKET_NAME \
        gs://ALEX_RESULTS_BUCKET_NAME
  11. Buat file yang hanya berisi gaji Alex sebagai angka:

    echo 123456 > ALEX_SALARY.txt
  12. Enkripsi file, lalu upload ke bucket 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

Menyiapkan resource Bola

Untuk menyiapkan resource untuk Bola, selesaikan petunjuk berikut.

  1. Di Cloud Shell, masukkan perintah berikut untuk membuat project untuk Bola, dengan mengganti BOLA_PROJECT_ID dengan nama pilihan Anda:

    gcloud projects create BOLA_PROJECT_ID
  2. Beralih ke project yang baru dibuat:

    gcloud config set project BOLA_PROJECT_ID
  3. Jika Anda belum melakukannya, aktifkan API yang diperlukan Bola sebagai collaborator data dan operator workload:

    gcloud services enable cloudkms.googleapis.com compute.googleapis.com confidentialcomputing.googleapis.com
  4. Buat key ring dan kunci enkripsi dengan 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
  5. Berikan peran cloudkms.cryptoKeyEncrypter kepada Bola agar dia dapat menggunakan kunci enkripsi yang baru dibuat untuk mengenkripsi data:

    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
  6. Buat akun layanan yang nantinya akan digunakan oleh workload untuk mendekripsi data:

    gcloud iam service-accounts create BOLA_SERVICE_ACCOUNT_NAME
  7. Berikan peran cloudkms.cryptoKeyDecrypter kepada akun layanan agar dapat menggunakan kunci enkripsi yang baru saja Anda buat untuk mendekripsi data:

    gcloud kms keys add-iam-policy-binding \
        projects/BOLA_PROJECT_ID/locations/global/keyRings/BOLA_KEYRING_NAME/cryptoKeys/BOLA_KEY_NAME \
        --member=serviceAccount:BOLA_SERVICE_ACCOUNT_NAME@BOLA_PROJECT_ID.iam.gserviceaccount.com \
        --role=roles/cloudkms.cryptoKeyDecrypter
  8. Buat workload identity pool, lalu hubungkan akun layanan ke workload identity pool tersebut dengan peran iam.workloadIdentityUser:

    gcloud iam workload-identity-pools create BOLA_POOL_NAME \
        --location=global
    gcloud iam service-accounts add-iam-policy-binding \
        BOLA_SERVICE_ACCOUNT_NAME@BOLA_PROJECT_ID.iam.gserviceaccount.com \
        --member="principalSet://iam.googleapis.com/projects/"$(gcloud projects describe BOLA_PROJECT_ID \
            --format="value(projectNumber)")"/locations/global/workloadIdentityPools/BOLA_POOL_NAME/*" \
        --role=roles/iam.workloadIdentityUser
  9. Buat bucket Cloud Storage untuk data input, dan bucket lain untuk menyimpan hasilnya:

    gcloud storage buckets create gs://BOLA_INPUT_BUCKET_NAME \
        gs://BOLA_RESULTS_BUCKET_NAME
  10. Buat file yang hanya berisi gaji Bola sebagai angka:

    echo 111111 > BOLA_SALARY.txt
  11. Enkripsi file, lalu upload ke bucket 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

Membuat akun layanan untuk workload

Selain akun layanan yang disiapkan Alex dan Bola untuk mendekripsi data mereka, akun layanan lain diperlukan untuk menjalankan beban kerja. Karena akun layanan digunakan untuk mendekripsi data rahasia dan memprosesnya, visibilitas data dibatasi untuk pemiliknya.

Dalam panduan ini, Bola mengoperasikan dan menjalankan beban kerja, tetapi siapa saja dapat mengambil peran ini, termasuk pihak ketiga.

Selesaikan langkah-langkah berikut di project Bola untuk menyiapkan akun layanan:

  1. Buat akun layanan untuk menjalankan beban kerja:

    gcloud iam service-accounts create WORKLOAD_SERVICE_ACCOUNT_NAME
    
  2. Berikan peran iam.serviceAccountUser kepada Bola untuk meniru akun layanan, yang diperlukan agar ia dapat membuat VM workload nanti:

    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
    
  3. Berikan peran confidentialcomputing.workloadUser kepada akun layanan agar dapat membuat token pengesahan:

    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
    
  4. Berikan peran logging.logWriter ke akun layanan untuk menulis log ke Cloud Logging, sehingga Anda dapat memeriksa progres beban kerja:

    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
    
  5. Berikan akses baca ke bucket Alex dan Bola yang berisi data terenkripsi mereka, dan akses tulis ke setiap bucket hasil mereka:

    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
    

    Hal ini mengasumsikan bahwa pengguna yang memberikan akses memiliki peran Storage Admin (roles/storage.admin) untuk project yang berisi bucket Cloud Storage yang sedang dioperasikan.

Membuat workload

Dalam panduan ini, Alex menyediakan kode untuk beban kerja dan mem-build image Docker untuk menyimpannya, tetapi siapa pun dapat mengambil peran ini, termasuk pihak ketiga.

Alex perlu membuat resource berikut untuk workload:

  • Kode yang menjalankan beban kerja.

  • Repositori Docker di Artifact Registry, yang dapat diakses oleh akun layanan yang menjalankan workload.

  • Image Docker yang berisi dan menjalankan kode beban kerja.

Untuk membuat dan menyiapkan resource, selesaikan langkah-langkah berikut dalam project Alex:

  1. Beralih ke project Alex:

    gcloud config set project ALEX_PROJECT_ID
    
  2. Buat repositori Docker di Artifact Registry:

    gcloud artifacts repositories create REPOSITORY_NAME \
        --repository-format=docker \
        --location=us
    
  3. Berikan peran Pembaca Artifact Registry (roles/artifactregistry.reader) ke akun layanan yang akan menjalankan beban kerja agar dapat membaca dari repositori:

    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
    
  4. Klik Open editor untuk membuka Editor Cloud Shell, lalu buat file baru bernama salary.go. Salin kode berikut ke dalam file, lalu simpan:

    // READ ME FIRST: Before compiling, customize the details in the USER VARIABLES
    // SECTION starting at line 30.
    
    package main
    
    import (
      kms "cloud.google.com/go/kms/apiv1"
      "cloud.google.com/go/storage"
      "context"
      "fmt"
      "google.golang.org/api/option"
      kmspb "google.golang.org/genproto/googleapis/cloud/kms/v1"
      "io/ioutil"
      "strconv"
      "strings"
      "time"
    )
    
    type collaborator struct {
      name         string
      wipName      string
      sa           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
    const collaborator1ServiceAccountName string = ""      // The name of Alex's service account that can decrypt their salary
    
    // 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
    const collaborator2ServiceAccountName string = ""      // The name of Bola's service account that can decrypt their salary
    
    // END USER VARIABLES SECTION
    // ==========================
    
    var collaborators = [2]collaborator{
      {
        collaborator1Name,
        "projects/" + collaborator1ProjectNumber + "/locations/global/workloadIdentityPools/" + collaborator1PoolName + "/providers/attestation-verifier",
        collaborator1ServiceAccountName + "@" + collaborator1ProjectName + ".iam.gserviceaccount.com",
        "projects/" + collaborator1ProjectName + "/locations/global/keyRings/" + collaborator1KMSKeyringName + "/cryptoKeys/" + collaborator1KMSKeyName,
        collaborator1BucketInputName,
        collaborator1EncryptedSalaryFileName,
        collaborator1BucketOutputName,
        collaborator1BucketOutputFileName,
      },
      {
        collaborator2Name,
        "projects/" + collaborator2ProjectNumber + "/locations/global/workloadIdentityPools/" + collaborator2PoolName + "/providers/attestation-verifier",
        collaborator2ServiceAccountName + "@" + collaborator2ProjectName + ".iam.gserviceaccount.com",
        "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"
            },
            "service_account_impersonation_url": "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/%s:generateAccessToken"
            }`
    
    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.sa, 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, trustedServiceAccountEmail, wippro string, encryptedData []byte) ([]byte, error) {
      cc := fmt.Sprintf(credentialConfig, wippro, trustedServiceAccountEmail)
      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 := ioutil.ReadAll(objectReader)
      if err != nil {
        return nil, err
      }
    
      return s, nil
    }
    
  5. Ubah USER VARIABLES SECTION dalam kode sumber, ganti nilai const kosong dengan nama resource yang relevan seperti yang dijelaskan dalam komentar kode. Jika Anda telah mengedit variabel placeholder seperti ALEX_PROJECT_ID yang ditampilkan dalam panduan ini, nilainya disertakan dalam contoh kode berikut, yang dapat Anda salin dan tempel di atas kode yang ada:

    // 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
    const collaborator1ServiceAccountName string = "ALEX_SERVICE_ACCOUNT_NAME"       // The name of Alex's service account that can decrypt their salary
    
    // 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
    const collaborator2ServiceAccountName string = "BOLA_SERVICE_ACCOUNT_NAME"       // The name of Bola's service account that can decrypt their salary
    

    Pastikan untuk memperbarui nomor project Alex dan Bola juga. Anda dapat mengambilnya dengan perintah berikut:

    gcloud projects describe PROJECT_ID --format="value(projectNumber)"
    
  6. Pastikan semua pihak membaca dan mengaudit kode sumber.

  7. Klik Terminal > New Terminal untuk membuka terminal dalam Cloud Shell Editor.

  8. Masukkan perintah berikut di terminal untuk menyiapkan lingkungan 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
    
  9. Masukkan perintah berikut untuk mengompilasi kode sumber ke biner yang ditautkan secara statis:

    CGO_ENABLED=0 go build -trimpath
    
  10. Buat file bernama Dockerfile di Cloud Shell Editor yang berisi konten berikut:

    FROM alpine:latest
    WORKDIR /test
    COPY salary /test
    ENTRYPOINT ["/test/salary"]
    CMD []
    
  11. Perbarui kredensial Docker Anda untuk menyertakan nama domain us-docker.pkg.dev:

    gcloud auth configure-docker us-docker.pkg.dev
    
  12. Buat image Docker dari Dockerfile dengan memasukkan perintah berikut di terminal:

    docker build -t \
        us-docker.pkg.dev/ALEX_PROJECT_ID/REPOSITORY_NAME/WORKLOAD_CONTAINER_NAME:latest .
    
  13. Kirim image Docker ke Artifact Registry:

    docker push \
        us-docker.pkg.dev/ALEX_PROJECT_ID/REPOSITORY_NAME/WORKLOAD_CONTAINER_NAME
    
  14. Dari respons push Docker, salin ringkasan image Docker (termasuk awalan sha256:) ke tempat yang aman untuk digunakan nanti.

  15. Pastikan semua pihak mengaudit image Docker dan memverifikasi bahwa image tersebut dapat dipercaya sebelum mengizinkan penggunaannya.

Memberi otorisasi pada workload

Dengan workload yang disetujui oleh kedua belah pihak, Alex dan Bola perlu menambahkan layanan verifier pengesahan Confidential Space sebagai penyedia ke workload identity pool mereka. Hal ini memungkinkan akun layanan yang terpasang ke beban kerja meniru akun layanan yang terhubung ke kumpulannya dan mengakses datanya, dengan syarat kondisi atribut tertentu terpenuhi. Artinya, kondisi atribut berfungsi sebagai kebijakan pengesahan.

Kondisi atribut yang digunakan dalam panduan ini adalah sebagai berikut:

  • Ringkasan image Docker yang sedang dijalankan

  • Alamat email akun layanan yang menjalankan beban kerja

Jika pelaku berbahaya mengubah image Docker, atau akun layanan yang berbeda disertakan ke beban kerja, beban kerja tidak akan diizinkan untuk mengakses data Alex atau Bola.

Untuk melihat kondisi atribut yang tersedia, lihat Pernyataan pengesahan.

Untuk menyiapkan penyedia bagi Alex dan Bola dengan kondisi yang diperlukan, selesaikan langkah-langkah berikut:

  1. Masukkan perintah berikut untuk membuat penyedia bagi 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=assertion.sub" \
        --attribute-condition="assertion.submods.container.image_digest == 'DOCKER_IMAGE_DIGEST' \
    && 'WORKLOAD_SERVICE_ACCOUNT_NAME@BOLA_PROJECT_ID.iam.gserviceaccount.com' in assertion.google_service_accounts \
    && assertion.swname == 'CONFIDENTIAL_SPACE' \
    && 'STABLE' in assertion.submods.confidential_space.support_attributes"
    
  2. Beralih ke project Bola:

    gcloud config set project BOLA_PROJECT_ID
    
  3. Masukkan perintah berikut untuk membuat penyedia 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=assertion.sub" \
        --attribute-condition="assertion.submods.container.image_digest == 'DOCKER_IMAGE_DIGEST' \
    && 'WORKLOAD_SERVICE_ACCOUNT_NAME@BOLA_PROJECT_ID.iam.gserviceaccount.com' in assertion.google_service_accounts \
    && assertion.swname == 'CONFIDENTIAL_SPACE' \
    && 'STABLE' in assertion.submods.confidential_space.support_attributes"
    

Men-deploy workload

Dengan penyedia yang ditambahkan ke workload identity pool Alex dan Bola serta resource yang diperlukan, saatnya operator beban kerja menjalankan beban kerja.

Untuk men-deploy workload, buat instance Confidential VM baru di project Bola yang memiliki properti berikut:

  • Konfigurasi yang didukung untuk instance AMD SEV atau Intel TDX Confidential VM.

  • OS berdasarkan image Confidential Space.

  • Booting Aman diaktifkan.

  • Image Docker yang dilampirkan yang dibuat Alex sebelumnya.

  • Akun layanan terlampir yang menjalankan beban kerja.

Masukkan perintah berikut di Cloud Shell Bola untuk men-deploy beban kerja:

gcloud compute instances create WORKLOAD_VM_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 \
    --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"

Anda dapat melihat progres beban kerja di project Bola dengan membuka Logs Explorer.

Buka Logs Explorer

Untuk menemukan log Confidential Space, filter menurut Kolom log berikut jika tersedia:

  • Jenis resource: Instance VM

  • ID Instance: ID instance VM

  • Nama log: confidential-space-launcher

Untuk memuat ulang log, klik Langsung ke sekarang.

Setelah beban kerja selesai, instance VM akan berhenti. Jika ingin mengubah file gaji terenkripsi dan men-deploy workload lagi, Anda hanya perlu memulai VM yang ada:

gcloud compute instances start WORKLOAD_VM_NAME --zone=us-west1-b

Men-debug workload

Anda dapat menggunakan Logs Explorer untuk memecahkan masalah seperti resource yang tidak disiapkan dengan benar, atau kondisi atribut di penyedia yang tidak cocok dengan klaim yang dibuat oleh workload Confidential Space.

Untuk melakukannya, Anda perlu melakukan perubahan berikut:

  • Perbarui penyedia workload identity pool Alex dan Bola untuk menghapus pernyataan support_attributes. Anda perlu menggunakan image debug Confidential Space untuk melakukan pemecahan masalah yang lebih mendalam, dan image tersebut tidak memiliki atribut dukungan untuk diverifikasi.

  • Buat VM workload menggunakan image debug Confidential Space, dan tetapkan metadata VM untuk mengalihkan STDOUT dan STDERR ke Cloud Logging untuk mengambil semua output dari workload.

Untuk melakukan perubahan, selesaikan langkah-langkah berikut:

  1. Beralih ke project Alex:

    gcloud config set project ALEX_PROJECT_ID
    
  2. Perbarui penyedia Alex untuk menghapus pernyataan 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=assertion.sub" \
        --attribute-condition="assertion.submods.container.image_digest == 'DOCKER_IMAGE_DIGEST' \
    && 'WORKLOAD_SERVICE_ACCOUNT_NAME@BOLA_PROJECT_ID.iam.gserviceaccount.com' in assertion.google_service_accounts \
    && assertion.swname == 'CONFIDENTIAL_SPACE'"
    
  3. Beralih ke project Bola:

    gcloud config set project BOLA_PROJECT_ID
    
  4. Perbarui penyedia Bola untuk menghapus pernyataan 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=assertion.sub" \
        --attribute-condition="assertion.submods.container.image_digest == 'DOCKER_IMAGE_DIGEST' \
    && 'WORKLOAD_SERVICE_ACCOUNT_NAME@BOLA_PROJECT_ID.iam.gserviceaccount.com' in assertion.google_service_accounts \
    && assertion.swname == 'CONFIDENTIAL_SPACE'"
    
  5. Buat VM baru dengan image debug Confidential Space, dan tee-container-log-redirect ditetapkan ke true dalam metadata.

    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"
    

Tidak seperti image produksi, image debug membuat VM tetap berjalan setelah workload selesai. Artinya, Anda dapat menggunakan SSH untuk terhubung ke VM guna melanjutkan proses debug.

Melihat hasil

Setelah beban kerja berhasil diselesaikan, Alex dan Bola dapat melihat hasilnya di bucket hasil masing-masing:

  1. Beralih ke project Alex:

    gcloud config set project ALEX_PROJECT_ID
    
  2. Cantumkan semua file dalam bucket hasilnya:

    gcloud storage ls gs://ALEX_RESULTS_BUCKET_NAME
    

    Kemudian, baca file terbaru:

    gcloud storage cat gs://ALEX_RESULTS_BUCKET_NAME/ALEX_RESULTS_FILE_NAME
    
  3. Beralih ke project Bola:

    gcloud config set project BOLA_PROJECT_ID
    
  4. Untuk Bola, cantumkan semua file di bucket hasilnya:

    gcloud storage ls gs://BOLA_RESULTS_BUCKET_NAME
    

    Kemudian, baca file terbaru:

    gcloud storage cat gs://BOLA_RESULTS_BUCKET_NAME/BOLA_RESULTS_FILE_NAME
    

Dengan membaca file tersebut, Alex dan Bola masing-masing mengetahui siapa yang berpenghasilan lebih tinggi tanpa mengungkapkan gaji mereka kepada satu sama lain.

Pembersihan

Untuk menghapus resource yang dibuat dalam panduan ini, selesaikan petunjuk berikut.

Membersihkan resource Alex

  1. Beralih ke project Alex:

    gcloud config set project ALEX_PROJECT_ID
    
  2. Hapus akun layanan yang mendekripsi data Alex:

    gcloud iam service-accounts delete \
        ALEX_SERVICE_ACCOUNT_NAME@ALEX_PROJECT_ID.iam.gserviceaccount.com
    
  3. Hapus workload identity pool Alex:

    gcloud iam workload-identity-pools delete ALEX_POOL_NAME \
        --location=global
    
  4. Hapus bucket Cloud Storage Alex:

    gcloud storage rm gs://ALEX_INPUT_BUCKET_NAME \
        gs://ALEX_RESULTS_BUCKET_NAME --recursive
    
  5. Hapus file gaji Alex dan kode Go:

    rm ALEX_SALARY.txt \
        ALEX_ENCRYPTED_SALARY_FILE \
        salary.go salary \
        go.mod go.sum
    
  6. Opsional: Nonaktifkan atau hancurkan kunci Cloud Key Management Service Alex.

  7. Opsional: Nonaktifkan project Alex.

Membersihkan resource Bola

  1. Beralih ke project Bola:

    gcloud config set project BOLA_PROJECT_ID
    
  2. Hapus VM workload:

    gcloud compute instances delete WORKLOAD_VM_NAME --zone=us-west1-b
    
  3. Hapus akun layanan yang mendekripsi data Bola dan akun layanan yang menjalankan beban kerja:

    gcloud iam service-accounts delete \
        BOLA_SERVICE_ACCOUNT_NAME@BOLA_PROJECT_ID.iam.gserviceaccount.com
    
    gcloud iam service-accounts delete \
        WORKLOAD_SERVICE_ACCOUNT_NAME@BOLA_PROJECT_ID.iam.gserviceaccount.com
    
  4. Hapus workload identity pool Bola:

    gcloud iam workload-identity-pools delete BOLA_POOL_NAME \
        --location=global
    
  5. Hapus bucket Cloud Storage Bola:

    gcloud storage rm gs://BOLA_INPUT_BUCKET_NAME \
        gs://BOLA_RESULTS_BUCKET_NAME --recursive
    
  6. Hapus file gaji Bola:

    rm BOLA_SALARY.txt \
        BOLA_ENCRYPTED_SALARY_FILE
    
  7. Opsional: Nonaktifkan atau hancurkan kunci Cloud Key Management Service Bola.

  8. Opsional: Matikan project Bola.