Azure에서 OpenID Connect를 구성해 임시 자격 증명 가져오기

Azure에서 OpenID Connect를 구성해 임시 자격 증명 가져오기

GitLab CI/CD job에서 JWT를 사용해서, 비밀을 저장하지 않고 Azure에서 임시 자격 증명을 가져오는 방법을 함께 알아볼게요. GitLab과 Azure 사이의 ID 페더레이션을 위해 OpenID Connect (OIDC)를 구성하는 것으로 시작합니다.

출처: 문서

본문

  • 티어(Tier): Free, Premium, Ultimate
  • 제공 방식(Offering): GitLab.com, GitLab Self-Managed, GitLab Dedicated

CI_JOB_JWT_V2GitLab 17.0에서 제거되었어요. 대신 ID 토큰을 사용하세요.

GitLab과 함께 OIDC를 사용하는 방법에 대한 자세한 내용은 클라우드 서비스 연결하기를 읽어보세요.

전제 조건:

  • Owner 액세스 수준을 가진 기존 Azure 구독에 접근.
  • 최소 Application Developer 액세스 수준으로 해당 Microsoft Entra ID 테넌트에 접근.
  • 로컬 Azure CLI 설치. 또는 Azure Cloud Shell로 모든 단계를 수행할 수 있어요.
  • Azure가 GitLab OIDC 엔드포인트에 연결해야 하므로 GitLab 인스턴스가 인터넷으로 공개 접근 가능해야 해요.
  • GitLab 프로젝트.

이 튜토리얼을 완료하려면:

  1. Entra ID 애플리케이션과 서비스 주체 만들기.
  2. Entra ID 페더레이션 ID 자격 증명 만들기.
  3. 서비스 주체에 권한 부여하기.
  4. 임시 자격 증명 가져오기.

Azure ID 페더레이션에 대한 자세한 내용은 workload identity federation을 참고하세요.

Entra ID 애플리케이션과 서비스 주체 만들기

GitLab용 Entra ID 애플리케이션과 서비스 주체를 만드는 방법:

  1. Azure CLI에서 GitLab용 애플리케이션을 만들어요: appId=$(az ad app create --display-name gitlab-oidc --query appId -otsv) appId(Application client ID) 출력을 저장해 두세요. 나중에 GitLab CI/CD 파이프라인을 구성할 때 필요해요.
  2. 해당 서비스 주체를 만들어요: az ad sp create --id $appId --query appId -otsv

Azure CLI 대신 Azure Portal로 이 리소스들을 만들 수도 있어요.

Entra ID 페더레이션 ID 자격 증명 만들기

<mygroup>/<myproject>의 특정 브랜치에 대해 앞서 만든 Entra ID 애플리케이션의 페더레이션 ID 자격 증명을 만들려면:

objectId=$(az ad app show --id $appId --query id -otsv)

cat <<EOF > body.json
{
  "name": "gitlab-federated-identity",
  "issuer": "https://gitlab.example.com",
  "subject": "project_path:<mygroup>/<myproject>:ref_type:branch:ref:<branch>",
  "description": "GitLab service account federated identity",
  "audiences": [
    "https://gitlab.example.com"
  ]
}
EOF

az rest --method POST --uri "https://graph.microsoft.com/beta/applications/$objectId/federatedIdentityCredentials" --body @body.json

issuer, subject, audiences 값 관련 문제는 문제 해결 세부 사항을 참고하세요.

선택적으로 이제 Azure Portal에서 Entra ID 애플리케이션과 Entra ID 페더레이션 ID 자격 증명을 검증할 수 있어요:

  1. Microsoft Entra ID App Registration 뷰를 열고 표시 이름 gitlab-oidc로 검색해 적절한 앱 등록을 선택해요.
  2. 개요 페이지에서 Application (client) ID, Object ID, Tenant ID 같은 세부 정보를 확인할 수 있어요.
  3. Certificates & secrets 아래 Federated credentials로 가서 Entra ID 페더레이션 ID 자격 증명을 검토해요.

모든 브랜치나 모든 태그에 대한 자격 증명 만들기

모든 브랜치나 태그(와일드카드 일치)에 대한 자격 증명을 만들려면 flexible federated identity credentials를 사용할 수 있어요.

<mygroup>/<myproject>의 모든 브랜치:

objectId=$(az ad app show --id $appId --query id -otsv)

cat <<EOF > body.json
{
  "name": "gitlab-federated-identity",
  "issuer": "https://gitlab.example.com",
  "subject": null,
  "claimsMatchingExpression": {
    "value": "claims['sub'] matches 'project_path:<mygroup>/<myproject>:ref_type:branch:ref:*'",
    "languageVersion": 1
  },
  "description": "GitLab service account federated identity",
  "audiences": [
    "https://gitlab.example.com"
  ]
}
EOF

