วิธีทำธุรกรรมเนื้อหาดิจิทัลด้วยการประมวลผลจากหลายฝ่ายและพื้นที่ลับ

1. ภาพรวม

ก่อนที่เราจะเริ่ม แม้ว่าไม่จำเป็นทั้งหมด แต่ความรู้เกี่ยวกับฟีเจอร์และแนวคิดต่อไปนี้จะเป็นประโยชน์ในโค้ดแล็บนี้

4670cd5427aa39a6.png

สิ่งที่คุณจะได้เรียนรู้

ห้องทดลองนี้มีการใช้งานอ้างอิงสำหรับการลงนามในบล็อกเชนที่สอดคล้องกับ MPC โดยใช้ Confidential Space เพื่ออธิบายแนวคิด เราจะยกตัวอย่างสถานการณ์ที่บริษัท Primus ต้องการโอนชิ้นงานดิจิทัลไปยังบริษัท Secundus ในสถานการณ์นี้ บริษัท Primus ใช้โมเดลที่สอดคล้องกับ MPC ซึ่งหมายความว่าบริษัทใช้การแชร์คีย์แบบกระจายแทนการใช้คีย์ส่วนตัวแต่ละรายการ โดยคีย์แชร์เหล่านี้จะถือครองโดยหลายฝ่าย ในกรณีนี้คืออลิซและบ็อบ แนวทางนี้ช่วยให้ Company Primus ได้รับประโยชน์หลายประการ ซึ่งรวมถึงประสบการณ์ของผู้ใช้ที่ง่ายขึ้น ประสิทธิภาพในการดำเนินงาน และการควบคุมคีย์ส่วนตัว

เพื่ออธิบายแง่มุมพื้นฐานของกระบวนการนี้ เราจะอธิบายรายละเอียดการตั้งค่าทางเทคนิคและแนะนำขั้นตอนการอนุมัติและการลงนามที่จะเริ่มการโอนชิ้นงานดิจิทัลจากบริษัท Primus ไปยังบริษัท Secundus โปรดทราบว่าบัญชาและขวัญใจซึ่งเป็นพนักงานของบริษัทไพรมัสทั้งคู่ต้องอนุมัติธุรกรรม

แม้ว่าการติดตั้งใช้งานอ้างอิงนี้จะแสดงการดำเนินการลายเซ็น แต่ก็ไม่ได้ครอบคลุมทุกด้านของการจัดการคีย์ MPC เช่น เราจะไม่พูดถึงการสร้างคีย์ นอกจากนี้ ยังมีแนวทางอื่นและแนวทางเสริม เช่น การใช้บริการที่ไม่ใช่ Google Cloud เพื่อสร้างลายเซ็นร่วม หรือให้ผู้ร่วมลงนามสร้างลายเซ็นบล็อกเชนในสภาพแวดล้อมของตนเอง ซึ่งเป็นสถาปัตยกรรมแบบกระจายศูนย์มากกว่า เราหวังว่าห้องทดลองนี้จะสร้างแรงบันดาลใจให้เกิดแนวทางต่างๆ ในการใช้ MPC บน Google Cloud

คุณจะทำงานกับเวิร์กโหลดอย่างง่ายที่ลงนามในธุรกรรม Ethereum ใน Confidential Space โดยใช้วัสดุคีย์ผู้ร่วมลงนาม การลงนามธุรกรรม Ethereum เป็นกระบวนการที่ผู้ใช้สามารถให้สิทธิ์ธุรกรรมในบล็อกเชน Ethereum หากต้องการส่งธุรกรรม Ethereum คุณต้องลงนามด้วยคีย์ส่วนตัว ซึ่งเป็นการพิสูจน์ว่าคุณเป็นเจ้าของบัญชีและอนุญาตให้ทำธุรกรรม กระบวนการลงนามมีดังนี้

  1. ผู้ส่งจะสร้างออบเจ็กต์ธุรกรรมที่ระบุที่อยู่ของผู้รับ จำนวน ETH ที่จะส่ง และข้อมูลอื่นๆ ที่เกี่ยวข้อง
  2. ระบบจะใช้คีย์ส่วนตัวของผู้ส่งเพื่อแฮชข้อมูลธุรกรรม
  3. จากนั้นระบบจะลงนามแฮชด้วยคีย์ส่วนตัว
  4. ระบบจะแนบลายเซ็นไปกับออบเจ็กต์ธุรกรรม
  5. ระบบจะกระจายธุรกรรมไปยังเครือข่าย Ethereum

เมื่อโหนดในเครือข่ายได้รับธุรกรรม โหนดจะยืนยันลายเซ็นเพื่อให้แน่ใจว่าเจ้าของบัญชีเป็นผู้ลงนาม หากลายเซ็นถูกต้อง โหนดจะเพิ่มธุรกรรมลงในบล็อกเชน

