For the complete documentation index, see llms.txt. Markdown versions of documentation pages are available by appending .md to the page URL.
主要導覽

使用 Terraform 管理服務帳戶

建立具備最小權限的非人員身分,並在 Terraform 之外核發 API 金鑰。

OpenAI 服務帳戶是隸屬於專案的非人員身分。Terraform 可以建立不含預設角色的帳戶、定義一組最小權限,並透過群組指派這組權限。請在 Terraform 之外,透過管理 API 建立及管理服務帳戶的 API 金鑰。

本指南依循典型的服務帳戶啟用工作流程:

  1. 建立不含預設專案角色或 API 金鑰的服務帳戶。
  2. 透過群組指派自訂專案角色,僅授予工作負載所需的權限。
  3. 建立限定權限範圍的 API 金鑰,並將其儲存至機密管理工具。

開始之前

完成 Terraform 供應器設定,將管理 API 金鑰匯出為環境變數 OPENAI_ADMIN_KEY,並將現有專案的 ID 匯出為環境變數 PROJECT_ID

評估服務帳戶的建立、匯入、替換及刪除操作時,請使用測試組織。

建立不含預設角色的服務帳戶

使用 Terraform 建立服務帳戶:

resource "openai_project_service_account" "application" {
  project_id = "proj_123"
  name       = "example-application-development-service-account"
}

output "service_account_id" {
  value = openai_project_service_account.application.service_account_id
}

proj_123 替換為服務帳戶將隸屬的現有專案 ID。

供應器會建立服務帳戶身分,但不會產生 API 金鑰或指派預設專案角色。Terraform 會將服務帳戶 ID 及其他非敏感中繼資料儲存在狀態中。在此階段,服務帳戶尚無任何專案權限。

指派最小權限

定義自訂專案角色,僅納入工作負載所需的權限。建立群組、將服務帳戶加入群組,再將角色指派給該群組。此範例允許群組成員建立回應:

resource "openai_project_role" "application" {
  project_id  = openai_project_service_account.application.project_id
  role_name   = "Application response writer"
  description = "Allows the application to create responses"
  permissions = ["api.responses.write"]
}

resource "openai_group" "application_access" {
  name = "example-application-development-access"
}

resource "openai_group_user" "application" {
  group_id = openai_group.application_access.group_id
  user_id  = openai_project_service_account.application.id
}

resource "openai_project_group_role" "application_access" {
  project_id = openai_project_service_account.application.project_id
  group_id   = openai_group.application_access.group_id
  role_id    = openai_project_role.application.role_id
}

openai_project_role 資源定義一組最小權限,openai_group_user 將服務帳戶加入群組,而 openai_project_group_role 則將角色指派給該群組。加入群組的每個服務帳戶都會繼承相同的專案角色。請將 api.responses.write 替換為工作負載獲准使用的最小權限集合。如需瞭解透過群組授予專案存取權的詳細資訊,請參閱專案與存取權

審查並套用組態:

terraform plan
terraform apply

如果自訂專案角色已能提供工作負載所需的權限, 就不要指派內建的 memberowner 角色。請將存取權限制在 已核准的權限集合內。

建立限定權限範圍的 API 金鑰

套用 Terraform 組態後,透過建立專案服務帳戶 API 金鑰端點建立 API 金鑰。API 只會傳回一次金鑰的完整值,因此請在發出請求前保護回應檔案:

SERVICE_ACCOUNT_ID="$(terraform output -raw service_account_id)"
umask 077

curl -X POST \
  "https://api.openai.com/v1/organization/projects/$PROJECT_ID/service_accounts/$SERVICE_ACCOUNT_ID/api_keys" \
  -H "Authorization: Bearer $OPENAI_ADMIN_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Production App",
    "scopes": ["api.responses.write"]
  }' \
  --output service-account-api-key.json

選擇能滿足工作負載需求的最小權限範圍。API 金鑰的權限範圍可以進一步限制服務帳戶的權限,但無法授予其所獲指派的專案角色以外的權限。

service-account-api-key.json 中的 value 傳遞給已核准的機密管理工作流程,且不要將其列印出來。機密管理工具儲存並驗證機密後,請刪除回應檔案:

rm service-account-api-key.json

只要 service-account-api-key.json 仍存在,就必須將其視為機密。不要提交此檔案、將金鑰寫入 Terraform 組態、透過 Terraform 輸出公開金鑰,或將其作為 Terraform 變數傳遞。

API 參考文件包含回應結構及各程式語言的範例。支援工作負載身分聯合的工作負載,可以使用相同的服務帳戶與最小權限角色,無需建立 API 金鑰。

匯入現有服務帳戶

由 Terraform 建立的服務帳戶不需要匯入。若要將在 Terraform 之外建立的服務帳戶納入管理,請使用相同的專案 ID 與名稱宣告該帳戶:

resource "openai_project_service_account" "application" {
  project_id = "proj_123"
  name       = "example-application-development-service-account"
}

在執行一般套用操作之前,先匯入現有身分:

SERVICE_ACCOUNT_ID="<existing-service-account-id>"

terraform import \
  openai_project_service_account.application \
  "$PROJECT_ID/$SERVICE_ACCOUNT_ID"

terraform plan

