프로그래밍 방식 사용자 접근 제어 관리

프로그래밍 방식 사용자 접근 제어 관리

이 가이드는 Hub API를 통해 조직 구성원 역할과 리소스 그룹 구성원 자격을 관리하는 방법을 설명해요: 구성원의 조직 역할·리소스 그룹 할당 변경, 리소스 그룹 나열, 그룹에 사용자 추가, 배치 워크플로까지요.

목차:

출처: 문서

본문

API로 구성원 역할 변경하기

Hub API로 구성원의 조직 역할(No Access / Read / Contributor / Write / Admin)과 선택적으로 리소스 그룹에서의 역할을 변경할 수 있어요. API는 요청당 구성원 한 명씩 업데이트해요. 여러 구성원의 역할을 바꾸려면 API를 반복문으로 호출해요(아래 예시).

OpenAPI 참조: PUT /api/organizations/{name}/members/{username}/role

전제 조건

  • 조직에 구독 플랜(예: Team 또는 Enterprise)이 있어야 해요. 그렇지 않으면 엔드포인트가 402를 반환해요.
  • 조직에 대해 Write(또는 Admin) 권한이 있는 조직 구성원으로 인증되어야 해요.
  • 대상 사용자가 이미 조직의 구성원이어야 해요.

기본 URL과 인증

  • 기본 URL: https://huggingface.co
  • 인증: 요청 헤더에 토큰을 보내요:
    Authorization: Bearer <your_...ken>
    
    조직에 범위가 지정된 "Write access to organizations settings / member management" 권한을 가진 세분화된 토큰을 https://huggingface.co/settings/tokens에서 만들어요.

구성원 역할 변경 엔드포인트

요청

PUT /api/organizations/{org_name}/members/{username}/role
Authorization: Bearer <your_...ken>
Content-Type: application/json

{
  "role": "read",
  "resourceGroups": []
}
  • 경로 파라미터
    • org_name: 조직 슬러그 (예: my-org).
    • username: 역할을 변경하는 구성원의 Hugging Face 사용자명.
  • 본문
    • role (필수): 구성원의 조직 수준 역할. 다음 중 하나: "no_access", "read", "contributor", "write", "admin".
    • resourceGroups (선택): 이 사용자에 대한 리소스 그룹 할당 배열. 각 항목:
      • id: 리소스 그룹 ID (24자 16진 문자열; 리소스 그룹 목록 API에서 ID를 얻어요).
      • role: 해당 리소스 그룹에서의 역할: "read", "contributor", "write", "admin".
    • resourceGroups를 생략하거나 []를 전달하면 사용자는 모든 리소스 그룹에서 제거돼요. 조직 역할만 바꾸고 리소스 그룹은 그대로 두려면 현재 리소스 그룹 구성원 자격을 전달해요(본문은 항상 조직 역할과 리소스 그룹 목록을 둘 다 설정해요).

예 (curl) – 조직 역할을 "read"로, 리소스 그룹 없음 (이전에 있던 그룹 제거)

curl -s -X PUT \
  -H "Authorization: Bearer ***" \
  -H "Content-Type: application/json" \
  -d '{"role":"read","resourceGroups":[]}' \
  "https://huggingface.co/api/organizations/my-org/members/member1/role"

예 (curl) – 조직 역할과 리소스 그룹 역할 설정 (현재 그룹 재정의)

curl -s -X PUT \
  -H "Authorization: Bearer ***" \
  -H "Content-Type: application/json" \
  -d '{"role":"write","resourceGroups":[{"id":"507f1f77bcf86cd799439011","role":"read"}]}' \
  "https://huggingface.co/api/organizations/my-org/members/member2/role"

성공 응답: 상태 200 OK; 본문: { "success": true }.

일반적인 오류

  • 400 — 잘못된 본문 (예: 잘못된 역할 또는 리소스 그룹 id).
  • 402 — 조직에 구독 플랜이 없음.
  • 403 — 허용되지 않음 (예: 조직에 대한 Write 부족, 또는 리소스 그룹이 조직에 없음).
  • 404 — 조직 또는 사용자를 찾을 수 없음.

여러 구성원 업데이트하기

API는 요청당 구성원 한 명을 변경해요. 벌크 엔드포인트는 없어요. 많은 구성원을 업데이트하려면 사용자명마다 엔드포인트를 한 번씩 호출해요(예: 목록 또는 CSV에서).

예: Bash – 사용자명 반복, 모두 같은 역할