ก่อนอื่น คุณจะต้องกำหนดค่าทรัพยากรระบบคลาวด์ที่จำเป็น จากนั้นคุณจะเรียกใช้เวิร์กโหลดใน Confidential Space Codelab นี้จะแนะนำขั้นตอนระดับสูงต่อไปนี้

  • วิธีกำหนดค่าทรัพยากรระบบคลาวด์ที่จำเป็นสำหรับการเรียกใช้ Confidential Space
  • วิธีให้สิทธิ์เข้าถึงทรัพยากรที่มีการป้องกันตามแอตทริบิวต์ของ
  • อะไร: คอนเทนเนอร์ของภาระงาน
  • ที่ไหน: สภาพแวดล้อม Confidential Space (อิมเมจ Confidential Space ใน Confidential VM)
  • ใคร: บัญชีที่เรียกใช้เวิร์กโหลด
  • วิธีเรียกใช้เวิร์กโหลดใน VM ที่เป็นความลับซึ่งเรียกใช้อิมเมจ VM ของ Confidential Space

API ที่จำเป็น

คุณต้องเปิดใช้ API ต่อไปนี้ในโปรเจ็กต์ที่ระบุเพื่อให้ทำตามคำแนะนำนี้ได้

ชื่อ API

ชื่อ API

cloudkms.googleapis.com

Cloud KMS

compute.googleapis.com

Compute Engine

confidentialcomputing.googleapis.com

Confidential Computing

iamcredentials.googleapis.com

IAM

artifactregistry.googleapis.com

Artifact Registry

2. ตั้งค่าทรัพยากรระบบคลาวด์

ก่อนเริ่มต้น

  • โคลน ที่เก็บนี้โดยใช้คำสั่งด้านล่างเพื่อรับสคริปต์ที่จำเป็นซึ่งใช้เป็นส่วนหนึ่งของ Codelab นี้
git clone https://github.com/GoogleCloudPlatform/confidential-space.git
  • เปลี่ยนไดเรกทอรีสำหรับ Codelab นี้
cd confidential-space/codelabs/digital_asset_transaction_codelab/scripts
  • ตรวจสอบว่าคุณได้ตั้งค่าตัวแปรสภาพแวดล้อมของโปรเจ็กต์ที่จำเป็นตามที่แสดงด้านล่าง ดูข้อมูลเพิ่มเติมเกี่ยวกับการตั้งค่าโปรเจ็กต์ GCP ได้ที่ Codelab นี้ คุณดูรายละเอียดเกี่ยวกับวิธีดึงรหัสโปรเจ็กต์และวิธีที่รหัสโปรเจ็กต์แตกต่างจากชื่อโปรเจ็กต์และหมายเลขโปรเจ็กต์ได้ที่นี่ .
export PRIMUS_PROJECT_ID=<GCP project id>
gcloud services enable \
   cloudapis.googleapis.com \
    cloudkms.googleapis.com \
    cloudresourcemanager.googleapis.com \
    cloudshell.googleapis.com \
    container.googleapis.com \
    containerregistry.googleapis.com \
    iam.googleapis.com \
    confidentialcomputing.googleapis.com
  • หากต้องการตั้งค่าตัวแปรสำหรับชื่อทรัพยากร ให้ใช้คำสั่งต่อไปนี้ โปรดทราบว่าการดำเนินการนี้จะลบล้างชื่อทรัพยากรที่เฉพาะเจาะจงสำหรับโปรเจ็กต์ GCP ของบริษัท ก. เช่น export PRIMUS_INPUT_STORAGE_BUCKET='primus-input-bucket'
  • คุณตั้งค่าตัวแปรต่อไปนี้สำหรับโปรเจ็กต์ GCP ในบริษัท ก. ได้

$PRIMUS_INPUT_STORAGE_BUCKET

ที่เก็บข้อมูลที่จัดเก็บคีย์ที่เข้ารหัส

$PRIMUS_RESULT_STORAGE_BUCKET

ที่เก็บข้อมูลที่จัดเก็บผลลัพธ์ของธุรกรรม MPC

$PRIMUS_KEY

คีย์ KMS ที่ใช้ในการเข้ารหัสข้อมูลที่จัดเก็บไว้ใน $PRIMUS_INPUT_STORAGE_BUCKET สำหรับ Primus Bank

$PRIMUS_KEYRING

พวงกุญแจ KMS ที่จะใช้สร้างคีย์การเข้ารหัส $PRIMUS_KEY สำหรับ Primus Bank

$PRIMUS_WIP_PROVIDER

