AWS에서 리소스 액세스

이 문서에서는 ID 제휴를 통해 Amazon Web Services(AWS)에서 Google Cloud 리소스에 액세스하는 방법을 설명합니다.

일반적으로 Google Cloud 외부에서 실행되는 애플리케이션이 Google Cloud 리소스에 액세스하려면 서비스 계정 키를 사용합니다. ID 제휴를 사용하면 AWS 사용자 또는 역할이 서비스 계정을 가장하도록 허용할 수 있습니다. 이를 통해 워크로드가 단기 액세스 토큰을 사용하여 Google Cloud 리소스에 직접 액세스할 수 있으며 서비스 계정 키와 관련된 유지보수 및 보안 부담이 사라집니다.

시작하기 전에

  1. 워크로드 아이덴티티 풀 관리자 역할(roles/iam.workloadIdentityPoolAdmin)이 있는지 확인합니다.

    또는 IAM 소유자(roles/owner) 및 편집자(roles/editor) 기본 역할에는 ID 제휴를 구성하는 권한도 포함됩니다. 프로덕션 환경에서는 기본 역할을 부여하지 말아야 하지만 개발 환경 또는 테스트 환경에서는 부여해도 됩니다.

  2. AWS 역할을 만들고 Amazon 리소스 이름(ARN)을 기록합니다.

  3. Google Cloud 서비스 계정을 만듭니다.

  4. 워크로드에 필요한 Google Cloud API를 호출할 수 있는 액세스 권한을 서비스 계정에 부여합니다.

워크로드 아이덴티티 풀 만들기

워크로드 아이덴티티 풀은 외부 ID 컬렉션의 컨테이너입니다. 워크로드 아이덴티티 풀은 서로 분리되어 있지만 풀 하나가 수에 상관없이 서비스 계정을 가장할 수 있습니다. 일반적으로 개발, 스테이징 또는 프로덕션과 같은 환경마다 새로운 풀을 만드는 것이 좋습니다. 이렇게 하면 일반적으로 AWS 계정마다 풀이 하나씩 생성됩니다.

새 워크로드 아이덴티티 풀을 만들려면 ID를 제공해야 합니다. 원하는 경우 설명표시 이름을 제공할 수도 있습니다.

gcloud

gcloud beta iam workload-identity-pools create 명령어를 실행하여 워크로드 아이덴티티 풀을 만듭니다.

gcloud beta iam workload-identity-pools create pool-id \
    --location="global" \
    --description="description" \
    --display-name="display-name"

응답은 다음과 같습니다.

Created WorkloadIdentityPool [pool-id].

REST

projects.locations.workloadIdentityPools.create 메서드는 워크로드 아이덴티티 풀을 만듭니다.

HTTP 메서드 및 URL:

POST https://iam.googleapis.com/v1beta/projects/project-id/locations/global/workloadIdentityPools?workloadIdentityPoolId=pool-id

JSON 요청 본문:

{
  "description": "description",
  "display-name": "display-name"
}

요청을 보내려면 다음 옵션 중 하나를 펼칩니다.

이 메서드는 다음과 비슷한 장기 실행 Operation을 반환합니다.

{
  "name": "projects/project-number/locations/global/workloadIdentityPools/pool-id/operations/operation-id"
}

AWS를 ID 공급업체로 추가

AWS를 워크로드 아이덴티티 풀의 ID 공급업체로 구성하려면 최소한 다음 정보를 제공합니다.

  • 제공업체의 ID

  • 이 문서의 이전 섹션에서 가져온 워크로드 아이덴티티 풀 ID

  • AWS 계정 ID

