For the complete documentation index, see llms.txt. Markdown versions of documentation pages are available by appending .md to the page URL.
Navegación principal

Administra cuentas de servicio con Terraform

Crea identidades no humanas con privilegios mínimos y emite claves de API fuera de Terraform.

Una cuenta de servicio de OpenAI es una identidad no humana que pertenece a un proyecto. Terraform puede crear la cuenta sin un rol predeterminado, definir un conjunto de permisos con privilegios mínimos y asignarlo mediante un grupo. Crea y administra las claves de API de las cuentas de servicio fuera de Terraform mediante la API de administración.

Esta guía sigue un flujo de trabajo habitual para incorporar una cuenta de servicio:

  1. Crea una cuenta de servicio sin un rol de proyecto predeterminado ni una clave de API.
  2. Asigna un rol de proyecto personalizado mediante un grupo y otorga solo los permisos que necesita la carga de trabajo.
  3. Crea una clave de API con alcances limitados y guárdala en tu administrador de secretos.

Antes de comenzar

Completa la configuración del proveedor de Terraform, exporta una clave de la API de administración como OPENAI_ADMIN_KEY y exporta el ID del proyecto existente como PROJECT_ID.

Usa una organización de prueba al evaluar la creación, importación, sustitución y eliminación de cuentas de servicio.

Crea una cuenta de servicio sin un rol predeterminado

Crea la cuenta de servicio con 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
}

Reemplaza proj_123 por el ID del proyecto existente al que pertenecerá la cuenta de servicio.

El proveedor crea la identidad de la cuenta de servicio sin generar una clave de API ni asignar un rol de proyecto predeterminado. Terraform guarda el ID de la cuenta de servicio y otros metadatos no sensibles en el estado. En esta etapa, la cuenta de servicio no tiene permisos en el proyecto.

Asigna permisos con privilegios mínimos

Define un rol de proyecto personalizado con solo los permisos que requiere la carga de trabajo. Crea un grupo, agrega la cuenta de servicio y asigna el rol al grupo. Este ejemplo permite que los miembros del grupo creen respuestas:

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
}

El recurso openai_project_role define el conjunto de permisos con privilegios mínimos, openai_group_user agrega la cuenta de servicio al grupo y openai_project_group_role asigna el rol a ese grupo. Todas las cuentas de servicio que se agregan al grupo heredan el mismo rol de proyecto. Reemplaza api.responses.write por el conjunto mínimo de permisos aprobados para tu carga de trabajo. Consulta Proyectos y acceso para obtener más información sobre el acceso a proyectos mediante grupos.

Revisa y aplica la configuración:

terraform plan
terraform apply

No asignes el rol integrado member ni owner cuando un rol de proyecto personalizado proporcione los permisos que necesita tu carga de trabajo. Limita el acceso al conjunto de permisos aprobado.

Crea una clave de API con alcances limitados

Después de aplicar la configuración de Terraform, crea una clave de API mediante el punto de acceso Crear una clave de API para una cuenta de servicio de proyecto. La API devuelve el valor completo de la clave una sola vez, así que protege el archivo de respuesta antes de realizar la solicitud:

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

Elige los alcances más restringidos que cubran las necesidades de la carga de trabajo. Los alcances de la clave de API pueden restringir aún más los permisos de la cuenta de servicio, pero no pueden otorgar permisos que no estén incluidos en el rol de proyecto asignado.

Pasa el valor de value de service-account-api-key.json a tu flujo de trabajo aprobado para administrar secretos sin imprimirlo. Una vez que tu administrador de secretos guarde y verifique el secreto, elimina el archivo de respuesta:

rm service-account-api-key.json

Trata service-account-api-key.json como un secreto mientras exista. No lo incluyas en un commit, no escribas la clave en la configuración de Terraform, no la expongas mediante una salida de Terraform ni la pases como una variable de Terraform.

La Referencia de la API incluye la estructura de la respuesta y ejemplos en distintos lenguajes. Las cargas de trabajo compatibles con la federación de identidades de carga de trabajo pueden usar la misma cuenta de servicio y el mismo rol con privilegios mínimos sin crear una clave de API.

Importa una cuenta de servicio existente

No necesitas importar una cuenta de servicio creada por Terraform. Para incorporar una cuenta de servicio creada fuera de Terraform, declárala con el mismo ID de proyecto y el mismo nombre:

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

Importa la identidad existente antes de aplicar la configuración de la forma habitual:

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

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

terraform plan

El primer plan después de la importación no debería proponer cambios en la cuenta de servicio. Si propone sustituirla, haz que el nombre y el proyecto configurados coincidan con los de la cuenta existente antes de aplicar el plan.

La importación no recupera ni guarda una clave de API, no cambia el rol de proyecto actual de la cuenta de servicio ni importa su pertenencia al grupo. Declara e importa los recursos existentes openai_project_role, openai_group, openai_group_user y openai_project_group_role si Terraform debe administrarlos. La carga de trabajo sigue leyendo los secretos existentes de tu administrador de secretos.

Importa la cuenta de servicio antes de aplicar la declaración del recurso. Si la aplicas primero, Terraform crea una cuenta de servicio distinta en lugar de incorporar la identidad existente.

Recupera o rota credenciales

El valor completo de la clave de API solo está disponible en la respuesta de creación de la clave. Las consultas posteriores de la clave de API del proyecto devuelven un valor parcialmente oculto, por lo que no puedes recuperar una clave perdida.

Reemplaza una credencial perdida o que debas rotar sin interrumpir la carga de trabajo:

  1. Declara la cuenta de reemplazo como un nuevo recurso openai_project_service_account, con un nombre de recurso de Terraform distinto al de la cuenta anterior.
  2. Aplica la configuración para crear la cuenta de servicio de reemplazo.
  3. Agrega la cuenta de reemplazo al grupo existente con openai_group_user para que herede el rol de proyecto con privilegios mínimos.
  4. Crea una clave de API para la cuenta de reemplazo mediante la API de administración y guárdala con tu flujo de trabajo aprobado para administrar secretos.
  5. Despliega la clave de reemplazo y verifica la carga de trabajo con la cuenta de reemplazo.
  6. Elimina el recurso openai_project_service_account anterior y su recurso openai_group_user de la configuración de Terraform. Conserva el rol, el grupo y la asignación de rol al grupo que la cuenta de servicio de reemplazo sigue usando.
  7. Revisa y aplica el plan que elimina la cuenta de servicio anterior y su pertenencia al grupo. Luego, ejecuta terraform plan y exige un resultado sin cambios.

Eliminar un recurso openai_project_service_account elimina la cuenta de servicio remota. Exige una revisión explícita de ese cambio, especialmente mientras la credencial anterior siga en uso para atender tráfico.

Para obtener más información sobre cómo se incorporan y eliminan recursos del estado, consulta Importación y reconciliación.

Ejecuta el ejemplo completo

Los ejemplos específicos usan valores concretos para explicar la creación de cuentas de servicio, la asignación de roles y la creación de claves de API. La configuración completa reemplaza los valores y permisos específicos del proyecto por variables para que puedas reutilizarla en distintos entornos.

Guarda la siguiente configuración como 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
}

Crea terraform.tfvars con el ID de un proyecto existente, un nombre único para la cuenta de servicio y el conjunto mínimo de permisos de proyecto aprobados:

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

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

Inicializa Terraform y luego revisa y aplica un plan guardado:

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

El primer plan debería incluir cinco recursos para agregar: la cuenta de servicio, su rol de proyecto personalizado, el grupo, la pertenencia al grupo y la asignación de rol al grupo. Ejecuta terraform plan de nuevo para confirmar que la configuración no produce más cambios.

Crea la clave de API de la cuenta de servicio fuera de Terraform:

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

Transfiere el valor devuelto de la clave de API a tu administrador de secretos aprobado y luego elimina service-account-api-key.json. No guardes la clave en la configuración, el estado ni las salidas de Terraform.