ผู้ให้บริการ Workload Identity Pool ซึ่งรวมถึงเงื่อนไขแอตทริบิวต์ที่จะใช้สำหรับโทเค็นที่ลงนามโดยบริการภาระงาน MPC

$PRIMUS_SERVICEACCOUNT

บัญชีบริการที่ $PRIMUS_WORKLOAD_IDENTITY_POOL ใช้เพื่อเข้าถึงทรัพยากรที่ได้รับการปกป้อง บัญชีบริการนี้จะมีสิทธิ์ดูคีย์ที่เข้ารหัสซึ่งจัดเก็บไว้ในที่เก็บข้อมูล $PRIMUS_INPUT_STORAGE_BUCKET

$PRIMUS_ARTIFACT_REPOSITORY

ที่เก็บสิ่งประดิษฐ์สำหรับจัดเก็บอิมเมจคอนเทนเนอร์ของภาระงาน

$WORKLOAD_SERVICEACCOUNT

บัญชีบริการที่มีสิทธิ์เข้าถึง Confidential VM ที่เรียกใช้ภาระงาน

$WORKLOAD_CONTAINER

คอนเทนเนอร์ Docker ที่เรียกใช้ภาระงาน

$WORKLOAD_IMAGE_NAME

ชื่อของอิมเมจคอนเทนเนอร์ของภาระงาน

$WORKLOAD_IMAGE_TAG

แท็กของอิมเมจคอนเทนเนอร์ของภาระงาน

  • เรียกใช้สคริปต์ต่อไปนี้เพื่อตั้งค่าชื่อตัวแปรที่เหลือเป็นค่าตามรหัสโปรเจ็กต์สำหรับชื่อทรัพยากร
source config_env.sh

ตั้งค่าทรัพยากรระบบคลาวด์

ในขั้นตอนนี้ คุณจะต้องตั้งค่าทรัพยากรระบบคลาวด์ที่จำเป็นสำหรับการประมวลผลแบบหลายฝ่าย สำหรับแล็บนี้ คุณจะใช้คีย์ส่วนตัวต่อไปนี้ 0000000000000000000000000000000000000000000000000000000000000001

ในสภาพแวดล้อมการใช้งานจริง คุณจะต้องสร้างคีย์ส่วนตัวของคุณเอง อย่างไรก็ตาม เพื่อวัตถุประสงค์ของแล็บนี้ เราจะแบ่งคีย์ส่วนตัวนี้ออกเป็น 2 ส่วนและเข้ารหัสแต่ละส่วน ในสถานการณ์การใช้งานจริง ไม่ควรจัดเก็บคีย์ไว้ในไฟล์ข้อความธรรมดา แต่คุณสามารถสร้างคีย์ส่วนตัวภายนอก Google Cloud (หรือข้ามไปเลยและแทนที่ด้วยการสร้างคีย์ย่อย MPC ที่กำหนดเอง) แล้วเข้ารหัสเพื่อให้ไม่มีใครเข้าถึงคีย์ส่วนตัวหรือคีย์แชร์ได้ เราจะใช้ Gcloud CLI เพื่อวัตถุประสงค์ของแล็บนี้

เรียกใช้สคริปต์ต่อไปนี้เพื่อตั้งค่าทรัพยากรระบบคลาวด์ที่จำเป็น ในขั้นตอนเหล่านี้ ระบบจะสร้างทรัพยากรที่กล่าวถึงด้านล่าง

  • ที่เก็บข้อมูล Cloud Storage ($PRIMUS_INPUT_STORAGE_BUCKET) เพื่อจัดเก็บส่วนของคีย์ส่วนตัวที่เข้ารหัส
  • ที่เก็บข้อมูล Cloud Storage ($PRIMUS_RESULT_STORAGE_BUCKET) เพื่อจัดเก็บผลลัพธ์ของธุรกรรมสินทรัพย์ดิจิทัล
  • คีย์การเข้ารหัส ($PRIMUS_KEY) และพวงกุญแจ ($PRIMUS_KEYRING) ใน KMS เพื่อเข้ารหัสการแชร์คีย์ส่วนตัว
  • Workload Identity Pool ($PRIMUS_WORKLOAD_IDENTITY_POOL) เพื่อตรวจสอบการอ้างสิทธิ์ตามเงื่อนไขของแอตทริบิวต์ที่กำหนดค่าไว้ภายใต้ผู้ให้บริการ
  • บัญชีบริการ ($PRIMUS_SERVICEACCOUNT) ที่แนบกับพูล Workload Identity ($PRIMUS_WORKLOAD_IDENTITY_POOL) ที่กล่าวถึงข้างต้นพร้อมสิทธิ์เข้าถึง IAM ต่อไปนี้
  • roles/cloudkms.cryptoKeyDecrypter เพื่อถอดรหัสข้อมูลโดยใช้คีย์ KMS
  • objectViewer เพื่ออ่านข้อมูลจากที่เก็บข้อมูล Cloud Storage
  • roles/iam.workloadIdentityUser เพื่อเชื่อมต่อบัญชีบริการนี้กับ Workload Identity Pool
