서비스 토큰

엔드포인트: /api/auth/service-tokens/

애플리케이션에 서비스 토큰을 발급하면 애플리케이션의 역할과 토큰의 접근 제어 규칙이 허용하는 범위에서 자동화 작업을 실행할 수 있습니다. 키는 alpst-로 시작합니다. 서비스 토큰으로는 사용자 API와 애플리케이션 API를 호출할 수 없습니다.

인증과 권한

토큰 관리와 이력 조회는 콘솔이나 CLI에 로그인한 사용자가 요청해야 합니다. 생성 요청은 service_token:create scope가 있는 호출자 본인의 개인 API 토큰으로도 보낼 수 있습니다. 나머지 관리 작업은 개인 API 토큰을 받지 않으며, 모든 관리 작업은 서비스 토큰을 403 permission_denied로 거부합니다.

Authorization: Bearer <access_token>을 사용하는 예제는 로그인한 세션으로 요청합니다. 이 경로에는 로그인 세션이 필요하지만, 생성 요청은 예외입니다. service_token:create가 있는 본인의 개인 API 토큰을 토큰 인증 형식으로 보내도 됩니다. 서비스 토큰으로는 호출할 수 없습니다. 토큰 생성과 승인은 설정 안내를 따르세요. CLI에서 생성한 서비스 토큰은 항상 웹 콘솔의 승인을 기다립니다. API 인증을 참고하세요.

작업필요한 권한
목록·상세·이력 조회전역 또는 해당 애플리케이션의 service_token:read
생성전역 또는 해당 애플리케이션의 service_token:create
수정service_token:update와 해당 애플리케이션의 토큰 생성 권한
키 교체service_token:rotate와 해당 애플리케이션의 토큰 생성 권한
비활성화service_token:disable과 해당 애플리케이션의 토큰 생성 권한
삭제service_token:delete
긴급 접근 활성화·해제로그인한 슈퍼유저 계정

관리자는 토큰 조회·생성·수정·키 교체·비활성화·삭제를 할 수 있습니다. 애플리케이션을 만든 사용자는 해당 애플리케이션의 application:maintainer 역할을 받습니다. 이 역할로 토큰을 조회·생성·수정할 수 있지만, 키 교체·비활성화·삭제에는 별도 권한이 필요합니다. service_token:manager 역할도 전역 또는 특정 애플리케이션의 토큰 조회·생성·수정 권한을 부여합니다. 관리자라도 슈퍼유저가 아니면 긴급 접근을 활성화하거나 해제할 수 없습니다.

워크스페이스가 정지된 동안에는 쓰기 요청이 403 workspace_suspended로 거부됩니다. 긴급 접근 활성화와 해제는 예외입니다.

토큰 목록 조회

요청

http
GET /api/auth/service-tokens/tokens/

service_token:read 권한이 있는 애플리케이션의 토큰만 표시됩니다.

쿼리 매개변수

매개변수유형설명
namestring이름으로 필터링
enabledboolean활성화 여부로 필터링. false에는 승인 대기 중인 토큰도 포함
activation_statestringpending 또는 active
applicationUUID애플리케이션으로 필터링
expiringboolean유효한 토큰 중 14일 안에 만료되는 토큰
staleboolean유효한 토큰 중 키를 발급한 지 180일이 지난 토큰
searchstring이름과 설명 검색
orderingstringadded_at, updated_at, last_used_at, expires_at, last_issued_at. 앞에 -를 붙이면 내림차순. 기본값: -updated_at
pageinteger1부터 시작하는 페이지 번호
page_sizeinteger페이지당 결과 수. 기본 15, 최대 100

비활성화한 토큰은 activation_state=active&enabled=false로, 승인 대기 중인 토큰은 activation_state=pending으로 조회하세요.

응답

200 OK와 함께 페이지 번호 기반 페이지네이션 형식으로 반환합니다.

json
{
  "count": 1,
  "current": 1,
  "next": null,
  "previous": null,
  "last": 1,
  "results": [
    {
      "id": "3f1c2a9e-7b6d-4e1f-9a2b-5c8d7e6f4a31",
      "name": "ci-deploy",
      "activation_state": "active",
      "enabled": true,
      "scopes": ["command:create", "command:read"],
      "expires_at": "2027-01-01T00:00:00Z"
    }
  ]
}

