서비스 계정 이해

배경

서비스 계정은 인증을 거쳐야 하며 Google API의 데이터에 액세스할 수 있는 승인을 받은 사람이 아닌 사용자를 나타내는 특별한 유형의 Google 계정입니다.

일반적으로 서비스 계정은 다음과 같은 상황에서 사용됩니다.

  • 가상 머신(VM)에서 워크로드 실행
  • 온프레미스 워크스테이션 또는 Google API를 호출하는 데이터 센터에서 워크로드 실행
  • 사람 사용자의 수명 주기와 관련이 없는 워크로드 실행

애플리케이션이 서비스 계정 ID를 사용하여 Google API를 호출하므로 사용자가 직접 관여하지 않습니다.

서비스 계정 관리

서비스 계정을 사용하기로 한 경우 다음 질문을 통해 서비스 계정의 용도를 이해할 수 있습니다.

  • 서비스 계정은 어떤 리소스에 액세스할 수 있나요?
  • 서비스 계정에 어떤 권한이 필요한가요?
  • 서비스 계정 ID를 사용하는 코드가 실행되는 곳은 Google Cloud Platform과 온프레미스 환경 중 어디인가요?

다음 플로차트를 사용하여 위 질문에 대한 대답을 알아보세요.

서비스 계정 플로차트

서비스 계정은 리소스이자 ID로 간주될 수 있습니다.

서비스 계정을 ID로 간주하면 프로젝트와 같은 리소스에 액세스할 수 있도록 서비스 계정에 역할을 부여할 수 있습니다.

서비스 계정을 리소스로 간주하면 다른 사용자에게 해당 서비스 계정에 액세스하거나 서비스 계정을 관리하는 역할을 부여할 수 있습니다.

서비스 계정에 액세스 권한 부여

리소스에 액세스하도록 서비스 계정에 액세스 권한을 부여하는 것은 다른 ID에 대한 액세스 권한을 부여하는 것과 유사합니다. 예를 들어 Google Compute Engine에서 실행 중인 애플리케이션에 Google Cloud Storage에 객체를 생성할 액세스 권한 부여하려면 해당 애플리케이션에 서비스 계정을 만들고 스토리지 객체 생성자 역할을 부여할 수 있습니다. 이 예시를 다이어그램으로 나타내면 다음과 같습니다.

서비스 계정 플로차트

서비스 계정에 역할 부여하기에 대해 자세히 알아보세요.

서비스 계정 가장하기

서비스 계정을 가장하여 Google API에 액세스하는 방법은 다음 3가지가 있습니다.

  • RSA 비공개 키를 사용한 인증
  • Cloud IAM 정책을 사용한 승인
  • Google Cloud 서비스에 작업 배포

RSA 비공개 키를 사용한 인증

모든 서비스 계정에는 정기적으로 순환되는 Google Cloud 관리 키 쌍이 있으며 비공개 키는 플랫폼에 의해 에스크로에 보관되며 직접 액세스할 수 없습니다.

또한 수동으로 사용자 관리 키 쌍을 만들 수도 있습니다. Google Cloud는 비공개 키와 공개 키를 생성하여 공개 키는 저장하며 비공개 키는 사용자에게 제공합니다. 키 쌍이 서비스 계정에서 삭제되면 Google에서 인증할 수 없습니다.

Cloud IAM 정책을 사용한 승인

모든 서비스 계정에는 서비스 계정에 액세스 권한을 부여하는 Cloud IAM 정책이 있습니다. 일부 권한을 부여하면 사용자의 사용자 인증 정보에 따라 사용자가 서비스 계정을 가장하거나 서비스 계정이 될 수 있습니다.

Google Cloud에 작업 배포

Compute Engine, App Engine, Cloud Functions와 같은 일부 Google Cloud 서비스를 사용하면 서비스 계정의 ID로 실행되는 작업(예: VM 또는 함수)을 배포할 수 있습니다.

이러한 방식으로 작업을 배포하려면 서비스 계정에는 원하는 서비스에 필요한 권한을 부여해야 하며 사용자 계정에는 서비스 계정에 대한 iam.serviceAccounts.actAs 권한도 부여해야 합니다. 이 권한은 서비스 계정 사용자 역할에 포함되어 있습니다. 또한 Google Cloud 서비스는 서비스 계정에서 Cloud IAM 권한을 유지해야 하지만 일반적으로 자동으로 수행됩니다.

예시

