
Stratoclave: Amazon Bedrock를 위한 테넌트 인식 크레딧 게이트웨이 — 이제 OpenAI codex 지원
요약
Stratoclave는 Amazon Bedrock 사용 시 발생하는 비용 추적 및 사용자 식별 문제를 해결하기 위한 오픈 소스 게이트웨이입니다. DynamoDB를 활용해 사용자별 크레딧 관리, 감사 로그, RBAC 권한 제어를 제공하며 최근 OpenAI codex 지원을 추가했습니다.
핵심 포인트
- Amazon Bedrock 앞단에서 테넌트별 크레딧 및 사용량 관리 가능
- Anthropic Messages API 및 OpenAI Responses API 경로 지원
- Cognito, AWS SSO, API 키를 통한 다양한 인증 방식 제공
- ECS Fargate와 DynamoDB 기반의 가벼운 아키텍처
만약 팀이 Amazon Bedrock를 위해 단일 AWS 계정을 공유하도록 허용한다면, Bedrock 단독으로는 해결할 수 없는 질문들에 빠르게 직면하게 됩니다: 누가 어떤 모델을 호출했는지, 누구의 예산으로 호출했는지, 어떤 신원을 통해 호출했는지에 대한 문제입니다. Stratoclave는 Postgres, Redis 또는 SaaS 컨트롤 플레인 (control plane)을 끌어들이지 않고도 Bedrock 앞에 이러한 답변들을 배치하는 작은 오픈 소스 (OSS) 게이트웨이입니다.
이 프로젝트는 원래 저 자신을 위해 작성되었습니다 — 저는 단지 Claude Code의 개인적인 사용을 위해 Bedrock 앞에 사용자별 크레딧 (per-user credits)을 두고 싶었을 뿐입니다. 이제는 Bedrock의 bedrock-mantle 엔드포인트를 통해 OpenAI codex / GPT-5.x까지 지원하는 수준으로 성장했습니다.
Repo:
littlemex/stratoclave(Apache 2.0, alpha)
실제 기능
Stratoclave는 ECS Fargate 상에서 실행되는 단일 FastAPI 서비스로, 두 가지 추론 경로 (inference routes)를 노출합니다:
| 경로 (Route) | 와이어 포맷 (Wire format) | 백엔드 (Backend) |
|---|---|---|
POST /v1/messages | Anthropic Messages API | us-east-1의 bedrock:Converse |
POST /openai/v1/responses | OpenAI Responses API | us-east-2 / us-west-2의 bedrock-mantle |
두 경로 모두 동일한 DynamoDB 기반의 크레딧 예약 (credit reservation), 동일한 messages:send / responses:send RBAC 권한 범위 (scopes), 동일한 감사 로그 (audit log), 그리고 동일한 세 가지 신원 경로 (Cognito 비밀번호, Vouch-by-STS를 통한 AWS SSO, 장기 유지되는 sk-stratoclave-* 키)를 공유합니다.
컨트롤 플레인 (control plane)은 하나의 AWS 리전 (us-east-1)과 하나의 Fargate 태스크 (task)로 구성됩니다. OpenAI를 위한 Bedrock은 리전 간 (cross-region)으로 작동하지만, 두 번째 컨트롤 플레인 리전은 배포되지 않습니다.
웹 콘솔 로그인 화면은 비밀번호 / SSO 로그인을 위해 Cognito 호스팅 UI (Hosted UI)로 리다이렉트됩니다. 반면 CLI 사용자는 stratoclave auth login을 실행한 다음 stratoclave ui open으로 이 탭을 포커스할 수 있습니다.
제가 실제로 원했던 것: 테넌트별, 사용자별 크레딧
이것이 존재하는 이유입니다. 모든 추론 호출(inference call)은 조건부 UpdateItem을 통해 호출자의 예산에서 max_tokens + input_estimate를 원자적(atomically)으로 예약하고, 업스트림(upstream)을 호출한 다음, 반환 시 실제 토큰 수와의 차액을 환불합니다. UsageLogs는 예약량이 아닌 실제 사용량을 항상 기록합니다. 동시 요청(Concurrent requests)은 할당량(quota)을 초과하여 경합(race)할 수 없습니다. 조건부 쓰기(conditional write)는 커밋되거나 실패합니다.
파이프라인은 하나의 파일(backend/mvp/_pipeline.py)에 존재하며 두 라우트(route) 간에 공유됩니다. OpenAI Responses 라우트는 추론 흔적(reasoning traces)이 출력을 한 자릿수만큼 늘릴 수 있기 때문에, 선불 예약 시 추가적인 추론 노력 승수(reasoning-effort multiplier, low / medium / high / xhigh에 대해 1× / 2× / 4× / 8×)를 적용합니다. 최소 예약량은 승수와 관계없이 8,192 토큰입니다.
개인 사용 기록은 동일한 UsageLogs 테이블에서 가져온 호출별 토큰 수, 모델 이름 및 크레딧 지출 내역을 보여줍니다.
STS를 통한 보증: IdP 비밀키를 보유하지 않는 비밀번호 없는 로그인
제가 가장 자랑스럽게 생각하는 단 하나의 동작입니다. CLI는 SigV4를 사용하여 sts:GetCallerIdentity 요청에 로컬에서 서명하고, 백엔드는 서명된 페이로드(payload)를 STS로 그대로 전달하며, 백엔드는 STS가 반환하는 Arn / UserId / Account만을 신뢰합니다. IdP 리프레시 토큰(refresh token)은 백엔드에 절대 닿지 않습니다.
이 패턴은 HashiCorp Vault가 AWS iam 인증 방식에서 10년 동안 사용해 온 방식과 동일합니다. ~/.aws/credentials를 채우는 모든 것은 동일한 방식으로 작동합니다: aws sso login, saml2aws, Entra ID / Okta / ADFS SAML 페더레이션 (federation), 심지어 장기 키(long-lived keys)를 사용하는 일반 IAM 사용자까지 포함됩니다 (신뢰할 수 있는 계정별로 명시적으로 허용되지 않는 한 기본적으로 거부(DENY)됩니다). EC2 인스턴스 프로파일(instance profiles)은 단일 사용자에게 귀속될 수 없기 때문에 기본적으로 거부됩니다.
백엔드가 완전히 침해되더라도 고객의 IAM Identity Center나 SAML IdP로 피벗(pivot)할 수 없습니다. 최악의 경우 피해 범위(blast radius)는 Stratoclave 자체 리소스 — Bedrock 과다 지출, DynamoDB 변조, 해당 배포 내에서의 사칭 — 로 제한됩니다.
trusted-accounts 관리자 페이지는 AWS 계정 ID와 allowed_role_patterns (fnmatch)를 관리하는 곳입니다. 이것이 외부 계정으로부터의 SSO 로그인을 제어하는 허용 목록(allowlist)입니다.
예상보다 더 중요하게 작용했던 세 가지 작은 요소들
1. stratoclave codex -- "..." (및 stratoclave claude -- "...")
30분 동안 유효한 일회성(ephemeral) responses:send (또는 messages:send) 키를 생성하고, 이를 환경 변수(env)를 통해 자식 프로세스에 전달한 뒤, 프로세스 종료 시 키를 폐기(revoke)하는 래퍼(wrapper) 서브커맨드입니다:
$ stratoclave codex -- "Write a hello-world Python function"
[INFO] Launching codex via Stratoclave proxy (model=openai.gpt-5.4, key=sk-stratoclave-...)
[INFO] Child process uses an ephemeral responses-only API key;
...
자식 프로세스는 정확히 하나의 경로(route)로 범위가 제한된 키를 할당받으며, 사용자의 Cognito 베어러(bearer) 토큰은 부모 프로세스를 절대 벗어나지 않습니다. codex에 의해 시작된 MCP 서버 및 도구 하위 프로세스(tool subprocesses)는 상속받은 환경 변수에 적절한 자격 증명이 포함되어 있지 않기 때문에, 사용자의 stratoclave 관리 엔드포인트(admin endpoints)로 다시 피벗(pivot)할 수 없습니다.
Claude Code를 위한 동일한 래퍼(wrapper)도 존재합니다 (stratoclave claude). 이들은 하나의 Rust 구조체(ChildLauncher)를 통해 환경 변수 삭제(env-scrub) 목록과 종료 시 취소(revoke-on-exit) 라이프사이클을 공유하므로, 한 곳에 적용된 수정 사항이 양쪽 모두에 적용됩니다.
2. /.well-known/stratoclave-config
전체 CLI 부트스트랩(bootstrap)을 구동하는 하나의 인증되지 않은 디스커버리 엔드포인트(discovery endpoint)입니다:
$ stratoclave setup https://<your>.cloudfront.net
$ stratoclave auth sso --profile your-aws-sso-profile # 또는 `auth login --email`
$ stratoclave codex -- "..."
CODEX_ENABLED=true인 경우, 해당 엔드포인트는 Cognito ID, 기본 모델 이름, OpenAI 베이스 경로(base path) 및 지원되는 리전(regions)을 반환합니다. 새로운 백엔드에 접속하는 이전 CLI 바이너리들은 모든 새로운 필드가 Optional로 처리되어 있기 때문에 문제없이 역직렬화(deserialize)됩니다.
3. CLI는 "프록시를 통해 무엇이 작동하는가"에 대한 신뢰할 수 있는 소스(source of truth)입니다.
커스텀 base_url을 사용하여 Anthropic Messages 또는 OpenAI Responses 규격을 따르는 모든 것은 작동합니다. CLI는 단지 편의성을 위한 래퍼(wrapper)일 뿐입니다. 만약 OpenAI SDK를 직접 사용하는 것을 선호한다면 다음과 같습니다:
import openai
client = openai.OpenAI(
...
Anthropic의 경우도 동일합니다:
from anthropic import Anthropic
client = Anthropic(
...
Claude Desktop의 Cowork (Gateway mode) 및 ANTHROPIC_BASE_URL을 사용하는 Cline / Continue / Aider도 동일한 방식으로 작동합니다.
개인 API 키(personal API-keys) 페이지는 사용자가 직접 장기 사용 가능한 sk-stratoclave-* 키를 관리하는 곳입니다. 이는 래퍼 하위 명령어가 종료 시 생성하고 즉시 취소하는 키 형태와 동일합니다.
스크린샷: 관리자 워크스루(admin walkthrough)
대시보드에서 프로비저닝된 테넌트 멤버(provisioned tenant member)에 이르기까지의 관리자 흐름(admin flow)을 위에서 아래로 보여줍니다.
대시보드는 테넌트(tenants), 사용자(users), 최근 활동(recent activity) 및 크레딧 소비(credit consumption)를 요약하여 보여줍니다.
신규 사용자 양식(new-user form)에서는 이메일, 역할 (admin / team_lead / user), 테넌트 할당(tenant assignment) 및 초기 크레딧 예산(initial credit budget)을 수집합니다.
사용자 상세 보기(user detail view)에서는 할당된 역할, 테넌트, 잔여 크레딧 대 총 크레딧(remaining vs total credit), 그리고 사용자 본인의 API 키를 보여줍니다.
테넌트 상세 보기(tenant detail view)에는 멤버 목록, 각 멤버의 크레딧 잔액, 그리고 테넌트 전체의 월간 한도(tenant-wide monthly cap)가 나열됩니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기