예제에는 토큰 필드 일부만 표시했습니다. 전체 필드는 다음 절에서 설명합니다.

예제

bash
curl "https://your-workspace.ap1.alpacon.io/api/auth/service-tokens/tokens/?activation_state=pending" \
  -H "Authorization: Bearer <access_token>"

토큰 필드

필드유형설명
idUUID읽기 전용 토큰 ID
namestring생성 시 필수, 최대 128자. 활성화된 토큰과 승인 대기 중인 토큰 사이에서 고유해야 함. 비활성화한 토큰의 이름은 재사용 가능
descriptionstring선택 사항. 기본값 ""
applicationUUID / object생성 시 UUID 필수, 수정 시 읽기 전용. 응답은 {id, name, service_type, username}
enabledboolean생성 시 읽기 전용. 변경하려면 승인 필요
activation_statestring읽기 전용. pending 또는 active
scopesarray[string]각 scope는 최대 64자이며 카탈로그의 scope 또는 와일드카드. 생성 시 scope 또는 프리셋 필요
presetsarray[string]생성할 때만 보내는 쓰기 전용 프리셋 키. 기본값 []
expires_atdatetime생성 시 미래의 ISO 8601 시각 필수. 변경하려면 승인 필요
rotation_policystring30d, 90d, 180d, 365d. 기본값 90d. 키 교체 시 새 만료일을 정하는 기간이며, 자동으로 키를 교체하지는 않음
ip_whitelistarray[string]IPv4/IPv6 주소 또는 CIDR. 항목당 최대 64자. []이면 제한 없음
rate_limitstring""이면 고정 기본값 1000/hour 적용. 별도 값은 양의 정수 N과 second, minute, hour, day, s, m, h, d를 조합한 N/period 형식. 최대 32자
allowed_time_start, allowed_time_endtime / nullUTC HH:MM[:SS]. 두 값을 함께 설정하거나 모두 비워야 함. null이면 제한 없음. 시작이 종료보다 늦으면 자정을 넘는 구간이며, 종료의 초가 0이면 해당 분 전체를 허용
allowed_daysarray[string]mon, tue, wed, thu, fri, sat, sun. 대소문자를 구분하지 않으며 []이면 모든 요일 허용
justificationstring쓰기 전용, 최대 1,024자. 위험도가 중간·높음인 토큰 생성과, 변경 후 scope의 위험도가 중간·높음인 토큰의 민감 필드 변경에 필수. 공백만 있으면 빈 값으로 처리
last_used_at, usage_countdatetime / integer읽기 전용 사용 정보. 관리자이거나 해당 애플리케이션의 토큰을 만들 수 있는 사용자에게만 표시하고, 나머지 사용자에게는 null 반환
last_issued_atdatetime읽기 전용. 생성 또는 마지막 키 교체 시각
break_glass_active, break_glass_expires_atboolean / datetime읽기 전용 긴급 접근 상태
added_at, updated_atdatetime읽기 전용 시각
permissionsobject읽기 전용 권한 정보 {update, delete, rotate, disable}
keystring생성 및 키 교체 응답에서만 반환. 승인 대기 상태로 생성해도 포함
scope_usagearray / null상세 응답에만 포함. 관리자이거나 해당 애플리케이션의 토큰을 만들 수 있는 사용자에게만 표시하고, 나머지 사용자에게는 null 반환

토큰 생성

요청

http
POST /api/auth/service-tokens/tokens/

토큰의 scope는 애플리케이션의 전역 역할이 허용하는 범위 안에 있어야 합니다. 슈퍼유저가 만들어도 같습니다. 프리셋은 직접 지정한 scope와 합쳐지며, 프리셋에서 사용할 수 없는 scope는 제외됩니다. 최종 scope 목록이 비어 있으면 생성할 수 없습니다. 발급할 수 없는 scope를 직접 요청하면 400 service_token_scope_not_mintable을 반환합니다.

서비스 토큰에는 ftp_session:create, session:create, session:invite, session:share, tunnel_session:create, tunnel_session:reconnect, userchannel:create, userchannel:update를 부여할 수 없습니다. 워크스페이스에서 Kubernetes 접근을 제공하지 않으면 클러스터 scope도 거부됩니다.

