신뢰할 수 있는 공간 Codelab

1. 개요

GPU 가속화 워크로드의 보안 및 개인 정보 보호를 강화할 준비가 되셨나요? 이 Codelab에서는 민감한 AI/ML 워크로드에 강력한 운영자 격리 및 가속기 지원을 제공하는 제품인 Trusted Space의 기능을 안내합니다.

중요한 데이터, 모델, 키를 보호하는 것이 그 어느 때보다 중요합니다. Trusted Space는 워크로드 운영자조차 액세스할 수 없는 안전하고 신뢰할 수 있는 환경에서 워크로드가 작동하도록 보장하여 솔루션을 제공합니다.

Trusted Space는 다음과 같은 기능을 제공합니다:

  • 향상된 개인 정보 보호 및 보안: Trusted Space는 암호화 증명으로 지원되는 민감한 애셋 (예: 모델, 중요한 데이터, 키)이 보호된 상태로 유지되는 신뢰할 수 있는 실행 환경을 제공합니다.
  • 운영자 격리: 운영자 간섭에 대한 우려를 없앱니다. Trusted Space를 사용하면 워크로드 운영자조차 액세스할 수 없으므로 SSH, 데이터 액세스, 소프트웨어 설치, 코드 조작을 방지할 수 있습니다.
  • 가속기 지원: Trusted Space는 H100, A100, T4, L4와 같은 GPU를 비롯한 다양한 하드웨어 가속기와 원활하게 작동하도록 설계되었습니다. 이를 통해 성능에 중요한 AI/ML 애플리케이션을 원활하게 실행할 수 있습니다.

학습할 내용

  • Trusted Space의 주요 제품을 이해합니다.
  • AI/ML 워크로드의 중요한 애셋을 보호하기 위해 Trusted Space 환경을 배포하고 구성하는 방법을 알아봅니다.

필요한 항목

Primus Company로 민감한 코드 생성 프롬프트 보호

이 Codelab에서는 직원 데이터의 개인 정보 보호 및 보안을 우선시하는 회사인 Primus의 입장에서 살펴봅니다. Primus는 개발자의 코딩 작업을 지원하기 위해 코드 생성 모델을 배포하려고 합니다. 하지만 직원들이 제출한 프롬프트의 기밀성을 보호하는 데 우려가 있습니다. 이러한 프롬프트에는 민감한 코드 스니펫, 내부 프로젝트 세부정보, 독점 알고리즘이 포함되는 경우가 많기 때문입니다.

Primus Company가 운영자를 신뢰하지 않는 이유는 무엇인가요?

Primus Corp는 경쟁이 치열한 시장에서 운영됩니다. 이들의 코드베이스에는 경쟁 우위를 제공하는 독점 알고리즘과 민감한 코드 스니펫을 비롯한 중요한 지적 재산이 포함되어 있습니다. 워크로드 운영자의 기업 스파이 가능성에 대해 우려하고 있습니다. 또한 직원 프롬프트에는 Primus Corp가 보호하려는 기밀 '알아야 할' 코드 부분이 포함될 수 있습니다.

이러한 우려를 해결하기 위해 Primus Corp는 Trusted Space를 활용하여 코드 생성을 위한 모델을 실행하는 추론 서버를 격리합니다. 작동 방식은 다음과 같습니다.

  • 프롬프트 암호화: 각 직원은 추론 서버에 프롬프트를 보내기 전에 Google Cloud에서 Primus Corp가 관리하는 KMS 키를 사용하여 암호화합니다. 이렇게 하면 해당 복호화 키를 사용할 수 있는 Trusted Space 환경만 복호화하고 일반 텍스트 프롬프트에 액세스할 수 있습니다. 실제 시나리오에서는 사용 가능한 라이브러리 (예: tink)에서 클라이언트 측 암호화를 처리할 수 있습니다. 이 Codelab의 일부로 봉투 암호화가 포함된 이 샘플 클라이언트 애플리케이션을 사용합니다.
  • 운영자 격리: Trusted Space 환경 내에서 실행되는 추론 서버만 암호화에 사용되는 키에 액세스할 수 있으며 신뢰할 수 있는 환경에서 프롬프트를 복호화할 수 있습니다. 암호화 키에 대한 액세스는 워크로드 아이덴티티 풀로 보호됩니다. Trusted Space의 격리 보장으로 인해 워크로드 운영자조차 암호화에 사용되는 키와 복호화된 콘텐츠에 액세스할 수 없습니다.
  • 가속기를 사용한 보안 추론: 추론 서버는 Trusted Space 설정의 일부로 보안 VM에서 실행됩니다. 이렇게 하면 워크로드 인스턴스가 부팅 수준 또는 커널 수준의 멀웨어루트킷으로 인해 손상되지 않습니다. 이 서버는 Trusted Space 환경 내에서 프롬프트를 복호화하고 코드 생성 모델을 사용하여 추론을 실행하며 생성된 코드를 직원에게 반환합니다.