또한 몇 가지 선택적 매개변수를 제공할 수도 있습니다.

  • 표시 이름설명

  • AWS 토큰의 속성을 Google 토큰의 속성에 매핑하는 속성 매핑 목록. 기본적으로 각 풀은 가장 일반적인 시나리오에 대비하여 다음과 같은 속성 매핑을 사용합니다.

    Google AWS 설명
    google.subject assertion.arn IAM이 인증하는 주 구성원입니다. 이는 Cloud Logging 로그 항목에 표시되는 제목이기도 합니다. 이 매핑은 arn:aws:sts::account-id:assumed-role/aws-role/aws-session-name 형식을 사용하여 ARN으로 자동 채워집니다.
    attribute.aws_role AWS 역할 arn:aws:sts::account-id:assumed-role/aws-role 형식을 사용하는 AWS 역할입니다.

    또한 IAM 역할 결합에서 참조할 수 있는 커스텀 매핑을 지정할 수 있습니다. assertion을 사용하여 AWS 사용자 인증 정보를 나타내고 Google 속성에는 google을, 커스텀 속성에는 attribute를 사용합니다. 예를 들어 다음은 google.subject에 대한 기본 매핑 외에 attribute.aws_accountassertion.account에 매핑합니다.

    google.subject=assertion.arn,
    attribute.aws_account=assertion.account
    

    참조할 수 있는 AWS 토큰의 속성 목록은 GetCallerIdentity() 문서를 참조하세요. AWS 문서의 속성은 카멜 표기법을 사용하지만 속성 매핑은 소문자를 사용합니다. 예를 들어 Accountassertion.account가 됩니다.

    좀 더 복잡한 어설션의 경우 Common Expression Language를 사용하면 됩니다. 예를 들면 다음과 같습니다.

    attribute.environment=assertion.arn.contains(":instance-profile/Production") ? "prod" : "test"
    

    표현식의 속성 특정 부분을 참조하려면 제공된 템플릿에 따라 속성에서 값을 추출하는 CEL extract() 함수를 사용합니다. extract()에 대한 자세한 내용은 속성에서 값 추출을 참조하세요.

    사용자 인증 정보에 속성이 포함되어 있는지 확인하려면 has() 함수를 사용합니다.

  • 주 구성원이 있어야 하는 속성을 지정하는 속성 조건. 이 조건은 외부 및 Google 사용자 인증 정보에 적용될 수 있습니다. 조건을 충족하지 않는 요청은 거부됩니다.

    속성 조건 형식은 부울을 반환하는 CEL 표현식으로 지정됩니다. 예를 들어 다음은 특정 AWS 역할이 없는 ID의 요청을 거부합니다.

    attribute.aws_role == "role-mapping"
    

    속성 조건의 일반적인 사용 사례에 대한 자세한 내용은 워크로드 아이덴티티 제휴 개요를 참조하세요.

다음 예시는 AWS를 ID 공급업체로 추가하는 방법을 보여줍니다.

gcloud

gcloud beta iam workload-identity-pools providers create-aws 명령어를 실행하여 AWS를 ID 공급업체로 추가합니다.

gcloud beta iam workload-identity-pools providers create-aws provider-id \
    --workload-identity-pool="pool-id"
    --account-id="aws-account-id"
    --location="global"

응답은 다음과 같습니다.

Created WorkloadIdentityPoolProvider [provider-id].

REST

projects.locations.workloadIdentityPools.providers.create 메서드는 AWS를 공급업체로 추가합니다.

HTTP 메서드 및 URL:

POST https://iam.googleapis.com/v1beta/projects/project-id/locations/global/workloadIdentityPools/pool-id/providers?workloadIdentityPoolProviderId=provider-id

JSON 요청 본문:

{
  "aws": {
    "accountId": "aws-account-id"
  }
}

요청을 보내려면 다음 옵션 중 하나를 펼칩니다.

이 메서드는 다음과 비슷한 장기 실행 Operation을 반환합니다.

{
  "name": "projects/project-number/locations/global/workloadIdentityPools/pool-id/providers/provider-id/operations/operation-id"
}

서비스 계정을 가장할 수 있는 권한 부여

외부 ID는 대부분의 Google Cloud 리소스에 직접 액세스할 수 없습니다. 대신 워크로드 아이덴티티가 사용자 역할(roles/iam.workloadIdentityUser)을 부여하여 서비스 계정을 가장하도록 허용할 수 있습니다.

AWS 역할에 이러한 역할 binding을 추가하려면 다음 형식을 사용합니다.

attribute.aws_role/arn:aws:sts::aws-account-id:assumed-role/aws-role-name

예를 들면 다음과 같습니다.