匯入後的第一份執行計畫應不會提出任何服務帳戶變更。如果計畫提出替換帳戶,請先將組態中的名稱與專案調整為與現有帳戶一致,再套用計畫。

匯入不會復原或儲存 API 金鑰、不會變更服務帳戶現有的專案角色,也不會匯入其群組成員資格。如果要由 Terraform 管理現有的 openai_project_roleopenai_groupopenai_group_useropenai_project_group_role 資源,請宣告並匯入這些資源。工作負載會繼續從機密管理工具讀取現有機密。

套用資源宣告之前,請先匯入服務帳戶。如果先執行套用操作, Terraform 會建立另一個服務帳戶, 而不是將現有身分納入管理。

復原或輪替憑證

API 金鑰的完整值僅會出現在建立 API 金鑰的回應中。之後擷取專案 API 金鑰時,傳回的值會經過遮蔽,因此無法復原遺失的金鑰。

在不中斷工作負載的情況下,替換遺失或需要輪替的憑證:

  1. 將替代帳戶宣告為新的 openai_project_service_account 資源,並使用與舊帳戶不同的 Terraform 資源名稱。
  2. 套用組態以建立替代服務帳戶。
  3. 使用 openai_group_user 將替代帳戶加入現有群組,讓它繼承最小權限專案角色。
  4. 透過管理 API 為替代帳戶建立 API 金鑰,並使用已核准的機密管理工作流程儲存金鑰。
  5. 部署替代金鑰,並使用替代帳戶驗證工作負載。
  6. 從 Terraform 組態中移除舊的 openai_project_service_account 及其 openai_group_user 資源。保留替代服務帳戶仍在使用的角色、群組與群組角色指派。
  7. 審查並套用刪除舊服務帳戶及其群組成員資格的執行計畫,接著執行 terraform plan,並確認結果顯示無需任何變更。

刪除 openai_project_service_account 資源會刪除遠端服務帳戶。務必明確要求審查這項變更,尤其是在舊憑證仍用於處理流量時。

如需更全面瞭解將資源納入狀態管理及移除資源的行為,請參閱匯入與調和

執行完整範例

前述各項範例使用具體值,說明如何建立服務帳戶、指派角色及建立 API 金鑰。完整組態則以變數取代專案特定的值與權限,方便在不同環境中重複使用。

將下列組態儲存為 main.tf

terraform {
  required_version = ">= 1.0"

  required_providers {
    openai = {
      source  = "openai/openai"
      version = ">= 1.0.0"
    }
  }
}

provider "openai" {}

variable "project_id" {
  type        = string
  description = "ID of the existing OpenAI project."
}

variable "service_account_name" {
  type        = string
  description = "Name of the application service account."
}

variable "project_role_permissions" {
  type        = list(string)
  description = "Least-privilege project permissions for the application."

  validation {
    condition     = length(var.project_role_permissions) > 0
    error_message = "Provide at least one approved project permission."
  }
}

resource "openai_project_service_account" "application" {
  project_id = var.project_id
  name       = var.service_account_name
}

resource "openai_project_role" "application" {
  project_id  = var.project_id
  role_name   = "Application API access"
  description = "Least-privilege permissions approved for the application"
  permissions = var.project_role_permissions
}

resource "openai_group" "application_access" {
  name = "${var.service_account_name}-access"
}

resource "openai_group_user" "application" {
  group_id = openai_group.application_access.group_id
  user_id  = openai_project_service_account.application.id
}

resource "openai_project_group_role" "application_access" {
  project_id = var.project_id
  group_id   = openai_group.application_access.group_id
  role_id    = openai_project_role.application.role_id
}

output "project_id" {
  value = var.project_id
}

output "service_account_id" {
  value = openai_project_service_account.application.service_account_id
}

output "group_id" {
  value = openai_group.application_access.group_id
}

output "project_role_id" {
  value = openai_project_role.application.role_id
}

建立 terraform.tfvars,填入現有專案 ID、不重複的服務帳戶名稱,以及已核准的最小專案權限集合:

project_id           = "proj_123"
service_account_name = "example-application-development-service-account"

project_role_permissions = [
  "api.responses.write",
]

初始化 Terraform,然後審查並套用已儲存的執行計畫:

terraform init
terraform fmt
terraform validate
terraform plan -out=tfplan
terraform show tfplan
terraform apply tfplan

第一份執行計畫應包含五項待新增的資源:服務帳戶、其自訂專案角色、群組、群組成員資格,以及群組角色指派。再次執行 terraform plan,確認組態不會再產生任何變更。

在 Terraform 之外建立服務帳戶 API 金鑰:

PROJECT_ID="$(terraform output -raw project_id)"
SERVICE_ACCOUNT_ID="$(terraform output -raw service_account_id)"
umask 077

curl -X POST \
  "https://api.openai.com/v1/organization/projects/$PROJECT_ID/service_accounts/$SERVICE_ACCOUNT_ID/api_keys" \
  -H "Authorization: Bearer $OPENAI_ADMIN_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Production App",
    "scopes": ["api.responses.write"]
  }' \
  --output service-account-api-key.json

將傳回的 API 金鑰值移至已核准的機密管理工具,然後刪除 service-account-api-key.json。不要將金鑰儲存在 Terraform 組態、狀態或輸出中。