./setup_resources.sh

3. สร้างภาระงาน

สร้างบัญชีบริการของเวิร์กโหลด

ตอนนี้คุณจะสร้างบัญชีบริการสำหรับภาระงานที่มีบทบาทและสิทธิ์ที่จำเป็น โดยให้เรียกใช้สคริปต์ต่อไปนี้ ซึ่งจะสร้างบัญชีบริการของเวิร์กโหลดสำหรับบริษัท ก. VM ที่เรียกใช้เวิร์กโหลดจะใช้บัญชีบริการนี้

บัญชีบริการของเวิร์กโหลด ($WORKLOAD_SERVICEACCOUNT) จะมีบทบาทต่อไปนี้

  • confidentialcomputing.workloadUser เพื่อรับโทเค็นการรับรอง
  • logging.logWriter เพื่อเขียนบันทึกลงใน Cloud Logging
  • objectViewer เพื่ออ่านข้อมูลจากที่เก็บข้อมูล $PRIMUS_INPUT_STORAGE_BUCKET Cloud Storage
  • objectUser เพื่อเขียนผลลัพธ์ของเวิร์กโหลดไปยังที่เก็บข้อมูล $PRIMUS_RESULT_STORAGE_BUCKET Cloud Storage
./create_workload_service_account.sh

สร้างภาระงาน

ขั้นตอนนี้เกี่ยวข้องกับการสร้างอิมเมจ Docker ของภาระงาน เวิร์กโหลดในโค้ดแล็บนี้คือแอปพลิเคชัน MPC ของ Node.js อย่างง่ายที่ลงนามในธุรกรรมดิจิทัลสำหรับการโอนสินทรัพย์โดยใช้การแชร์คีย์ส่วนตัวที่เข้ารหัส ที่นี่คือโค้ดโปรเจ็กต์ของเวิร์กโหลด โปรเจ็กต์ภาระงานมีไฟล์ต่อไปนี้

package.json: ไฟล์นี้มีรายการแพ็กเกจที่ควรใช้สำหรับแอปพลิเคชัน MPC ของเวิร์กโหลด ในกรณีนี้ เราจะใช้ไลบรารี @google-cloud/kms, @google-cloud/storage, ethers และ fast-crc32c ที่นี่คือไฟล์ package.json ที่เราจะใช้สำหรับโค้ดแล็บนี้

index.js: นี่คือจุดแรกเข้าของแอปพลิเคชันเวิร์กโหลด และระบุคำสั่งที่ควรเรียกใช้เมื่อคอนเทนเนอร์เวิร์กโหลดเริ่มต้น นอกจากนี้ เรายังได้รวมตัวอย่างธุรกรรมที่ไม่ได้ลงนามซึ่งปกติแล้วจะมาจากแอปพลิเคชันที่ไม่น่าเชื่อถือที่ขอให้ผู้ใช้ลงนาม ไฟล์ index.js นี้ยังนําเข้าฟังก์ชันจาก mpc.js ซึ่งเราจะสร้างในขั้นตอนถัดไปด้วย ด้านล่างนี้คือเนื้อหาของไฟล์ index.js และคุณยังดูได้ที่นี่

import {signTransaction, submitTransaction, uploadFromMemory} from './mpc.js';

const signAndSubmitTransaction = async () => {
  try {
    // Create the unsigned transaction object
    const unsignedTransaction = {
      nonce: 0,
      gasLimit: 21000,
      gasPrice: '0x09184e72a000',
      to: '0x0000000000000000000000000000000000000000',
      value: '0x00',
      data: '0x',
    };

    // Sign the transaction
    const signedTransaction = await signTransaction(unsignedTransaction);

    // Submit the transaction to Ganache
    const transaction = await submitTransaction(signedTransaction);

    // Write the transaction receipt
    uploadFromMemory(transaction);

    return transaction;
  } catch (e) {
    console.log(e);
    uploadFromMemory(e);
  }
};

await signAndSubmitTransaction();

mpc.js: ส่วนนี้คือที่ที่การลงนามธุรกรรมเกิดขึ้น โดยจะนำเข้าฟังก์ชันจาก kms-decrypt และ credential-config ซึ่งเราจะพูดถึงในส่วนถัดไป ด้านล่างนี้คือเนื้อหาของไฟล์ mpc.js และคุณยังดูเนื้อหาได้ที่นี่

import {Storage} from '@google-cloud/storage';
import {ethers} from 'ethers';

import {credentialConfig} from './credential-config.js';
import {decryptSymmetric} from './kms-decrypt.js';

