Terraform으로 프로젝트와 접근 관리하기
Terraform으로 프로젝트와 접근 관리하기 (Manage projects and access with Terraform)
출처: 문서
이 가이드로 OpenAI 프로젝트를 만들고 재사용 가능한 접근 제어를 구축해요. 프로젝트 역할로 identity가 무엇을 할 수 있는지 정의하고, identity를 조직 그룹으로 모은 다음, 그룹을 프로젝트에 연결해요.
메인 워크플로를 완료하면 다음과 같은 반복 가능한 구성을 갖게 돼요:
- 애플리케이션용 OpenAI 프로젝트를 만들어요.
- 최소 권한(least-privilege) 프로젝트 역할을 정의해요.
- 접근이 필요한 identity를 위한 조직 그룹을 만들어요.
- 역할을 통해 그룹에 프로젝트 접근 권한을 부여해요.
- 기존 조직 사용자를 그룹에 추가해요.
시작하기 전에
Terraform 프로바이더 설정을 완료하고 Admin API 키를 OPENAI_ADMIN_KEY로 export해요. 또한 기존 조직 사용자의 ID와 애플리케이션에 승인된 권한 식별자도 필요해요. 워크플로를 평가할 때는 테스트 조직을 사용해요.
openai_project를 destroy하면 프로젝트가 영구 삭제되는 대신 보관(archive)돼요. 보관된 프로젝트는 복원할 수 없어요.
프로젝트 경계 만들기
애플리케이션용 프로젝트를 만들어요:
resource "openai_project" "application" {
name = "example-application-development"
}
프로젝트는 애플리케이션의 API 사용량, 서비스 계정, 비율 한도, 지출 알림, 프로젝트 설정의 경계를 만들어요. Terraform은 생성된 ID를 openai_project.application.project_id로 제공해요. 프로젝트 수준 리소스는 해당 값을 참조할 수 있으므로, Terraform은 프로젝트를 먼저 생성해요.
이 집중된 예시는 구체적인 이름을 사용해요. 이후의 완전한 예시는 이를 변수로 대체해서 여러 환경에서 구성을 재사용할 수 있게 해요.
프로젝트 권한 정의하기
애플리케이션에 승인된 권한으로 프로젝트 역할을 만들어요:
resource "openai_project_role" "application" {
project_id = openai_project.application.project_id
role_name = "Application API access"
description = "Permissions approved for this application"
permissions = ["api.webhooks.read"]
}
openai_project_role 리소스는 프로젝트 안에서 identity가 무엇을 할 수 있는지 정의해요. 이 예시는 웹훅 구성을 읽을 권한을 부여해요. api.webhooks.read를 애플리케이션에 승인된 권한 식별자로 바꾸고, 필요한 권한만 시작해요.
permissions를 변경하면 역할이 업데이트돼요. 변경을 적용하기 전에 terraform plan을 실행해 추가되거나 제거되는 모든 권한을 검토해요.
그룹 만들기 또는 재사용하기
Terraform이 수명 주기를 소유해야 할 때 조직 그룹을 만들어요:
resource "openai_group" "application_access" {
name = "example-application-development-access"
}
그룹은 조직 수준에 존재하며 여러 프로젝트에서 재사용할 수 있어요. -access로 끝나는 이름은 멤버십이 단순히 팀을 설명하는 것이 아니라 접근 권한을 부여함을 전달해요.
다른 시스템이 기존 그룹을 소유하고 있다면 대신 읽어요:
data "openai_group" "application_access" {
group_id = "group_123"
}
데이터 소스는 이 구성이 그룹의 수명 주기를 책임지지 않게 하면서 그룹을 읽어요. SCIM으로 관리되는 그룹을 읽을 수는 있지만, 멤버십 변경은 그룹을 소유한 identity 시스템에서 유지해요.
그룹에 프로젝트 접근 권한 부여하기
그룹을 프로젝트 안의 커스텀 역할에 연결해요:
resource "openai_project_group_role" "application_access" {
project_id = openai_project.application.project_id
group_id = openai_group.application_access.group_id
role_id = openai_project_role.application.role_id
}
이 예시는 Terraform이 관리하는 그룹을 사용해요. 데이터 소스를 통해 기존 그룹을 재사용했다면 group_id 표현식을 data.openai_group.application_access.group_id로 바꿔요.
이 할당은 세 개의 객체를 연결해요:
project_id는 그룹이 접근 권한을 받는 위치를 식별해요.group_id는 접근 권한을 받는 identity 모음을 식별해요.role_id는 그룹이 받는 권한을 식별해요.
그룹 멤버는 이 프로젝트에서 커스텀 역할을 상속해요. 역할이나 그룹만 추가한다고 해서 접근 권한이 부여되지는 않아요. 할당(assignment)이 둘 사이의 연결이에요.
사용자 및 기타 identity 추가하기
openai_group_user로 Terraform이 관리하는 조직 그룹에 identity를 추가해요:
resource "openai_group_user" "application_developer" {
group_id = openai_group.application_access.group_id
user_id = "user_123"
}
user_id는 기존 조직 사용자나 서비스 계정을 식별할 수 있어요. 서비스 계정을 추가하려면 user_id로 openai_project_service_account.application.id를 사용해요. 그룹 기반 서비스 계정 접근, 인증, 자격 증명 수명 주기 요구사항은 Service accounts를 참고해요.
그룹 기반 접근이 적절하지 않을 때는 직접 역할 할당을 사용해요:
resource "openai_project_user_role" "application_developer" {
project_id = openai_project.application.project_id
user_id = "user_123"
role_id = openai_project_role.application.role_id
}
조직 전체 권한의 경우 조직 역할을 만들고 직접 또는 그룹을 통해 할당해요:
variable "organization_role_permissions" {
type = list(string)
}
resource "openai_role" "platform_operator" {
role_name = "Platform operator"
description = "Organization permissions for the platform team"
permissions = var.organization_role_permissions
}
resource "openai_user_role" "platform_operator" {
user_id = "user_123"
role_id = openai_role.platform_operator.role_id
}
organization_role_permissions를 승인된 조직 수준 권한 식별자로 설정해요. 각 할당이 필요한 최소 범위를 갖도록 조직 권한과 프로젝트 권한을 분리해 두는 게 좋아요.
현재 할당 확인하기
접근을 변경하기 전에 identity에 할당된 조직 및 프로젝트 역할을 읽어요:
data "openai_user_roles" "current" {
user_id = "user_123"
}
data "openai_project_user_roles" "current" {
project_id = openai_project.application.project_id
user_id = "user_123"
}
output "organization_roles" {
value = data.openai_user_roles.current.roles
}
output "project_roles" {
value = data.openai_project_user_roles.current.roles
}
데이터 소스는 현재 할당을 보고하지만, Terraform이 이들을 책임지게 만들지는 않아요.
할당 제거하기
Terraform이 이미 할당을 관리하고 있다면, 해당 리소스 블록을 제거하면 다음 계획이 원격 할당 삭제를 제안해요. 계획을 검토하고 다른 경로로 필요한 접근이 여전히 부여되는지 확인해요.
기존(사전 생성된) 할당의 경우 먼저 일치하는 리소스를 선언하고 문서화된 복합 ID로 import해요. 구성을 제거하고 삭제를 적용하기 전에 첫 번째 계획이 no-op인지 확인해요.
Terraform은 상태에 기록된 할당만 제거할 수 있어요. 기존 기본(default) 할당을 제거하려면 먼저 해당 Terraform 리소스로 import해요. 그런 다음 구성에서 해당 리소스를 제거하고 결과 destroy 계획을 적용해요. 조직이 이 import-and-destroy 워크플로를 허용하지 않으면 승인된 대시보드 또는 Administration API 프로세스를 통해 할당을 제거해요.
Import 형식과 안전한 도입 시퀀스는 Import and reconciliation을 참고해요.
완전한 예시 실행하기
집중된 예시들은 각 관계를 명확히 하기 위해 구체적인 값을 사용해요. 완전한 구성은 반복되는 환경별 값을 변수로 대체해 리소스 정의를 바꾸지 않고 재사용할 수 있게 해요.
다음 구성을 main.tf로 저장해요:
terraform {
required_version = ">= 1.0"
required_providers {
openai = {
source = "openai/openai"
version = ">= 1.0.0"
}
}
}
provider "openai" {}
variable "project_name" {
type = string
}
variable "project_role_permissions" {
type = list(string)
}
variable "user_id" {
type = string
}
resource "openai_project" "application" {
name = var.project_name
}
resource "openai_project_role" "application" {
project_id = openai_project.application.project_id
role_name = "Application API access"
description = "Permissions approved for this application"
permissions = var.project_role_permissions
}
resource "openai_group" "application_access" {
name = "${var.project_name}-access"
}
resource "openai_project_group_role" "application_access" {
project_id = openai_project.application.project_id
group_id = openai_group.application_access.group_id
role_id = openai_project_role.application.role_id
}
resource "openai_group_user" "application_developer" {
group_id = openai_group.application_access.group_id
user_id = var.user_id
}
output "project_id" {
value = openai_project.application.project_id
}
output "group_id" {
value = openai_group.application_access.group_id
}
output "project_role_id" {
value = openai_project_role.application.role_id
}
고유한 프로젝트 이름, 기존 조직 사용자 ID, 승인된 권한으로 terraform.tfvars를 만들어요:
project_name = "example-application-development"
user_id = "user_123"
project_role_permissions = [
"api.webhooks.read",
]
Terraform을 초기화한 다음 저장된 계획을 검토하고 적용해요:
terraform init
terraform fmt
terraform validate
terraform plan -out=tfplan
terraform show tfplan
terraform apply tfplan
첫 번째 계획에는 추가할 리소스 다섯 개가 포함되어야 해요. Apply 후 사용자는 그룹을 통해 커스텀 프로젝트 역할을 상속하며, terraform output이 프로젝트, 그룹, 프로젝트 역할 ID를 출력해요. terraform plan을 다시 실행해서 구성이 더 이상 변경을 생성하지 않는지 확인해요.
사람 사용자를 더 추가하려면 각 사용자에 고유한 Terraform 리소스 이름으로 그룹 멤버십 패턴을 반복해요. 비사람(nonhuman) identity를 구성하려면 Service accounts를 참고해요. Model, tool, and data controls와 Rate limits and spend를 사용해 프로젝트 가드레일을 추가해요.