요청 본문

json
{
  "name": "ci-deploy",
  "application": "9d2e4b71-0c3a-4f5e-8b6d-1a2c3e4f5a6b",
  "scopes": ["command:create", "command:read"],
  "expires_at": "2027-01-01T00:00:00Z",
  "rotation_policy": "90d",
  "justification": "Run deployment checks from CI"
}

응답

두 경우 모두 토큰과 키가 생성됩니다.

상태조건토큰 상태
201 Created로그인한 관리자가 웹 콘솔에서 위험도가 낮은 토큰을 생성activation_state: "active", enabled: true
202 Accepted그 외 모든 생성 요청. CLI, 개인 API 토큰, 관리자가 아닌 호출자, 위험도가 중간·높음인 scope 포함activation_state: "pending", enabled: false

와일드카드가 있으면 위험도는 높음입니다. 명령어·업로드·다운로드·세션 scope 중 접근 제어가 필요한 scope는 중간이며, 나머지는 낮음입니다. 명령 scope가 있는 토큰을 생성하면 항상 202를 반환하며 justification이 필수입니다. 로그인한 관리자가 웹 콘솔에서 생성해도 같습니다.

202 응답은 key를 포함한 전체 토큰에 status, risk_level, risk_details, approval_request_id를 추가합니다. 주요 필드는 다음과 같습니다.

json
{
  "id": "3f1c2a9e-7b6d-4e1f-9a2b-5c8d7e6f4a31",
  "key": "alpst-xxxxxxxxxxxxxxxxxx",
  "activation_state": "pending",
  "enabled": false,
  "status": "pending_approval",
  "risk_level": "medium",
  "risk_details": [],
  "approval_request_id": "5cf4106b-b6c5-4ae3-b33c-e90e7a872155"
}

risk_details의 각 항목은 {scope, reason, level} 형식이며, 위 예제에서는 생략했습니다. 승인자에게는 키가 전달되지 않으므로 이 응답의 키를 저장하세요. 승인 대기 중인 토큰은 승인받기 전까지 어디에서도 인증에 쓸 수 없습니다. 승인 요청은 7일 후 만료됩니다.

슈퍼유저 또는 요청에 지정된 승인자가 웹 콘솔에서 승인합니다. CLI나 토큰으로는 승인할 수 없습니다. 승인 정책에서 금지하지 않는 한 요청자도 자신의 요청을 승인할 수 있습니다. 승인 시 애플리케이션의 역할과 만료 시각을 다시 확인합니다. 요청이 거절·취소·만료되면 대기 중인 키는 무효화됩니다.

승인 후 GET /api/auth/service-tokens/tokens/{id}/는 200과 함께 activation_state: "active", enabled: true를 반환합니다. 그다음 ACL을 추가하세요. ACL 쓰기 요청의 대상은 승인을 받아 활성화된 서비스 토큰이어야 합니다.

예제

bash
curl -X POST "https://your-workspace.ap1.alpacon.io/api/auth/service-tokens/tokens/" \
  -H "Authorization: Bearer <access_token>" \
  -H "Content-Type: application/json" \
  -d '{"name":"ci-deploy","application":"9d2e4b71-0c3a-4f5e-8b6d-1a2c3e4f5a6b","scopes":["command:create","command:read"],"expires_at":"2027-01-01T00:00:00Z","justification":"Run deployment checks from CI"}'

토큰 상세 조회

http
GET /api/auth/service-tokens/tokens/{id}/

id는 토큰 UUID입니다. 200과 함께 토큰 필드와 scope_usage를 반환하며 키는 포함하지 않습니다. activation_state와 enabled를 읽으면 승인 대기 중이던 토큰이 활성화됐는지 확인할 수 있습니다.

토큰 수정

요청

http
PATCH /api/auth/service-tokens/tokens/{id}/
PUT /api/auth/service-tokens/tokens/{id}/

name과 description 변경은 즉시 적용됩니다. 다음 민감 필드 중 하나라도 포함한 요청은 호출자와 관계없이 202를 반환하고 승인을 기다립니다.

  • scopes, enabled, expires_at, rotation_policy
  • ip_whitelist, rate_limit
  • allowed_time_start, allowed_time_end, allowed_days

