Erste Umgebung für vertrauliche Gruppenbereiche erstellen

In diesem Leitfaden möchten Alex und Bola herausfinden, wer das höchste Gehalt hat, ohne sich gegenseitig die Zahlen offenzulegen. Sie entscheiden sich für die Nutzung von Confidential Space, um ihre Daten vertraulich zu behandeln, und einigen sich darauf, die folgenden Rollen anzunehmen:

  • Alex: Datenmitbearbeiter, Arbeitslastautor

  • Bola: Datenmitbearbeiter, Arbeitslastoperator

Diese Anordnung soll die Dinge für diesen Leitfaden so einfach wie möglich halten. Die Autoren und Operatoren von Arbeitslasten können jedoch völlig unabhängig von den Datenmitbearbeitern sein und Sie können so viele Mitbearbeiter haben, wie Sie möchten.

Hinweise

In dieser Anleitung wird ein Confidential Space-Szenario mit einem einzelnen Konto in einer einzelnen Organisation mit Zugriff auf mehrere Projekte veranschaulicht, sodass Sie den gesamten Prozess durchlaufen können. In einer Produktionsbereitstellung haben Mitbearbeiter, Arbeitslastautoren und Arbeitslastoperatoren separate Konten und ihre eigenen Projekte in eigenständigen Organisationen, die nicht füreinander zugänglich sind und ihre vertraulichen Daten getrennt halten.

Confidential Space kann mit vielen Diensten von Google Cloudinteragieren, um seine Ergebnisse zu erzielen, einschließlich, aber nicht beschränkt auf:

In dieser Anleitung werden alle diese Features verwendet und grundlegende Kenntnisse von ihnen vorausgesetzt.

Erforderliche Rollen

Bitten Sie Ihren Administrator, Ihnen die folgenden IAM-Rollen für das Projekt zuzuweisen, damit Sie die nötigen Berechtigungen für diese Anleitung haben:

  • Cloud KMS-Administrator (roles/cloudkms.admin) für die Datenmitbearbeiter (Alex und Bola).
  • IAM Workload Identity-Pooladministrator (roles/iam.workloadIdentityPoolAdmin) für die Datenmitbearbeiter (Alex und Bola).
  • Service Usage-Administrator (roles/serviceusage.serviceUsageAdmin) für die Datenmitbearbeiter (Alex und Bola).
  • Storage-Administrator (roles/storage.admin) für die Datenmitbearbeiter (Alex und Bola) und den Arbeitslastoperator (Bola).
  • Dienstkontoadministrator (roles/iam.serviceAccountAdmin) für den Arbeitslastoperator (Bola).
  • Compute-Administrator (roles/compute.admin) für den Arbeitslastoperator (Bola).
  • Sicherheitsadministrator (roles/securityAdmin) für den Arbeitslastoperator (Bola).
  • Artifact Registry-Administrator (roles/artifactregistry.admin) für den Arbeitslastautor (Alex).

Weitere Informationen zum Zuweisen von Rollen finden Sie unter Zugriff auf Projekte, Ordner und Organisationen verwalten.

Sie können die erforderlichen Berechtigungen auch über benutzerdefinierte Rollen oder andere vordefinierte Rollen erhalten.

Ressourcen für Datenmitbearbeiter einrichten

Sowohl Alex als auch Bola benötigen unabhängige Projekte mit den folgenden Ressourcen:

  • Die vertraulichen Daten selbst.

  • Ein Verschlüsselungsschlüssel, um diese Daten zu verschlüsseln und vertraulich zu behandeln.

  • Ein Cloud Storage-Bucket, in dem die verschlüsselten Daten gespeichert werden.

  • Ein Workload Identity-Pool. Die Arbeitslast, die die vertraulichen Daten verarbeitet, verwendet den Pool, um auf die privaten Daten zuzugreifen und sie zu entschlüsseln.

So legen Sie los: Google Cloud

Zur Google Cloud Console

Ressourcen von Alex einrichten

Führen Sie die folgenden Anweisungen aus, um die Ressourcen für Alex einzurichten.

  1. Klicken Sie auf Cloud Shell aktivieren.
  2. Geben Sie in Cloud Shell den folgenden Befehl ein, um ein Projekt für Alex zu erstellen. Ersetzen Sie dabei ALEX_PROJECT_ID durch einen Namen Ihrer Wahl:

    gcloud projects create ALEX_PROJECT_ID
  3. Wechseln Sie zum neu erstellten Projekt:

    gcloud config set project ALEX_PROJECT_ID
  4. Aktivieren Sie die APIs, die Alex als Datenmitbearbeiter und Arbeitslastautor benötigt:

    gcloud services enable \
        artifactregistry.googleapis.com \
        cloudkms.googleapis.com \
        iamcredentials.googleapis.com
  5. Schlüsselbund und Verschlüsselungsschlüssel mit dem Cloud Key Management Service erstellen:

    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. Weisen Sie Alex die Rolle cloudkms.cryptoKeyEncrypter zu, damit er den neu erstellten Verschlüsselungsschlüssel zum Verschlüsseln von Daten verwenden kann:

    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. Workload Identity-Pool für Alex erstellen:

    gcloud iam workload-identity-pools create ALEX_POOL_NAME \
        --location=global
  8. Erstellen Sie einen Cloud Storage-Bucket für die Eingabedaten und einen weiteren zum Speichern der Ergebnisse:

    gcloud storage buckets create gs://ALEX_INPUT_BUCKET_NAME \
        gs://ALEX_OUTPUT_BUCKET_NAME
  9. Erstellen Sie eine Datei, die nur das Gehalt von Alex als Zahl enthält:

    echo 123456 > ALEX_SALARY.txt
  10. Verschlüsseln Sie die Datei und laden Sie sie dann in den Bucket von Alex hoch:

    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