서비스 계정으로 VM 실행

예를 들어 장기 실행 중인 작업이 있으며 직원에게 이를 시작할 권한이 있다고 가정해보겠습니다. 작업을 마지막으로 시작한 직원이 퇴사할 때 작업이 종료되는 일이 발생해서는 안 됩니다.

이 문제를 해결하는 방법은 작업을 시작하고 중지할 서비스 계정을 만드는 것입니다. 이를 위해 수행해야 하는 단계는 다음과 같습니다.

  1. 서비스 계정을 만듭니다.

  2. 작업 시작 권한이 필요한 직원에게 서비스 계정에 대한 서비스 계정 사용자(roles/iam.serviceAccountUser) 역할을 부여합니다. 이 시나리오에서는 서비스 계정이 리소스로 취급됩니다.

  3. 같은 직원에게 Compute 인스턴스 관리자(roles/compute.instanceAdmin.v1) 역할을 부여합니다.

  4. 이제 직원은 해당 서비스 계정을 실행하는 Compute Engine 인스턴스를 만들고 연결하고 서비스 계정을 사용하여 작업을 시작할 수 있습니다. 예를 들면 다음과 같습니다.

    gcloud compute instances create my-instance --scopes=cloud-platform \
        --service-account=my-service-account@test9q.iam.gserviceaccount.com \
        --zone=us-central1-a
        

Google Cloud로 데이터 마이그레이션

다른 클라우드 제공업체를 통해 일부 데이터를 처리하며, 처리된 데이터를 Google Cloud Platform으로 전송하려고 한다고 가정해보겠습니다. 외부 클라우드의 가상 머신에서 서비스 계정을 사용하여 Google Cloud Platform으로 데이터를 내보낼 수 있습니다. 이를 위해서는 서비스 계정을 만들 때 서비스 계정 키를 만들고 다운로드한 다음 외부 프로세스에서 해당 키를 사용하여 Cloud Platform API를 호출해야 합니다.

서비스 계정 상태 확인

시간이 지남에 따라 더 많은 서비스 계정이 생겨나면 어떤 서비스 계정이 어떤 용도로 사용되는지 파악하기 어려울 수 있습니다.

서비스 계정의 표시 이름은 서비스 계정의 목적이나 서비스 계정 담당자와 같이 서비스 계정에 대한 추가 정보를 파악하는 데 유용한 방법입니다. 새로운 서비스 계정을 만들 때 표시 이름을 입력할 수 있습니다. 기존 서비스 계정의 경우 serviceAccounts.update() 메서드를 사용하여 표시 이름을 수정합니다.

서비스 계정 삭제 및 다시 만들기

서비스 계정은 삭제 후 동일한 이름으로 새롭게 다시 만들 수 있습니다. 단, 삭제된 서비스 계정의 이름을 재사용할 경우 예상하지 못한 동작의 원인이 될 수 있습니다.

서비스 계정을 삭제하더라도 역할 binding은 바로 삭제되지 않습니다. 최근에 삭제한 서비스 계정과 동일한 이름으로 서비스 계정을 새로 만들 경우 이전 결합이 계속해서 존재할 수도 있습니다. 하지만 두 계정의 이메일 주소가 동일하더라도 이전 결합이 새로운 서비스 계정에 적용되지는 않습니다. 이는 서비스 계정을 만들 때 Cloud IAM 내에서 고유 ID가 할당되기 때문입니다. 내부적으로 모든 역할 binding은 서비스 계정의 이메일 주소가 아닌 고유 ID를 사용해 부여됩니다. 따라서 삭제된 서비스 계정의 기존 역할 binding은 동일한 이메일 주소를 사용하더라도 새로운 서비스 계정에 적용되지 않습니다.

예상치 못한 동작을 방지하려면 모든 서비스 계정에 고유한 새 이름을 사용하는 것이 좋습니다. 또한 실수로 서비스 계정을 삭제한 경우 새 서비스 계정을 만드는 대신 서비스 계정 삭제를 취소할 수 있습니다.

원래의 서비스 계정 삭제를 취소할 수 없고 동일한 이름과 역할의 새 서비스 계정을 만들어야 하는 경우 다음 단계를 따르세요.

  1. 새 서비스 계정을 만듭니다.
  2. 새 서비스 계정이 액세스해야 하는 각 리소스에 대해 원래의 서비스 계정에 부여된 모든 역할을 취소합니다.

  3. 원래의 서비스 계정에서 역할을 취소한 후에 새 서비스 계정에 역할을 부여합니다.

