콘텐츠로 이동

작업 공간 GitLab 인증

원천 · framework/evomind/web/workflow-project-evo-service기준 · 릴리스 v0.12.0커밋 · 2e32c6cc파일 · docs/operations/workspace-token.md기준선 · 2026-11-12

웹 채팅의 workflow 작업 공간(workspace-runner.md)은 사용자를 대신해 GitLab 에 clone·push·MR 을 한다. 이 문서는 그 실행이 어떤 GitLab 계정·토큰으로 도는지, 토큰을 어떻게 보관·전달하는지, 설정과 남은 한계를 적는다.

출처 source 무엇
사용자별 등록 user 사용자가 설정 화면에서 직접 등록한 자기 GitLab 토큰. 권장.
배포 설정 local WORKSPACE_GITLAB_TOKEN 환경 변수 하나. 사용자별 등록을 쓰지 않는 구성·개발 환경의 대체 수단.
  • 사용자가 등록한 토큰이 있으면 그것을 쓰고, 없으면 로컬 토큰으로 돌아간다.
  • 둘 다 없으면 그 사용자의 실행 인증이 없다(configured=false). 실행을 거부하는 판단은 호출 쪽이 한다.
  • 사용자 계정이 비활성이면 등록한 토큰도 쓰지 않는다.
  • 토큰은 어떤 경우에도 환경 변수로만 받고, DB·볼륨·이미지·로그·응답·감사·문서에 원문을 남기지 않는다.
환경 변수 기본값 설명
WORKSPACE_ENABLED false 기능 스위치. 꺼져 있으면 실행 인증을 만들지 않고 등록 API 도 거절한다.
WORKSPACE_TOKEN_KEY (비움) 사용자별 토큰을 암호화하는 AES-GCM 키(base64, 16·24·32바이트). 비우면 사용자별 등록을 열지 않는다.
WORKSPACE_GITLAB_HOST (비움) GitLab 허용 호스트. https 여야 한다. 토큰 등록 때 이 호스트로만 사용자 조회를 한다. 작업 이미지의 clone 허용 호스트(RUNNER_ALLOWED_GIT_HOSTS)와 같은 서버다.
WORKSPACE_GITLAB_TOKEN (비움) 로컬(공용) 토큰. 비밀이며 값은 문서·로그·이슈에 적지 않는다.
WORKSPACE_GITLAB_USER_NAME (비움) 로컬 토큰의 커밋 작성자 이름. 비우면 git 작성자 변수를 넘기지 않는다.
WORKSPACE_GITLAB_USER_EMAIL (비움) 로컬 토큰의 커밋 작성자 메일.
WORKSPACE_GITLAB_TOKEN_EXPIRES_AT (비움) 로컬 토큰의 만료일(ISO-8601). 날짜만(2026-12-31)도 받고 그날 끝까지 유효로 본다.
WORKSPACE_TOKEN_EXPIRY_WARNING 14d 만료일이 이 기간 안이면 화면에 경고를 담는다.
  • 키 만드는 법: openssl rand -base64 32. 값은 배포 서버의 .env 에만 두고 저장소·이슈·MR·문서에 적지 않는다.
  • 키를 바꾸면 이미 등록된 토큰은 복호화되지 않는다. 등록 행은 지우지 않지만 쓰지 않고 “등록 없음”으로 다루므로 사용자가 다시 등록해야 한다.
  • 기능을 켰는데 암호화 키도 로컬 토큰도 없으면 기동할 때 값이 아니라 빠진 항목만 경고 로그로 알린다.
  • deploy/.env.example·deploy/docker-compose.yml 에 같은 이름으로 전달한다.
  • 테이블 workspace_gitlab_tokens(V31): 사용자당 한 행. token_cipher 에 base64(nonce‖암호문‖태그) 만 둔다.
  • 알고리즘 AES/GCM/NoPadding, nonce 12바이트(등록할 때마다 새로), 태그 128비트. 복호화는 실행 인증을 만들 때 한 번뿐이다.
  • 함께 남기는 값: GitLab 사용자 id·사용자 이름·프로필 이름·메일·만료일(등록할 때 GitLab 이 확인해 준 값), 등록 시각.
  • 원문을 되돌려 주는 API 는 없다. 화면에도 등록 직후에도 다시 보여 주지 않는다.
  • 삭제는 행을 지운다. 이후 실행에는 그 토큰이 쓰이지 않는다. GitLab 에서 토큰을 폐기(revoke)하는 것은 사용자가 한다 — 화면이 안내한다.

POST /api/workspace/auth/token {"token": "glpat-…"} (인증 필요)

  1. 기능 스위치 · 암호화 키 · https 호스트 확인 (아니면 409)
  2. 토큰 형식 검사 — URL 안전 문자만, 8~255자 (400 invalid_token_format)
  3. 배포 설정의 GitLab 호스트에 GET /api/v4/user(PRIVATE-TOKEN) — 사용자 id·이름·프로필 이름·메일 확인. GET /api/v4/personal_access_tokens/self 로 만료일을 덧붙인다(권한이 없으면 만료일만 모른다).
    • 거절(401·403) → 400 invalid_token
    • 닿지 못함·비정상 응답 → 502 gitlab_unreachable
  4. AES-GCM 으로 암호화해 저장하고, 상태(AuthStatusView)를 돌려준다.
  • 어떤 토큰 종류든 된다(personal·project·group). 이슈 조회와 push 에는 api 범위(또는 push 만이면 write_repository)가 필요하다.
  • 등록한 토큰의 GitLab 사용자가 지금 에이전트 ID 의 소유자와 다르면 상태의 agentIdMismatch 가 true — 화면이 “에이전트 ID 를 다시 등록하세요”를 안내한다. 에이전트 ID 등록은 등록 당시 토큰의 GitLab 사용자 id 를 workspace_agent_ids.gitlab_user_id 에 함께 남긴다.
  • 실패 로그에는 사용자 이름과 GitLab 사용자 id 만 남긴다. 토큰·암호문·호스트는 남기지 않는다.