Ressourcen von Bola einrichten

Führen Sie die folgenden Anweisungen aus, um die Ressourcen für Bola einzurichten.

  1. Geben Sie in Cloud Shell den folgenden Befehl ein, um ein Projekt für Bola zu erstellen. Ersetzen Sie dabei BOLA_PROJECT_ID durch einen Namen Ihrer Wahl:

    gcloud projects create BOLA_PROJECT_ID
  2. Wechseln Sie zum neu erstellten Projekt:

    gcloud config set project BOLA_PROJECT_ID
  3. Aktivieren Sie die APIs, die Bola als Datenmitbearbeiter und Arbeitslastoperator benötigt:

    gcloud services enable \
        cloudkms.googleapis.com \
        compute.googleapis.com \
        confidentialcomputing.googleapis.com \
        iamcredentials.googleapis.com
  4. Schlüsselbund und Verschlüsselungsschlüssel mit dem Cloud Key Management Service erstellen:

    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. Weisen Sie Bola die Rolle cloudkms.cryptoKeyEncrypter zu, damit sie den neu erstellten Verschlüsselungsschlüssel zum Verschlüsseln von Daten verwenden kann:

    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. Workload Identity-Pool für Bola erstellen:

    gcloud iam workload-identity-pools create BOLA_POOL_NAME \
        --location=global
  7. Erstellen Sie einen Cloud Storage-Bucket für die Eingabedaten und einen weiteren zum Speichern der Ergebnisse:

    gcloud storage buckets create gs://BOLA_INPUT_BUCKET_NAME \
        gs://BOLA_OUTPUT_BUCKET_NAME
  8. Erstellen Sie eine Datei, die nur das Gehalt von Bola als Zahl enthält:

    echo 111111 > BOLA_SALARY.txt
  9. Verschlüsseln Sie die Datei und laden Sie sie dann in den Bucket von Bola hoch:

    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

Dienstkonto für die Arbeitslast erstellen

In dieser Anleitung wird die Arbeitslast von Bola betrieben und ausgeführt. Jedoch kann jeder diese Rollen übernehmen, auch ein Dritter. Der VM-Instanz, die Bola zum Ausführen des Arbeitslast erstellt, ist ein Dienstkonto angehängt, das die Berechtigung hat, Attestierungstokens zu generieren, Logs zu schreiben, die verschlüsselten Daten von Alex und Bola zu lesen und Ergebnisse in bestimmte Cloud Storage-Buckets zu schreiben.

Führen Sie im Projekt von Bola die folgenden Schritte aus, um das Dienstkonto einzurichten:

  1. Erstellen Sie ein Dienstkonto, um die Arbeitslast auszuführen:

    gcloud iam service-accounts create WORKLOAD_SERVICE_ACCOUNT_NAME
    
  2. Weisen Sie Bola die Rolle iam.serviceAccountUser zu, damit er das Dienstkonto später an die Arbeitslast-VM anhängen kann:

    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. Weisen Sie dem Dienstkonto die Rolle confidentialcomputing.workloadUser zu, damit es ein Attestierungstoken generieren kann:

    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. Weisen Sie dem Dienstkonto die Rolle logging.logWriter zu, damit es Logs in Cloud Logging schreiben kann. So können Sie den Fortschritt der Arbeitslast prüfen:

    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. Gewähren Sie dem Dienstkonto Lesezugriff auf die beiden Buckets von Alex und Bola, die ihre verschlüsselten Daten enthalten, und Schreibzugriff auf jeden ihrer Ergebnis-Buckets:

    gcloud storage buckets add-iam-policy-binding gs://ALEX_INPUT_BUCKET_NAME \
        --member=serviceAccount:WORKLOAD_SERVICE_ACCOUNT_NAME@BOLA_PROJECT_ID.iam.gserviceaccount.com \
        --role=roles/storage.objectViewer
    
    gcloud storage buckets add-iam-policy-binding gs://ALEX_OUTPUT_BUCKET_NAME \
        --member=serviceAccount:WORKLOAD_SERVICE_ACCOUNT_NAME@BOLA_PROJECT_ID.iam.gserviceaccount.com \
        --role=roles/storage.objectAdmin
    
    gcloud storage buckets add-iam-policy-binding gs://BOLA_INPUT_BUCKET_NAME \
        --member=serviceAccount:WORKLOAD_SERVICE_ACCOUNT_NAME@BOLA_PROJECT_ID.iam.gserviceaccount.com \
        --role=roles/storage.objectViewer
    
    gcloud storage buckets add-iam-policy-binding gs://BOLA_OUTPUT_BUCKET_NAME \
        --member=serviceAccount:WORKLOAD_SERVICE_ACCOUNT_NAME@BOLA_PROJECT_ID.iam.gserviceaccount.com \
        --role=roles/storage.objectAdmin
    

    Dabei wird davon ausgegangen, dass der Nutzer, der den Zugriff gewährt, die Rolle „Storage-Administrator“ (roles/storage.admin) für das Projekt hat, das den Cloud Storage-Bucket enthält, auf den zugegriffen wird.

