서버리스에서 Cognito Identity Pool 설정하기

이전 섹션에서 Cognito Identity Pool을 사용하여 로그인한 사용자가 접근할 수 있는 AWS 리소스를 제어하는 방법을 살펴보았습니다. 또한 Cognito User Pool을 인증 프로바이더로 연결했습니다.

리소스 생성

Change indicator resources/cognito-identity-pool.yml에 다음 내용을 추가하세요.

Resources:
  # 사용자 풀과 인증할 연동된 아이덴티티
  CognitoIdentityPool:
    Type: AWS::Cognito::IdentityPool
    Properties:
      # 스테이지 기반으로 이름 생성
      IdentityPoolName: ${self:custom.stage}IdentityPool
      # 인증되지 않은 사용자 허용 안 함
      AllowUnauthenticatedIdentities: false
      # 사용자 풀에 연결
      CognitoIdentityProviders:
        - ClientId:
            Ref: CognitoUserPoolClient
          ProviderName:
            Fn::GetAtt: [ "CognitoUserPool", "ProviderName" ]
            
  # IAM 역할
  CognitoIdentityPoolRoles:
    Type: AWS::Cognito::IdentityPoolRoleAttachment
    Properties:
      IdentityPoolId:
        Ref: CognitoIdentityPool
      Roles:
        authenticated:
          Fn::GetAtt: [CognitoAuthRole, Arn]
          
  # 인증된 사용자를 위한 IAM 역할
  CognitoAuthRole:
    Type: AWS::IAM::Role
    Properties:
      Path: /
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: 'Allow'
            Principal:
              Federated: 'cognito-identity.amazonaws.com'
            Action:
              - 'sts:AssumeRoleWithWebIdentity'
            Condition:
              StringEquals:
                'cognito-identity.amazonaws.com:aud':
                  Ref: CognitoIdentityPool
              'ForAnyValue:StringLike':
                'cognito-identity.amazonaws.com:amr': authenticated
      Policies:
        - PolicyName: 'CognitoAuthorizedPolicy'
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: 'Allow'
                Action:
                  - 'mobileanalytics:PutEvents'
                  - 'cognito-sync:*'
                  - 'cognito-identity:*'
                Resource: '*'
              
              # 사용자가 API를 호출할 수 있도록 허용
              - Effect: 'Allow'
                Action:
                  - 'execute-api:Invoke'
                Resource:
                  Fn::Join:
                    - ''
                    -
                      - 'arn:aws:execute-api:'
                      - Ref: AWS::Region
                      - ':'
                      - Ref: AWS::AccountId
                      - ':'
                      - Ref: ApiGatewayRestApi
                      - '/*'
              
              # 사용자가 S3 버킷 내 자신의 폴더에 파일을 업로드할 수 있도록 허용
              - Effect: 'Allow'
                Action:
                  - 's3:*'
                Resource:
                  - Fn::Join:
                    - ''
                    -
                      - Fn::GetAtt: [AttachmentsBucket, Arn]
                      - '/private/'
                      - '$'
                      - '{cognito-identity.amazonaws.com:sub}/*'
  
# 생성된 Identity Pool ID 출력
Outputs:
  IdentityPoolId:
    Value:
      Ref: CognitoIdentityPool

이 설정이 복잡해 보이지만, Cognito Identity Pool 생성 챕터에서 다룬 내용과 거의 동일합니다. CloudFormation이 다소 장황할 수 있어서 조금 부담스러워 보일 수 있습니다.

이 설정의 각 부분을 간단히 살펴보겠습니다:

  1. 먼저 ${self:custom.stage}를 사용해 스테이지 이름을 기반으로 Identity Pool의 이름을 지정합니다.

  2. AllowUnauthenticatedIdentities: false를 추가해 로그인한 사용자만 허용하도록 설정합니다.

  3. 다음으로 사용자 풀을 아이덴티티 프로바이더로 사용하도록 지정합니다. 특히 Ref: CognitoUserPoolClient 라인을 사용해 이를 수행합니다. Serverless에서 Cognito 사용자 풀 구성 챕터를 다시 보면, 여기서 참조하는 CognitoUserPoolClient 아래의 블록을 확인할 수 있습니다.

  4. 그런 다음 인증된 사용자에게 IAM 역할을 연결합니다.

  5. 이 역할에 다양한 부분을 추가합니다. 이는 Cognito Identity Pool 생성 챕터에서 사용한 것과 정확히 동일합니다. CloudFormation에서 작동하도록 이 형식으로 작성해야 합니다.

  6. ApiGatewayRestApi 참조는 serverless.yml에서 API 엔드포인트를 정의할 때 Serverless Framework에 의해 생성됩니다. 따라서 여기서는 생성 중인 API 리소스를 참조합니다.

  7. S3 버킷의 이름은 AWS에서 생성됩니다. 따라서 이 경우 Fn::GetAtt: [AttachmentsBucket, Arn]을 사용해 정확한 이름을 가져옵니다.

  8. 마지막으로 Outputs: 블록에서 생성된 Identity Pool ID를 출력합니다.

리소스 추가하기

Change indicator serverless.yml에서 리소스를 참조해 보겠습니다. resources: 블록을 다음으로 교체하세요.

# 별도의 CloudFormation 템플릿으로 리소스 생성
resources:
  # DynamoDB
  - ${file(resources/dynamodb-table.yml)}
  # S3
  - ${file(resources/s3-bucket.yml)}
  # Cognito
  - ${file(resources/cognito-user-pool.yml)}
  - ${file(resources/cognito-identity-pool.yml)}

이제 새로운 서버리스 인프라를 배포할 준비가 거의 끝났습니다. 여기에 한 가지 리소스를 더 추가할 예정입니다. 이렇게 하면 프론트엔드에서 CORS 오류를 디버깅하기가 더 쉬워질 것입니다.