2. Cloud 리소스 설정

시작하기 전에

  • 아래 명령어를 사용하여 이 저장소를 클론하여 이 Codelab의 일부로 사용되는 필수 스크립트를 가져옵니다.
git clone https://github.com/GoogleCloudPlatform/confidential-space.git
  • 이 Codelab의 디렉터리를 변경합니다.
cd confidential-space/codelabs/trusted_space_codelab/scripts
  • 아래와 같이 필수 프로젝트 환경 변수를 설정했는지 확인합니다. GCP 프로젝트 설정에 관한 자세한 내용은 이 Codelab을 참고하세요. 프로젝트 ID를 검색하는 방법과 프로젝트 이름 및 프로젝트 번호와 어떻게 다른지에 관한 자세한 내용은 여기를 참고하세요.
export PRIMUS_PROJECT_ID=<GCP project id of Primus>
gcloud services enable \
    cloudapis.googleapis.com \
    cloudresourcemanager.googleapis.com \
    cloudkms.googleapis.com \
    cloudshell.googleapis.com \
    container.googleapis.com \
    containerregistry.googleapis.com \
    iam.googleapis.com \
    confidentialcomputing.googleapis.com
  • 다음 명령어를 사용하여 위에 지정된 리소스 이름의 변수에 값을 할당합니다. 이러한 변수를 사용하면 필요에 따라 리소스 이름을 맞춤설정하고 이미 생성된 경우 기존 리소스를 사용할 수도 있습니다. (예: export PRIMUS_SERVICE_ACCOUNT='my-service-account')
  1. Primus 프로젝트의 기존 클라우드 리소스 이름으로 다음 변수를 설정할 수 있습니다. 변수가 설정되면 Primus 프로젝트의 해당 기존 클라우드 리소스가 사용됩니다. 변수가 설정되지 않으면 프로젝트 이름에서 클라우드 리소스 이름이 생성되고 새 클라우드 리소스가 해당 이름으로 생성됩니다. 다음은 리소스 이름에 지원되는 변수입니다.

$PRIMUS_PROJECT_REGION

Primus Company의 리전 리소스가 생성되는 리전입니다.

$PRIMUS_SERVICE_LOCATION

Primus Company의 리소스가 생성되는 위치입니다.

$PRIMUS_PROJECT_ZONE

Primus Company의 영역 리소스가 생성되는 영역입니다.

$PRIMUS_WORKLOAD_IDENTITY_POOL

클라우드 리소스를 보호하기 위한 Primus Company의 워크로드 아이덴티티 풀입니다.

$PRIMUS_WIP_PROVIDER

증명 검증 도구 서비스에서 서명한 토큰에 사용할 승인 조건을 포함하는 Primus Company의 워크로드 아이덴티티 풀 제공업체입니다.

$PRIMUS_SERVICEACCOUNT

$PRIMUS_WORKLOAD_IDENTITY_POOL이 보호된 리소스에 액세스하는 데 사용하는 Primus Company의 서비스 계정입니다. 이 단계에서는 $PRIMUS_INPUT_STORAGE_BUCKET 버킷에 저장된 고객 데이터를 볼 수 있는 권한이 있습니다.

$PRIMUS_ENC_KEY

KMS 키는 Primus Company의 직원이 제공한 프롬프트를 암호화하는 데 사용됩니다.

$PRIMUS_ENC_KEYRING

Primus Company의 암호화 키 $PRIMUS_ENC_KEY를 만드는 데 사용되는 KMS 키링입니다.

$PRIMUS_ENC_KEYVERSION

암호화 키 $PRIMUS_ENC_KEY의 KMS 키 버전입니다. 기본값은 1입니다. 이전에 순환되고 버전이 업데이트된 기존 키를 사용하는 경우 이 값을 업데이트합니다.

$PRIMUS_ARTIFACT_REPOSITORY

워크로드 Docker 이미지가 푸시되는 아티팩트 저장소입니다.

$PRIMUS_PROJECT_REPOSITORY_REGION

게시된 워크로드 Docker 이미지가 있는 아티팩트 저장소의 리전입니다.

$WORKLOAD_VM

워크로드 VM의 이름입니다.

$WORKLOAD_IMAGE_NAME

워크로드 Docker 이미지의 이름입니다.