Arbeitslast erstellen

In dieser Anleitung stellt Alex den Code für die Arbeitslast bereit und erstellt ein Docker-Image, der ihn enthalten soll. Jedoch kann jeder diese Rollen übernehmen, auch ein Dritter.

Alex muss die folgenden Ressourcen für die Arbeitslast erstellen:

  • Den Code, der die Arbeitslast ausführt.

  • Ein Docker-Repository in Artifact Registry, auf das das Dienstkonto Zugriff hat, das die Arbeitslast ausführt.

  • Ein Docker-Image, das den Arbeitslastcode enthält und ausführt.

So erstellen und richten Sie die Ressourcen im Projekt von Alex ein:

  1. Wechseln Sie zu Alex' Projekt:

    gcloud config set project ALEX_PROJECT_ID
    
  2. Klicken Sie auf Editor öffnen, um den Cloud Shell-Editor zu öffnen, und erstellen Sie dann eine neue Datei mit dem Namen salary.go. Kopieren Sie den folgenden Code in die Datei und speichern Sie sie dann:

    package main
    
    import (
      "context"
      "fmt"
      "io"
      "os"
      "strconv"
      "strings"
      "time"
    
      kms "cloud.google.com/go/kms/apiv1"
      kmspb "cloud.google.com/go/kms/apiv1/kmspb"
      "cloud.google.com/go/storage"
      "google.golang.org/api/option"
    )
    
    type collaborator struct {
      name         string
      wipName      string
      keyName      string
      inputBucket  string
      inputFile    string
      outputBucket string
    }
    
    // The following values are pulled from environment variables
    
    // Alex's values
    var collaborator1Name string = os.Getenv("COLLAB_1_NAME") // Alex's name
    var collaborator1EncryptedSalaryFileName string = os.Getenv("COLLAB_1_ENCRYPTED_SALARY") // The name of Alex's encrypted salary file.
    var collaborator1BucketInputName string = os.Getenv("COLLAB_1_INPUT_BUCKET") // The name of the storage bucket that contains Alex's encrypted salary file.
    var collaborator1BucketOutputName string = os.Getenv("COLLAB_1_OUTPUT_BUCKET") // The name of the storage bucket to store Alex's results in.
    var collaborator1KMSKeyringName string = os.Getenv("COLLAB_1_KEYRING_NAME") // Alex's Key Management Service key ring.
    var collaborator1KMSKeyName string = os.Getenv("COLLAB_1_KEY_NAME") // Alex's Key Management Service key.
    var collaborator1ProjectName string = os.Getenv("COLLAB_1_PROJECT_ID") // Alex's project ID.
    var collaborator1ProjectNumber string = os.Getenv("COLLAB_1_PROJECT_NUMBER") // Alex's project number.
    var collaborator1PoolName string = os.Getenv("COLLAB_1_POOL_NAME") // Alex's workload identity pool name.
    
    // Bola's values
    var collaborator2Name string = os.Getenv("COLLAB_2_NAME") // Bola's name
    var collaborator2EncryptedSalaryFileName string = os.Getenv("COLLAB_2_ENCRYPTED_SALARY") // The name of Bola's encrypted salary file.
    var collaborator2BucketInputName string = os.Getenv("COLLAB_2_INPUT_BUCKET") // The name of the storage bucket that contains Bola's encrypted salary file.
    var collaborator2BucketOutputName string = os.Getenv("COLLAB_2_OUTPUT_BUCKET") // The name of the storage bucket to store Bola's results in.
    var collaborator2KMSKeyringName string = os.Getenv("COLLAB_2_KEYRING_NAME") // Bola's Key Management Service key ring.
    var collaborator2KMSKeyName string = os.Getenv("COLLAB_2_KEY_NAME") // Bola's Key Management Service key.
    var collaborator2ProjectName string = os.Getenv("COLLAB_2_PROJECT_ID") // Bola's project ID.
    var collaborator2ProjectNumber string = os.Getenv("COLLAB_2_PROJECT_NUMBER") // Bola's project number.
    var collaborator2PoolName string = os.Getenv("COLLAB_2_POOL_NAME") // Bola's workload identity pool name.
    
    var collaborators = [2]collaborator{
      {
        collaborator1Name,
        "projects/" + collaborator1ProjectNumber + "/locations/global/workloadIdentityPools/" + collaborator1PoolName + "/providers/attestation-verifier",
        "projects/" + collaborator1ProjectName + "/locations/global/keyRings/" + collaborator1KMSKeyringName + "/cryptoKeys/" + collaborator1KMSKeyName,
        collaborator1BucketInputName,
        collaborator1EncryptedSalaryFileName,
        collaborator1BucketOutputName,
      },
      {
        collaborator2Name,
        "projects/" + collaborator2ProjectNumber + "/locations/global/workloadIdentityPools/" + collaborator2PoolName + "/providers/attestation-verifier",
        "projects/" + collaborator2ProjectName + "/locations/global/keyRings/" + collaborator2KMSKeyringName + "/cryptoKeys/" + collaborator2KMSKeyName,
        collaborator2BucketInputName,
        collaborator2EncryptedSalaryFileName,
        collaborator2BucketOutputName,
      },
    }
    
    const credentialConfig = `{
            "type": "external_account",
            "audience": "//iam.googleapis.com/%s",
            "subject_token_type": "urn:ietf:params:oauth:token-type:jwt",
            "token_url": "https://sts.googleapis.com/v1/token",
            "credential_source": {
              "file": "/run/container_launcher/attestation_verifier_claims_token"
            }
            }`
    
    func main() {
      fmt.Println("workload started")
      ctx := context.Background()
    
      storageClient, err := storage.NewClient(ctx) // Using the default credential on the Compute Engine VM
      if err != nil {
        panic(err)
      }
    
      // Get and decrypt
      s0, err := getSalary(ctx, storageClient, collaborators[0])
      if err != nil {
        panic(err)
      }
    
      s1, err := getSalary(ctx, storageClient, collaborators[1])
      if err != nil {
        panic(err)
      }
    
      res := ""
      if s0 > s1 {
        res = fmt.Sprintf("%s earns more!\n", collaborators[0].name)
      } else if s1 > s0 {
        res = fmt.Sprintf("%s earns more!\n", collaborators[1].name)
      } else {
        res = "You earn the same!\n"
      }
    
      now := time.Now()
      for _, cw := range collaborators {
        outputWriter := storageClient.Bucket(cw.outputBucket).Object(fmt.Sprintf("comparison-result-%d", now.Unix())).NewWriter(ctx)
    
        _, err = outputWriter.Write([]byte(res))
        if err != nil {
          fmt.Printf("Could not write: %v", err)
          panic(err)
        }
        if err = outputWriter.Close(); err != nil {
          fmt.Printf("Could not close: %v", err)
          panic(err)
        }
      }
    }
    
    func getSalary(ctx context.Context, storageClient *storage.Client, cw collaborator) (float64, error) {
      encryptedBytes, err := getFile(ctx, storageClient, cw.inputBucket, cw.inputFile)
      if err != nil {
        return 0.0, err
      }
      decryptedByte, err := decryptByte(ctx, cw.keyName, cw.wipName, encryptedBytes)
      if err != nil {
        return 0.0, err
      }
      decryptedNumber := strings.TrimSpace(string(decryptedByte))
      num, err := strconv.ParseFloat(decryptedNumber, 64)
      if err != nil {
        return 0.0, err
      }
      return num, nil
    }
    
    func decryptByte(ctx context.Context, keyName, wippro string, encryptedData []byte) ([]byte, error) {
      cc := fmt.Sprintf(credentialConfig, wippro)
      kmsClient, err := kms.NewKeyManagementClient(ctx, option.WithCredentialsJSON([]byte(cc)))
      if err != nil {
        return nil, fmt.Errorf("creating a new KMS client with federated credentials: %w", err)
      }
    
      decryptRequest := &kmspb.DecryptRequest{
        Name:       keyName,
        Ciphertext: encryptedData,
      }
      decryptResponse, err := kmsClient.Decrypt(ctx, decryptRequest)
      if err != nil {
        return nil, fmt.Errorf("could not decrypt ciphertext: %w", err)
      }
    
      return decryptResponse.Plaintext, nil
    }
    
    func getFile(ctx context.Context, c *storage.Client, bucketName string, objPath string) ([]byte, error) {
      bucketHandle := c.Bucket(bucketName)
      objectHandle := bucketHandle.Object(objPath)
    
      objectReader, err := objectHandle.NewReader(ctx)
      if err != nil {
        return nil, err
      }
      defer objectReader.Close()
    
      s, err := io.ReadAll(objectReader)
      if err != nil {
        return nil, err
      }
    
      return s, nil
    }
    
  3. Achten Sie darauf, dass alle Parteien den Quellcode lesen und prüfen.

  4. Erstellen Sie im Cloud Shell-Editor eine Datei mit dem Namen Dockerfile mit folgendem Inhalt:

    # Compile the provided Go code to a statically linked binary
    FROM golang:latest AS build
    WORKDIR /build
    COPY salary.go .
    RUN go mod init salary
    RUN go get cloud.google.com/go/kms/apiv1 cloud.google.com/go/storage google.golang.org/api/option google.golang.org/genproto/googleapis/cloud/kms/v1
    RUN CGO_ENABLED=0 go build -trimpath
    
    # Build the workload container image
    FROM alpine:latest AS run
    WORKDIR /test
    COPY --from=build /build/salary /test/salary
    ENTRYPOINT ["/test/salary"]
    CMD []
    
    # Allow the workload to access the following environment variables
    LABEL "tee.launch_policy.allow_env_override"="\
    COLLAB_1_NAME,\
    COLLAB_2_NAME,\
    COLLAB_1_ENCRYPTED_SALARY,\
    COLLAB_2_ENCRYPTED_SALARY,\
    COLLAB_1_INPUT_BUCKET,\
    COLLAB_2_INPUT_BUCKET,\
    COLLAB_1_OUTPUT_BUCKET,\
    COLLAB_2_OUTPUT_BUCKET,\
    COLLAB_1_KEYRING_NAME,\
    COLLAB_2_KEYRING_NAME,\
    COLLAB_1_KEY_NAME,\
    COLLAB_2_KEY_NAME,\
    COLLAB_1_PROJECT_ID,\
    COLLAB_2_PROJECT_ID,\
    COLLAB_1_PROJECT_NUMBER,\
    COLLAB_2_PROJECT_NUMBER,\
    COLLAB_1_POOL_NAME,\
    COLLAB_2_POOL_NAME"
    

    In diesem Dockerfile wird ein mehrstufiger Build verwendet, um zuerst den Go-Code zu kompilieren und dann die kompilierte Version dieses Codes in den endgültigen Arbeitslastcontainer zu kopieren. Außerdem können bestimmte Umgebungsvariablen in diesem Arbeitslastcontainer verwendet werden. Werte für diese Umgebungsvariablen werden später den spezifischen Ressourcen zugeordnet, die für die Ausführung der Arbeitslast erforderlich sind.

  5. Klicken Sie auf Terminal öffnen, um zu Cloud Shell zurückzukehren, oder rufen Sie das im Cloud Shell-Editor integrierte Terminal über das Menü Ansicht auf.

  6. Docker-Repository in Artifact Registry erstellen

    gcloud artifacts repositories create REPOSITORY_NAME \
        --repository-format=docker \
        --location=us
    
  7. Gewähren Sie dem Dienstkonto, das die Arbeitslast ausführen wird, die Rolle "Artifact Registry-Leser" (roles/artifactregistry.reader), damit es aus dem Repository lesen kann:

    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
    
  8. Aktualisieren Sie Ihre Docker-Anmeldedaten, um den Domainnamen us-docker.pkg.dev einzuschließen:

    gcloud auth configure-docker us-docker.pkg.dev
    
  9. Erstellen Sie ein Docker-Image aus Dockerfile, indem Sie den folgenden Befehl in das Terminal eingeben:

    docker build -t \
        "us-docker.pkg.dev/ALEX_PROJECT_ID/\
    REPOSITORY_NAME/WORKLOAD_CONTAINER_NAME:latest" .
    
  10. Übertragen Sie das Docker-Image per Push an Artifact Registry:

    docker push \
        us-docker.pkg.dev/ALEX_PROJECT_ID/REPOSITORY_NAME/WORKLOAD_CONTAINER_NAME
    
  11. In der Docker-Push-Antwort wird der SHA256-Digest des Images aufgeführt, der später zum Autorisieren der Arbeitslast erforderlich ist. Der Digest sieht dann ungefähr so aus:

    sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
    

    Kopieren Sie den Image-Digest (einschließlich des Präfixes sha256:) an einen Ort, an dem Sie darauf verweisen können. Sie können den Digest auch in das folgende Codebeispiel eingeben, um die restlichen Codebeispiele in dieser Anleitung, die den Wert benötigen, vorab auszufüllen:

    WORKLOAD_CONTAINER_IMAGE_DIGEST
    
  12. Sorgen Sie dafür, dass alle Parteien das Docker-Image prüfen und verifizieren, dass es vertrauenswürdig ist, bevor sie die Verwendung autorisieren.

