beeyev / thumbor-s3-docker

A docker image for thumbor with AWS S3 / Minio integration for cropping, resizing, applying filters and optimizing images on the fly.
MIT License
49 stars 10 forks source link

Enable Thumbor to access S3 resources using AWS Managed Policies #35

Closed tschaffter closed 1 month ago

tschaffter commented 1 month ago

Thank you for developing and maintaining this Thumbor Docker image! It's been a great help to us in our project, and we appreciate all the effort you've put into it.

We encountered an issue while attempting to provide the Docker container on AWS ECS access to an S3 bucket using an AWS managed policy instead of passing AWS credentials directly. When we try to access an image, Thumbor throws an InvalidAccessKeyId error. This happens when attempting to fetch an image from within the container.

Error Details:

2024-09-20 17:24:52 thumbor:ERROR ERROR: Traceback (most recent call last):
File "/usr/local/lib/python3.10/site-packages/thumbor/handlers/__init__.py", line 212, in get_image
    result = await self._fetch(self.context.request.image_url)
File "/usr/local/lib/python3.10/site-packages/thumbor/handlers/__init__.py", line 884, in _fetch
    loader_result = await self.context.modules.loader.load(
File "/usr/local/lib/python3.10/site-packages/thumbor_aws/loader.py", line 89, in load
    status_code, body, last_modified = await client.get_data(
File "/usr/local/lib/python3.10/site-packages/thumbor_aws/s3_client.py", line 143, in get_data
    response = await client.get_object(Bucket=bucket, Key=path)
File "/usr/local/lib/python3.10/site-packages/aiobotocore/client.py", line 371, in _make_api_call
    raise error_class(parsed_response, operation_name)
botocore.exceptions.ClientError: An error occurred (InvalidAccessKeyId) when calling the GetObject operation: The AWS Access Key Id you provided does not exist in our records.

Steps to Reproduce:

  1. Configure Thumbor to use an AWS managed policy for S3 access.
  2. Try to access an image hosted in the S3 bucket.
  3. Observe the InvalidAccessKeyId error in the logs.

Expected Behavior: Thumbor should successfully access the S3 bucket using the permissions granted by the managed policy, without the need for hardcoded AWS credentials.

Actual Behavior: Thumbor fails to access the S3 bucket and throws an InvalidAccessKeyId error.

Suggested Solution: It seems that Thumbor might not be properly configured to use IAM roles or managed policies. We suggest updating the Thumbor configuration to fully support AWS managed policies for S3 access. This could involve:

  1. Ensuring that the AWS SDK within Thumbor is correctly set up to use the IAM role or managed policy assigned to the ECS task/container.
  2. Verifying that Thumbor is not defaulting to looking for static credentials in the environment or configuration files.

Environment:

Additional Context: This issue prevents us from using the recommended security practices for AWS deployments, where sensitive credentials should not be hardcoded or passed explicitly.

We would appreciate any guidance on how to configure Thumbor to work with AWS managed policies, or if this could be implemented as a feature.

tschaffter commented 1 month ago

Similar issues submitted to other Thumbor Docker images:

tschaffter commented 1 month ago

I can successfully download an image in the S3 bucket with the AWS CLI from inside the Thumbor container. This command is run right after installing the AWS CLI client, without configuring any AWS profile or credentials thanks to the AWS managed policy that we have set in place:

/app # aws s3 cp s3://BUCKET_NAME/img/triforce.png triforce.png
download: s3://BUCKET_NAME/img/triforce.png to ./triforce.png
tschaffter commented 1 month ago

@beeyev There is one difference between the config example provided by thumbor_aws and the config file generated by the Docker image. The former uses None values while the latter specifies 'None'.

thumbor_aws uses None: https://github.com/thumbor/thumbor-aws/tree/main?tab=readme-ov-file#loader

This image generates a config file that includes 'None': from the actual config file inside the container: /usr/local/etc/thumbor.conf:

## Secret access key for S3 Loader.
## Defaults to: None
AWS_LOADER_S3_SECRET_ACCESS_KEY = 'None'

## Access key ID for S3 Loader.
## Defaults to: None
AWS_LOADER_S3_ACCESS_KEY_ID = 'None'

I think that thumbor_aws evaluates the value as the string "None" and not as the None value.

beeyev commented 1 month ago

Thank you, I will check it!

tschaffter commented 1 month ago

I can now confirm that specifying None instead of 'None' solved the issue.

beeyev commented 1 month ago

@tschaffter I built a new test docker image with possible fix ghcr.io/beeyev/thumbor-s3:debian-test could you please check if it works?

tschaffter commented 1 month ago

I will give it a try today. Thanks!

tschaffter commented 1 month ago

@beeyev I get this error when stepping into the container and fetching an image with wget.

Event Time Message
2024-09-30T16:04:34.403Z 2024-09-30 16:04:34 thumbor:ERROR ERROR: Traceback (most recent call last):
2024-09-30T16:04:34.403Z File "/usr/local/lib/python3.12/site-packages/thumbor/handlers/init.py", line 214, in get_image
2024-09-30T16:04:34.403Z result = await self._fetch(self.context.request.image_url)
2024-09-30T16:04:34.403Z ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2024-09-30T16:04:34.403Z File "/usr/local/lib/python3.12/site-packages/thumbor/handlers/init.py", line 916, in _fetch
2024-09-30T16:04:34.403Z loader_result = await self.context.modules.loader.load(
2024-09-30T16:04:34.403Z ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2024-09-30T16:04:34.403Z File "/usr/local/lib/python3.12/site-packages/thumbor_aws/loader.py", line 89, in load
2024-09-30T16:04:34.403Z status_code, body, last_modified = await client.get_data(
2024-09-30T16:04:34.403Z ^^^^^^^^^^^^^^^^^^^^^^
2024-09-30T16:04:34.403Z File "/usr/local/lib/python3.12/site-packages/thumbor_aws/s3_client.py", line 141, in get_data
2024-09-30T16:04:34.403Z async with self.get_client() as client:
2024-09-30T16:04:34.403Z ^^^^^^^^^^^^^^^^^
2024-09-30T16:04:34.403Z File "/usr/local/lib/python3.12/site-packages/thumbor_aws/s3_client.py", line 95, in get_client
2024-09-30T16:04:34.403Z region_name=self.region_name,
2024-09-30T16:04:34.403Z ^^^^^^^^^^^^^^^^
2024-09-30T16:04:34.403Z File "/usr/local/lib/python3.12/site-packages/thumbor_aws/s3_client.py", line 46, in region_name
2024-09-30T16:04:34.403Z "region_name", self.config.AWS_STORAGE_REGION_NAME
2024-09-30T16:04:34.403Z ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2024-09-30T16:04:34.403Z File "/usr/local/lib/python3.12/site-packages/derpconf/config.py", line 225, in getattr
2024-09-30T16:04:34.403Z raise AttributeError(name)
2024-09-30T16:04:34.403Z AttributeError: AWS_STORAGE_REGION_NAME. Did you mean: 'AWS_LOADER_REGION_NAME'?
2024-09-30T16:04:34.403Z 2024-09-30 16:04:34 thumbor:ERROR [BaseHandler] get_image failed for url triforce.png. error: AWS_STORAGE_REGION_NAME
2024-09-30T16:04:34.403Z 2024-09-30 16:04:34 tornado.access:ERROR 500 GET /unsafe/600x600/triforce.png (127.0.0.1) 4.49ms

I do not specify the environment variable AWS_STORAGE_REGION_NAME when starting the container.

# echo $AWS_STORAGE_REGION_NAME

This Key-Value is not specified in the config file because this PR only prints some KVs if their key is specified.

$ cat /usr/local/etc/thumbor.conf
...

################################# AWS Storage ##################################
# Documentation: https://github.com/thumbor/thumbor-aws#storage

## Region where thumbor's objects are going to be stored.
## Defaults to: 'us-east-1'

## S3 Bucket where thumbor's objects are going to be stored.
## Defaults to: 'thumbor'
beeyev commented 1 month ago

What configuration do you use? Can you provide the values please

tschaffter commented 1 month ago

Here are the environment variables passed to the Thumbor container deployed with AWS CDK (dev deployment):

thumbor_props = ServiceProps(
    "openchallenges-thumbor",
    8889,
    512,
    "ghcr.io/beeyev/thumbor-s3:debian-test",
    {
        "LOG_LEVEL": "info",
        "PORT": "8889",
        "LOADER": "thumbor_aws.loader",
        "AWS_LOADER_REGION_NAME": "us-east-1",
        "AWS_LOADER_BUCKET_NAME": bucket_stack.openchallenges_img_bucket.bucket_name,
        "AWS_LOADER_S3_ENDPOINT_URL": "http://s3.us-east-1.amazonaws.com",
        "AWS_LOADER_ROOT_PATH": "img",
        "STORAGE": "thumbor.storages.file_storage",
        "FILE_STORAGE_ROOT_PATH": "/data/storage",
        "RESULT_STORAGE": "thumbor.result_storages.file_storage",
        "RESULT_STORAGE_FILE_STORAGE_ROOT_PATH": "/data/result_storage",
        "RESULT_STORAGE_STORES_UNSAFE": "True",
        "RESULT_STORAGE_EXPIRATION_SECONDS": "2629746",
        "SECURITY_KEY": secrets["SECURITY_KEY"],
        "ALLOW_UNSAFE_URL": "True",
        "QUALITY": "100",
        "MAX_AGE": "86400",
        "AUTO_PNG_TO_JPG": "True",
        "HTTP_LOADER_VALIDATE_CERTS": "False",
    },
)
beeyev commented 1 month ago

@tschaffter I just updated the docker image ghcr.io/beeyev/thumbor-s3:debian-test Could you please pull the update and try again?

tschaffter commented 1 month ago

@beeyev The latest image works!

beeyev commented 1 month ago

Amazing! I will prepare the new release tomorrow

tschaffter commented 1 month ago

Thanks so much for fixing that so quickly.

beeyev commented 1 month ago

@tschaffter I updated the docker image with the fix. Thank you for your help solving this issue 👍

tschaffter commented 1 month ago

@beeyev Could you please update the image beeyev/thumbor-s3:7.7-alpine too (last updated 10 months ago)? I need SVG to PNG conversion, which is not available in the slim version.

https://hub.docker.com/r/beeyev/thumbor-s3/tags https://github.com/beeyev/thumbor-s3-docker/pkgs/container/thumbor-s3

beeyev commented 1 month ago

@tschaffter I deprecated this image, because full-featured thumbor instance can't work stable on alpine linux. You need to use debian if you want all features, or you can use slim-alpine if you are fine with the basic functionality.

beeyev/thumbor-s3:debian
beeyev/thumbor-s3:slim-alpine
beeyev/thumbor-s3:7-debian
beeyev/thumbor-s3:7-slim-alpine
beeyev/thumbor-s3:7.7-debian
beeyev/thumbor-s3:7.7-slim-alpine

image