서비스 계정에 대한 권한

이 섹션에서는 서비스 계정에 부여된 권한 또는 서비스 계정을 가장할 수 있는 권한이 있는 사용자 계정에 대한 일반적인 시나리오를 설명합니다.

서비스 계정에 최소한의 권한 부여

목표를 달성하는 데 필요한 최소한의 권한 모음만 서비스 계정에 부여해야 합니다. 서비스 계정에 특정 리소스에 대한 역할 부여에 대해 자세히 알아보세요.

사용자에게 서비스 계정 액세스 권한을 부여하는 경우 해당 사용자가 서비스 계정에 권한이 부여된 모든 리소스에 액세스할 수 있음에 유의하세요. 따라서 서비스 계정의 권한을 신중하게 구성해야 합니다. 즉, 팀에서 누가 서비스 계정의 역할을 수행하거나 가장할 수 있는지 엄격하게 관리해야 합니다.

App Engine 및 Compute Engine 인스턴스를 업데이트할 수 있는 Cloud IAM 역할이 있는 사용자(예: App Engine 배포자 또는 Compute 인스턴스 관리자)는 이러한 인스턴스를 실행하는 데 사용되는 서비스 계정으로 코드를 실행하고 서비스 계정에 액세스 권한이 있는 모든 리소스에 간접적으로 액세스할 수 있습니다. 마찬가지로 Compute Engine 인스턴스에 대한 SSH 액세스 역시 해당 인스턴스로 코드를 실행할 수 있는 기능을 제공할 수 있습니다.

일반적인 시나리오에 대한 서비스 계정 권한

서비스 계정은 다양한 시나리오에서 사용할 수 있으며 각 시나리오에는 특정 권한이 필요합니다. 이 섹션에서는 일반적인 시나리오와 필요한 권한에 대해 설명합니다.

장기 실행 작업 시작

권한:

  • iam.serviceAccounts.actAs

역할:

  • roles/editor(편집자)
  • roles/iam.serviceAccountUser(서비스 계정 사용자)

사용자 또는 서비스는 서비스 계정을 장기 실행 작업 서비스에 바인딩할 수 있습니다. 몇 가지 예를 들면 다음과 같습니다.

  • Compute Engine VM
  • App Engine 앱
  • Cloud Functions 함수
  • Dataflow 작업

이 시나리오에서 사용자는 서비스별로 다양한 작업을 배포할 수 있는 권한과 iam.serviceAccounts.actAs를 통해 서비스 계정에 부여되는 서비스 계정을 가장할 수 있는 권한을 모두 부여받아야 합니다. iam.serviceAccounts.actAs 권한을 부여받은 것만으로 서비스 계정을 가장할 수는 없습니다.

서비스 계정에 대해 iam.serviceAccounts.actAs 권한이 부여되면 서비스 계정으로 실행되는 장기 실행 작업을 시작할 수 있습니다. 작업이 시작되면 더 이상 서비스 계정에 대한 액세스 권한을 유지할 필요가 없습니다. 사용자가 액세스 권한을 상실하더라도 작업은 계속 실행됩니다. 작업 서비스는 서비스 계정에 대한 자체 권한을 계속 사용하여 해당 서비스 계정 ID로 작업을 계속 실행합니다.

Compute Engine VM에서의 인스턴스 메타데이터 설정과 같이 장기 실행 작업을 변경하려면 iam.serviceAccounts.actAs 권한이 필요합니다.

이 흐름에 대한 자세한 내용은 Compute Engine 문서의 인스턴스의 서비스 계정 만들기 및 사용 설정을 참조하세요.

직접 서비스 계정 가장하기

권한:

  • iam.serviceAccounts.getAccessToken
  • iam.serviceAccounts.signBlob
  • iam.serviceAccounts.signJwt
  • iam.serviceAccounts.implicitDelegation

역할:

  • roles/iam.serviceAccountTokenCreator(서비스 계정 토큰 생성자)

필요한 권한을 부여받은 사용자 또는 서비스는 몇 가지 일반적인 시나리오에서 서비스 계정의 ID를 직접 가장하거나 행사할 수 있습니다.