PATCH {"enabled": false}도 승인이 필요합니다. 즉시 사용을 막으려면 토큰 비활성화를 쓰세요. 별도의 활성화 경로는 없으므로 PATCH {"enabled": true}를 요청한 뒤 승인을 기다려야 합니다. 다시 활성화할 때는 애플리케이션의 역할을 재확인합니다.

토큰 하나에는 변경 승인 요청을 하나만 대기시킬 수 있습니다. 최초 승인을 기다리는 토큰은 수정할 수 없습니다. application은 읽기 전용이므로 다른 애플리케이션에 연결하려면 새 토큰을 만드세요. 수정 요청에는 presets를 보낼 수 없습니다.

PUT은 ip_whitelist, rate_limit, allowed_days의 기본값도 적용하므로 202를 반환합니다. 일부 필드만 바꿀 때는 PATCH를 쓰세요.

응답

즉시 적용되는 수정은 키를 제외한 토큰과 200을 반환합니다. 민감 필드 수정 응답은 다음과 같습니다.

json
{
  "status": "pending_approval",
  "risk_level": "medium",
  "risk_details": [],
  "approval_request_id": "5cf4106b-b6c5-4ae3-b33c-e90e7a872155"
}

이 본문에는 키가 없습니다. risk_details의 항목은 {scope, reason, level} 형식이며 예제에서는 생략했습니다. scope를 바꿀 때는 요청 시점과 승인 시점 모두 애플리케이션의 역할이 허용하는 범위 안에 있어야 합니다.

예제

bash
curl -X PATCH "https://your-workspace.ap1.alpacon.io/api/auth/service-tokens/tokens/3f1c2a9e-7b6d-4e1f-9a2b-5c8d7e6f4a31/" \
  -H "Authorization: Bearer <access_token>" \
  -H "Content-Type: application/json" \
  -d '{"rate_limit":"2000/hour","justification":"Support deployment checks across more servers"}'

키 교체

http
POST /api/auth/service-tokens/tokens/{id}/rotate/

선택 사항인 reason에 최대 1,024자로 사유를 보낼 수 있습니다. 키 교체에는 승인이 필요 없지만, 호출자 본인의 전역 역할이 토큰에 저장된 scope를 모두 허용해야 합니다. 승인 대기 중이거나 비활성화된 토큰은 키를 교체할 수 없습니다.

200과 함께 토큰과 새 key를 반환합니다. 기존 키는 즉시 인증에 쓸 수 없으며, 두 키를 함께 쓸 수 있는 유예 기간은 없습니다. 만료일은 기존 만료일이 아니라 교체 시점에 rotation_policy를 더한 날짜로 다시 정하므로, 남은 유효 기간이 줄어들 수도 있습니다. 키를 교체할 때 자동화에서 쓰는 시크릿도 함께 갱신하세요.

bash
curl -X POST "https://your-workspace.ap1.alpacon.io/api/auth/service-tokens/tokens/3f1c2a9e-7b6d-4e1f-9a2b-5c8d7e6f4a31/rotate/" \
  -H "Authorization: Bearer <access_token>" \
  -H "Content-Type: application/json" \
  -d '{"reason":"Scheduled key rotation"}'

토큰 비활성화

http
POST /api/auth/service-tokens/tokens/{id}/disable/

선택 사항인 reason에 최대 1,024자로 사유를 보낼 수 있습니다. 204 No Content를 반환하고 승인 없이 토큰을 즉시 비활성화합니다. 해당 토큰의 긴급 접근도 모두 종료합니다. 승인 대기 중인 토큰은 비활성화할 수 없습니다.

애플리케이션의 역할이나 권한이 제거되어 토큰에 저장된 scope가 남은 권한을 넘으면 토큰이 비활성화됩니다.

토큰 삭제

http
DELETE /api/auth/service-tokens/tokens/{id}/

선택 사항인 reason에 최대 1,024자로 사유를 보낼 수 있습니다. 204 No Content를 반환하며 토큰은 인증에 쓸 수 없게 됩니다. 승인 대기 중인 토큰을 삭제하면 발급 요청도 취소되고 키가 무효화됩니다. 애플리케이션이 남아 있으면 토큰 이력을 계속 조회할 수 있습니다.

긴급 접근