az rest --method POST --uri "https://graph.microsoft.com/beta/applications/$objectId/federatedIdentityCredentials" --body @body.json

<mygroup>/<myproject>의 모든 태그:

objectId=$(az ad app show --id $appId --query id -otsv)

cat <<EOF > body.json
{
  "name": "gitlab-federated-identity",
  "issuer": "https://gitlab.example.com",
  "subject": null,
  "claimsMatchingExpression": {
    "value": "claims['sub'] matches 'project_path:<mygroup>/<myproject>:ref_type:tag:ref:*'",
    "languageVersion": 1
  },
  "description": "GitLab service account federated identity",
  "audiences": [
    "https://gitlab.example.com"
  ]
}
EOF

az rest --method POST --uri "https://graph.microsoft.com/beta/applications/$objectId/federatedIdentityCredentials" --body @body.json

서비스 주체에 권한 부여하기

자격 증명을 만든 뒤에는 role assignment로 이전 서비스 주체에 권한을 부여해 Azure 리소스에 접근할 수 있게 해요:

az role assignment create --assignee $appId --role Reader --scope /subscriptions/<subscription-id>

구독 ID는 다음에서 찾을 수 있어요:

위 명령은 전체 구독에 읽기 전용 권한을 부여해요. 조직 맥락에서 최소 권한 원칙 적용에 대한 자세한 내용은 Entra ID 역할 모범 사례를 읽어보세요.

임시 자격 증명 가져오기

Entra ID 애플리케이션과 페더레이션 ID 자격 증명을 구성한 뒤에는 CI/CD job이 Azure CLI로 임시 자격 증명을 가져올 수 있어요:

default:
  image: mcr.microsoft.com/azure-cli:latest

variables:
  AZURE_CLIENT_ID: "<client-id>"
  AZURE_TENANT_ID: "<tenant-id>"

auth:
  id_tokens:
    GITLAB_OIDC_TOKEN:
      aud: https://gitlab.com
  script:
    - az login --service-principal -u $AZURE_CLIENT_ID -t $AZURE_TENANT_ID --federated-token $GITLAB_OIDC_TOKEN
    - az account show

CI/CD 변수는 다음과 같아요:

문제 해결 (Troubleshooting)

오류: No matching federated identity record found

ERROR: AADSTS70021: No matching federated identity record found for presented assertion. 오류를 받으면 다음을 확인해야 해요:

  • Entra ID 페더레이션 ID 자격 증명에 정의된 Issuer(예: https://gitlab.com 또는 자신의 GitLab URL).
  • Entra ID 페더레이션 ID 자격 증명에 정의된 Subject identifier(예: project_path:<mygroup>/<myproject>:ref_type:branch:ref:<branch>). - gitlab-group/gitlab-project 프로젝트와 main 브랜치라면: project_path:gitlab-group/gitlab-project:ref_type:branch:ref:main. - mygroupmyproject의 올바른 값은 GitLab 프로젝트에 접근할 때 URL을 확인하거나, 프로젝트 개요 페이지 오른쪽 위에서 Code를 선택해 알아낼 수 있어요.
  • Entra ID 페더레이션 ID 자격 증명에 정의된 Audience(예: https://gitlab.com 또는 자신의 GitLab URL).

이 설정과 AZURE_CLIENT_ID, AZURE_TENANT_ID CI/CD 변수는 Azure Portal에서 검토할 수 있어요:

  1. Microsoft Entra ID App Registration 뷰를 열고 표시 이름 gitlab-oidc로 검색해 적절한 앱 등록을 선택해요.
  2. 개요 페이지에서 Application (client) ID, Object ID, Tenant ID 같은 세부 정보를 확인할 수 있어요.
  3. Certificates & secrets 아래 Federated credentials로 가서 Entra ID 페더레이션 ID 자격 증명을 검토해요.

자세한 내용은 클라우드 서비스 연결하기를 참고하세요.

Request to External OIDC endpoint failed 메시지

ERROR: AADSTS501661: Request to External OIDC endpoint failed. 오류를 받으면 GitLab 인스턴스가 인터넷에서 공개적으로 접근 가능한지 확인해야 해요.

Azure는 OIDC로 인증하려면 다음 GitLab 엔드포인트에 접근할 수 있어야 해요:

  • GET /.well-known/openid-configuration
  • GET /oauth/discovery/keys

방화벽을 업데이트했는데도 이 오류가 계속되면 Redis 캐시를 비우고 다시 시도해 보세요.

No matching federated identity record found for presented assertion audience 메시지

ERROR: AADSTS700212: No matching federated identity record found for presented assertion audience 'https://gitlab.com' 오류를 받으면 CI/CD job이 올바른 aud 값을 사용하는지 확인해야 해요.

aud 값은 페더레이션 ID 자격 증명을 만들 때 사용한 audience와 일치해야 해요.

더 알아보기 (Learn more)