ORG_NAME="my-org"
ROLE="read"
for username in member1 member2 member3 member4; do
  echo "Setting $username to $ROLE ..."
  curl -s -w "\n%{http_code}" -X PUT \
    -H "Authorization: Bearer ***" \
    -H "Content-Type: application/json" \
    -d "{\"role\":\"$ROLE\",\"resourceGroups\":[]}" \
    "https://huggingface.co/api/organizations/$ORG_NAME/members/$username/role"
  echo ""
done

예: Python – 사용자명 반복

import os
import requests

BASE_URL = "https://huggingface.co"
HF_TOKEN = os.environ.get("HF_TOKEN", "")

def change_member_role(org_name: str, username: str, role: str, resource_groups: list | None = None):
    payload = {"role": role, "resourceGroups": resource_groups or []}
    r = requests.put(
        f"{BASE_URL}/api/organizations/{org_name}/members/{username}/role",
        headers={"Authorization": f"Bearer {HF_TOKEN}", "Content-Type": "application/json"},
        json=payload,
    )
    if r.status_code != 200:
        raise RuntimeError(f"{r.status_code}: {r.text}")
    return r.json()

org_name = "my-org"
role = "read"
for username in ["member1", "member2", "member3", "member4"]:
    print(f"Setting {username} to {role} ... ", end="")
    try:
        change_member_role(org_name, username, role)
        print("OK")
    except Exception as e:
        print(f"Failed: {e}")

사용자마다 다른 역할이 필요하면 (username, role) 쌍(예: CSV에서)을 반복하며 각각 change_member_role을 호출해요.

Resource Groups API

다음 엔드포인트로 리소스 그룹을 나열하고 그룹에 사용자를 추가할 수 있어요. 기존 구성원의 조직 수준 역할이나 리소스 그룹 할당을 변경하려면 위의 API로 구성원 역할 변경을 참고해요.

OpenAPI 참조: Resource groups

목차 — API 접근 방식:

목표 섹션
많은 사용자를 하나의 리소스 그룹에 추가 리소스 그룹에 사용자 추가
같은 사용자를 여러 리소스 그룹에 추가 API 반복으로 배치 추가
그룹마다 다른 사용자 추가 API 반복으로 배치 추가

기본 URL과 인증

  • 기본 URL: https://huggingface.co
  • 인증: 다음 중 하나를 사용해요:
    • 액세스 토큰 (스크립트 권장): 조직에 범위가 지정된 "Write access to organizations settings / member management" 권한을 가진 세분화된 토큰을 https://huggingface.co/settings/tokens에서 만들고 요청 헤더에 보내요:
      Authorization: Bearer <your_...ken>
      
    • 세션 쿠키: Hub UI와 같은 세션을 공유하는 브라우저나 도구에서 호출한다면 쿠키가 자동으로 전송돼요.

리소스 그룹 나열하기

조직에 대해 관리할 수 있는 모든 리소스 그룹을 가져와요. 이를 사용해 각 그룹의 id를 얻어 사용자 추가 호출에 써요.

요청

GET /api/organizations/{org_name}/resource-groups
Authorization: Bearer <your_...ken>

예 (curl)

curl -s -H "Authorization: Bearer ***" \
  "https://huggingface.co/api/organizations/my-org/resource-groups"

예 응답 (간략화)

[
  {
    "id": "507f1f77bcf86cd799439011",
    "name": "Cohort 2024",
    "description": "Members in this group",
    "users": [...],
    "repos": [...]
  }
]

사용자를 추가할 때 각 리소스 그룹의 id를 사용해요.

리소스 그룹에 사용자 추가하기

한 요청으로 하나의 리소스 그룹에 한 명 이상의 사용자를 추가해요. 같은 요청에 여러 사용자를 보낼 수 있어요.

요청

POST /api/organizations/{org_name}/resource-groups/{resource_group_id}/users
Authorization: Bearer <your_...ken>
Content-Type: application/json

{
  "users": [
    { "user": "member1", "role": "read" },
    { "user": "member2", "role": "read" },
    { "user": "member3", "role": "write" }
  ]
}
  • 경로 파라미터
    • org_name: 조직 슬러그 (예: my-org).
    • resource_group_id: 리소스 그룹의 id (목록 엔드포인트의 24자 16진 문자열).
  • 본문
    • users: 객체 배열. 각 객체는 다음을 가져야 해요:
      • user: Hugging Face 사용자명 (필수).
      • role: "read", "contributor", "write", "admin" 중 하나.