긴급 접근은 IP 허용 목록과 허용 시간·요일 제한만 일시적으로 해제합니다. 토큰은 승인·활성화된 상태여야 하며, 키도 유효하고 만료되지 않아야 합니다. 소속 애플리케이션이 삭제된 경우에는 사용할 수 없습니다. 요청 수 제한, scope, 애플리케이션 역할, ACL은 그대로 적용됩니다. 접근 제어 목록을 참고하세요.

활성화

http
POST /api/auth/service-tokens/tokens/{id}/break-glass/

로그인한 슈퍼유저만 긴급 접근을 활성화할 수 있습니다. 워크스페이스가 정지된 동안에도 가능합니다.

필드유형필수설명
justificationstring예비어 있지 않은 사유, 최대 2,048자
duration_hoursinteger아니요1~8시간, 기본 4시간
json
{
  "justification": "Restore deployment access during the incident",
  "duration_hours": 2
}

201과 함께 {id, service_token, activated_by, justification, activated_at, expires_at, deactivated_at, is_active}를 반환합니다. 승인 대기 중인 토큰은 거부됩니다. 긴급 접근을 활성화해도 비활성화되거나 만료된 토큰을 쓸 수는 없습니다. 활성화한 사용자의 계정이 활성 상태이고 슈퍼유저인 동안에만 예외가 적용됩니다. 계정을 비활성화하거나 슈퍼유저 권한을 해제하면 예외도 종료됩니다.

해제

http
DELETE /api/auth/service-tokens/tokens/{id}/break-glass/

로그인한 슈퍼유저만 해제할 수 있습니다. 204를 반환하고 이 토큰의 활성 긴급 접근을 모두 종료합니다. 활성 긴급 접근이 없으면 400 service_token_break_glass_not_active를 반환합니다. 활성화와 해제는 이력에 기록되며 웹훅도 전송됩니다.

토큰 이력

요청

http
GET /api/auth/service-tokens/history/?service_token={token_id}
GET /api/auth/service-tokens/history/{history_id}/

두 경로 모두 해당 애플리케이션의 service_token:read 권한이 필요합니다. 목록에는 service_token 쿼리 매개변수도 필수입니다. 매개변수가 없으면 400 service_token_history_scope_required, 토큰 ID가 잘못됐거나 접근할 수 없으면 404 api_not_found를 반환합니다. 상세 조회는 이력 UUID를 사용하며 이 쿼리 매개변수가 없어도 됩니다.

쿼리 매개변수

매개변수유형설명
service_tokenUUID목록 조회에 필수인 토큰 ID
change_typestring변경 유형 하나
change_type__instring쉼표로 구분한 변경 유형
changed_byUUID변경한 사용자
added_at__gte, added_at__ltedatetime지정 시각을 포함하는 조회 범위
orderingstringadded_at 또는 -added_at. 기본값 -added_at
page, page_sizeinteger목록 페이지네이션. 페이지당 기본 15개, 최대 100개

변경 유형은 created, activated, updated, rotated, disabled, deleted, break_glass_activated, break_glass_deactivated입니다.

응답

목록은 200과 함께 count, current, next, previous, last, results를 반환합니다. 상세 조회는 이력 한 건을 반환합니다.

json
{
  "id": "660e8400-e29b-41d4-a716-446655440000",
  "service_token_id": "3f1c2a9e-7b6d-4e1f-9a2b-5c8d7e6f4a31",
  "service_token_name": "ci-deploy",
  "change_type": "updated",
  "changed_by": null,
  "changes": {"description": {"old": "", "new": "Deployment checks"}},
  "reason": "Clarify the token's purpose",
  "added_at": "2026-10-24T10:00:00Z"
}

키는 ***로 마스킹됩니다. 토큰을 삭제한 뒤에도 이력을 조회할 수 있지만 애플리케이션을 삭제하면 조회할 수 없습니다.

읽기 전용 보조 API

토큰이나 ACL을 만들기 전에 이 경로에서 scope·프리셋·서버를 고를 수 있습니다. 인증은 필수입니다. scope와 서버 조회에는 요청한 애플리케이션의 토큰 생성 권한도 필요합니다. 개인 API 토큰으로 서버를 조회하려면 server:read가 있어야 합니다.