const providers = ethers.providers;
const Wallet = ethers.Wallet;

// The ID of the GCS bucket holding the encrypted keys
const bucketName = process.env.KEY_BUCKET;

// Name of the encrypted key files.
const encryptedKeyFile1 = 'alice_encrypted_key_share';
const encryptedKeyFile2 = 'bob_encrypted_key_share';

// Create a new storage client with the credentials
const storageWithCreds = new Storage({
  credentials: credentialConfig,
});

// Create a new storage client without the credentials
const storage = new Storage();

const downloadIntoMemory = async (keyFile) => {
  // Downloads the file into a buffer in memory.
  const contents =
      await storageWithCreds.bucket(bucketName).file(keyFile).download();

  return contents;
};

const provider =
    new providers.JsonRpcProvider(`http://${process.env.NODE_URL}:80`);

export const signTransaction = async (unsignedTransaction) => {
  /* Check if Alice and Bob have both approved the transaction
  For this example, we're checking if their encrypted keys are available. */
  const encryptedKey1 =
      await downloadIntoMemory(encryptedKeyFile1).catch(console.error);
  const encryptedKey2 =
      await downloadIntoMemory(encryptedKeyFile2).catch(console.error);

  // For each key share, make a call to KMS to decrypt the key
  const privateKeyshare1 = await decryptSymmetric(encryptedKey1[0]);
  const privateKeyshare2 = await decryptSymmetric(encryptedKey2[0]);

  /* Perform the MPC calculations
  In this example, we're combining the private key shares
  Alternatively, you could import your mpc calculations here */
  const wallet = new Wallet(privateKeyshare1 + privateKeyshare2);

  // Sign the transaction
  const signedTransaction = await wallet.signTransaction(unsignedTransaction);

  return signedTransaction;
};

export const submitTransaction = async (signedTransaction) => {
  // This can now be sent to Ganache
  const hash = await provider.sendTransaction(signedTransaction);
  return hash;
};

export const uploadFromMemory = async (contents) => {
  // Upload the results to the bucket without service account impersonation
  await storage.bucket(process.env.RESULTS_BUCKET)
      .file('transaction_receipt_' + Date.now())
      .save(JSON.stringify(contents));
};

kms-decrypt.js: ไฟล์นี้มีโค้ดสำหรับการถอดรหัสโดยใช้คีย์ที่จัดการใน KMS เนื้อหาของไฟล์ kms-decrypt.js อยู่ด้านล่าง และคุณยังดูได้ที่นี่

import {KeyManagementServiceClient} from '@google-cloud/kms';
import crc32c from 'fast-crc32c';

import {credentialConfig} from './credential-config.js';

const projectId = process.env.PRIMUS_PROJECT_ID;
const locationId = process.env.PRIMUS_LOCATION;
const keyRingId = process.env.PRIMUS_ENC_KEYRING;
const keyId = process.env.PRIMUS_ENC_KEY;

// Instantiates a client
const client = new KeyManagementServiceClient({
  credentials: credentialConfig,
});

// Build the key name
const keyName = client.cryptoKeyPath(projectId, locationId, keyRingId, keyId);

export const decryptSymmetric = async (ciphertext) => {
  const ciphertextCrc32c = crc32c.calculate(ciphertext);
  const [decryptResponse] = await client.decrypt({
    name: keyName,
    ciphertext,
    ciphertextCrc32c: {
      value: ciphertextCrc32c,
    },
  });

  // Optional, but recommended: perform integrity verification on
  // decryptResponse. For more details on ensuring E2E in-transit integrity to
  // and from Cloud KMS visit:
  // https://cloud.google.com/kms/docs/data-integrity-guidelines
  if (crc32c.calculate(decryptResponse.plaintext) !==
      Number(decryptResponse.plaintextCrc32c.value)) {
    throw new Error('Decrypt: response corrupted in-transit');
  }

  const plaintext = decryptResponse.plaintext.toString();

  return plaintext;
};

credential-config.js: ไฟล์จะจัดเก็บเส้นทางและรายละเอียดของ Workload Identity Pool สำหรับการแอบอ้างเป็นบัญชีบริการ ที่นี่คือไฟล์ credential-config.js ที่เราจะใช้สำหรับโค้ดแล็บนี้

Dockerfile: สุดท้าย เราจะสร้าง Dockerfile ที่จะใช้สร้างอิมเมจ Docker ของภาระงาน โดยจะกำหนด Dockerfile ตามที่ระบุไว้ที่นี่

FROM node:16.18.0

ENV NODE_ENV=production

WORKDIR /app

COPY ["package.json", "package-lock.json*", "./"]

RUN npm install --production

COPY . .

