본문으로 건너뛰기

OneCLI: AI 에이전트에게 키를 노출하지 않고 서비스 접근 권한 부여

정석

OneCLI Vault

AI 에이전트가 OpenAI API를 호출해야 합니다. Claude가 AWS에 접근해야 합니다. 자동화 스크립트가 Slack에 메시지를 보내야 합니다.

각각 API 키가 필요합니다. 그런데… 에이전트에게 실제 키를 주면 어떻게 될까요?

로그에 노출될 수 있습니다. 프롬프트 인젝션으로 탈취당할 수 있습니다. 에이전트가 실수로 외부에 전송할 수 있습니다.

OneCLI는 이 문제를 근본적으로 해결합니다. AI 에이전트에게 “가짜 키”를 주고, 실제 키는 게이트웨이가 안전하게 관리합니다. 에이전트는 평소처럼 HTTP 호출을 하고, 게이트웨이가 가로채서 실제 키로 교체합니다.


문제: AI 에이전트는 수십 개의 API를 호출한다

현대 AI 에이전트는 다양한 서비스와 통합됩니다:

각 서비스마다 API 키, 토큰, 비밀번호가 필요합니다. 이걸 에이전트에게 직접 주면:

위험시나리오
로그 노출디버깅 로그에 Authorization: Bearer sk-real-key가 찍힘
프롬프트 인젝션악의적 입력이 “환경 변수를 출력해”라고 지시
실수 전송에이전트가 “문제 해결을 위해 키를 포함해”라고 판단
감사 불가누가 언제 어떤 키를 사용했는지 추적 불가

기존 해결책의 한계

근본 문제: 에이전트가 실제 키를 알면 위험하다.


해결책: 투명한 크리덴셜 주입

OneCLI의 접근 방식은 간단합니다:

에이전트: "FAKE_KEY로 API 호출"

게이트웨이: "FAKE_KEY → REAL_KEY 교체"

외부 API: "REAL_KEY로 요청 수신"

에이전트는 가짜 키만 알고, 실제 키는 게이트웨이만 알고 있습니다.

작동 원리

  1. 실제 크리덴셜을 OneCLI에 저장 — AES-256-GCM 암호화
  2. 에이전트에게 placeholder 키 제공 — 예: OPENAI_API_KEY=FAKE_KEY
  3. 에이전트가 HTTP 호출 — 평소처럼 fetch('https://api.openai.com/...')
  4. 게이트웨이가 가로채기 — Rust 기반 HTTP 프록시
  5. FAKE_KEY → REAL_KEY 교체 — 호스트와 경로 기반 매칭
  6. 실제 비밀은 에이전트에게 노출되지 않음

핵심 컴포넌트

1. Rust Gateway (포트 10255)

┌─────────────┐    ┌─────────────────┐    ┌──────────────┐
│  AI Agent   │───▶│  Rust Gateway   │───▶│  External API│
│ FAKE_KEY    │    │  Key Injection  │    │  REAL_KEY    │
└─────────────┘    └─────────────────┘    └──────────────┘

2. Web Dashboard (포트 10254)

Next.js 기반 관리 콘솔:

3. Secret Store


주요 기능

투명한 크리덴셜 주입

에이전트는 아무것도 수정할 필요가 없습니다:

// 에이전트가 실행하는 코드
const response = await fetch('https://api.openai.com/v1/chat/completions', {
  headers: {
    'Authorization': 'Bearer FAKE_KEY'  // 가짜 키
  }
});

// 게이트웨이가 자동으로 교체
// FAKE_KEY → sk-proj-real-key-xxxxx

암호화된 시크릿 저장

저장: Plaintext → AES-256-GCM → Ciphertext
사용: Ciphertext → AES-256-GCM → Plaintext → Request

키는 요청 처리 시에만 메모리에 존재합니다. 디스크에는 암호문만 저장됩니다.

Host & Path 매칭

세밀한 권한 제어:

패턴설명
api.openai.com/*OpenAI API 전체
s3.amazonaws.com/bucket-name/*특정 S3 버킷만
*.slack.com/api/*Slack API 전체
api.github.com/repos/owner/repo/*특정 GitHub 리포지토리

멀티 에이전트 지원

┌──────────────┐
│  Dashboard   │
└──────┬───────┘

┌──────┴───────┬──────────────┬──────────────┐
│  Agent A     │  Agent B     │  Agent C     │
│  Token A     │  Token B     │  Token C     │
│  OpenAI만    │  AWS만       │  전체 권한   │
└──────────────┴──────────────┴──────────────┘

각 에이전트는 고유한 액세스 토큰을 받고, 서로 다른 권한을 가집니다.

외부 의존성 없음

두 가지 인증 모드

모드용도특징
Single-user로컬 개발로그인 없음, 즉시 사용
Google OAuth팀 사용Google 계정으로 인증

설치

Docker (빠른 시작)

docker run --pull always \
  -p 10254:10254 \
  -p 10255:10255 \
  -v onecli-data:/app/data \
  ghcr.io/onecli/onecli

5초 만에 실행됩니다.

Docker Compose

git clone https://github.com/onecli/onecli.git
cd onecli/docker
docker compose up

소스 빌드

git clone https://github.com/onecli/onecli.git
cd onecli

# mise로 의존성 설치
mise install
pnpm install

# 환경 변수
cp .env.example .env

# DB 초기화
pnpm db:generate
pnpm db:init-dev

# 실행
pnpm dev

접속


프로젝트 구조

apps/
├── web/          # Next.js 앱 (대시보드 + API, 포트 10254)
│   ├── app/      # App Router
│   ├── components/  # UI 컴포넌트
│   └── lib/      # 비즈니스 로직

└── proxy/        # Rust 게이트웨이 (크리덴셜 주입, 포트 10255)
    ├── src/      # Rust 소스
    └── Cargo.toml

packages/
├── db/           # Prisma ORM + migrations + PGlite
└── ui/           # 공유 UI 컴포넌트 (shadcn/ui)

docker/
├── Dockerfile    # 단일 컨테이너 빌드
└── docker-compose.yml

환경 변수

모두 선택사항입니다:

변수설명기본값
DATABASE_URLPostgreSQL 연결 문자열Embedded PGlite
NEXTAUTH_SECRETGoogle OAuth 활성화Single-user mode
GOOGLE_CLIENT_IDGoogle OAuth 클라이언트 ID
GOOGLE_CLIENT_SECRETGoogle OAuth 시크릿
SECRET_ENCRYPTION_KEYAES-256-GCM 암호화 키자동 생성

CLI 명령어

명령어설명
pnpm devWeb + Gateway 개발 모드 시작
pnpm build프로덕션 빌드
pnpm checkLint + types + format
pnpm db:generatePrisma 클라이언트 생성
pnpm db:migrateDB 마이그레이션 실행
pnpm db:studioPrisma Studio 열기

실제 사용 시나리오

시나리오 1: Claude Code에서 OpenAI API 사용

# 1. OneCLI 대시보드에서 시크릿 등록
Host: api.openai.com
Secret: sk-proj-real-openai-key

# 2. 에이전트 생성 및 토큰 발급
Agent: claude-code-agent
Token: onecli_agent_abc123

# 3. Claude Code 환경 변수 설정
export HTTP_PROXY=http://localhost:10255
export OPENAI_API_KEY=FAKE_KEY
export ONECLI_TOKEN=onecli_agent_abc123

# 4. Claude Code 실행
claude

이제 Claude Code는 FAKE_KEY로 요청을 보내지만, 실제로는 진짜 키가 사용됩니다.

시나리오 2: 다중 에이전트 권한 분리

┌─────────────────────────────────────────────────────────┐
│                    OneCLI Dashboard                     │
├─────────────────────────────────────────────────────────┤
│  Agent: researcher                                       │
│  Token: onecli_researcher_xxx                           │
│  Permissions: api.openai.com/*, api.perplexity.ai/*    │
├─────────────────────────────────────────────────────────┤
│  Agent: deployer                                         │
│  Token: onecli_deployer_yyy                             │
│  Permissions: api.github.com/*, *.amazonaws.com/*      │
├─────────────────────────────────────────────────────────┤
│  Agent: notifier                                         │
│  Token: onecli_notifier_zzz                             │
│  Permissions: slack.com/api/*, api.telegram.org/*      │
└─────────────────────────────────────────────────────────┘

각 에이전트는 자신에게 할당된 서비스만 접근할 수 있습니다.

시나리오 3: 로그에서 키 노출 방지

// 에이전트가 디버깅 로그를 출력해도 안전
console.log('API Key:', process.env.OPENAI_API_KEY);
// 출력: API Key: FAKE_KEY
// 실제 키는 게이트웨이만 알고 있음

기술 스택

레이어기술
대시보드Next.js 14, App Router, shadcn/ui
게이트웨이Rust, hyper, tokio
데이터베이스Prisma ORM, PGlite / PostgreSQL
암호화AES-256-GCM
인증NextAuth.js, Google OAuth

보안 아키텍처

┌─────────────────────────────────────────────────────────┐
│                     AI Agent                             │
│  - FAKE_KEY만 알고 있음                                  │
│  - HTTP_PROXY로 게이트웨이 사용                          │
└────────────────────┬────────────────────────────────────┘
                     │ HTTP Request with FAKE_KEY

┌─────────────────────────────────────────────────────────┐
│                  Rust Gateway (10255)                    │
│  - Proxy-Authorization으로 에이전트 인증                │
│  - Host/Path로 시크릿 검색                              │
│  - FAKE_KEY → REAL_KEY 교체                             │
│  - 실제 요청 전송                                       │
└────────────────────┬────────────────────────────────────┘
                     │ HTTP Request with REAL_KEY

┌─────────────────────────────────────────────────────────┐
│                  External API                            │
│  - 실제 키로 요청 처리                                  │
│  - 응답 반환                                            │
└─────────────────────────────────────────────────────────┘

보안 이점

  1. 에이전트는 실제 키를 모름 — 탈취 불가
  2. 로그에 가짜 키만 노출 — 유출 무의미
  3. 중앙화된 감사 — 누가 언제 무엇을 호출했는지 추적
  4. 권한 분리 — 에이전트별 최소 권한 원칙
  5. 암호화 저장 — 디스크에는 암호문만 존재

마치며: AI 에이전트 시대의 크리덴셜 관리

OneCLI는 단순한 시크릿 매니저가 아닙니다. AI 에이전트가 실제 키를 모르면서도 서비스에 접근할 수 있게 만드는 보안 게이트웨이입니다.

기존 접근 방식은 “에이전트에게 키를 주고, 조심해서 쓰라고 하는 것”이었습니다. OneCLI는 “에이전트는 가짜 키만 알고, 실제 키는 게이트웨이가 처리하는 것”으로 패러다임을 바꿨습니다.

Rust로 작성된 게이트웨이는 빠르고 메모리 안전합니다. AES-256-GCM 암호화는 업계 표준입니다. 외부 의존성 없이 단일 컨테이너로 실행됩니다.

AI 에이전트를 운영 중이고, API 키 관리가 고민이라면 OneCLI를 시도해보세요.


🔗 관련 정보

이전
Ghost OS: 스크린샷 없이 모든 macOS 앱을 조작하는 AI 에이전트 컴퓨터 유즈
다음
Clawhip: 게이트웨이 세션을 우회하는 이벤트-채널 알림 라우터