S3 バケットからイメージをプルする ECS 上の Flask アプリ

S3 バケットからイメージをプルする ECS 上の Flask アプリ

S3 バケットから画像を取得して表示する Flask アプリがあります。

資格情報部分をどのように実装すればよいでしょうか? つまり、次のようになります:

バケットからイメージを取得するには、AWS 認証情報を持つ boto3 を使用する必要がありますか?

AWS 認証情報なしで boto3 を使用して、ECS にロールをアタッチできますか? 認証情報なしでイメージをプルできるようになりますか?

現時点で私が実現したいのは、アプリを CodePipeline から ECS に配置し、イメージを s3 バケットに更新して、ECS 上の Flask アプリが s3 バケットの新しいイメージを表示することです。

資格情報などのベストプラクティスが何なのかわかりません。

答え1

常にIAMロールを使用する明示的なアクセス/シークレットキーを本番環境で使用しないでください。詳細については、EC2 インスタンスロールここ、同じことが当てはまるECS IAM ロール

ECS の場合は、次の操作を行う必要があります。

  1. IAMロールの作成s3:GetObjectS3 バケットからのアクセス権限を持ちます。
  2. 添付そのIAMロールをECSタスクに追加しますTaskRole
  3. EC2ベースのECSではなくECS Fargateを使用している場合は、ExecutionRoleこれにより、基本的に Fargate にタスクを起動する権限が付与されます。

CloudFormation テンプレートそれは次のようになります:

Parameters:
  S3BucketName:
    Type: String

Resources:
  TaskDefinition:
    Type: AWS::ECS::TaskDefinition
    Properties:
      NetworkMode: awsvpc
      TaskRoleArn: !Ref TaskRole
      ExecutionRoleArn: !Ref ExecutionRole
      RequiresCompatibilities:
      - FARGATE
      Cpu: ...
      Memory: ...
      ContainerDefinitions:
      - ...


  TaskRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Statement:
        - Effect: Allow
          Principal:
            Service: [ ecs-tasks.amazonaws.com ]
          Action:
          - sts:AssumeRole
      Path: /
      Policies:
      - PolicyName: TaskAccess
        PolicyDocument:
          Version: '2012-10-17'
          Statement:
          - Action:
            - s3:GetObject
            Effect: Allow
            Resource:
            - !Sub "arn:aws:s3:::${S3BucketName}/*"

  ExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Statement:
        - Effect: Allow
          Principal:
            Service: [ ecs-tasks.amazonaws.com ]
          Action: 
          - sts:AssumeRole
      Path: /
      ManagedPolicyArns:
      - arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy

しかし、多くの場合、意味がありませんダウンロード中 公開画像S3からFlaskウェブアプリに画像をアップロードする代わりに公共S3 に保存し、 を使用して HTML から直接参照します<img src="https://your-bucket-name.s3.amazonaws.com/whatever/image.jpg"/>

画像が非公開それでもFlaskにダウンロードするのではなく、代わりに作成する必要があります署名済みURLS3 内のファイルへの時間制限付きアクセスを提供します。ここでも、最初に S3 から Flask にファイルをダウンロードせずに、S3 の場所に直接リンクします。

お役に立てれば幸いです :)

関連情報