$WORKLOAD_IMAGE_TAG

워크로드 컨테이너 이미지의 태그입니다.

$WORKLOAD_SERVICEACCOUNT

워크로드를 실행하는 컨피덴셜 VM에 액세스할 수 있는 권한이 있는 서비스 계정입니다.

$CLIENT_VM

추론 서버의 클라이언트 애플리케이션을 실행하는 클라이언트 VM의 이름입니다.

$CLIENT_SERVICEACCOUNT

$CLIENT_VM에서 사용하는 서비스 계정입니다.

  • 프로젝트 $PRIMUS_PROJECT_ID에 스토리지 관리자, Artifact Registry 관리자, Cloud KMS 관리자, 서비스 계정 관리자, IAM 워크로드 아이덴티티 풀 관리자 역할이 필요합니다. GCP Console을 사용하여 IAM 역할을 부여하는 방법은 이 가이드를 참고하세요.
  • $PRIMUS_PROJECT_ID의 경우 다음 스크립트를 실행하여 나머지 변수 이름을 리소스 이름의 프로젝트 ID를 기반으로 하는 값으로 설정합니다.
source config_env.sh

Primus Company 리소스 설정

이 단계에서는 Primus에 필요한 클라우드 리소스를 설정합니다. 다음 스크립트를 실행하여 Primus의 리소스를 설정합니다. 다음 리소스는 스크립트 실행의 일부로 생성됩니다.

  • KMS의 암호화 키 ($PRIMUS_ENC_KEY) 및 키링 ($PRIMUS_ENC_KEYRING)을 사용하여 Primus Company의 고객 데이터 파일을 암호화합니다.
  • 제공업체에서 구성된 속성 조건을 기반으로 클레임을 검증하는 워크로드 아이덴티티 풀 ($PRIMUS_WORKLOAD_IDENTITY_POOL)입니다.
  • 위에 언급된 워크로드 아이덴티티 풀 ($PRIMUS_WORKLOAD_IDENTITY_POOL)에 연결된 서비스 계정 ($PRIMUS_SERVICE_ACCOUNT)은 KMS 키를 사용하여 데이터 복호화 (roles/cloudkms.cryptoKeyDecrypter 역할 사용), KMS 키를 사용하여 데이터 암호화 (roles/cloudkms.cryptoKeyEncrypter 역할 사용), 클라우드 스토리지 버킷에서 데이터 읽기 (objectViewer 역할 사용), 서비스 계정을 워크로드 아이덴티티 풀에 연결 (roles/iam.workloadIdentityUser 사용)할 수 있습니다.
./setup_primus_resources.sh

3. 워크로드 만들기

워크로드 서비스 계정 만들기

이제 필요한 역할과 권한이 있는 워크로드의 서비스 계정을 만듭니다. 다음 스크립트를 실행하여 Primus 프로젝트에서 워크로드 서비스 계정을 만듭니다. 이 서비스 계정은 추론 서버를 실행하는 VM에서 사용됩니다.

이 워크로드 서비스 계정 ($WORKLOAD_SERVICEACCOUNT)에는 다음 역할이 있습니다.

  • 증명 토큰을 가져오는 confidentialcomputing.workloadUser
  • Cloud Logging에 로그를 쓰는 logging.logWriter
./create_workload_service_account.sh

워크로드 만들기

이 단계에서는 워크로드 Docker 이미지를 만듭니다. 워크로드는 Primus Company에서 작성합니다. 이 Codelab에서 사용되는 워크로드는 공개적으로 사용 가능한 GCS 버킷 (Vertex Model Garden)의 codegemma 모델을 사용하는 Python 코드입니다. 워크로드는 codegemma 모델을 로드하고 Primus 개발자의 코드 생성 요청을 처리하는 추론 서버를 실행합니다.

코드 생성 요청 시 워크로드는 암호화된 프롬프트와 함께 래핑된 DEK를 가져옵니다. 그런 다음 워크로드는 DEK를 복호화하기 위해 KMS API를 호출하고 이 DEK를 사용하여 프롬프트를 복호화합니다. 암호화 키 (DEK용)는 워크로드 아이덴티티 풀을 통해 보호되며 속성 조건을 충족하는 워크로드에 액세스 권한이 부여됩니다. 이러한 속성 조건은 워크로드 승인에 관한 다음 섹션에서 자세히 설명합니다. 추론 서버에 복호화된 프롬프트가 있으면 로드된 모델을 사용하여 코드를 생성하고 응답을 다시 반환합니다.