gcloud iam service-accounts add-iam-policy-binding service-account-email \
    --role roles/iam.workloadIdentityUser \
    --member "principalSet://iam.googleapis.com/projects/project-number/locations/global/workloadIdentityPools/pool-id/attribute.aws_role/arn:aws:sts::aws-account-id:assumed-role/aws-role-name"

AWS 사용자에 이 binding을 추가하려면 다음 형식을 사용합니다.

subject/arn:aws:sts::aws-account-id:assumed-role/aws-role-name/aws-session-name

AWS ARN에서 AWS 역할 세션을 추출하는 방법에 대한 자세한 내용은 IAM 식별자의 AWS 문서를 참조하세요.

다음 예시는 AWS 사용자에 binding을 추가하는 방법을 보여줍니다.

gcloud iam service-accounts add-iam-policy-binding service-account-email \
    --role roles/iam.workloadIdentityUser \
    --member "principal://iam.googleapis.com/projects/project-number/locations/global/workloadIdentityPools/pool-id/subject/arn:aws:sts::aws-account-id:assumed-role/aws-role-name/aws-session-name

커스텀 속성에 따라 액세스 권한을 부여할 수도 있습니다. 예를 들면 다음과 같습니다.

gcloud iam service-accounts add-iam-policy-binding service-account-email \
    --role="roles/iam.workloadIdentityUser" \
    --member="principalSet://iam.googleapis.com/projects/project-number/locations/global/workloadIdentityPools/pool-id/attribute.custom-attribute/arn:aws:sts::aws-account-id:aws-role-name"

액세스 권한을 취소하려면 add-iam-policy-bindingremove-iam-policy-binding으로 바꿉니다.

REST API나 클라이언트 라이브러리를 사용하여 binding을 추가하거나 취소할 수도 있습니다. 자세한 내용은 리소스에 대한 액세스 권한 부여, 변경, 취소를 참조하세요.

AWS 토큰을 Google 토큰으로 교환

AWS 역할이나 사용자가 서비스 계정을 가장할 수 있으면 개발자는 AWS 사용자 인증 정보를 Google 사용자 인증 정보로 교환할 수 있습니다. 교환 과정의 일환으로 AWS GetCallerIdentity() 메서드에 대한 직렬화된 버전의 요청을 보안 토큰 서비스에 전달합니다. 이렇게 하면 Google Cloud가 AWS 주 구성원의 ID를 확인하고 서비스 계정을 가장할 수 있는 권한이 있는지 확인할 수 있습니다.