Arbeitslast autorisieren

Nachdem die Arbeitslast von beiden Parteien genehmigt wurde, müssen Alex und Bola die Google Cloud-Attestierung als Anbieter zu ihren Workload Identity-Pools hinzufügen. Der Anbieter gibt den zu verwendenden Attestierungsdienst und die Eigenschaften an, die die Arbeitslast erfüllen muss, damit sie auf die Daten von Alex oder Bola zugreifen darf. Wenn ein böswilliger Akteur das Docker-Image ändert oder eine andere gemessene Eigenschaft manipuliert, wird der Arbeitslast der Zugriff verweigert.

In dieser Anleitung werden Attributzuordnungen verwendet, um der Arbeitslast basierend auf dem Image-Digest direkten Ressourcenzugriff zu gewähren. In anderen Situationen kann es jedoch besser sein, die Identitätsübernahme des Dienstkontos zu verwenden, um auf die Ressourcen zuzugreifen. Weitere Informationen finden Sie unter Zugriff auf externe Arbeitslasten.

Führen Sie die folgenden Schritte aus, um die Anbieter für Alex und Bola mit den erforderlichen Bedingungen einzurichten:

  1. Geben Sie den folgenden Befehl ein, um den Anbieter für Alex zu erstellen:

    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'"
    
  2. Rufen Sie die Projektnummer von Alex für den nächsten Befehl ab:

    gcloud projects describe ALEX_PROJECT_ID --format="value(projectNumber)"
    
  3. Weisen Sie der föderierten Identität, die vom Anbieter von Alex definiert wurde, die Rolle cloudkms.cryptoKeyDecrypter zu und geben Sie das Attribut image_digest an, damit nur Arbeitslastcontainer mit dem angegebenen Digest ihre KMS-Schlüssel entschlüsseln können:

    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
    
  4. So wechseln Sie zum Projekt von Bola:

    gcloud config set project BOLA_PROJECT_ID
    
  5. Geben Sie den folgenden Befehl ein, um den Anbieter für Bola zu erstellen:

    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'"
    
  6. Rufen Sie die Projektnummer von Bola für den nächsten Befehl ab:

    gcloud projects describe BOLA_PROJECT_ID --format="value(projectNumber)"
    
  7. Weisen Sie der föderierten Identität, die vom Anbieter von Bola definiert wird, die Rolle cloudkms.cryptoKeyDecrypter zu und geben Sie das Attribut image_digest an, damit nur Arbeitslastcontainer mit dem angegebenen Digest ihre KMS-Schlüssel entschlüsseln können:

    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
    