다음 스크립트를 실행하여 다음 단계가 실행되는 워크로드를 만듭니다.

  • Primus가 소유한 Artifact Registry($PRIMUS_ARTIFACT_REGISTRY)를 만듭니다.
  • 필요한 리소스 이름으로 워크로드 코드를 업데이트합니다.
  • 추론 서버 워크로드를 빌드하고 워크로드 코드의 Docker 이미지를 빌드하기 위한 Dockerfile을 만듭니다. 이 Codelab에 사용되는 Dockerfile은 다음과 같습니다.
  • Primus가 소유한 Artifact Registry ($PRIMUS_ARTIFACT_REGISTRY)에 Docker 이미지를 빌드하고 게시합니다.
  • $PRIMUS_ARTIFACT_REGISTRY$WORKLOAD_SERVICEACCOUNT 읽기 권한을 부여합니다. 워크로드 컨테이너가 Artifact Registry에서 워크로드 Docker 이미지를 가져오려면 이 작업이 필요합니다.
./create_workload.sh

참고로 이 Codelab에서 생성되고 사용되는 워크로드의 generate() 메서드는 다음과 같습니다 (전체 워크로드 코드는 여기에서 확인할 수 있음).

def generate():
  try:
    data = request.get_json()
    ciphertext = base64.b64decode(data["ciphertext"])
    wrapped_dek = base64.b64decode(data["wrapped_dek"])
    unwrapped_dek_response = kms_client.decrypt(
        request={"name": key_name, "ciphertext": wrapped_dek}
    )
    unwrapped_dek = unwrapped_dek_response.plaintext
    f = Fernet(unwrapped_dek)
    plaintext = f.decrypt(ciphertext)
    prompt = plaintext.decode("utf-8")
    tokens = tokenizer(prompt, return_tensors="pt")
    outputs = model.generate(**tokens, max_new_tokens=128)
    generated_code = tokenizer.decode(outputs[0])
    generated_code_bytes = generated_code.encode("utf-8")

    response = f.encrypt(generated_code_bytes)
    ciphertext_base64 = base64.b64encode(response).decode("utf-8")
    response = {"generated_code_ciphertext": ciphertext_base64}
    return jsonify(response)

  except (ValueError, TypeError, KeyError) as e:
    return jsonify({"error": str(e)}), 500

4. 워크로드 승인 및 실행

워크로드 승인

Primus는 다음 리소스의 속성을 기반으로 프롬프트 암호화에 사용되는 KMS 키에 액세스할 수 있도록 워크로드를 승인하려고 합니다.

  • 무엇: 확인된 코드
  • 위치: 보안 환경
  • 누구: 신뢰할 수 있는 운영자

Primus는 워크로드 아이덴티티 제휴를 사용하여 이러한 요구사항을 기반으로 액세스 정책을 적용합니다. 워크로드 아이덴티티 제휴를 사용하면 속성 조건을 지정할 수 있습니다. 이러한 조건은 워크로드 아이덴티티 풀 (WIP)로 인증할 수 있는 ID를 제한합니다. 증명 검증 도구를 워크로드 아이덴티티 풀 제공업체로 WIP에 추가하여 측정을 제공하고 정책을 적용할 수 있습니다.

워크로드 아이덴티티 풀은 클라우드 리소스 설정 단계의 일부로 이미 이전에 생성되었습니다. 이제 Primus는 새 OIDC 워크로드 아이덴티티 풀 제공업체를 만듭니다. 지정된 --attribute-condition은 워크로드 컨테이너에 대한 액세스 권한을 부여합니다. 이를 위한 요구사항은 다음과 같습니다.

  • 무엇: $PRIMUS_ARTIFACT_REPOSITORY 저장소에 업로드된 최신 $WORKLOAD_IMAGE_NAME입니다.
  • 위치: 컨피덴셜 Space 신뢰할 수 있는 실행 환경이 완전히 지원되는 컨피덴셜 Space VM 이미지에서 실행됩니다.
  • 누구: Primus $WORKLOAD_SERVICE_ACCOUNT 서비스 계정입니다.
export WORKLOAD_IMAGE_DIGEST=$(gcloud artifacts docker images describe ${PRIMUS_PROJECT_REPOSITORY_REGION}-docker.pkg.dev/$PRIMUS_PROJECT_ID/$PRIMUS_ARTIFACT_REPOSITORY/$WORKLOAD_IMAGE_NAME:$WORKLOAD_IMAGE_TAG  --format="value(image_summary.digest)" --project ${PRIMUS_PROJECT_ID})
gcloud iam workload-identity-pools providers create-oidc $PRIMUS_WIP_PROVIDER \
  --location="global" \
  --project="$PRIMUS_PROJECT_ID" \
  --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 == 'HARDENED_SHIELDED' && assertion.hwmodel == 'GCP_SHIELDED_VM' && 
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@$PRIMUS_PROJECT_ID.iam.gserviceaccount.com' in assertion.google_service_accounts"