예 (curl)

curl -s -X POST \
  -H "Authorization: Bearer ***" \
  -H "Content-Type: application/json" \
  -d '{"users":[{"user":"member1","role":"read"},{"user":"member2","role":"read"}]}' \
  "https://huggingface.co/api/organizations/my-org/resource-groups/507f1f77bcf86cd799439011/users"

성공: 상태 200 OK; 본문은 업데이트된 리소스 그룹 객체 (users에 새 사용자 포함).

일반적인 오류:

  • 400 — 예: 사용자를 찾을 수 없음, 중복 사용자명, 잘못된 본문.
  • 403 — 허용되지 않음 (예: 조직에 없음, 또는 이미 리소스 그룹에 있음). 메시지가 사용자가 조직에 없는지 그룹에 이미 있는지 알려줘요.

이메일로 구성원 추가 (해결 방법)

사용자 추가 엔드포인트는 Hugging Face 사용자명만 받고 이메일은 받지 않아요. 이메일 목록(예: 구성원 이메일)이 있다면 먼저 이메일 → 사용자명을 해석한 다음 사용자 추가 API를 호출해요.

이메일 필터링은 이메일의 도메인이 조직의 허용 도메인 중 하나와 일치할 때 동작해요: Organization email domain(Settings → Account → Organization email domain) 및/또는 조직의 SSO allowed domains(SSO가 구성된 경우).

1단계 – 이메일을 사용자명으로 해석

GET /api/organizations/{org_name}/members?email={email}&limit=1
Authorization: Bearer <your_...ken>

응답은 구성원 배열이고, 각 구성원은 user(사용자명)를 가져요. 사용자 추가 호출에 user를 사용해요.

2단계 – 리소스 그룹에 추가

1단계의 사용자명을 일반 사용자 추가 요청에 사용해요:

POST /api/organizations/{org_name}/resource-groups/{resource_group_id}/users
Content-Type: application/json
Body: { "users": [{ "user": "<username from step 1>", "role": "read" }] }

예: 이메일 하나 (bash)

ORG_NAME="my-org"
RG_ID="507f1f77bcf86cd799439011"
EMAIL="[email protected]"

# Step 1: look up member by email (domain must match org's Organization email domain or SSO allowed domains)
MEMBERS=$(curl -s -H "Authorization: Bearer ***" \
  "https://huggingface.co/api/organizations/$ORG_NAME/members?email=$EMAIL&limit=1")
USERNAME=$(echo "$MEMBERS" | jq -r '(.[0] // {} | .user // "")')
if [ -z "$USERNAME" ]; then
  echo "No member found for $EMAIL"
  exit 1
fi
# Step 2: add to resource group
curl -s -X POST -H "Authorization: Bearer ***" -H "Content-Type: application/json" \
  -d "{\"users\":[{\"user\":\"$USERNAME\",\"role\":\"read\"}]}" \
  "https://huggingface.co/api/organizations/$ORG_NAME/resource-groups/$RG_ID/users"

예: 여러 이메일 반복 (Python)

import os
import requests

BASE = "https://huggingface.co"
ORG = "my-org"
RG_ID = "507f1f77bcf86cd799439011"
ROLE = "read"
headers = {"Authorization": f"Bearer {os.environ['HF_TOKEN']}", "Content-Type": "application/json"}

emails = ["[email protected]", "[email protected]"]
for email in emails:
    # Step 1: resolve email → username (email domain must match org's Organization email domain or SSO allowed domains)
    r = requests.get(f"{BASE}/api/organizations/{ORG}/members", params={"email": email, "limit": 1}, headers=headers)
    r.raise_for_status()
    members = r.json()
    if not members:
        print(f"No member found for {email}")
        continue
    username = members[0]["user"]
    # Step 2: add that user to the resource group
    add_r = requests.post(
        f"{BASE}/api/organizations/{ORG}/resource-groups/{RG_ID}/users",
        headers=headers,
        json={"users": [{"user": username, "role": ROLE}]},
    )
    if add_r.status_code == 200:
        print(f"Added {username} ({email})")
    else:
        print(f"Failed {email}: {add_r.status_code} {add_r.text}")

사용자가 이미 리소스 그룹에 있으면 추가 호출이 403을 반환해요; 스크립트가 실패로 보고하고, 원하면 그 경우를 건너뛰거나 무시할 수 있어요.