먼저 사용자는 iam.serviceAccounts.getAccessToken 권한을 사용하고 generateAccessToken() 메서드를 호출하여 서비스 계정에 대한 단기 사용자 인증 정보를 가져올 수 있습니다. 사용자는 단기 사용자 인증 정보를 사용하여 Google Cloud에 명령어를 실행하고 서비스 계정이 액세스할 수 있는 모든 리소스에 액세스할 수 있습니다. 예를 들어 이 흐름을 사용하면 다운로드한 외부 서비스 계정 키를 사용하지 않고도 gcloud --impersonate-service-account 플래그를 사용하여 서비스 계정을 가장할 수 있습니다.

두 번째로 사용자는 iam.serviceAccounts.signBlob 권한을 사용하고 signBlob() 또는 signJwt() 메서드를 호출하여 서비스 계정의 Google 관리 비공개 키로 서명된 아티팩트를 가져올 수 있습니다. Google 관리 비공개 키는 항상 에스크로에 보관되며 직접 노출되지 않습니다. signBlob()은 임의 페이로드의 서명(예: Cloud Storage 서명 URL)을 허용하고, signJwt()는 올바르게 구성된 JWT의 서명만 허용합니다.

마지막으로 사용자는 서비스 계정의 사용자 인증 정보를 가져오지 않고 서비스 계정을 가장하거나 행사할 수 있습니다. 이 고급 사용 사례는 generateAccessToken() 메서드를 사용하는 프로그래매틱 액세스에만 지원됩니다. A, B, C 등 최소 3개의 서비스 계정이 있는 시나리오에서 서비스 계정 AB에 대한 iam.serviceAccounts.implicitDelegation 권한이 부여되고 BC에 대한 iam.serviceAccounts.getAccessToken 권한이 부여되면 서비스 계정 A는 서비스 계정 C의 액세스 토큰을 가져올 수 있습니다.

OpenID Connect(OIDC) ID 토큰 생성

권한:

  • iam.serviceAccounts.getOpenIdToken

역할:

  • roles/iam.serviceAccountTokenCreator(서비스 계정 토큰 생성자)

사용자 또는 서비스는 iam.serviceAccounts.getOpenIdToken 권한을 사용하여 서비스 계정 ID를 나타내며 Google OIDC 제공업체가 서명한(accounts.google.com) OpenID Connect(OIDC) 호환 JWT 토큰을 생성할 수 있습니다.

조직에서 Google에 액세스 권한을 부여하기 위해 추가 ID 제휴를 배포하지 않으면 대부분의 Google API에서 이러한 토큰을 직접 허용하지 않습니다. 사용자 실행 애플리케이션에 OIDC 기반 액세스를 허용하는 IAP(Identity-Aware Proxy)와 같은 경우는 예외입니다.

외부 비공개 키 생성

권한:

  • iam.serviceAccountKeys.create

역할:

  • roles/editor(편집자)
  • roles/iam.serviceAccountAdmin(서비스 계정 관리자)

사용자 또는 서비스는 Google을 서비스 계정으로 직접 인증하는 데 사용할 수 있는 외부 비공개 키 자료(RSA)를 생성할 수 있습니다. 그런 다음 이 키 자료를 애플리케이션 기본 사용자 인증 정보(ADC) 라이브러리 또는 gcloud auth activate-service-account 명령어와 함께 사용할 수 있습니다. 그러면 키 자료에 대한 액세스 권한을 가진 모든 사용자가 서비스 계정이 액세스할 수 있는 모든 리소스에 대한 전체 액세스 권한을 갖게 됩니다. 이러한 비공개 키 자료는 가장 중요한 문제로 취급되어야 하며 자료가 더 오래 존재할수록 보안 수준이 낮은 것으로 간주되어야 합니다. 따라서 강력한 보안을 유지하려면 비공개 키 자료를 순환하는 것이 중요합니다.

서비스 계정 키 관리

서비스 계정 키에는 다음 2가지 유형이 있습니다.

  • GCP 관리 키. 이 키는 App Engine 및 Compute Engine과 같은 Cloud Platform 서비스에서 사용됩니다. 키를 다운로드할 수는 없으며, 자동으로 순환되면서 최대 2주까지 서명하는 데 사용됩니다. 순환 프로세스는 확률적입니다. 즉 새로운 키의 사용량은 키의 전체 기간 동안 점진적으로 늘거나 줄어듭니다. 따라서 서비스 계정의 공개 키 집합을 최대 24시간까지 캐싱하여 현재 키 집합에 언제든지 액세스할 수 있도록 하는 것이 좋습니다.

  • 사용자 관리 키. 이 키는 사용자가 만들고 다운로드하고 관리합니다. 이 키는 생성 후 10년 후에 만료되며, 서비스 계정에서 삭제되면 인증이 중지됩니다.

