1. 總覽
機密空間提供安全的環境,方便您進行多方協作。本程式碼研究室將說明如何使用 Sensitive Space 保護機密的智慧財產 (例如機器學習模型)。
在這個程式碼研究室中,您將使用機密空間,讓一間公司安全地共用專屬機器學習模型,與希望使用模型的其他公司共用。具體來說,Company Primus 的機器學習模型只會發布至在機密空間中運作的工作負載,讓 Primus 保有對智慧財產的完整控制權。「公司安全部門」將成為工作負載管理者,並在機密空間中執行機器學習工作負載。Secundus 會載入這個模型,並使用 Secundus 擁有的範例資料執行推論。
Primus 是編寫工作負載程式碼的工作負載作者,以及想保護智慧財產不受不受信任的工作負載操作者 Secundus 的協作者。Secundus 是機器學習工作負載的工作負載操作者。
課程內容
- 如何設定環境,雙方可以共用專屬機器學習模型,同時保有對智慧財產的控制權。
軟硬體需求
- Google Cloud Platform 專案
- 對 Google Compute Engine ( 程式碼研究室)、機密 VM、容器和遠端存放區的基本知識
- 瞭解服務帳戶、工作負載身分聯盟和屬性條件的基本知識。
與機密空間設定相關的角色
在本程式碼研究室中,Company Primus 將是資源擁有者和工作負載作者,他將負責下列事項:
- 使用機器學習模型設定必要的雲端資源
- 編寫工作負載程式碼
- 發布工作負載映像檔
- 設定工作負載身分集區政策,防範不受信任的操作人員保護機器學習模型
Secundus Company 將負責營運,且負責下列事項:
- 設定必要的雲端資源,以儲存工作負載所用的範例映像檔和結果
- 使用 Primus 提供的模型,在機密空間中執行機器學習工作負載
機密空間的運作方式
您在機密空間中執行工作負載時,系統會使用已設定的資源執行下列程序:
- 工作負載會從工作負載身分池中要求
$PRIMUS_SERVICEACCOUNT
的一般 Google 存取權杖。可提供工作負載和環境憑證附加資訊的 Attestation Verifier 服務權杖。 - 如果 Attestation Verifier 服務權杖中的工作負載評估要求與 WIP 中的屬性條件相符,就會傳回
$PRIMUS_SERVICEACCOUNT.
的存取權杖 - 工作負載會使用與
$PRIMUS_SERVICEACCOUNT
相關聯的服務帳戶存取權杖,存取儲存在$PRIMUS_INPUT_STORAGE_BUCKET
值區中的機器學習模型。 - 工作負載會對 Secundus 擁有的資料執行作業,而該工作負載在其專案中由 Secundus 負責運作與執行。
- 工作負載會使用
$WORKLOAD_SERVICEACCOUNT
服務帳戶,將作業結果寫入$SECUNDUS_RESULT_STORAGE_BUCKET
值區。
2. 設定 Cloud 資源
事前準備
- 使用下列指令複製 這個存放區,即可取得本程式碼研究室中使用的必要指令碼。
git clone https://github.com/GoogleCloudPlatform/confidential-space.git
- 變更本程式碼研究室的目錄。
cd confidential-space/codelabs/ml_model_protection/scripts
export PRIMUS_PROJECT_ID=<GCP project id of Primus>
export SECUNDUS_PROJECT_ID=<GCP project id of Secundus>
- 為您的專案啟用計費功能。
- 為這兩項專案啟用 Sensitive Computing API 和下列 API。
gcloud services enable \
cloudapis.googleapis.com \
cloudresourcemanager.googleapis.com \
cloudshell.googleapis.com \
container.googleapis.com \
containerregistry.googleapis.com \
iam.googleapis.com \
confidentialcomputing.googleapis.com
- 使用下列指令,將值指派給上方指定資源名稱的變數。這些變數可讓您視需求自訂資源名稱,以及使用已建立的資源。(例如
export PRIMUS_INPUT_STORAGE_BUCKET='my-input-bucket'
)
- 您可以在 Primus 專案中,使用現有的雲端資源名稱設定下列變數。如果設定了變數,就會使用 Primus 專案中的相應現有雲端資源。如未設定這個變數,系統會從專案名稱產生雲端資源名稱,並使用該名稱建立新的雲端資源。以下是系統支援的資源名稱變數:
| 儲存 Primus 機器學習模型的值區。 |
| 驗證憑證附加資訊的 Primus 工作負載身分集區 (WIP)。 |
| Primus 的工作負載身分集區提供者,包括用於認證驗證者服務簽署權杖的授權條件。 |
| Primus 服務帳戶, |
| 要推送工作負載 Docker 映像檔的構件存放區。 |
- 您可以在 Secundus 專案中,使用現有的雲端資源名稱設定下列變數。如果設定了變數,系統會使用 Secundus 專案中的對應現有雲端資源。如未設定這個變數,系統會從專案名稱產生雲端資源名稱,並使用該名稱建立新的雲端資源。以下是系統支援的資源名稱變數:
| 儲存 Secundus 想要使用 Primus 模型進行分類的樣本圖片的值區。 |
| 儲存工作負載結果的值區。 |
| 工作負載容器映像檔的名稱。 |
| 工作負載容器映像檔的標記。 |
| 有權存取執行工作負載的機密 VM 的服務帳戶。 |
- 您在這兩個專案都需要特定權限。您可以參閱這份指南,瞭解如何使用 GCP 主控台授予 IAM 角色:
- 您需要為「
$PRIMUS_PROJECT_ID
」建立「Storage 管理員」、「Artifact Registry 管理員」、「服務帳戶管理員」和「IAM 工作負載身分集區管理員」。 - 您需要為
$SECUNDUS_PROJECT_ID
建立 Compute 管理員、Storage 管理員、服務帳戶管理員、IAM 工作負載身分集區管理員和安全性管理員 (選用)。 - 執行下列指令碼,根據資源名稱的專案 ID 將其餘變數名稱設為值。
source config_env.sh
設定 Primus Company 資源
在這個步驟中,您將替 Primus 設定必要的雲端資源。執行下列指令碼,設定 Primus 的資源。系統會在執行指令碼時建立下列資源:
- 用來儲存 Primus 機器學習模型的 Cloud Storage 值區 (
$PRIMUS_INPUT_STORAGE_BUCKET
)。 - Workload Identity 集區 (
$PRIMUS_WORKLOAD_IDENTITY_POOL
),可根據供應商設定的屬性條件驗證著作權聲明。 - 附加至上述工作負載身分集區 (
$PRIMUS_WORKLOAD_IDENTITY_POOL
) 的服務帳戶 ($PRIMUS_SERVICEACCOUNT
),具備 IAM 權限,可從 Cloud Storage 值區讀取資料 (使用objectViewer
角色),並將這個服務帳戶連結至 Workload Identity 集區 (使用roles/iam.workloadIdentityUser
角色)。
進行這項雲端資源時,我們會使用 TensorFlow 模型。我們可以將包含模型架構、權重和訓練設定的完整模型儲存在 ZIP 封存檔中。在本程式碼研究室中,我們將使用此處的 ImageNet 資料集訓練的 MobileNet V1 模型。
./setup_primus_company_resources.sh
前面提到的指令碼會設定雲端資源,我們現在要下載模型,並將模型發布至指令碼建立的 Cloud Storage 值區。
- 請按這裡下載預先訓練模型。
- 下載完成後,將下載的 tar 檔案重新命名為 model.tar.gz。
- 從含有 model.tar.gz 檔案的目錄執行下列指令,將 model.tar.gz 檔案發布到 Cloud Storage 值區。
gsutil cp model.tar.gz gs://${PRIMUS_INPUT_STORAGE_BUCKET}/
設定 Secundus Company 資源
在這個步驟中,您將為安全設定設定必要的雲端資源。執行下列指令碼,設定 Secundus 的資源。執行以下步驟時,系統會建立下列資源:
- Cloud Storage 值區 (
$SECUNDUS_INPUT_STORAGE_BUCKET
),用於儲存範例圖片,以便依據 Secundus 執行推論。 - 用來儲存 Secundus 執行機器學習工作負載結果的 Cloud Storage 值區 (
$SECUNDUS_RESULT_STORAGE_BUCKET
)。
您可以在這裡取得本程式碼研究室的部分圖片範例。
./setup_secundus_company_resources.sh
3. 建立工作負載
建立工作負載服務帳戶
現在,您將為具備必要角色和權限的工作負載建立服務帳戶。執行下列指令碼,在 Secundus 專案中建立工作負載服務帳戶。這個服務帳戶將由執行機器學習工作負載的 VM 使用。
這個工作負載服務帳戶 ($WORKLOAD_SERVICEACCOUNT
) 會具備下列角色:
confidentialcomputing.workloadUser
可取得認證權杖logging.logWriter
,以便將記錄檔寫入 Cloud Logging。objectViewer
可從$SECUNDUS_INPUT_STORAGE_BUCKET
雲端儲存空間值區讀取資料。objectUser
:將工作負載結果寫入$SECUNDUS_RESULT_STORAGE_BUCKET
雲端儲存空間值區。
./create_workload_service_account.sh
建立工作負載
在這個步驟中,您將建立工作負載 Docker 映像檔。工作負載由 Primus 編寫。本程式碼研究室使用的工作負載為機器學習 Python 程式碼。程式碼會存取儲存在 Primus 儲存空間值區中的機器學習模型,並根據儲存在 Storage 值區中的範例圖片執行推論。
只有符合必要屬性條件的工作負載,才能存取 Primus 儲存空間值區中儲存的機器學習模型。下一節將進一步說明如何授權工作負載。
以下是本程式碼研究室會建立及使用工作負載的 run_inference() 方法。您可以在這裡找到完整的工作負載程式碼。
def run_inference(image_path, model):
try:
# Read and preprocess the image
image = tf.image.decode_image(tf.io.read_file(image_path), channels=3)
image = tf.image.resize(image, (128, 128))
image = tf.image.convert_image_dtype(image, tf.float32)
image = tf.expand_dims(image, axis=0)
# Get predictions from the model
predictions = model(image)
predicted_class = np.argmax(predictions)
top_k = 5
top_indices = np.argsort(predictions[0])[-top_k:][::-1]
# Convert top_indices to a TensorFlow tensor
top_indices_tensor = tf.convert_to_tensor(top_indices, dtype=tf.int32)
# Use TensorFlow tensor for indexing
top_scores = tf.gather(predictions[0], top_indices_tensor)
return {
"predicted_class": int(predicted_class),
"top_k_predictions": [
{"class_index": int(idx), "score": float(score)}
for idx, score in zip(top_indices, top_scores)
],
}
except Exception as e:
return {"error": str(e)}
執行下列指令碼來建立工作負載,並在其中執行下列步驟:
- 建立 Primus 擁有的 Artifact Registry(
$PRIMUS_ARTIFACT_REGISTRY
)。 - 使用必要的資源名稱更新工作負載程式碼。
- 建構機器學習工作負載並建立 Dockerfile,用來建構工作負載程式碼的 Docker 映像檔。這裡是本程式碼研究室使用的 Dockerfile。
- 建構 Docker 映像檔並發布至 Primus 擁有的 Artifact Registry (
$PRIMUS_ARTIFACT_REGISTRY
)。 - 向
$WORKLOAD_SERVICEACCOUNT
授予$PRIMUS_ARTIFACT_REGISTRY
的讀取權限。這樣工作負載容器才能從 Artifact Registry 提取工作負載 Docker 映像檔。
./create_workload.sh
此外,還可以為工作負載編寫程式碼,確保工作負載在使用模型前,請檢查模型的雜湊或簽名,確保模型載入的機器學習模型符合預期。這類額外檢查的優點在於可確保機器學習模型的完整性。採用這種做法時,在工作負載預期會使用不同版本的機器學習模型時,工作負載操作員也必須更新工作負載映像檔或其參數。
4. 授權並執行工作負載
授權工作負載
Primus 想要依據下列資源的屬性,授權工作負載存取他們的機器學習模型:
- 內容:已驗證的程式碼
- 位置:安全的環境
- 對象:值得信賴的運算子
Primus 使用工作負載身分聯盟,根據這些規定強制執行存取權政策。Workload Identity 聯盟可讓您指定屬性條件。這些條件會限制哪些身分可使用工作負載身分池 (WIP) 進行驗證。您可以將認證驗證器服務新增至 WIP,做為工作負載識別資訊提供者提供者,以呈現測量結果並強制執行政策。
稍早已在雲端資源設定步驟中建立 Workload Identity 集區。Primus 現在會建立新的 OIDC 工作負載身分池提供者。指定的 --attribute-condition
會授權存取工作負載容器。它需要:
- 內容:上傳至
$PRIMUS_ARTIFACT_REPOSITORY
存放區的最新版$WORKLOAD_IMAGE_NAME
。 - 位置:機密空間信任的執行環境在完全支援的機密空間 VM 映像檔上執行。
- 使用者:Secundus
$WORKLOAD_SERVICE_ACCOUNT
服務帳戶。
export WORKLOAD_IMAGE_DIGEST=$(docker images –digests ${PRIMUS_PROJECT_REPOSITORY_REGION}-docker.pkg.dev/${PRIMUS_PROJECT_ID}/${PRIMUS_ARTIFACT_REPOSITORY}/${WORKLOAD_IMAGE_NAME}:${WORKLOAD_IMAGE_TAG}| awk 'NR>1{ print $3 }')
gcloud config set project $PRIMUS_PROJECT_ID
gcloud iam workload-identity-pools providers create-oidc $PRIMUS_WIP_PROVIDER \
--location="global" \
--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_digest == '${WORKLOAD_IMAGE_DIGEST}' &&
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@$SECUNDUS_PROJECT_ID.iam.gserviceaccount.com' in assertion.google_service_accounts"
執行工作負載
在這個步驟中,我們將透過機密空間 VM 執行工作負載。系統會使用中繼資料標記傳遞必要的 TEE 引數。系統會使用「tee-cmd
」傳遞工作負載容器的引數部分。工作負載執行作業的結果會發布至 $SECUNDUS_RESULT_STORAGE_BUCKET
。
gcloud config set project $SECUNDUS_PROJECT_ID
gcloud compute instances create ${WORKLOAD_VM} \
--confidential-compute-type=SEV \
--shielded-secure-boot \
--maintenance-policy=TERMINATE \
--scopes=cloud-platform --zone=${SECUNDUS_PROJECT_ZONE} \
--image-project=confidential-space-images \
--image-family=confidential-space \
--service-account=${WORKLOAD_SERVICEACCOUNT}@${SECUNDUS_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}
查看結果
成功完成工作負載後,機器學習工作負載的結果會發布至 $SECUNDUS_RESULT_STORAGE_BUCKET
。
gsutil cat gs://$SECUNDUS_RESULT_STORAGE_BUCKET/result
以下列舉幾個範例圖片的推論結果:
Image: sample_image_1.jpeg, Response: {'predicted_class': 531, 'top_k_predictions': [{'class_index': 531, 'score': 12.08437442779541}, {'class_index': 812, 'score': 10.269512176513672}, {'class_index': 557, 'score': 9.202644348144531}, {'class_index': 782, 'score': 9.08737564086914}, {'class_index': 828, 'score': 8.912498474121094}]}
Image: sample_image_2.jpeg, Response: {'predicted_class': 905, 'top_k_predictions': [{'class_index': 905, 'score': 9.53619384765625}, {'class_index': 557, 'score': 7.928380966186523}, {'class_index': 783, 'score': 7.70129919052124}, {'class_index': 531, 'score': 7.611623287200928}, {'class_index': 906, 'score': 7.021416187286377}]}
Image: sample_image_3.jpeg, Response: {'predicted_class': 905, 'top_k_predictions': [{'class_index': 905, 'score': 6.09878396987915}, {'class_index': 447, 'score': 5.992854118347168}, {'class_index': 444, 'score': 5.9582319259643555}, {'class_index': 816, 'score': 5.502010345458984}, {'class_index': 796, 'score': 5.450454235076904}]}
對於 Secundus Storage 值區中的每個範例圖片,您會在結果中看到一個項目。此項目包含兩項重要資訊:
- predict_class 索引:這個數值索引代表模型預測圖片所屬的類別。
- Top_k_predictions::提供最多 K 次圖片預測結果,並由高到低排名。在本程式碼研究室中,k 的值設為 5,但您可以在工作負載程式碼中進行調整,讓系統增加或減少預測結果。
如要將類別索引轉譯為使用者可理解的類別名稱,請參閱這裡提供的標籤清單。舉例來說,如果類別索引是 2,就會對應到類別標籤「tench」。
在本程式碼研究室中,我們展示了由 Primus 擁有的模型,且該模型僅發布到在 TEE 中執行的工作負載。Secundus 會在 TEE 中執行機器學習工作負載,且這項工作負載可使用 Primus 擁有的模型,而 Primus 保有模型的完全控制權。
執行未經授權的工作負載
Secundus 會從自己的構件存放區 (未經 Primus 授權) 提取不同的工作負載映像檔來變更工作負載映像檔。Primus 的工作負載身分集區只授權 ${PRIMUS_PROJECT_REPOSITORY_REGION}-docker.pkg.dev/$PRIMUS_PROJECT_ID/$PRIMUS_ARTIFACT_REPOSITORY/$WORKLOAD_IMAGE_NAME:$WORKLOAD_IMAGE_TAG
工作負載映像檔。
重新執行工作負載
當 Secundus 嘗試使用這個新的工作負載映像檔執行原始工作負載時,就會失敗。如要查看錯誤,請刪除原始結果檔案和 VM 執行個體,然後再次嘗試執行工作負載。
請確認 Secundus 的 Artifact Registry (名稱:us-docker.pkg.dev/${SECUNDUS_PROJECT_ID}/custom-image/${WORKLOAD_IMAGE_NAME}:${WORKLOAD_IMAGE_TAG}
) 和 Workload serviceaccount ($WORKLOAD_SERVICEACCOUNT
) 底下發布了新的 Docker 映像檔,並授予 Artifact Registry 讀取者權限,以便讀取這個新的工作負載映像檔。這是為了確保工作負載不會在 Primus 的 WIP 政策拒絕工作負載提供的權杖之前結束。
刪除現有的結果檔案和 VM 執行個體
- 將專案設為
$SECUNDUS_PROJECT_ID
專案。
gcloud config set project $SECUNDUS_PROJECT_ID
- 刪除結果檔案。
gsutil rm gs://$SECUNDUS_RESULT_STORAGE_BUCKET/result
- 刪除機密 VM 執行個體。
gcloud compute instances delete ${WORKLOAD_VM}
執行未經授權的工作負載:
gcloud compute instances create ${WORKLOAD_VM} \
--confidential-compute-type=SEV \
--shielded-secure-boot \
--maintenance-policy=TERMINATE \
--scopes=cloud-platform --zone=${SECUNDUS_PROJECT_ZONE} \
--image-project=confidential-space-images \
--image-family=confidential-space \
--service-account=${WORKLOAD_SERVICE_ACCOUNT}@${SECUNDUS_PROJECT_ID}.iam.gserviceaccount.com \
--metadata ^~^tee-image-reference=us-docker.pkg.dev/${SECUNDUS_PROJECT_ID}/custom-image/${WORKLOAD_IMAGE_NAME}:${WORKLOAD_IMAGE_TAG}
查看錯誤
除了工作負載結果之外,系統會顯示錯誤 (The given credential is rejected by the attribute condition
)。
gsutil cat gs://$SECUNDUS_RESULT_STORAGE_BUCKET/result
5. 清除
這裡使用的指令碼可用來清除我們在本程式碼研究室中建立的資源。這項清理作業將刪除下列資源:
- Primus 的輸入儲存空間值區 (
$PRIMUS_INPUT_STORAGE_BUCKET)
。 - Primus 服務帳戶 (
$PRIMUS_SERVICEACCOUNT
)。 - Primus (
$PRIMUS_ARTIFACT_REPOSITORY
) 的構件存放區。 - Primus 工作負載身分池 (
$PRIMUS_WORKLOAD_IDENTITY_POOL
)。 - Secundus 的工作負載服務帳戶 (
$WORKLOAD_SERVICEACCOUNT
)。 - 輸入 Secundus (
$SECUNDUS_INPUT_STORAGE_BUCKET)
) 的輸入儲存值區。 - 工作負載運算執行個體。
- Secundus 結果儲存空間值區 (
$SECUNDUS_RESULT_STORAGE_BUCKET
)。
$ ./cleanup.sh
如果試用完畢,請考慮刪除專案。
- 前往 Cloud Platform 主控台
- 選取您要關閉的專案,然後按一下「刪除」會安排將專案刪除
後續步驟
查看一些類似的程式碼研究室...