Arbeitslast testen

Da nun sowohl dem Workload Identity-Pool von Alex als auch dem von Bola Anbieter hinzugefügt wurden, ist es Zeit, dass der Arbeitslastoperator die Arbeitslast testet.

Zum Testen der Arbeitslast erstellen Sie eine neue Confidential VM-Instanz im Projekt von Bola mit den folgenden Attributen:

Geben Sie den folgenden Befehl im Cloud Shell von Bola ein, um die Arbeitslast zu testen:

gcloud compute instances create WORKLOAD_VM_2_NAME \
    --confidential-compute-type=SEV \
    --shielded-secure-boot \
    --scopes=cloud-platform \
    --zone=us-west1-b \
    --maintenance-policy=MIGRATE \
    --min-cpu-platform="AMD Milan" \
    --image-project=confidential-space-images \
    --image-family=confidential-space-debug \
    --service-account=WORKLOAD_SERVICE_ACCOUNT_NAME@BOLA_PROJECT_ID.iam.gserviceaccount.com \
    --metadata="^~^tee-image-reference=us-docker.pkg.dev/\
ALEX_PROJECT_ID/REPOSITORY_NAME/WORKLOAD_CONTAINER_NAME:latest\
~tee-container-log-redirect=true\
~tee-env-COLLAB_1_NAME=Alex\
~tee-env-COLLAB_2_NAME=Bola\
~tee-env-COLLAB_1_ENCRYPTED_SALARY=ALEX_ENCRYPTED_SALARY_FILE\
~tee-env-COLLAB_2_ENCRYPTED_SALARY=BOLA_ENCRYPTED_SALARY_FILE\
~tee-env-COLLAB_1_INPUT_BUCKET=ALEX_INPUT_BUCKET_NAME\
~tee-env-COLLAB_2_INPUT_BUCKET=BOLA_INPUT_BUCKET_NAME\
~tee-env-COLLAB_1_OUTPUT_BUCKET=ALEX_OUTPUT_BUCKET_NAME\
~tee-env-COLLAB_2_OUTPUT_BUCKET=BOLA_OUTPUT_BUCKET_NAME\
~tee-env-COLLAB_1_KEYRING_NAME=ALEX_KEYRING_NAME\
~tee-env-COLLAB_2_KEYRING_NAME=BOLA_KEYRING_NAME\
~tee-env-COLLAB_1_KEY_NAME=ALEX_KEY_NAME\
~tee-env-COLLAB_2_KEY_NAME=BOLA_KEY_NAME\
~tee-env-COLLAB_1_PROJECT_ID=ALEX_PROJECT_ID\
~tee-env-COLLAB_2_PROJECT_ID=BOLA_PROJECT_ID\
~tee-env-COLLAB_1_PROJECT_NUMBER=ALEX_PROJECT_NUMBER\
~tee-env-COLLAB_2_PROJECT_NUMBER=BOLA_PROJECT_NUMBER\
~tee-env-COLLAB_1_POOL_NAME=ALEX_POOL_NAME\
~tee-env-COLLAB_2_POOL_NAME=BOLA_POOL_NAME"

