로컬 보안
- 규범적
- 초안 1.0
- 갱신일
- Markdown으로 보기
10.1 기본 원칙
localhost에서만 수신 대기한다고 절대적으로 안전한 것은 아니다. 악성 웹 페이지가 여전히 로컬 포트에 접근을 시도할 수 있기 때문이다. 그래서 LMSP는 여러 조치를 결합한다.
- 서비스는 기본적으로 루프백 주소에 바인딩해야 한다. LAN 모드가 켜져 있지 않은 한(10.5절)
0.0.0.0이나 그 밖의 루프백이 아닌 주소에서 수신 대기해서는 안 된다. - 서비스는 처음 실행할 때 엔트로피가 높은 임의의 서비스 비밀 값을 생성하고, 내장된 기본값이 아니라 그 값으로 토큰을 발급하고 검증하는 것이 좋다.
- 핵심 인터페이스에 대한 모든 요청은 4.2절에 나열된 부트스트랩 엔드포인트를 제외하고 유효한 베어러 토큰을 담아야 한다. 루프백에서 왔다는 것만으로는 결코 충분하지 않다.
10.2 페어링과 토큰
클라이언트는 로컬 페어링 코드로 자신만의 베어러 토큰을 얻는다. 사용자는 서비스가 제공하는 방법으로 서비스가 페어링 코드를 보여 주게 하고, 클라이언트는 그 코드를 제출한다.
POST /lmsp/v1/pair
Content-Type: application/json
{
"client_name": "example-client",
"pairing_code": "K7QD-4M2X",
"scopes": ["inference"]
}
| 요청 필드 | 의미 |
|---|---|
client_name |
클라이언트의 표시 이름. 사용자에게 보인다. |
pairing_code |
사용자가 서비스에서 얻은 코드. |
scopes |
요청하는 스코프의 선택적 목록. 기본값은 ["inference"]. |
서비스는 토큰으로 답한다. token_type은 항상 Bearer이다.
{
"client_id": "cli_01J8MAT3W6X9B2D5F8H1K4N7QZ",
"access_token": "lmsp_example_3f9a1c52e7d84b60",
"token_type": "Bearer",
"scopes": ["inference"]
}
그 뒤 클라이언트는 모든 요청에 Authorization: Bearer <token>을 보낸다.
- 페어링 코드는 일회용이어야 하며 5분 안에 만료되는 것이 좋다. 최소 40비트의 엔트로피를 담는 것이 좋다. 서비스는 실패한 시도에 속도 제한을 걸어야 한다. 틀렸거나 만료된 코드에는
401과unauthorized로 응답한다. - 토큰은 클라이언트마다 독립적이므로, 사용자는 다른 클라이언트에 영향을 주지 않고 한 클라이언트를 폐기할 수 있다. 서비스는 사용자가 페어링된 클라이언트를 나열하고 폐기할 수 있게 하는 것이 좋다.
- 클라이언트는 토큰을 운영체제 키체인이나 자격 증명 관리자에 보관하는 것이 좋다. 서비스는 각 토큰의 해시만 저장하는 것이 좋다.
- 토큰이 없거나, 올바르지 않거나, 폐기된 경우에는
401,unauthorized,WWW-Authenticate: Bearer헤더로 응답한다. 토큰은 유효하지만 엔드포인트가 요구하는 스코프가 없으면403과forbidden으로 응답한다.
10.3 스코프
권한은 별개의 스코프로 나뉜다. 모델 다운로드, 모델 삭제, 도구 실행이 inference 스코프에 얹혀 가는 일은 결코 없다.
| 스코프 | 허용하는 것 |
|---|---|
inference |
모델 카탈로그 읽기, 응답과 작업 만들기, 클라이언트 자신의 작업 읽기와 취소. |
models:manage |
모델 로드와 언로드. |
models:install |
예약됨. 모델 다운로드와 삭제. |
tools:execute |
예약됨. 서비스 측에서 도구 실행. |
작업과 저장된 응답은 그것을 만든 클라이언트에 속한다. 서비스는 다른 클라이언트의 요청에는 그것들이 없는 것처럼 응답하는 것이 좋다(task_not_found 또는 response_not_found).
10.4 브라우저 및 네트워크 보호
- 서비스는 기본적으로 교차 출처 브라우저 요청을 거부하고, 명시적으로 설정된
Origin값만 허용해야 한다. 다른Origin을 가진 요청에는403과forbidden으로 응답한다. - 출처가 허용되면 서비스는 그 CORS 프리플라이트 요청에 응답하고,
Access-Control-Allow-Origin에*가 아니라 정확히 그 출처를 담아 보낸다. - 서비스는 DNS 리바인딩을 막기 위해
Host헤더를 검증해야 한다. 서비스가 담당하는 호스트 이름, 즉 루프백 이름과 주소, 그리고 LAN 모드를 위해 설정된 이름만 받아들인다. 그 밖의 값에는403과forbidden으로 응답한다.
10.5 LAN 모드
LAN 모드는 루프백 주소 밖에서도 수신 대기하는 것을 뜻한다.
- 서비스는 사용자가 명시적으로 켜지 않는 한 LAN 모드를 활성화해서는 안 된다.
- LAN 모드에서 서비스는 인증을 요구해야 하며 TLS도 활성화하는 것이 좋다. 클라이언트는 사용자가 명시적으로 허용하지 않는 한 루프백이 아닌 주소로 일반 HTTP를 통해 토큰을 보내지 않는 것이 좋다.
- mDNS 광고는 LAN 모드이면서 사용자가 LAN 검색도 켠 경우에만 허용된다(3.2절).
10.6 로깅과 개인정보
- 모델 경로, 로그, 프롬프트, 생성된 콘텐츠는 mDNS 광고에 포함되어서는 안 된다.
- 기본적으로 서비스는 메타데이터(시각, 엔드포인트, 상태 코드, id, 토큰 수, 소요 시간)만 기록하는 것이 좋다. 전체 프롬프트나 생성된 콘텐츠는 기록하지 않는 것이 좋다.
- 상태 점검 응답과 오류 상세 정보에는 모델 경로, 프롬프트, 액세스 토큰, 그 밖의 민감한 정보가 포함되어서는 안 된다.