LABEL "tee.launch_policy.allow_cmd_override"="true"
LABEL "tee.launch_policy.allow_env_override"="NODE_URL,RESULTS_BUCKET,KEY_BUCKET,PRIMUS_PROJECT_NUMBER,PRIMUS_PROJECT_ID,PRIMUS_WORKLOAD_IDENTITY_POOL,PRIMUS_WIP_PROVIDER,PRIMUS_SERVICEACCOUNT,PRIMUS_ENC_KEYRING,PRIMUS_ENC_KEY"

CMD [ "node", "index.js" ]

หมายเหตุ: LABEL "tee.launch_policy.allow_cmd_override"="true" ใน Dockerfile เป็นนโยบายการเปิดตัวที่ผู้สร้างอิมเมจตั้งค่าไว้ ซึ่งจะช่วยให้ผู้ปฏิบัติงานลบล้าง CMD ได้เมื่อเรียกใช้เวิร์กโหลด โดยค่าเริ่มต้น ระบบจะตั้งค่า allow_cmd_override เป็นเท็จ LABEL "tee.launch_policy.allow_env_override" จะบอก Confidential Space ว่าผู้ใช้รูปภาพใช้ตัวแปรสภาพแวดล้อมใดได้

เรียกใช้สคริปต์ต่อไปนี้เพื่อสร้างภาระงานที่จะดำเนินการตามขั้นตอนต่อไปนี้

  • สร้าง Artifact Registry($PRIMUS_ARTIFACT_REPOSITORY) เพื่อจัดเก็บอิมเมจ Docker ของภาระงาน
  • อัปเดตโค้ดภาระงานด้วยชื่อทรัพยากรที่จำเป็น ที่นี่คือโค้ดของเวิร์กโหลดที่ใช้สำหรับ Codelab นี้
  • สร้าง Dockerfile สำหรับสร้างอิมเมจ Docker ของโค้ดภาระงาน ดู Dockerfile ได้ที่นี่
  • สร้างและเผยแพร่อิมเมจ Docker ไปยัง Artifact Registry ($PRIMUS_ARTIFACT_REPOSITORY) ที่สร้างไว้ในขั้นตอนก่อนหน้า
  • ให้สิทธิ์อ่านแก่ $WORKLOAD_SERVICEACCOUNT สำหรับ $PRIMUS_ARTIFACT_REPOSITORY ซึ่งจำเป็นเพื่อให้คอนเทนเนอร์ของภาระงานดึงอิมเมจ Docker ของภาระงานจาก Artifact Registry ได้
./create_workload.sh

สร้างโหนดบล็อกเชน

โหนด Ethereum ของ Ganache

เราต้องสร้างอินสแตนซ์ Ethereum Ganache ก่อนที่จะให้สิทธิ์เวิร์กโหลด ระบบจะส่งธุรกรรมที่ลงนามแล้วไปยังอินสแตนซ์ Ganache นี้ โปรดจดที่อยู่ IP ของอินสแตนซ์นี้ หลังจากเรียกใช้คำสั่งด้านล่างแล้ว คุณอาจต้องป้อน y เพื่อเปิดใช้ API

gcloud compute instances create-with-container ${ETHEREUM_NODE} \
  --zone=${PRIMUS_PROJECT_ZONE} \
  --tags=http-server \
  --project=${PRIMUS_PROJECT_ID} \
  --shielded-secure-boot \
  --shielded-vtpm \
  --shielded-integrity-monitoring \
  --container-image=docker.io/trufflesuite/ganache:v7.7.3 \
--container-arg=--wallet.accounts=\"0x0000000000000000000000000000000000000000000000000000000000000001,0x21E19E0C9BAB2400000\" \
  --container-arg=--port=80

4. ให้สิทธิ์และเรียกใช้เวิร์กโหลด

ให้สิทธิ์ภาระงาน

ในขั้นตอนนี้ เราจะตั้งค่าผู้ให้บริการ Workload Identity Pool ภายใต้ Workload Identity Pool ($PRIMUS_WORKLOAD_IDENTITY_POOL) โดยมีการกำหนดค่าเงื่อนไขแอตทริบิวต์สำหรับ Workload Identity ดังที่แสดงด้านล่าง เงื่อนไขข้อหนึ่งคือการตรวจสอบว่ามีการดึงอิมเมจของเวิร์กโหลดจากที่เก็บอาร์ติแฟกต์ที่คาดไว้