사용자 인증 정보를 교환하려면 다음 안내를 따르세요.

  1. 임시 AWS 사용자 인증 정보를 가져옵니다.

  2. 서명 버전 4를 사용하여 AWS GetCallerIdentity() 메서드에 대한 직렬화된 서명된 요청을 만듭니다.

    요청에는 다음 필드가 포함됩니다.

    • url: ‌GetCallerIdentity()를 위한 AWS STS 엔드포인트의 URL입니다(예: ‌https://sts.amazonaws.com?Action=GetCallerIdentity&Version=2011-06-15). 리전 엔드포인트도 지원됩니다.
    • method: HTTP 요청 메서드: POST
    • headers: 다음을 포함하는 HTTP 요청 헤더입니다.
      • Authorization: 요청 서명입니다.
      • host: url 필드의 호스트 이름입니다(예: sts.amazonaws.com).
      • x-amz-date: 요청을 보내는 시간으로, ISO 8601 Basic 문자열로 형식이 지정됩니다. 일반적으로 현재 시간으로 설정되며 재생 공격을 방지하는 데 사용됩니다.
      • x-goog-cloud-target-resource: ID 공급업체의 전체 리소스 이름입니다. 예를 들면 다음과 같습니다.
        //iam.googleapis.com/projects/project-number/locations/global/workloadIdentityPools/pool-id/providers/provider-id
        

    요청은 다음과 비슷합니다.

    {
      "url": "https://sts.amazonaws.com?Action=GetCallerIdentity&Version=2011-06-15",
      "method": "POST",
      "headers": [
        {
          "key": "Authorization",
          "value" : "AWS4-HMAC-SHA256 Credential=AKIASOZTBDV4D7ABCDEDF/20200228/us-east-1/sts/aws4_request, SignedHeaders=host;x-amz-date,Signature=abcedefdfedfd"
        },
        {
          "key": "host",
          "value": "sts.amazonaws.com"
        },
        {
          "key": "x-amz-date",
          "value": "20200228T225005Z"
        },
        {
          "key": "x-goog-cloud-target-resource",
          "value": "//iam.googleapis.com/projects/12345678/locations/global/workloadIdentityPools/my-pool/providers/my-aws-provider"
        }
      ]
    }
    
  3. 직렬화된 요청을 보안 토큰 서비스 token() 메서드에 전달하여 AWS 사용자 인증 정보를 제휴 액세스 토큰으로 교환합니다.

    REST

    token 메서드는 타사 토큰을 Google 토큰으로 교환합니다.

    아래의 요청 데이터를 사용하기 전에 다음을 바꿉니다.

    • project-number: Google Cloud 프로젝트 번호입니다.
    • pool-id: 이 가이드의 앞부분에서 만든 워크로드 아이덴티티 풀의 ID입니다.
    • provider-id: 이 가이드의 앞부분에서 구성한 AWS ID 공급업체의 ID입니다.
    • aws-request: GetCallerIdentity()에 대한 직렬화된 서명된 요청이며 URL 이스케이프 처리된 JSON 형식입니다.

    HTTP 메서드 및 URL:

    POST https://sts.googleapis.com/v1beta/token

    JSON 요청 본문:

    {
      "audience": "//iam.googleapis.com/projects/project-number/locations/global/workloadIdentityPools/pool-id/providers/provider-id",
      "grantType": "urn:ietf:params:oauth:grant-type:token-exchange",
      "requestedTokenType": "urn:ietf:params:oauth:token-type:access_token",
      "scope": "https://www.googleapis.com/auth/cloud-platform",
      "subjectTokenType": "urn:ietf:params:aws:token-type:aws4_request",
      "subjectToken": "aws-request"
    }
    

    요청을 보내려면 다음 옵션 중 하나를 펼칩니다.

     

    이 메서드는 제휴 토큰을 반환합니다.

  4. generateAccessToken()을 호출하여 제휴 토큰과 서비스 계정 액세스 토큰을 교환합니다. 제휴 토큰은 일부 Google Cloud APIs만 지원하지만 서비스 계정 액세스 토큰은 모든 Google Cloud APIs가 지원합니다.

    REST

    Service Account Credentials API의 serviceAccounts.generateAccessToken 메서드는 서비스 계정의 OAuth 2.0 액세스 토큰을 생성합니다.

    아래의 요청 데이터를 사용하기 전에 다음을 바꿉니다.

    • project-id: Google Cloud 프로젝트 ID
    • sa-id: 서비스 계정의 ID. sa-name@project-id.iam.gserviceaccount.com 형식의 서비스 계정 이메일 주소이거나 서비스 계정의 고유 숫자 ID일 수 있습니다.
    • token: 제휴 액세스 토큰입니다.

    HTTP 메서드 및 URL:

    POST https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/sa-name@project-id.iam.gserviceaccount.com:generateAccessToken

    JSON 요청 본문:

    {
      "scope": [
        "https://www.googleapis.com/auth/cloud-platform"
      ]
    }
    

    요청을 보내려면 다음 옵션 중 하나를 펼칩니다.

    generateAccessToken 요청이 성공하면 응답 본문에 OAuth 2.0 액세스 토큰과 만료 시간이 포함됩니다. 이후 accessTokenexpireTime에 도달할 때까지 서비스 계정 대신 요청을 인증하는 데 사용할 수 있습니다.

    {
      "accessToken": "eyJ0eXAi...NiJ9",
      "expireTime": "2020-04-07T15:01:23.045123456Z"
    }
    

서비스 계정에 대한 액세스 토큰이 있으면 이 토큰을 통해 요청의 Authorization 헤더에 토큰을 포함하여 Google Cloud APIs를 호출할 수 있습니다.

Authorization: Bearer access-token

요청이 서비스 계정으로 승인됩니다.

다음 단계