DELETE /api/workspace/auth/token (인증 필요) — 등록을 지우고 상태를 돌려준다(로컬 토큰이 있으면 그쪽으로 돌아간다).

호출 쪽이 runner 의 /v1/exec·/v1/repo/* 요청 env 에 아래 값을 싣는다 — 그 실행의 프로세스에만 전달되고 디스크에 쓰지 않는다. runner 는 요청의 환경 변수를 자식에게만 넘기고 감사에 값을 남기지 않는다.

변수 설명
GITLAB_TOKEN glab 인증. glab 은 이 값으로 GITLAB_HOST 의 API 를 부른다.
GITLAB_HOST glab 이 쓸 GitLab 호스트(https).
GIT_ASKPASS /usr/local/bin/git-askpass — git 이 https 자격증명을 물을 때 환경 변수만 읽어 답한다(작업 이미지에 들어 있다).
GLAB_CONFIG_DIR 호출 쪽이 사용자 홈 안의 휘발성 설정 폴더를 정해 넘긴다(토큰은 env 로만 가고 설정 폴더에 쓰지 않는다).
GIT_AUTHOR_NAME·GIT_AUTHOR_EMAIL·GIT_COMMITTER_NAME·GIT_COMMITTER_EMAIL 커밋 작성자. GitLab 프로필 값(사용자 등록) 또는 설정 값(로컬 토큰)이 있을 때만 넣는다.
  • git(clone·push)은 GIT_ASKPASS 도우미로만 자격증명을 받는다. 사용자 이름은 oauth2(또는 GIT_ASKPASS_USERNAME), 비밀번호는 GITLAB_TOKEN 이다. 토큰이 원격 주소·.git/config·credential 저장소에 남지 않는다(이미지 설정이 credential.helper = 로 저장소를 끈다).
  • 작업 이미지의 git-askpass 는 토큰이 없으면 빈 값을 낸다 — 인증 없이 실행하면 git 이 묻지 않고 실패한다.

GET /api/workspace/auth (인증 필요) — 설정 화면과 작업 공간 창이 실행에 쓰는 GitLab 계정·만료를 안내한다.

{"enabled": true, "source": "user", "configured": true,
"gitlabUserName": "Hong Gil Dong", "expiresAt": "2026-12-31T00:00:00Z", "warning": null,
"canRegister": true, "agentIdMismatch": false}
  • source — user(내가 등록) · local(배포 설정 토큰).
  • configured — 이 사용자의 실행에 인증을 실을 수 있는지(기능·토큰·계정 활성).
  • warning — expiring(만료 임박) · expired(지남) · invalid_expiry(만료일 형식 오류) · null.
  • canRegister — 암호화 키가 있어 등록 폼을 열 수 있는지.
  • agentIdMismatch — 등록한 에이전트 ID 의 GitLab 사용자와 지금 토큰의 GitLab 사용자가 다른지(둘 다 알 때만 판단).
  • 토큰·GitLab 주소는 응답에 없다.

설정 > 작업 공간(SettingsModal → WorkspaceAuthSection) — 지금 쓰는 출처·GitLab 사용자·만료일과 경고, 토큰 등록 폼(비밀번호 입력), 등록한 토큰 삭제. 입력한 토큰은 등록 뒤 즉시 비우고 다시 보여 주지 않는다.

기준 확인 방법
토큰 원문이 로그·감사·응답·이미지·볼륨에 없다 앱 로그·감사 테이블에서 토큰 문자열 검색, GET /api/workspace/auth 응답에 없음, DB 행은 token_cipher 만, 이미지에 값을 넣지 않음
삭제하면 이후 쓰이지 않는다 삭제 뒤 configured=false(로컬 토큰이 없을 때), 다음 실행 env 에 없음
등록 토큰으로 이슈 조회·push 시험 계정으로 등록 → 작업 공간에서 glab issue view·git push
비활성 계정은 토큰을 쓰지 않는다 credentialsFor 가 빈 값, configured=false
토큰 종류·사용자·만료 표시, 불일치 경고 등록 응답·화면에 GitLab 사용자·만료일, 다른 사용자 토큰으로 바꾸면 agentIdMismatch=true
  • 토큰 폐기(revoke)를 GitLab 에 대신 요청하지 않는다 — 삭제는 서버 보관만 지운다. 화면이 GitLab 에서 폐기하도록 안내한다.
  • 로컬 토큰 단계의 에이전트 ID 는 소유자를 모르므로(gitlab_user_id 가 비어 있음) 불일치 판단을 하지 않는다.
  • 토큰 범위(scope)를 서버가 검사하지 않는다 — GitLab 이 주는 만료일·프로필만 확인하고, 실제 권한은 첫 실행에서 드러난다.