gcloud config set project $PRIMUS_PROJECT_ID
gcloud iam workload-identity-pools providers create-oidc ${PRIMUS_WIP_PROVIDER} \
 --location="${PRIMUS_PROJECT_LOCATION}" \
 --workload-identity-pool="$PRIMUS_WORKLOAD_IDENTITY_POOL" \
 --issuer-uri="https://confidentialcomputing.googleapis.com/" \
 --allowed-audiences="https://sts.googleapis.com" \
 --attribute-mapping="google.subject='assertion.sub'" \
 --attribute-condition="assertion.swname == 'CONFIDENTIAL_SPACE' && 'STABLE' in assertion.submods.confidential_space.support_attributes && assertion.submods.container.image_reference == '${PRIMUS_PROJECT_REPOSITORY_REGION}-docker.pkg.dev/$PRIMUS_PROJECT_ID/$PRIMUS_ARTIFACT_REPOSITORY/$WORKLOAD_IMAGE_NAME:$WORKLOAD_IMAGE_TAG' && '$WORKLOAD_SERVICEACCOUNT@$PRIMUS_PROJECT_ID.iam.gserviceaccount.com' in assertion.google_service_accounts"

เรียกใช้ภาระงาน

ส่วนนี้จะอธิบายวิธีเรียกใช้เวิร์กโหลดใน Confidential VM โดยเราจะส่งอาร์กิวเมนต์ TEE ที่จำเป็นโดยใช้แฟล็กข้อมูลเมตา นอกจากนี้ เราจะตั้งค่าตัวแปรสภาพแวดล้อมสำหรับคอนเทนเนอร์ภาระงานโดยใช้แฟล็ก "tee-env-*" รูปภาพมีตัวแปรต่อไปนี้

  • NODE_URL: URL ของโหนด Ethereum ที่จะประมวลผลธุรกรรมที่ลงนามแล้ว
  • RESULTS_BUCKET: ที่เก็บข้อมูลที่จัดเก็บผลลัพธ์ของธุรกรรม MPC
  • KEY_BUCKET: บัคเก็ตที่จัดเก็บคีย์ที่เข้ารหัส MPC
  • PRIMUS_PROJECT_NUMBER: หมายเลขโปรเจ็กต์ที่ใช้สำหรับไฟล์กำหนดค่าข้อมูลเข้าสู่ระบบ
  • PRIMUS_PROJECT_ID: รหัสโปรเจ็กต์ที่ใช้สำหรับไฟล์การกำหนดค่าข้อมูลเข้าสู่ระบบ ผลการดำเนินการของเวิร์กโหลดจะเผยแพร่ไปยัง $PRIMUS_RESULT_STORAGE_BUCKET
  • PRIMUS_WORKLOAD_IDENTITY_POOL: พูล Workload Identity ที่ใช้เพื่อตรวจสอบความถูกต้องของคำกล่าวอ้าง
  • PRIMUS_WIP_POROVIDER: ผู้ให้บริการ Workload Identity Pool ซึ่งรวมถึงเงื่อนไขแอตทริบิวต์ที่จะใช้ในการตรวจสอบโทเค็นที่เวิร์กโหลดแสดง
  • WORKLOAD_SERVICEACCOUNT: บัญชีบริการของเวิร์กโหลด
gcloud compute instances create $WORKLOAD_VM \
 --confidential-compute-type=SEV \
 --shielded-secure-boot \
 --maintenance-policy=TERMINATE \
 --scopes=cloud-platform \
 --zone=${PRIMUS_PROJECT_ZONE} \
 --project=${PRIMUS_PROJECT_ID} \
 --image-project=confidential-space-images \
 --image-family=confidential-space \
 --service-account=$WORKLOAD_SERVICEACCOUNT@$PRIMUS_PROJECT_ID.iam.gserviceaccount.com \
 --metadata "^~^tee-image-reference=${PRIMUS_PROJECT_REPOSITORY_REGION}-docker.pkg.dev/$PRIMUS_PROJECT_ID/$PRIMUS_ARTIFACT_REPOSITORY/$WORKLOAD_IMAGE_NAME:$WORKLOAD_IMAGE_TAG~tee-restart-policy=Never~tee-env-NODE_URL=$(gcloud compute instances describe ${ETHEREUM_NODE} --format='get(networkInterfaces[0].networkIP)' --zone=${PRIMUS_PROJECT_ZONE})~tee-env-RESULTS_BUCKET=$PRIMUS_RESULT_STORAGE_BUCKET~tee-env-KEY_BUCKET=$PRIMUS_INPUT_STORAGE_BUCKET~tee-env-PRIMUS_PROJECT_ID=$PRIMUS_PROJECT_ID~tee-env-PRIMUS_PROJECT_NUMBER=$(gcloud projects describe $PRIMUS_PROJECT_ID --format="value(projectNumber)")~tee-env-PRIMUS_WORKLOAD_IDENTITY_POOL=$PRIMUS_WORKLOAD_IDENTITY_POOL~tee-env-PRIMUS_PROJECT_LOCATION=${PRIMUS_PROJECT_LOCATION}~tee-env-PRIMUS_WIP_PROVIDER=$PRIMUS_WIP_PROVIDER~tee-env-PRIMUS_SERVICEACCOUNT=$PRIMUS_SERVICEACCOUNT~tee-env-PRIMUS_KEY=${PRIMUS_KEY}~tee-env-PRIMUS_KEYRING=${PRIMUS_KEYRING}"