사용자 관리 키를 사용하려면 다음과 같은 키 관리 요구사항을 처리할 프로세스를 갖추고 있는지 확인해야 합니다.

  • 키 저장
  • 키 배포
  • 키 해지
  • 키 순환
  • 키 무단 사용 방지
  • 키 복구

서비스 계정의 유효한 비공개 키에 액세스할 수 있는 사용자는 누구나 서비스 계정을 통해 리소스에 액세스할 수 있습니다. 서비스 계정에 대한 키의 액세스 수명 주기(즉, 서비스 계정에 액세스 권한이 있는 데이터)는 키를 다운로드한 사용자의 수명 주기와 관계가 없습니다.

항상 개발자가 소스 코드에 키를 추가하거나 이를 워크스테이션의 다운로드 디렉터리에 남겨두지 않도록 하세요.

키 보안을 강화하려면 아래의 안내를 따르세요.

  • IAM 서비스 계정 API를 사용하여 서비스 계정 키를 자동으로 순환합니다. 새로운 키를 만들고 애플리케이션에서 새로운 키를 사용하도록 전환한 다음 이전 키를 삭제하여 키를 순환할 수 있습니다. serviceAccount.keys.create() 메서드와 serviceAccount.keys.delete() 메서드를 함께 사용하여 순환을 자동화합니다. GCP 관리 키는 대략 1주일 주기로 순환합니다.

Compute Engine에서 서비스 계정 사용

Compute Engine 인스턴스가 다른 Cloud Platform 리소스에 액세스하려면 서비스 계정으로 실행해야 합니다. Compute Engine 인스턴스의 보안을 위해 다음 사항을 고려하세요.

  • 같은 프로젝트에 서비스 계정이 서로 다른 VM을 만들 수 있습니다. 이미 만들어진 VM 서비스 계정을 변경하려면 instances.setServiceAccount 메서드를 사용합니다.

  • 서비스 계정에 IAM 역할을 부여하여 서비스 계정에서 액세스할 수 있는 항목을 정의할 수 있습니다. 대부분 더 이상 범위에 의존할 필요가 없습니다. 이렇게 하면 인스턴스를 다시 만들지 않고도 VM 서비스 계정의 권한을 수정할 수 있는 장점이 있습니다.

  • 인스턴스는 Cloud Platform 리소스에 액세스하기 위해 서비스 계정에 의존하므로, 실행 중인 인스턴스에서 아직 서비스 계정을 사용 중이라면 해당 계정을 삭제하면 안 됩니다. 서비스 계정을 삭제하면 인스턴스가 작업에 실패할 수 있습니다.

권장사항

  • 서비스 계정 역할을 할 사용자를 지정합니다. 서비스 계정에 대해 서비스 계정 사용자인 사람은 서비스 계정이 액세스할 수 있는 모든 리소스에 간접적으로 액세스할 수 있습니다. 따라서 사용자에게 serviceAccountUser 역할을 부여할 때는 주의해야 합니다.

  • 목표를 달성하는 데 필요한 최소한의 권한 모음만 서비스 계정에 부여합니다. 서비스 계정에 특정 리소스에 대한 역할 부여에 대해 자세히 알아보세요.

  • 서비스별로 필요한 권한만 부여하여 각 서비스 계정을 만듭니다.

  • 서비스 계정의 표시 이름을 사용하여 서비스 계정 상태를 확인합니다. 서비스 계정을 만들 때 서비스 계정의 목적을 나타내는 표시 이름을 입력합니다.

  • 서비스 계정의 이름 지정 규칙을 정의합니다.

  • 사용자 관리 서비스 계정 키의 순환을 자동화하는 프로세스를 구현합니다.

  • IAM 서비스 계정 API를 활용하여 키 순환을 구현합니다.

  • serviceAccount.keys.list() 메서드 또는 Console의 로그 뷰어 페이지를 사용하여 서비스 계정 및 키를 감사합니다.

  • 애플리케이션에서 서비스 계정에 액세스할 수 없게 하려는 경우가 아니면 App Engine 또는 Compute Engine에서 실행 중인 인스턴스에서 사용 중인 서비스 계정을 삭제해서는 안 됩니다.