한계: 이메일 필터는 조직에 Organization email domain 및/또는 SSO allowed domains가 설정되어 있고 이메일 도메인이 그중 하나와 일치할 때만 적용돼요. 그렇지 않으면 members API로 이메일로 조회할 수 없어요; 이메일 → 사용자명에 대해 다른 소스(예: 자신의 디렉터리)가 필요해요.

API 반복으로 배치 추가하기

많은 사용자를 하나의 리소스 그룹에 한두 번의 요청으로(예: 사용자명 목록을 청크로 나눠) 추가하거나, 그룹을 반복하며 각각 사용자 추가 엔드포인트를 호출해 여러 리소스 그룹에 사용자를 추가할 수 있어요.

예: Bash – 한 그룹, 한 요청에 여러 사용자

#!/bin/bash
# Add a list of users to a single resource group.
# Usage: ./add-users-to-rg.sh <org_name> <resource_group_id> <role>

ORG_NAME="${1:-my-org}"
RG_ID="${2:-507f1f77bcf86cd799439011}"
ROLE="${3:-read}"

USERS="member1 member2 member3 member4"
USERS_JSON=$(echo "$USERS" | tr ' ' '\n' | while read u; do
  [ -n "$u" ] && echo "{\"user\":\"$u\",\"role\":\"$ROLE\"}"
done | paste -sd ',' -)

curl -s -w "\nHTTP_STATUS:%{http_code}" -X POST \
  -H "Authorization: Bearer ***" \
  -H "Content-Type: application/json" \
  -d "{\"users\":[$USERS_JSON]}" \
  "https://huggingface.co/api/organizations/$ORG_NAME/resource-groups/$RG_ID/users"

예: Bash – 여러 그룹 반복

# Get group IDs and add users to each
curl -s -H "Authorization: Bearer ***" \
  "https://huggingface.co/api/organizations/my-org/resource-groups" \
  | jq -r '.[].id' \
  | while read -r RG_ID; do
      [ -z "$RG_ID" ] && continue
      echo "Adding users to resource group $RG_ID ..."
      curl -s -X POST -H "Authorization: Bearer ***" -H "Content-Type: application/json" \
        -d "{\"users\":[$USERS_JSON]}" \
        "https://huggingface.co/api/organizations/my-org/resource-groups/$RG_ID/users"
    done

예: Python – 하나 또는 여러 그룹에 배치 추가

import os
import requests

BASE_URL = "https://huggingface.co"
HF_TOKEN = os.environ.get("HF_TOKEN", "")

def list_resource_groups(org_name: str):
    r = requests.get(
        f"{BASE_URL}/api/organizations/{org_name}/resource-groups",
        headers={"Authorization": f"Bearer {HF_TOKEN}"},
    )
    r.raise_for_status()
    return r.json()

def add_users_to_resource_group(org_name: str, resource_group_id: str, users_with_roles: list):
    """users_with_roles: list of {"user": "username", "role": "read"|"write"|"contributor"|"admin"}"""
    r = requests.post(
        f"{BASE_URL}/api/organizations/{org_name}/resource-groups/{resource_group_id}/users",
        headers={"Authorization": f"Bearer {HF_TOKEN}", "Content-Type": "application/json"},
        json={"users": users_with_roles},
    )
    if r.status_code != 200:
        raise RuntimeError(f"Add users failed {r.status_code}: {r.text}")
    return r.json()

# Example: same users added to every resource group
org_name = "my-org"
role = "read"
usernames = ["member1", "member2", "member3"]
users_with_roles = [{"user": u, "role": role} for u in usernames]

for rg in list_resource_groups(org_name):
    add_users_to_resource_group(org_name, rg["id"], users_with_roles)

긴 사용자명 목록은 청크로 나눠(예: 요청당 50명) 큰 요청 본문이나 타임아웃을 피하기 위해 청크마다 API를 한 번씩 호출해요.

중요 참고 사항

  1. 사용자명만 — API는 Hugging Face 사용자명을 받고 이메일은 받지 않아요. API를 호출하기 전에 이메일 → 사용자명 매핑(예: 자신의 디렉터리 또는 조직 구성원 목록에서)이 필요해요.
  2. 사용자가 조직에 있어야 함 — 요청의 모든 사용자가 이미 조직 구성원이어야 해요. 그렇지 않으면 요청이 어떤 사용자가 조직에 없다는 메시지와 함께 403을 반환해요.
  3. 멱등성 — 사용자가 이미 리소스 그룹에 있으면 백엔드가 그 요청에 403을 반환할 수 있어요. 스크립트가 오류를 잡고 계속하거나, 그룹의 users 목록을 먼저 가져와 이미 그룹에 있는 사용자를 건너뛸 수 있어요.
  4. 속도 제한 — 대량 배치에서는 요청 사이에 짧은 지연(예: 0.5–1초)을 추가해 속도 제한을 피할 수 있어요.
  5. 토큰 범위 — 액세스 토큰은 조직에 충분한 권한이 있어야 해요(보통 최소 "Write access to organizations settings / member management"). 토큰을 안전하게 생성·저장하고 버전 관리에 커밋하지 마세요.

API로 auto-join 구성하기

Auto-join은 지정된 역할로 조직 구성원을 Resource Group에 자동으로 추가해요. API로 활성화·비활성화할 수 있고, 선택적으로 모든 조직 구성원을 포함할지 Read+ 구성원만 포함할지 고를 수 있어요.

auto-join 활성화

POST /api/organizations/{org_name}/resource-groups/{resource_group_id}/settings
Authorization: Bearer <your_...ken>
Content-Type: application/json

{
  "autoJoin": {
    "enabled": true,
    "role": "read",
    "scope": "read_plus"
  }
}
  • 경로 파라미터
  • 본문
    • role: 자동 추가된 구성원에게 할당할 역할. "read", "contributor", "write", "admin" 중 하나.
    • scope (선택): 자동으로 추가할 조직 구성원 범위. "all"은 모든 조직 구성원을 포함. "read_plus"no_access 조직 역할의 구성원을 제외. 생략 시 기본값은 "all".

기존 Resource Group에 auto-join을 활성화하면 선택된 범위에 맞는 현재 조직 구성원이 즉시 추가돼요(백필).

auto-join 비활성화

"enabled": false인 같은 요청을 보내요. 비활성화 시 role 필드는 필요하지 않아요:

POST /api/organizations/{org_name}/resource-groups/{resource_group_id}/settings
Authorization: Bearer <your_...ken>
Content-Type: application/json

{
  "autoJoin": {
    "enabled": false
  }
}

[!NOTE] auto-join을 비활성화해도 이전에 자동 추가된 구성원은 제거되지 않아요. 미래의 조직 구성원이 자동 추가되는 것만 막을 뿐이에요. 기존 구성원은 Resource Group에 남아요.

API로 지출 한도 설정하기

Spend limits는 Resource Group에 귀속되는 월간 컴퓨팅 지출에 상한을 두니 update 엔드포인트로 설정해요:

PATCH /api/organizations/{org_name}/resource-groups/{resource_group_id}
Authorization: Bearer <your_...ken>
Content-Type: application/json

{
  "spendLimits": {
    "total": 500000,
    "spaces": 100000,
    "jobs": 50000
  }
}
  • 경로 파라미터
  • 본문
    • spendLimits: 센트 단위의 월간 한도. 위 예시는 총 $5,000 한도(Spaces $1,000, Jobs $500)를 설정해요.
      • total: 모든 제품에 걸친 그룹 결합 지출 한도.
      • inferenceProviders, spaces, jobs, endpoints: 제품별 한도, total 위에 적용. 둘 중 더 엄격한 쪽이 적용돼요.

보낸 키만 업데이트되고 나머지는 현재 값을 유지해요. null을 보내면 한도를 제거해요:

PATCH /api/organizations/{org_name}/resource-groups/{resource_group_id}
Authorization: Bearer <your_...ken>
Content-Type: application/json

{
  "spendLimits": {
    "jobs": null
  }
}

예 (curl)

curl -s -X PATCH \
  -H "Authorization: Bearer ***" \
  -H "Content-Type: application/json" \
  -d '{"spendLimits": {"total": 500000}}' \
  "https://huggingface.co/api/organizations/my-org/resource-groups/507f1f77bcf86cd799439011"

응답은 spendLimits를 포함한 업데이트된 리소스 그룹이에요.

더 알아보기 (Learn more)

  • 구성원 역할·리소스 그룹은 PUT .../members/{username}/rolePOST .../resource-groups/{rg}/users로 관리해요.
  • 이메일로 추가하려면 먼저 members API로 이메일 → 사용자명을 해석해요.
  • Resource Groups 문서에서 접근 제어 모델 전체를 확인해 보세요.