Fortschritt ansehen

Sie können den Fortschritt der Arbeitslast im Projekt von Bola ansehen. Rufen Sie dazu den Logs-Explorer auf.

Zum Log-Explorer

Wenn Sie nur Confidential Space-Logeinträge aufrufen möchten, filtern Sie nach den folgenden Logfeldern, sofern verfügbar:

  • Ressourcentyp:VM-Instanz

  • Instanz-ID: Die Instanz-ID der VM

  • Logname: confidential-space-launcher

Wenn Sie das Log aktualisieren möchten, klicken Sie auf  Zu jetzt springen. Sie können auch zu früheren Ergebnissen scrollen und dann wieder zum Ende des Logs scrollen, um die neuesten Einträge zu laden.

Ergebnisse aufrufen

Wenn die Arbeitslastaufgabe beendet wird und 0 zurückgibt, sind keine Fehler aufgetreten. Sie können jetzt die Ausgabe in den Ausgabebuckets von Alex und Bola prüfen:

  1. Wechseln Sie zu Alex' Projekt:

    gcloud config set project ALEX_PROJECT_ID
    
  2. Listen Sie alle Dateien in seinem Ergebnis-Bucket auf:

    gcloud storage ls gs://ALEX_OUTPUT_BUCKET_NAME
    
  3. Lesen Sie die zuletzt aufgeführte Datei ein und ersetzen Sie ALEX_OUTPUT_CLOUD_STORAGE_PATH durch den Pfad der Datei, einschließlich gs://:

    gcloud storage cat ALEX_OUTPUT_CLOUD_STORAGE_PATH
    

    Wenn keine Datei vorhanden ist, müssen Sie Ihre Arbeitslast debuggen.

  4. So wechseln Sie zum Projekt von Bola:

    gcloud config set project BOLA_PROJECT_ID
    
  5. Listen Sie alle Dateien in seinem Ergebnis-Bucket auf:

    gcloud storage ls gs://BOLA_OUTPUT_BUCKET_NAME
    
  6. Lesen Sie die zuletzt aufgeführte Datei ein und ersetzen Sie BOLA_RESULTS_CLOUD_STORAGE_PATH durch den Pfad der Datei, einschließlich gs://:

    gcloud storage cat BOLA_RESULTS_CLOUD_STORAGE_PATH
    

    Wenn keine Datei vorhanden ist, müssen Sie Ihre Arbeitslast debuggen.

  7. Nachdem Sie die Ergebnisse gelesen haben, beenden Sie die VM-Instanz:

    gcloud compute instances stop WORKLOAD_VM_2_NAME --zone=us-west1-b
    

Indem sie die Dateien lesen, stellen Alex und Bola jeweils fest, wer mehr verdient, ohne sich dabei jemals gegenseitig ihre Gehälter offenzulegen.

Arbeitslast debuggen und neu starten

Eine Confidential Space-Umgebung besteht aus vielen Teilen. Es ist möglich, dass etwas falsch konfiguriert wurde, was dazu führt, dass die Arbeitslast fehlschlägt.

Anders als beim Confidential Space-Produktions-Image wird die VM-Instanz beim Debugging-Image nach Abschluss der Arbeitslast nicht beendet. Wenn die Logs nicht genügend Informationen zur Behebung des Problems enthalten, müssen Sie sich als Nächstes über SSH mit Ihrer VM-Instanz verbinden und mit dem Debugging fortfahren.

Wenn Sie mit dem Debugging fertig sind, beenden Sie die VM-Instanz:

gcloud compute instances stop WORKLOAD_VM_2_NAME --zone=us-west1-b

Wenn Sie die Arbeitslast in der Umgebung mit Debugging ausführen möchten, starten Sie die VM noch einmal:

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

Umgebung für die Produktion härten

Nachdem Sie die Arbeitslast erfolgreich getestet haben, ist es an der Zeit, die Confidential Space-Umgebung für die Produktionsbereitstellung zu härten. Alex und Bola müssen ihren Anbietern eine support_attributes-Assertion hinzufügen, um zu bestätigen, dass das Confidential Space-Produktions-Image für die Arbeitslast verwendet wird:

  1. Wechseln Sie zu Alex' Projekt:

    gcloud config set project ALEX_PROJECT_ID
    
  2. Geben Sie den folgenden Befehl ein, um den Anbieter für Alex zu aktualisieren:

    gcloud iam workload-identity-pools providers update-oidc attestation-verifier \
        --location=global \
        --workload-identity-pool=ALEX_POOL_NAME \
        --issuer-uri="https://confidentialcomputing.googleapis.com/" \
        --allowed-audiences="https://sts.googleapis.com" \
        --attribute-mapping="google.subject=\"gcpcs\
    ::\"+assertion.submods.container.image_digest+\"\
    ::\"+assertion.submods.gce.project_number+\"\
    ::\"+assertion.submods.gce.instance_id,\
    attribute.image_digest=assertion.submods.container.image_digest" \
        --attribute-condition="assertion.swname == 'CONFIDENTIAL_SPACE' \
            && 'STABLE' in assertion.submods.confidential_space.support_attributes"
    
  3. So wechseln Sie zum Projekt von Bola:

    gcloud config set project BOLA_PROJECT_ID
    
  4. Geben Sie den folgenden Befehl ein, um den Anbieter für Bola zu aktualisieren:

    gcloud iam workload-identity-pools providers update-oidc attestation-verifier \
        --location=global \
        --workload-identity-pool=BOLA_POOL_NAME \
        --issuer-uri="https://confidentialcomputing.googleapis.com/" \
        --allowed-audiences="https://sts.googleapis.com" \
        --attribute-mapping="google.subject=\"gcpcs\
    ::\"+assertion.submods.container.image_digest+\"\
    ::\"+assertion.submods.gce.project_number+\"\
    ::\"+assertion.submods.gce.instance_id,\
    attribute.image_digest=assertion.submods.container.image_digest" \
        --attribute-condition="assertion.swname == 'CONFIDENTIAL_SPACE' \
            && 'STABLE' in assertion.submods.confidential_space.support_attributes"
    

Produktionsarbeitslast bereitstellen

Bola muss eine separate VM-Instanz erstellen, um die Produktionsarbeitslast auszuführen. Im Vergleich zur Testarbeitslast gibt es folgende Unterschiede:

  • Das Betriebssystem basiert auf dem Confidential Space-Produktions-Image. Dabei ist SSH deaktiviert und die VM-Instanz wird nach Abschluss der Arbeitslast beendet.

  • Die Protokollierungsumleitung wurde entfernt. In Cloud Logging werden nur einfache Logs angezeigt, die keine vertraulichen Informationen enthalten.

Geben Sie den folgenden Befehl im Cloud Shell von Bola ein, um die Produktionsarbeitslast bereitzustellen:

gcloud compute instances create WORKLOAD_VM_NAME \
    --confidential-compute-type=SEV \
    --shielded-secure-boot \
    --scopes=cloud-platform \
    --zone=us-west1-b \
    --maintenance-policy=MIGRATE \
    --image-project=confidential-space-images \
    --image-family=confidential-space \
    --service-account=WORKLOAD_SERVICE_ACCOUNT_NAME@BOLA_PROJECT_ID.iam.gserviceaccount.com \
    --metadata="^~^tee-image-reference=us-docker.pkg.dev/\
ALEX_PROJECT_ID/REPOSITORY_NAME/WORKLOAD_CONTAINER_NAME:latest\
~tee-env-COLLAB_1_NAME=Alex\
~tee-env-COLLAB_2_NAME=Bola\
~tee-env-COLLAB_1_ENCRYPTED_SALARY=ALEX_ENCRYPTED_SALARY_FILE\
~tee-env-COLLAB_2_ENCRYPTED_SALARY=BOLA_ENCRYPTED_SALARY_FILE\
~tee-env-COLLAB_1_INPUT_BUCKET=ALEX_INPUT_BUCKET_NAME\
~tee-env-COLLAB_2_INPUT_BUCKET=BOLA_INPUT_BUCKET_NAME\
~tee-env-COLLAB_1_OUTPUT_BUCKET=ALEX_OUTPUT_BUCKET_NAME\
~tee-env-COLLAB_2_OUTPUT_BUCKET=BOLA_OUTPUT_BUCKET_NAME\
~tee-env-COLLAB_1_KEYRING_NAME=ALEX_KEYRING_NAME\
~tee-env-COLLAB_2_KEYRING_NAME=BOLA_KEYRING_NAME\
~tee-env-COLLAB_1_KEY_NAME=ALEX_KEY_NAME\
~tee-env-COLLAB_2_KEY_NAME=BOLA_KEY_NAME\
~tee-env-COLLAB_1_PROJECT_ID=ALEX_PROJECT_ID\
~tee-env-COLLAB_2_PROJECT_ID=BOLA_PROJECT_ID\
~tee-env-COLLAB_1_PROJECT_NUMBER=ALEX_PROJECT_NUMBER\
~tee-env-COLLAB_2_PROJECT_NUMBER=BOLA_PROJECT_NUMBER\
~tee-env-COLLAB_1_POOL_NAME=ALEX_POOL_NAME\
~tee-env-COLLAB_2_POOL_NAME=BOLA_POOL_NAME"

Die Art und Weise, wie Sie den Fortschritt ansehen und die Ergebnisse ansehen, ist dieselbe wie beim Testen der Arbeitslast.

Wenn die Produktionsarbeitslast abgeschlossen ist, wird die VM-Instanz beendet. Wenn Sie andere Ergebnisse sehen möchten, können Sie die Gehälter ändern, sie neu verschlüsseln, sie noch einmal in die entsprechenden Cloud Storage-Buckets hochladen und dann die VM-Instanz neu starten, um die Arbeitslast noch einmal auszuführen:

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

Bereinigen

Führen Sie die folgenden Schritte aus, um die in dieser Anleitung erstellten Ressourcen zu entfernen.

Alexanders Ressourcen bereinigen

  1. Wechseln Sie zu Alex' Projekt:

    gcloud config set project ALEX_PROJECT_ID
    
  2. Löschen Sie den Workload Identity-Pool von Alex:

    gcloud iam workload-identity-pools delete ALEX_POOL_NAME \
        --location=global
    
  3. Löschen Sie die Cloud Storage-Buckets von Alex:

    gcloud storage rm gs://ALEX_INPUT_BUCKET_NAME \
        gs://ALEX_OUTPUT_BUCKET_NAME --recursive
    
  4. Löschen Sie die Gehaltsdateien von Alex, den Go-Code und die Dockerfile:

    rm ALEX_SALARY.txt \
        ALEX_ENCRYPTED_SALARY_FILE \
        salary.go \
        Dockerfile
    
  5. Optional: Deaktivieren oder löschen Sie den Cloud Key Management Service-Schlüssel von Alex.

  6. Optional: Beenden Sie das Projekt von Alex.

Bola-Ressourcen bereinigen

  1. So wechseln Sie zum Projekt von Bola:

    gcloud config set project BOLA_PROJECT_ID
    
  2. Löschen Sie die VM, auf der der Testworkflow ausgeführt wurde:

    gcloud compute instances delete WORKLOAD_VM_2_NAME --zone=us-west1-b
    
  3. Löschen Sie die VM, auf der der Produktionsworkflow ausgeführt wurde:

    gcloud compute instances delete WORKLOAD_VM_NAME --zone=us-west1-b
    
  4. Löschen Sie das Dienstkonto, mit dem die Arbeitslast ausgeführt wurde:

    gcloud iam service-accounts delete \
        WORKLOAD_SERVICE_ACCOUNT_NAME@BOLA_PROJECT_ID.iam.gserviceaccount.com
    
  5. Workload Identity-Pool von Bola löschen:

    gcloud iam workload-identity-pools delete BOLA_POOL_NAME \
        --location=global
    
  6. Löschen Sie die Cloud Storage-Buckets von Bola:

    gcloud storage rm gs://BOLA_INPUT_BUCKET_NAME \
        gs://BOLA_OUTPUT_BUCKET_NAME --recursive
    
  7. Gehaltsdateien von Bola löschen:

    rm BOLA_SALARY.txt \
        BOLA_ENCRYPTED_SALARY_FILE
    
  8. Optional: Deaktivieren oder löschen Sie den Cloud Key Management Service-Schlüssel von Bola.

  9. Optional: Beenden Sie das Projekt von Bola.