플러그인

플러그인 (Plugins)

플러그인을 사용하면 외부 서비스를 LiteLLM UI 사이드바에서 AI Gateway 옆의 선택 가능한 모드로 표시할 수 있어요. 각 플러그인은 자체 백엔드로 실행돼요. LiteLLM이 요청을 프록시하고, 범위가 지정된 자격 증명을 주입하며, iframe에 단기 유효 신원 클레임을 넘겨 사용자가 다시 인증하지 않도록 해요.

대시보드 아래에 내부 도구(리포팅 UI, 에이전트 컨트롤 플레인, 데이터 라벨링 앱)를 제공하면서 호출자의 master key를 그 도구에 노출하지 않으려 할 때 유용해요.

출처: 문서

본문

플러그인을 사용하면 외부 서비스를 LiteLLM UI 사이드바에서 AI Gateway 옆의 선택 가능한 모드로 표시할 수 있어요. 각 플러그인은 자체 백엔드로 실행돼요. LiteLLM이 요청을 프록시하고, 범위가 지정된 자격 증명을 주입하며, iframe에 단기 유효 신원 클레임을 넘겨 사용자가 다시 인증하지 않도록 해요.

대시보드 아래에 내부 도구(리포팅 UI, 에이전트 컨트롤 플레인, 데이터 라벨링 앱)를 제공하면서 호출자의 master key를 그 도구에 노출하지 않으려 할 때 유용해요.

플러그인을 선택하면 AI Gateway 내비게이션을 플러그인 자체의 내비게이션으로 바꿔요. 아래 페이지는 LiteLLM 대시보드 프레임 안에 로드된 Agent Control Plane 플러그인이에요.

info

v1.89.3+에서 사용 가능해요.

빠른 시작 (Quick start)

1. config.yaml에서 플러그인 등록하기

    general_settings:
      master_key: os.environ/LITELLM_MASTER_KEY
      plugins:
        - name: my-plugin              # unique identifier, no spaces
          display_name: My Plugin      # label shown in the UI dropdown
          url: "https://my-plugin.example.com"
          plugin_key: "sk-plugin-..."  # plugin's own auth credential

plugin_key는 프록시가 플러그인에 전달하는 모든 요청에 Authorization: Bearer ***로 주입돼요. 호출자의 LiteLLM 자격 증명은 먼저 제거되므로 플러그인은 활성 LiteLLM API 키를 받지 못해요.

대시보드의 Admin Settings > Plugins에서도 플러그인을 추가할 수 있어요. 같은 필드가 적용돼요. plugin_key는 쓰기 전용이며 저장 후 API에서 반환되지 않아요.

2. 두 플러그인 엔드포인트 구현하기

플러그인 서비스는 두 개의 공개 엔드포인트를 노출해야 해요. GET /api/plugin-manifest는 LiteLLM UI가 사이드바를 렌더링하는 데 쓰는 플러그인 메타데이터를 반환하고, POST /api/plugin-auth는 LiteLLM이 iframe에 넘겨주는 신원 클레임을 복호화해 사용자가 두 번 로그인하지 않도록 해요.

최소 매니페스트:

    {
      "name": "my-plugin",
      "display_name": "My Plugin",
      "version": "1.0.0",
      "nav_items": [
        { "key": "home",    "label": "Home",    "icon": "HomeOutlined",    "path": "/" },
        { "key": "reports", "label": "Reports", "icon": "BarChartOutlined", "path": "/reports" }
      ],
      "capabilities": ["reports", "data"]
    }

POST /api/plugin-auth의 경우 iframe이 session_claim 암호문을 전달해요. 프록시는 LITELLM_SALT_KEY를 플러그인과 절대 공유하지 않아요. 대신 각 플러그인에는 자체 전용 키가 준비되는데, HMAC-SHA256(LITELLM_SALT_KEY, plugin_name)로 파생돼요. 프록시 호스트에서 한 번 계산하고 그 결과를 비밀로 플러그인에 넘겨줘요 (예: PLUGIN_AUTH_KEY로):

    python -c 'import base64,hmac,hashlib,os; \
    print(base64.urlsafe_b64encode(hmac.new(os.environ["LITELLM_SALT_KEY"].encode(), b"my-plugin", hashlib.sha256).digest()).decode())'

이 범위 키만 가진 손상된 플러그인은 LITELLM_SALT_KEY를 복구하거나 다른 LiteLLM 비밀을 복호화할 수 없어요.

플러그인에서 클레임을 복호화하고 검증해요:

    import json, os, time
    from cryptography.fernet import Fernet

    _CLAIM_TTL_SECONDS = 30

    def plugin_auth(session_claim: str) -> dict:
        cipher = Fernet(os.environ["PLUGIN_AUTH_KEY"].encode())
        claim = json.loads(cipher.decrypt(session_claim.encode(), ttl=_CLAIM_TTL_SECONDS))
        if claim.get("plugin") != "my-plugin":
            raise ValueError("claim audience mismatch")
        if int(claim.get("exp", 0)) < int(time.time()):
            raise ValueError("claim expired")
        return claim

클레임 페이로드는 { "plugin", "user_id", "user_role", "exp" }예요. LiteLLM bearer 토큰은 담지 않아요. user_iduser_role로 플러그인의 자체 세션을 만들고, /plugin-proxy/<name>/* 리버스 프록시를 통해 LiteLLM으로의 API 호출을 인증하세요. 리버스 프록시가 당신을 위해 plugin_key를 주입해요.

플러그인이 사용자에 대해 받는 것

LiteLLM은 의도적으로 최소한의 사용자 컨텍스트를 전달해요. 플러그인은 호출자의 이메일, 키 별칭, 팀, 예산, bearer 토큰을 절대 보지 못해요. 식별자와 역할만 받아요.

복호화된 session_claim 페이로드는 정확히 네 개의 필드를 담아요:

    {
      "plugin": "my-plugin",
      "user_id": "user_abc123",
      "user_role": "proxy_admin",
      "exp": 1750460400
    }

plugin은 클레임이 발행된 플러그인 이름이에요. 나머지를 신뢰하기 전에 항상 자신의 플러그인과 일치하는지 확인하세요. 그래야 한 플러그인용 클레임이 다른 플러그인에 재생될 수 없어요. user_id는 호출자의 LiteLLM 내부 사용자 식별자예요. 프로필 데이터를 조회해야 할 때 LiteLLM의 /user/info에 대한 안정적 조인 키로 사용하세요. user_role은 호출자의 LiteLLM 역할 문자열이에요 (예: proxy_admin, internal_user, internal_user_viewer). 대략적인 권한 힌트로 쓰고, 자체 검사는 스스로 적용하세요. exp는 30초 뒤로 설정된 Unix 타임스탬프예요. Fernet ttl 인자가 이미 만료된 암호문을 거부하지만, exp를 독립적으로 검증하면 프록시와 플러그인 사이의 시계 스큐를 잡아내요.

프록시가 둘을 해석하지 못하면(예: 인증되지 않은 호출자) user_iduser_role 둘 다 기본값 ""이 돼요. 빈 문자열을 인증되지 않은 것으로 취급하세요. 역할이 없는데 높은 접근을 부여하지 마세요.

프록시가 플러그인 백엔드로 하는 모든 /plugin-proxy/<name>/<path> 호출에서 같은 신원이 두 헤더로 전달돼요:

    x-litellm-user-id: user_abc123
    x-litellm-user-role: proxy_admin

이 헤더는 정보 제공용이에요. 플러그인은 헤더가 아니라 검증된 session_claim에서 발급된 자체 세션에 대해 요청을 인증해야 해요. 헤더는 독립적으로 검증할 수 없으니까요.

iframe 인증 동작 방식

    LiteLLM UI
      GET /api/plugins/auth-token        -> { session_claim }
      postMessage({ type:"litellm-auth", session_claim }, pluginOrigin)
           |
           v
    Plugin iframe (browser)
      POST /api/plugin-auth { session_claim }
           |
           v
    Plugin server
      decrypt(session_claim, PLUGIN_AUTH_KEY) -> { user_id, user_role, exp }
      establish plugin session -> stored in sessionStorage

LiteLLM bearer 토큰은 프록시 밖으로 절대 나가지 않아요. 클레임은 호출자의 신원만 전달하고 30초 후 만료되므로, postMessage를 가로채도 플러그인의 범위 키가 없으면 쓸모없는 암호문만 얻어요.

프록시 라우트

GET /api/plugins는 등록된 플러그인을 나열하며, 각각 name, display_name, url을 반환해요. plugin_key는 절대 반환되지 않아요. 서버 쪽에만 남아요. 호출자는 인증되어야 해요.

GET /api/plugins/auth-token?plugin_name=<name>은 그 플러그인의 단기 유효 암호화 신원 클레임을 반환해요. 프록시에 LITELLM_SALT_KEY가 설정돼야 하고(그렇지 않으면 503), 플러그인이 등록돼야 해요(그렇지 않으면 404).

ANY /plugin-proxy/{name}/{path}는 플러그인 백엔드로의 인증된 리버스 프록시예요. 접근은 proxy_admin으로 제한돼요.

리버스 프록시 동작

admin(또는 서버-투-서버 호출자)이 /plugin-proxy/<name>/<path>를 치면 프록시는 호출자를 로컬로 인증한 뒤 요청을 다시 써서 플러그인의 url로 전달해요.

전달 전에 모든 LiteLLM 자격 증명 헤더가 제거돼요. 여기에는 Authorization, x-api-key, API-Key, x-goog-api-key, Ocp-Apim-Subscription-Key, x-litellm-api-key, 설정된 litellm_key_header_name, Cookie가 포함돼요. 플러그인은 호출자의 활성 LiteLLM 키를 절대 받을 수 없어요.

그런 다음 plugin_keyAuthorization: Bearer ***로 주입돼요. 그것이 플러그인이 받는 유일한 자격 증명이에요.

호출자 신원은 x-litellm-user-idx-litellm-user-role로 전달돼 플러그인이 자체 권한 부여를 실행할 수 있어요. 이는 정보 힌트이지 자격 증명이 아니에요.

응답은 Content-Security-Policy: sandboxX-Content-Type-Options: nosniff로 샌드박스 처리돼 플러그인이 제어하는 바이트가 LiteLLM 오리진에서 서빙돼도 대시보드를 상대로 실행되지 않도록 해요.

보안 체크리스트

플러그인을 사용자에게 노출하기 전에 다음을 확인하세요: LITELLM_SALT_KEY가 프록시에 설정되어 있고 플러그인과 절대 공유되지 않으며, 플러그인은 파생된 HMAC(LITELLM_SALT_KEY, plugin_name) 키(전용 비밀로 준비된 것)만 보유하고, plugin_key는 LiteLLM master key가 아니라 플러그인에 범위가 지정된 전용 자격 증명인지를 확인하세요. 플러그인의 POST /api/plugin-auth는 클레임의 plugin 청중(audience)과 exp(30초 TTL)를 모두 강제해야 해요. 플러그인은 x-litellm-user-idx-litellm-user-role을 인증 증명이 아니라 신원 힌트로 취급하고, 프로덕션에서는 플러그인 서비스 URL이 HTTPS를 사용해야 해요.

더 알아보기 (Learn more)

  • LiteLLM Enterprise
  • 플러그인 보안 모델: LITELLM_SALT_KEY, plugin_key, session_claim