ตรวจสอบผลลัพธ์ใน Cloud Storage

คุณดูใบเสร็จการทำธุรกรรมได้ใน Cloud Storage อาจใช้เวลา 2-3 นาทีในการบูต Confidential Space และให้ผลลัพธ์ปรากฏ คุณจะทราบว่าคอนเทนเนอร์เสร็จสมบูรณ์เมื่อ VM อยู่ในสถานะหยุด

  1. ไปที่หน้าเบราว์เซอร์ Cloud Storage
  2. คลิก $PRIMUS_RESULT_STORAGE_BUCKET
  3. คลิกไฟล์ transaction_receipt
  4. คลิกดาวน์โหลดเพื่อดาวน์โหลดและดูการตอบกลับธุรกรรม

หรือจะเรียกใช้คำสั่งต่อไปนี้เพื่อดูผลลัพธ์ก็ได้

gcloud config set project $PRIMUS_PROJECT_ID
gsutil cat gs://$PRIMUS_RESULT_STORAGE_BUCKET/transaction_receipt

หมายเหตุ: หากผลลัพธ์ไม่ปรากฏ คุณสามารถไปที่ $WORKLOAD_VM ในหน้า Compute Engine Cloud Console แล้วคลิก "Serial port 1 (console)" เพื่อดูบันทึก

ตรวจสอบธุรกรรมบล็อกเชนของ Ganache

นอกจากนี้ คุณยังดูธุรกรรมในบันทึกบล็อกเชนได้ด้วย

  1. ไปที่หน้า Cloud Compute Engine
  2. คลิก ${ETHEREUM_NODE} VM
  3. คลิก SSH เพื่อเปิดหน้าต่าง SSH ในเบราว์เซอร์
  4. ในหน้าต่าง SSH ให้ป้อน sudo docker ps เพื่อดูคอนเทนเนอร์ Ganache ที่ทำงานอยู่
  5. ค้นหารหัสคอนเทนเนอร์สำหรับ trufflesuite/ganache:v7.7.3
  6. ป้อน sudo docker logs CONTAINER_ID โดยแทนที่ CONTAINER_ID ด้วยรหัสสำหรับ trufflesuite/ganache:v7.7.3
  7. ดูบันทึกสำหรับ Ganache และยืนยันว่ามีธุรกรรมแสดงอยู่ในบันทึก

5. ล้างข้อมูล

ที่นี่คือสคริปต์ที่ใช้ล้างข้อมูลทรัพยากรที่เราสร้างขึ้นเป็นส่วนหนึ่งของ Codelab นี้ การล้างข้อมูลนี้จะลบทรัพยากรต่อไปนี้

  • ที่เก็บข้อมูลอินพุตที่ใช้จัดเก็บคีย์ที่เข้ารหัสแล้ว ($PRIMUS_INPUT_STORAGE_BUCKET)
  • คีย์การเข้ารหัส ($PRIMUS_KEY)
  • บัญชีบริการที่ใช้เพื่อเข้าถึงทรัพยากรที่ได้รับการปกป้อง ($PRIMUS_SERVICEACCOUNT)
  • พูล Workload Identity ($PRIMUS_WORKLOAD_IDENTITY_POOL)
  • บัญชีบริการของภาระงาน ($WORKLOAD_SERVICEACCOUNT)
  • อินสแตนซ์การประมวลผลของภาระงาน ($WORKLOAD_VM และ $ETHEREUM_NODE)
  • ที่เก็บข้อมูลผลลัพธ์ที่ใช้จัดเก็บผลลัพธ์ของธุรกรรม ($PRIMUS_RESULT_STORAGE_BUCKET)
  • รีจิสทรีของอาร์ติแฟกต์ที่ใช้จัดเก็บอิมเมจของภาระงาน ($PRIMUS_ARTIFACT_REPOSITORY)
./cleanup.sh

หากสำรวจเสร็จแล้ว โปรดพิจารณาลบโปรเจ็กต์

  • ไปที่คอนโซล Cloud Platform
  • เลือกโปรเจ็กต์ที่ต้องการปิด แล้วคลิก "ลบ" ที่ด้านบน ซึ่งจะเป็นการกำหนดเวลาให้ลบโปรเจ็กต์

สิ่งต่อไปที่ควรทำ

ลองดู Codelab ที่คล้ายกันเหล่านี้

อ่านเพิ่มเติม