위의 명령어는 hwmodel이 'GCP_SHIELDED_VM'으로 설정되고 swname이 'HARDENED_SHIELDED'로 설정되어 있는지 확인하여 워크로드가 신뢰할 수 있는 공간 환경에서 실행되고 있는지 확인합니다. 또한 보안을 강화하고 실행 중인 워크로드의 무결성을 보장하기 위해 image_digestimage_reference와 같은 워크로드별 어설션을 포함합니다.

워크로드 실행

이 단계에서는 가속기가 연결된 Trusted Space VM에서 워크로드를 실행합니다. 필수 TEE 인수는 메타데이터 플래그를 사용하여 전달됩니다. 워크로드 컨테이너의 인수는 플래그의 'tee-cmd' 부분을 사용하여 전달됩니다. 워크로드 VM에 Nvidia Tesla T4 GPU를 장착하려면 --accelerator=type=nvidia-tesla-t4,count=1 플래그를 사용합니다. 이렇게 하면 VM에 GPU가 하나 연결됩니다. 적절한 GPU 드라이버의 설치를 트리거하려면 메타데이터 플래그에 tee-install-gpu-driver=true도 포함해야 합니다.

gcloud compute instances create ${WORKLOAD_VM} \
  --accelerator=type=nvidia-tesla-t4,count=1 \
  --machine-type=n1-standard-16 \
  --shielded-secure-boot \
  --image-project=conf-space-images-preview \
  --image=confidential-space-0-gpupreview-796705b \
  --zone=${PRIMUS_PROJECT_ZONE} \
  --maintenance-policy=TERMINATE \
  --boot-disk-size=40 \
  --scopes=cloud-platform \
  --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-install-gpu-driver=true~tee-restart-policy=Never"

추론 쿼리 실행

워크로드 추론 서버가 성공적으로 실행되면 이제 Primus Company의 직원이 추론 서버에 코드 생성 요청을 보낼 수 있습니다.

이 Codelab의 일부로 추론 서버와 상호작용하는 클라이언트 애플리케이션을 설정하기 위해 다음 스크립트를 사용합니다. 이 스크립트를 실행하여 클라이언트 VM을 설정합니다.

./setup_client.sh

다음 단계에서는 클라이언트 VM에 SSH로 연결하고 Python 가상 환경 내에서 샘플 클라이언트 애플리케이션을 실행하는 방법을 보여줍니다. 이 샘플 애플리케이션은 Fernet 라이브러리를 사용하여 봉투 암호화를 활용하지만 특정 암호화 라이브러리는 다양한 사용 사례에 맞게 조정할 수 있습니다.

gcloud compute ssh ${CLIENT_VM} --zone=${PRIMUS_PROJECT_ZONE}

다음 명령어를 실행하여 클라이언트 VM에서 Python 가상 환경을 활성화하고 클라이언트 애플리케이션을 실행합니다.

source venv/bin/activate
python3 inference_client.py

이 샘플 클라이언트 애플리케이션의 출력에는 암호화 및 일반 텍스트 프롬프트 요청과 그에 해당하는 암호화 및 복호화된 응답이 표시됩니다.

5. 삭제

다음은 이 Codelab의 일부로 만든 리소스를 삭제하는 데 사용할 수 있는 스크립트입니다. 이 삭제의 일부로 다음 리소스가 삭제됩니다.

  • Primus 서비스 계정 ($PRIMUS_SERVICEACCOUNT)
  • Primus 암호화 키 ($PRIMUS_ENC_KEY)
  • Primus의 아티팩트 저장소 ($PRIMUS_ARTIFACT_REPOSITORY)
  • 제공업체가 있는 Primus 워크로드 아이덴티티 풀 ($PRIMUS_WORKLOAD_IDENTITY_POOL)
  • Primus의 워크로드 서비스 계정 ($WORKLOAD_SERVICEACCOUNT)
  • 워크로드 VM ($WORKLOAD_VM) 및 클라이언트 VM ($CLIENT_VM)
./cleanup.sh

탐색을 완료한 경우 프로젝트를 삭제하는 것이 좋습니다.

  • Cloud Platform Console으로 이동합니다.
  • 종료하려는 프로젝트를 선택한 다음 상단에서 '삭제'를 클릭합니다. 이렇게 하면 프로젝트가 삭제되도록 예약됩니다.