서비스 계정 이해

배경

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

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

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

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

서비스 계정 관리

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

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

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

서비스 계정 플로차트

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

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

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

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

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

서비스 계정 플로차트

서비스 계정을 포함하여 모든 유형의 구성원에 역할 부여에 대해 알아보세요.

서비스 계정 상태 확인

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

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

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

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

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

마찬가지로 리소스에 서비스 계정을 연결한 후 서비스 계정을 삭제하고 이름이 같은 새 서비스 계정을 만들면 새 서비스 계정이 리소스에 연결되지 않습니다.

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

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

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

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

또한 새 서비스 계정을 원래 서비스 계정과 동일한 리소스에 연결해야 하는 경우 다음 중 하나를 수행합니다.

서비스 계정에 대한 권한

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

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

모든 유형의 구성원과 마찬가지로 서비스 계정에 목표를 달성하는 데 필요한 최소 권한 집합만 부여해야 합니다. 서비스 계정을 포함하여 모든 유형의 구성원에 역할 부여에 대해 알아보세요.

사용자에게 서비스 계정 액세스 권한을 부여하는 경우 이 사용자가 서비스 계정에 권한이 부여된 모든 리소스에 액세스할 수 있음에 유의하세요. 따라서 서비스 계정의 권한을 신중하게 구성해야 합니다. 즉, 팀에서 누가 서비스 계정의 역할을 수행하거나 가장할 수 있는지 엄격하게 관리해야 합니다. 사용자가 Compute Engine 및 App Engine 기본 서비스 계정과 같이 권한이 높은 서비스 계정을 가장하도록 허용할 경우에는 특히 주의해야 합니다.

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

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

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

리소스에 서비스 계정 연결

서비스 계정으로 인증하는 장기 실행 작업을 시작하려면 작업을 실행할 리소스에 서비스 계정을 연결해야 합니다.

권한:

  • 리소스를 만들 수 있는 권한
  • iam.serviceAccounts.actAs

이러한 권한이 포함된 역할을 확인하려면 역할 목록에서 권한을 검색합니다.

장기 실행 작업을 서비스 계정으로 실행할 수 있는 몇 가지 Google Cloud 리소스가 있습니다. 다음은 이러한 리소스의 몇 가지 예시입니다.

  • Compute Engine VM
  • App Engine 앱
  • Cloud Functions

이러한 리소스를 만들 때 서비스 계정을 연결할 수 있습니다. 이 서비스 계정은 리소스의 ID 역할을 합니다.

리소스를 만들고 서비스 계정을 연결하려면 리소스를 만들 수 있는 권한과 리소스에 연결할 서비스 계정을 가장할 수 있는 권한이 필요합니다. iam.serviceAccounts.actAs 권한이 포함된 모든 역할에서 서비스 계정을 가장할 수 있는 권한을 제공합니다.

리소스를 만들고 서비스 계정을 여기에 연결한 후에는 리소스에서 장기 실행 작업을 시작할 수 있습니다. 작업은 리소스에 연결된 서비스 계정으로 실행되고 이 서비스 계정을 사용하여 Google Cloud API에 대한 요청을 승인합니다.

서비스 계정을 리소스에 연결하는 방법에 대한 자세한 내용은 리소스에 서비스 계정 연결을 참조하세요.

직접 서비스 계정 가장하기

권한:

  • 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 제공업체가 서명한 OpenID Connect(OIDC) 호환 JWT 토큰(accounts.google.com)을 생성할 수 있습니다.

조직에서 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시간까지 캐싱하여 현재 키 집합에 언제든지 액세스할 수 있도록 하는 것이 좋습니다.

  • 사용자 관리 키. 사용자가 이 키를 생성, 다운로드, 관리합니다. 서비스 계정에서 이 키를 삭제하면 인증에 사용할 수 없습니다.

사용자 관리 키의 경우 다음과 같은 키 관리 요구사항을 처리할 수 있는 프로세스가 있는지 확인해야 합니다.

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

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

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

키 보안을 강화하려면 다음 안내를 따르세요.

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

Compute Engine에서 서비스 계정 사용

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

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

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

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

권장사항

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

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

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

  • 서비스 계정의 표시 이름을 사용하여 서비스 계정을 추적합니다. 서비스 계정을 만들 때 서비스 계정의 목적을 나타내는 표시 이름을 입력하세요.

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

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

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

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

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