Un compte de service OpenAI est une identité non humaine qui appartient à un projet. Terraform permet de créer ce compte sans rôle par défaut, de définir un ensemble d’autorisations selon le principe du moindre privilège et de les attribuer au compte par l’intermédiaire d’un groupe. Créez et gérez les clés API du compte de service en dehors de Terraform à l’aide de l’API d’administration.
Ce guide présente les étapes habituelles de mise en service d’un compte de service :
- Créez un compte de service sans rôle de projet par défaut ni clé API.
- Attribuez-lui un rôle de projet personnalisé par l’intermédiaire d’un groupe en accordant uniquement les autorisations nécessaires à la charge de travail.
- Créez une clé API de portée limitée et stockez-la dans votre gestionnaire de secrets.
Avant de commencer
Terminez la configuration du fournisseur Terraform, puis exportez une clé API d’administration dans la variable OPENAI_ADMIN_KEY et l’identifiant du projet existant dans la variable PROJECT_ID.
Utilisez une organisation de test pour évaluer la création, l’importation, le remplacement et la suppression de comptes de service.
Créer un compte de service sans rôle par défaut
Créez le compte de service avec 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
}
Remplacez proj_123 par l’identifiant du projet existant auquel appartiendra le compte de service.
Le fournisseur crée l’identité du compte de service sans générer de clé API ni lui attribuer de rôle de projet par défaut. Terraform conserve l’identifiant du compte de service et d’autres métadonnées non sensibles dans son état. À ce stade, le compte de service ne dispose d’aucune autorisation sur le projet.
Attribuer des autorisations selon le principe du moindre privilège
Définissez un rôle de projet personnalisé qui accorde uniquement les autorisations nécessaires à la charge de travail. Créez un groupe, ajoutez-y le compte de service et attribuez le rôle au groupe. Dans cet exemple, les membres du groupe peuvent créer des réponses :
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
}
La ressource openai_project_role définit l’ensemble minimal d’autorisations, openai_group_user ajoute le compte de service au groupe et openai_project_group_role attribue le rôle à ce groupe. Chaque compte de service ajouté au groupe hérite du même rôle de projet. Remplacez api.responses.write par l’ensemble minimal d’autorisations approuvées pour votre charge de travail. Consultez Projets et accès pour en savoir plus sur l’accès aux projets par l’intermédiaire de groupes.
Vérifiez et appliquez la configuration :
terraform plan
terraform apply
N’attribuez aucun des rôles prédéfinis member ou owner si un rôle de projet personnalisé accorde les autorisations nécessaires à votre charge de travail. Limitez l’accès aux seules autorisations approuvées.
Créer une clé API de portée limitée
Après avoir appliqué la configuration Terraform, créez une clé API à l’aide du point de terminaison Créer une clé API pour un compte de service de projet. L’API ne renvoie la valeur complète de la clé qu’une seule fois. Protégez donc le fichier de réponse avant d’envoyer la requête :
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
Limitez la portée de la clé au strict nécessaire pour la charge de travail. La portée d’une clé API peut restreindre davantage les autorisations du compte de service, mais elle ne peut lui accorder aucune autorisation en dehors de son rôle de projet.
Transférez le contenu du champ value de service-account-api-key.json vers votre gestionnaire de secrets en suivant la procédure approuvée, sans afficher la valeur. Une fois le secret stocké et vérifié par votre gestionnaire de secrets, supprimez le fichier de réponse :
rm service-account-api-key.json
Traitez service-account-api-key.json comme un secret tant que ce fichier existe. Ne l’ajoutez à aucun commit. N’inscrivez pas la clé dans la configuration Terraform, ne l’exposez pas dans une sortie Terraform et ne la transmettez pas dans une variable Terraform.
La référence de l’API décrit la structure de la réponse et fournit des exemples par langage. Les charges de travail qui prennent en charge la fédération d’identités de charge de travail peuvent utiliser le même compte de service et le même rôle de moindre privilège sans créer de clé API.
Importer un compte de service existant
Vous n’avez pas besoin d’importer un compte de service créé par Terraform. Pour gérer avec Terraform un compte de service créé en dehors de Terraform, déclarez-le avec son identifiant de projet et son nom actuels :
resource "openai_project_service_account" "application" {
project_id = "proj_123"
name = "example-application-development-service-account"
}
Importez l’identité existante avant d’appliquer la configuration comme d’habitude :
SERVICE_ACCOUNT_ID="<existing-service-account-id>"
terraform import \
openai_project_service_account.application \
"$PROJECT_ID/$SERVICE_ACCOUNT_ID"
terraform plan
Le premier plan après l’importation ne devrait proposer aucune modification du compte de service. S’il propose de le remplacer, corrigez le nom et le projet dans la configuration pour qu’ils correspondent à ceux du compte existant avant d’appliquer le plan.
L’importation ne récupère ni ne stocke de clé API. Elle ne modifie pas le rôle de projet actuel du compte de service et n’importe pas son appartenance au groupe. Déclarez et importez les ressources existantes openai_project_role, openai_group, openai_group_user et openai_project_group_role si Terraform doit les gérer. La charge de travail continue de lire les secrets existants depuis votre gestionnaire de secrets.
Importez le compte de service avant d’appliquer la déclaration de ressource. Si vous appliquez d’abord la déclaration, Terraform crée un autre compte de service au lieu de prendre en charge l’identité existante.
Récupérer ou renouveler des identifiants
Seule la réponse à la requête de création de la clé API contient sa valeur complète. Si vous consultez ensuite la clé API du projet, sa valeur est masquée. Vous ne pouvez donc pas récupérer une clé perdue.
Pour remplacer un identifiant perdu ou le renouveler sans interrompre la charge de travail, procédez comme suit :
- Déclarez le compte de remplacement comme une nouvelle ressource
openai_project_service_accountet donnez à cette ressource Terraform un nom différent de celui utilisé pour l’ancien compte. - Appliquez la configuration pour créer le compte de service de remplacement.
- Ajoutez le nouveau compte au groupe existant avec
openai_group_userpour qu’il hérite du rôle de projet de moindre privilège. - Créez une clé API pour le nouveau compte à l’aide de l’API d’administration et stockez-la dans votre gestionnaire de secrets en suivant la procédure approuvée.
- Déployez la nouvelle clé et vérifiez que la charge de travail fonctionne avec le nouveau compte.
- Retirez de la configuration Terraform l’ancienne ressource
openai_project_service_accountet la ressourceopenai_group_userassociée. Conservez le rôle, le groupe et l’attribution du rôle au groupe dont dépend toujours le nouveau compte de service. - Vérifiez et appliquez le plan qui supprime l’ancien compte de service et son appartenance au groupe. Exécutez ensuite
terraform planet assurez-vous que le plan ne propose aucune modification.
La suppression d’une ressource openai_project_service_account supprime le compte de service distant. Exigez une vérification explicite de cette modification, en particulier si des requêtes utilisent encore l’ancien identifiant.
Pour en savoir plus sur l’intégration de ressources existantes à l’état Terraform et sur leur suppression, consultez Importation et réconciliation.
Exécuter l’exemple complet
Les exemples précédents utilisent des valeurs concrètes pour illustrer la création d’un compte de service, l’attribution d’un rôle et la création d’une clé API. La configuration complète utilise des variables pour les valeurs et les autorisations propres au projet afin que vous puissiez la réutiliser dans plusieurs environnements.
Enregistrez la configuration suivante dans 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
}
Créez le fichier terraform.tfvars en indiquant l’identifiant d’un projet existant, un nom unique pour le compte de service et l’ensemble minimal d’autorisations approuvées pour le projet :
project_id = "proj_123"
service_account_name = "example-application-development-service-account"
project_role_permissions = [
"api.responses.write",
]
Initialisez Terraform, puis enregistrez le plan, vérifiez-le et appliquez-le :
terraform init
terraform fmt
terraform validate
terraform plan -out=tfplan
terraform show tfplan
terraform apply tfplan
Le premier plan devrait prévoir l’ajout de cinq ressources : le compte de service, son rôle de projet personnalisé, le groupe, l’appartenance du compte au groupe et l’attribution du rôle au groupe. Exécutez de nouveau terraform plan pour confirmer que la configuration n’entraîne aucune modification supplémentaire.
Créez la clé API du compte de service en dehors 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
Transférez la valeur de la clé API renvoyée dans votre gestionnaire de secrets approuvé, puis supprimez service-account-api-key.json. Ne stockez la clé ni dans la configuration Terraform, ni dans son état, ni dans ses sorties.