InfoGrab DocsInfoGrab Docs

복합 ID(Composite Identity)

요약

보안상의 이유로, 쓰기 작업을 수행하는 GitLab 플랫폼의 AI 생성 활동에는 복합 ID를 사용해야 합니다. 복합 ID 토큰을 생성하려면 다음이 필요합니다: 기본 토큰 소유자인 서비스 계정 사용자. 인스턴스 전체 또는 그룹 범위로 지정할 수 있습니다.

보안상의 이유로, 쓰기 작업을 수행하는 GitLab 플랫폼의 AI 생성 활동에는 복합 ID를 사용해야 합니다.

복합 ID를 사용하는 기능:

사전 요구 사항#

복합 ID 토큰을 생성하려면 다음이 필요합니다:

기본 토큰 소유자인 서비스 계정 사용자.

인스턴스 전체 또는 그룹 범위로 지정할 수 있습니다. 인스턴스 전체 계정은 GitLab 자체 기능에 일반적으로 사용되며, 고객 에이전틱 플로는 범위를 좁게 지정한 계정을 사용해야 합니다.

  • 특정 권한이 있는 사용자만 서비스 계정을 생성할 수 있습니다. 계정이 생성되는 위치와 방법을 미리 계획하세요.

  • 서비스 계정은 여러 기능에서 공유할 수 있지만, 동일한 계정을 공유하면 UI에서 작업을 구분하기 어려워집니다(예: 동일 사용자가 MR을 생성하고 리뷰하는 것처럼 보일 수 있음).

가용성 및 라이선스:

서비스 계정은 Premium 및 Ultimate에서 사용 가능합니다.

  • 따라서, 복합 ID는 GitLab Premium 또는 Ultimate 라이선스가 필요합니다.

서비스 계정에는 composite_identity_enforcedtrue로 설정되어 있어야 합니다.

이 설정은 서비스 계정 생성 UI에서는 제공되지 않으며, 프로그래밍 방식으로 구성해야 합니다.

복합 ID에 사용되는 OAuth 애플리케이션은 user:*의 동적 스코프를 활성화해야 합니다.

이 스코프는 OAuth 애플리케이션 UI에서 제공되지 않으며, 프로그래밍 방식으로 구성해야 합니다.

복합 ID 토큰 생성 방법#

OAuth 토큰만 지원됩니다.

  • 서비스 계정은 로그인할 수 없는 봇 사용자이므로, 일반적인 인가 코드 플로(브라우저 동의)는 작동하지 않습니다.

  • 서드파티 서비스와 통합하는 경우:

서비스 계정 + OAuth 앱에 대한 OAuth 그랜트를 수동으로 생성하세요. Amazon Q 예시를 참고하세요.

  • AI 요청을 시작한 사람 사용자에 대한 구체적인 동적 스코프가 그랜트 스코프에 포함되어야 하며, user:$ID 형식으로 지정합니다(예: user:123). 필요에 따라 다른 스코프도 포함하세요(예: api).

  • https://gitlab.example.com/oauth/token을 통해 그랜트를 액세스 토큰으로 교환합니다.

  • 서드파티 서비스와 통합하지 않는 경우:

액세스 그랜트 단계를 건너뛰고 OAuth 액세스 토큰을 직접 생성할 수 있으며, 스코프에 user:$ID와 필요한 기본 스코프를 포함시킵니다.

  • grant_type=refresh_token을 사용하여 표준 https://gitlab.example.com/oauth/token> 엔드포인트를 통해 토큰을 갱신합니다.

  • 반환된 액세스 토큰은 서비스 계정에 속하지만, 스코프에 user:$ID를 포함합니다. 표준 OAuth 액세스 토큰처럼 갱신됩니다.

최소 예시#

  • OAuth 애플리케이션 생성(이 단계는 맞춤형 OAuth 앱을 원하는 경우에만 필요합니다. GitLab Duo Workflow 기본 OAuth 애플리케이션과 서비스 계정은 ee/app/services/ai/duo_workflows/onboarding_service.rb를 호출하여 생성됩니다):
# Rails console
app = Authn::OauthApplication.new(
  name: "Composite Identity App",
  redirect_uri: Gitlab::Routing.url_helpers.root_url, # unused but cannot be nil
  scopes: ::Gitlab::Auth::AI_WORKFLOW_SCOPES + [::Gitlab::Auth::DYNAMIC_USER],
  trusted: false,
  confidential: false # public client (no secret required)
)
app.save!
  • 서비스 계정 + 사람 사용자에 대한 인가 그랜트 생성:
# Assuming you want to create a composite OAuth token for the GitLab Duo Workflow OAuth application and service account + root user in your GDK.
org = Organizations::Organization.default_organization
user = User.first

oauth_token_service = Ai::DuoWorkflows::CreateCompositeOauthAccessTokenService.new(
  current_user: user,
  organization: org,
).execute
oauth_token_service.payload[:oauth_access_token].plaintext_token

인가 평가 방법#

복합 ID 토큰으로 만든 요청은 다음 두 조건이 모두 참인 경우에만 인가됩니다:

  • 서비스 계정이 해당 리소스에 접근할 수 있어야 합니다.

  • 토큰 스코프의 user:$ID로 식별된 사람 사용자가 해당 리소스에 접근할 수 있어야 합니다.

요청 컨텍스트와 current_user#

요청에 복합 ID OAuth 토큰이 포함된 경우, Rails 요청 컨텍스트는 current_useruser:$ID 스코프에서 추출한 사람 사용자로 재정의합니다. 토큰 자체는 서비스 계정에 속하지만, 요청을 시작한 사용자가 현재 사용자로 간주됩니다. 즉:

  • current_user에 의존하는 모든 코드는 사람 사용자로 실행됩니다.

  • resolve_composite_identity_actor를 사용하여 귀속에 대한 올바른 액터를 결정하세요. 결과는 현재 요청에 대해 ID가 연결된 방식에 따라 달라집니다.

올바른 액터에 작업 귀속하기#

모든 쓰기 작업에 대한 액터를 확인할 때는 항상 resolve_composite_identity_actor를 사용하세요. 컨텍스트를 직접 판단할 필요가 없습니다. 컨텍스트는 요청 경계에서 자동으로 설정됩니다:

actor = Gitlab::Auth::Identity.resolve_composite_identity_actor(current_user)

작성자를 설정하는 곳(예: 노트, 이슈/MR, 커밋, 파이프라인 사용자 컨텍스트)에서 반환된 actor를 사용하세요.

메서드는 상황에 맞는 올바른 액터를 반환합니다:

  • 서비스 계정이 요청한 경우(OAuth 토큰에 user:$ID 스코프 포함, 또는 CI job): 내부적으로 :authentication 컨텍스트로 태깅됩니다. 서비스 계정을 반환합니다. SA가 액터이며 귀속되어야 합니다.

  • 사람이 요청했으나 SA가 부수적으로 연결된 경우(예: 사람이 SA를 리뷰어로 지정): 내부적으로 :permission_check 컨텍스트로 태깅됩니다. 사람을 반환합니다. 사람이 액터이며 귀속되어야 합니다.

  • 복합 ID가 없는 경우: current_user를 그대로 반환합니다.

시나리오에 따라 이 메서드를 다르게 호출할 필요가 없습니다. ID 시스템이 요청 인증 시 컨텍스트를 기록하며, resolve_composite_identity_actor가 자동으로 사용합니다.

참조: MR !204010, MR !223788

빠른 설정 확인#

# Expect 200 only if BOTH the human and service account can read the project
curl --silent --show-error --fail --header "Authorization: Bearer " \
  "https://gitlab.example.com/api/v4/projects/%2F"

일반적인 결과:

  • 403: 주체 중 하나가 권한이 없는 경우.

  • 404: 어느 주체도 리소스를 볼 수 없거나, 리소스를 찾을 수 없는 경우.

로컬/GDK 테스트 팁#

# Rails console
service_account = User.find_by_username("service_account")
service_account.update!(composite_identity_enforced: true)

문제 해결#

  • 동적 스코프가 거부되거나 무시되는 경우: OAuth 앱에 dynamic_scopes: "user:*"가 설정되어 있는지 확인하세요.

  • 토큰에 user:$ID가 없는 경우: 스코프에 구체적인 user:$ID를 포함하여 그랜트/토큰을 재발급하세요.

  • 플랫폼 작업이 사람 대신 서비스 계정에(또는 반대로) 귀속되는 경우: ID가 연결된 컨텍스트를 확인하세요. OAuth/CI 플로는 :authentication을 사용하며(SA에 귀속), 웹/할당 플로는 :permission_check를 사용합니다(사람에 귀속). 올바른 액터에 작업 귀속하기를 참고하세요.

  • 토큰 교환 시 422 오류: 리다이렉트 URI 불일치 또는 그랜트 만료.

  • API 요청 시 403 오류: 두 주체 모두 필요한 프로젝트/그룹 권한이 있는지, 기본 스코프(예: api)가 포함되어 있는지 확인하세요.

복합 ID(Composite Identity)

GitLab v19.1
원문 보기
요약

보안상의 이유로, 쓰기 작업을 수행하는 GitLab 플랫폼의 AI 생성 활동에는 복합 ID를 사용해야 합니다. 복합 ID 토큰을 생성하려면 다음이 필요합니다: 기본 토큰 소유자인 서비스 계정 사용자. 인스턴스 전체 또는 그룹 범위로 지정할 수 있습니다.

보안상의 이유로, 쓰기 작업을 수행하는 GitLab 플랫폼의 AI 생성 활동에는 복합 ID를 사용해야 합니다.

복합 ID를 사용하는 기능:

사전 요구 사항#

복합 ID 토큰을 생성하려면 다음이 필요합니다:

기본 토큰 소유자인 서비스 계정 사용자.

인스턴스 전체 또는 그룹 범위로 지정할 수 있습니다. 인스턴스 전체 계정은 GitLab 자체 기능에 일반적으로 사용되며, 고객 에이전틱 플로는 범위를 좁게 지정한 계정을 사용해야 합니다.

  • 특정 권한이 있는 사용자만 서비스 계정을 생성할 수 있습니다. 계정이 생성되는 위치와 방법을 미리 계획하세요.

  • 서비스 계정은 여러 기능에서 공유할 수 있지만, 동일한 계정을 공유하면 UI에서 작업을 구분하기 어려워집니다(예: 동일 사용자가 MR을 생성하고 리뷰하는 것처럼 보일 수 있음).

가용성 및 라이선스:

서비스 계정은 Premium 및 Ultimate에서 사용 가능합니다.

  • 따라서, 복합 ID는 GitLab Premium 또는 Ultimate 라이선스가 필요합니다.

서비스 계정에는 composite_identity_enforcedtrue로 설정되어 있어야 합니다.

이 설정은 서비스 계정 생성 UI에서는 제공되지 않으며, 프로그래밍 방식으로 구성해야 합니다.

복합 ID에 사용되는 OAuth 애플리케이션은 user:*의 동적 스코프를 활성화해야 합니다.

이 스코프는 OAuth 애플리케이션 UI에서 제공되지 않으며, 프로그래밍 방식으로 구성해야 합니다.

복합 ID 토큰 생성 방법#

OAuth 토큰만 지원됩니다.

  • 서비스 계정은 로그인할 수 없는 봇 사용자이므로, 일반적인 인가 코드 플로(브라우저 동의)는 작동하지 않습니다.

  • 서드파티 서비스와 통합하는 경우:

서비스 계정 + OAuth 앱에 대한 OAuth 그랜트를 수동으로 생성하세요. Amazon Q 예시를 참고하세요.

  • AI 요청을 시작한 사람 사용자에 대한 구체적인 동적 스코프가 그랜트 스코프에 포함되어야 하며, user:$ID 형식으로 지정합니다(예: user:123). 필요에 따라 다른 스코프도 포함하세요(예: api).

  • https://gitlab.example.com/oauth/token을 통해 그랜트를 액세스 토큰으로 교환합니다.

  • 서드파티 서비스와 통합하지 않는 경우:

액세스 그랜트 단계를 건너뛰고 OAuth 액세스 토큰을 직접 생성할 수 있으며, 스코프에 user:$ID와 필요한 기본 스코프를 포함시킵니다.

  • grant_type=refresh_token을 사용하여 표준 https://gitlab.example.com/oauth/token> 엔드포인트를 통해 토큰을 갱신합니다.

  • 반환된 액세스 토큰은 서비스 계정에 속하지만, 스코프에 user:$ID를 포함합니다. 표준 OAuth 액세스 토큰처럼 갱신됩니다.

최소 예시#

  • OAuth 애플리케이션 생성(이 단계는 맞춤형 OAuth 앱을 원하는 경우에만 필요합니다. GitLab Duo Workflow 기본 OAuth 애플리케이션과 서비스 계정은 ee/app/services/ai/duo_workflows/onboarding_service.rb를 호출하여 생성됩니다):
# Rails console
app = Authn::OauthApplication.new(
  name: "Composite Identity App",
  redirect_uri: Gitlab::Routing.url_helpers.root_url, # unused but cannot be nil
  scopes: ::Gitlab::Auth::AI_WORKFLOW_SCOPES + [::Gitlab::Auth::DYNAMIC_USER],
  trusted: false,
  confidential: false # public client (no secret required)
)
app.save!
  • 서비스 계정 + 사람 사용자에 대한 인가 그랜트 생성:
# Assuming you want to create a composite OAuth token for the GitLab Duo Workflow OAuth application and service account + root user in your GDK.
org = Organizations::Organization.default_organization
user = User.first

oauth_token_service = Ai::DuoWorkflows::CreateCompositeOauthAccessTokenService.new(
  current_user: user,
  organization: org,
).execute
oauth_token_service.payload[:oauth_access_token].plaintext_token

인가 평가 방법#

복합 ID 토큰으로 만든 요청은 다음 두 조건이 모두 참인 경우에만 인가됩니다:

  • 서비스 계정이 해당 리소스에 접근할 수 있어야 합니다.

  • 토큰 스코프의 user:$ID로 식별된 사람 사용자가 해당 리소스에 접근할 수 있어야 합니다.

요청 컨텍스트와 current_user#

요청에 복합 ID OAuth 토큰이 포함된 경우, Rails 요청 컨텍스트는 current_useruser:$ID 스코프에서 추출한 사람 사용자로 재정의합니다. 토큰 자체는 서비스 계정에 속하지만, 요청을 시작한 사용자가 현재 사용자로 간주됩니다. 즉:

  • current_user에 의존하는 모든 코드는 사람 사용자로 실행됩니다.

  • resolve_composite_identity_actor를 사용하여 귀속에 대한 올바른 액터를 결정하세요. 결과는 현재 요청에 대해 ID가 연결된 방식에 따라 달라집니다.

올바른 액터에 작업 귀속하기#

모든 쓰기 작업에 대한 액터를 확인할 때는 항상 resolve_composite_identity_actor를 사용하세요. 컨텍스트를 직접 판단할 필요가 없습니다. 컨텍스트는 요청 경계에서 자동으로 설정됩니다:

actor = Gitlab::Auth::Identity.resolve_composite_identity_actor(current_user)

작성자를 설정하는 곳(예: 노트, 이슈/MR, 커밋, 파이프라인 사용자 컨텍스트)에서 반환된 actor를 사용하세요.

메서드는 상황에 맞는 올바른 액터를 반환합니다:

  • 서비스 계정이 요청한 경우(OAuth 토큰에 user:$ID 스코프 포함, 또는 CI job): 내부적으로 :authentication 컨텍스트로 태깅됩니다. 서비스 계정을 반환합니다. SA가 액터이며 귀속되어야 합니다.

  • 사람이 요청했으나 SA가 부수적으로 연결된 경우(예: 사람이 SA를 리뷰어로 지정): 내부적으로 :permission_check 컨텍스트로 태깅됩니다. 사람을 반환합니다. 사람이 액터이며 귀속되어야 합니다.

  • 복합 ID가 없는 경우: current_user를 그대로 반환합니다.

시나리오에 따라 이 메서드를 다르게 호출할 필요가 없습니다. ID 시스템이 요청 인증 시 컨텍스트를 기록하며, resolve_composite_identity_actor가 자동으로 사용합니다.

참조: MR !204010, MR !223788

빠른 설정 확인#

# Expect 200 only if BOTH the human and service account can read the project
curl --silent --show-error --fail --header "Authorization: Bearer " \
  "https://gitlab.example.com/api/v4/projects/%2F"

일반적인 결과:

  • 403: 주체 중 하나가 권한이 없는 경우.

  • 404: 어느 주체도 리소스를 볼 수 없거나, 리소스를 찾을 수 없는 경우.

로컬/GDK 테스트 팁#

# Rails console
service_account = User.find_by_username("service_account")
service_account.update!(composite_identity_enforced: true)

문제 해결#

  • 동적 스코프가 거부되거나 무시되는 경우: OAuth 앱에 dynamic_scopes: "user:*"가 설정되어 있는지 확인하세요.

  • 토큰에 user:$ID가 없는 경우: 스코프에 구체적인 user:$ID를 포함하여 그랜트/토큰을 재발급하세요.

  • 플랫폼 작업이 사람 대신 서비스 계정에(또는 반대로) 귀속되는 경우: ID가 연결된 컨텍스트를 확인하세요. OAuth/CI 플로는 :authentication을 사용하며(SA에 귀속), 웹/할당 플로는 :permission_check를 사용합니다(사람에 귀속). 올바른 액터에 작업 귀속하기를 참고하세요.

  • 토큰 교환 시 422 오류: 리다이렉트 URI 불일치 또는 그랜트 만료.

  • API 요청 시 403 오류: 두 주체 모두 필요한 프로젝트/그룹 권한이 있는지, 기본 스코프(예: api)가 포함되어 있는지 확인하세요.