1

I have a flask app that I want to pull images to display from an s3 bucket.

How do I implement the credentials parts? what I mean is:

Do I use boto3 with aws credentials to pull the images from the bucket?

Can I use boto3 without the aws credentials and attach a role to the ECS? so it can pull the images without credentials?

At the moment what I want to achieve is to put the app in the CodePipeline to ECS and I want to update the images to the s3 bucket, so the flask app on ECS display the new images on s3 bucket.

I am confused as to what is a best practice for credentials etc.

1 Answer 1

1

Always use IAM Roles and never use any explicit access/secret keys in production. Read more about EC2 instance roles here, the same applies to ECS IAM Roles.

In your ECS case you should:

  1. Create IAM Role with permissions to s3:GetObject from the S3 bucket.
  2. Attach that IAM Role to your ECS Task as a TaskRole.
  3. If you are using ECS Fargate instead of EC2-based ECS you will also need an ExecutionRole that essentially gives Fargate the permissions to launch your task.

In CloudFormation template it would be something like this:

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

However there is often no point downloading public images from S3 to your Flask web app. Instead make the images public in S3 and refer directly to them from your HTML with <img src="https://your-bucket-name.s3.amazonaws.com/whatever/image.jpg"/>.

If the images are not public you still shouldn't download them to Flask and instead create pre-signed URLs that provide time-limited access to the files in S3. Again linking directly to the S3 location without downloading the files from S3 to Flask first.

Hope that helps :)

1
  • This is exactly what I was looking for, this is gold! Thank you very much for your time. Unfortunately I didn't go with that approach as the HTML code is complicated and assosiated with a jupyter notebook and it would be lot of trouble, I ended up pushing the new images I want to server in codecommit and from there to the pipeline Jan 28, 2020 at 8:46

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .