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:
- Crea una cuenta de servicio sin un rol de proyecto predeterminado ni una clave de API.
- Asigna un rol de proyecto personalizado mediante un grupo y otorga solo los permisos que necesita la carga de trabajo.
- 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:
- 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. - Aplica la configuración para crear la cuenta de servicio de reemplazo.
- Agrega la cuenta de reemplazo al grupo existente con
openai_group_userpara que herede el rol de proyecto con privilegios mínimos. - 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.
- Despliega la clave de reemplazo y verifica la carga de trabajo con la cuenta de reemplazo.
- Elimina el recurso
openai_project_service_accountanterior y su recursoopenai_group_userde 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. - Revisa y aplica el plan que elimina la cuenta de servicio anterior y su pertenencia al grupo. Luego, ejecuta
terraform plany 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.