요청매개변수200 응답
GET /api/auth/service-tokens/scopes/application UUID 필수{resources: [{name, actions, acl, allowed_actions}], wildcards}. actions는 워크스페이스 카탈로그, allowed_actions는 애플리케이션이 위임할 수 있는 작업. 애플리케이션에 *가 있을 때만 wildcards에 포함
GET /api/auth/service-tokens/presets/없음프리셋 ID를 키로 쓰는 객체. 각 값은 언어별 name·description(en, ko)과 permissions 배열. 사용할 수 없는 확장 기능과 서비스 토큰에 발급할 수 없는 scope는 제외
GET /api/auth/service-tokens/servers/application UUID 필수. 선택: 지정한 토큰이 이미 접근할 수 있는 서버를 제외하는 exclude_service_token UUID, 이름 검색용 search, ordering(name 또는 platform, 기본 name), page, page_size호출자와 애플리케이션 모두 접근할 수 있는 서버 객체 {id, name, os, platform, is_connected, is_deleted}의 페이지. 기본 15개, 최대 100개

application이 없으면 400 service_token_application_required를 반환합니다. ID가 잘못됐거나 애플리케이션이 없거나 삭제됐다면 404 api_not_found, 해당 애플리케이션의 토큰 생성 권한이 없다면 403 service_token_application_forbidden을 반환합니다.

오류 응답

상태오류 코드설명
400unique, service_token_name_exists활성화된 토큰 또는 승인 대기 중인 토큰과 이름 중복
400service_token_scopes_required프리셋을 적용한 뒤 남은 scope가 없음
400service_token_scope_invalid, service_token_invalid_presetscope가 잘못됐거나 알 수 없거나 사용할 수 없는 프리셋
400service_token_scope_not_mintable서비스 토큰에 발급할 수 없는 scope 요청
400service_token_scope_exceeds_role애플리케이션의 역할이 허용하는 범위 초과
400service_token_scope_exceeds_rbac키를 교체하는 사용자가 토큰의 scope를 보유하지 않음
400api_token_invalid_expiration만료 시각이 미래가 아님
400service_token_invalid_ip_whitelist, service_token_invalid_rate_limit, service_token_invalid_time_windowIP 범위, 요청 수, 허용 시간 또는 요일이 잘못됨
400service_token_justification_required위험도가 중간·높음인 토큰 발급 또는 민감 필드 변경에 필요한 사유 누락
400service_token_pending_activation토큰이 최초 승인 대기 중
400service_token_update_pending변경 승인 요청이 이미 대기 중
400service_token_presets_not_allowed_on_update수정 요청에 프리셋 포함
400service_token_disabled비활성화된 토큰의 키 교체 불가
400service_token_request_superseded발급 요청으로 토큰을 활성화할 수 없는 상태
400required, blank긴급 접근 사유를 포함한 필수 필드가 없거나 비어 있음
400service_token_break_glass_not_active해제할 활성 긴급 접근이 없음
400service_token_history_scope_required, service_token_application_required이력 또는 보조 API의 필수 매개변수 누락
401auth_token_missing인증 정보 누락
403permission_denied이 관리 경로에서 받지 않는 인증 정보 유형
403service_token_application_forbidden해당 애플리케이션의 토큰 생성 권한 없음
403service_token_break_glass_unauthorized긴급 접근 호출자가 슈퍼유저가 아님
403rbac_permission_required, rbac_object_permission_required, api_token_scope_missing역할 권한 또는 개인 API 토큰 scope 부족
403workspace_suspended워크스페이스 정지 중 쓰기 요청 거부
404api_not_found토큰·이력·애플리케이션이 없거나 조회할 수 없음

발급받은 alpst- 키를 쓸 때 토큰이 유효하지 않거나 비활성화·승인 대기·만료·삭제 상태이면 401 auth_authentication_failed를 반환합니다. 삭제된 애플리케이션의 토큰도 같습니다. IP 또는 시간 제한에 걸리면 401 auth_ip_not_allowed 또는 auth_access_outside_allowed_time을 반환합니다. 요청 수 제한을 넘으면 Retry-After와 함께 429 api_rate_limited, 인증 정보를 확인할 수 없으면 503 auth_verification_unavailable을 반환합니다. API 인증을 참고하세요.

최종 수정: