Skip to content

Cannot use AWS_ROLE_ARN and AWS_WEB_IDENTITY_TOKEN_FILE for S3 Credentials #10473

@aguynamedjoetoo

Description

@aguynamedjoetoo

Bug report

Describe the bug

When using an IAM role with strapi for the AWS upload plugin, permission is denied when attempting to configure the credentials.

Specifically, in this instance, I am using an IAM role within a pod in kubernetes using IAM Roles for Service Accounts. This automatically injects two env vars: AWS_WEB_IDENTITY_TOKEN_FILE and AWS_ROLE_ARN. I have confirmed for sure these two values exist, additionally I have verified I can perform actions against the named S3 bucket using the AWS cli within the same pod with no issue (or additional configuration needed).

This is using strapi 3.6.1 and strapi-provider-upload-aws-s3 v3.6.3

Steps to reproduce the behavior

  1. Configure an IAM role within a kubernetes pod (Realistically, an EC2 instance with an instance profile should provide a similar interface)
  2. Configure the s3 plugin with a configuration similar to (Note: I've also confirmed S3_ASSETS_BUCKET is the proper value):
var AWS = require('aws-sdk');

module.exports = ({ env }) => ({
  upload: {
    provider: 'aws-s3',
    providerOptions: {
      credentials: new AWS.TokenFileWebIdentityCredentials(),
      region: env('AWS_REGION') || 'us-west-2',
      params: {
        Bucket: env('S3_ASSETS_BUCKET'),
      },
    },
  },
});
  1. Attempt to upload an asset in the strapi admin UI
  2. Observe an error in the strapi logs similar to:
[2021-06-11T18:52:13.763Z] [2021-06-11t18:52:13.761z] error AccessDenied: Access Denied
    at Request.extractError (/srv/app/node_modules/strapi-provider-upload-aws-s3/node_modules/aws-sdk/lib/services/s3.js:718:35)
    at Request.callListeners (/srv/app/node_modules/strapi-provider-upload-aws-s3/node_modules/aws-sdk/lib/sequential_executor.js:106:20)
    at Request.emit (/srv/app/node_modules/strapi-provider-upload-aws-s3/node_modules/aws-sdk/lib/sequential_executor.js:78:10)
    at Request.emit (/srv/app/node_modules/strapi-provider-upload-aws-s3/node_modules/aws-sdk/lib/request.js:688:14)
    at Request.transition (/srv/app/node_modules/strapi-provider-upload-aws-s3/node_modules/aws-sdk/lib/request.js:22:10)
    at AcceptorStateMachine.runTo (/srv/app/node_modules/strapi-provider-upload-aws-s3/node_modules/aws-sdk/lib/state_machine.js:14:12)
    at /srv/app/node_modules/strapi-provider-upload-aws-s3/node_modules/aws-sdk/lib/state_machine.js:26:10
    at Request.<anonymous> (/srv/app/node_modules/strapi-provider-upload-aws-s3/node_modules/aws-sdk/lib/request.js:38:9)
    at Request.<anonymous> (/srv/app/node_modules/strapi-provider-upload-aws-s3/node_modules/aws-sdk/lib/request.js:690:12)
    at Request.callListeners (/srv/app/node_modules/strapi-provider-upload-aws-s3/node_modules/aws-sdk/lib/sequential_executor.js:116:18)
    at Request.emit (/srv/app/node_modules/strapi-provider-upload-aws-s3/node_modules/aws-sdk/lib/sequential_executor.js:78:10)
    at Request.emit (/srv/app/node_modules/strapi-provider-upload-aws-s3/node_modules/aws-sdk/lib/request.js:688:14)
    at Request.transition (/srv/app/node_modules/strapi-provider-upload-aws-s3/node_modules/aws-sdk/lib/request.js:22:10)
    at AcceptorStateMachine.runTo (/srv/app/node_modules/strapi-provider-upload-aws-s3/node_modules/aws-sdk/lib/state_machine.js:14:12)
    at /srv/app/node_modules/strapi-provider-upload-aws-s3/node_modules/aws-sdk/lib/state_machine.js:26:10
    at Request.<anonymous> (/srv/app/node_modules/strapi-provider-upload-aws-s3/node_modules/aws-sdk/lib/request.js:38:9)
[2021-06-11T18:52:13.764Z] error Error: Internal Server Error
    at convertToStrapiError (/srv/app/node_modules/strapi-plugin-upload/errors.js:38:26)
    at Object.upload (/srv/app/node_modules/strapi-plugin-upload/config/functions/bootstrap.js:35:11)
    at processTicksAndRejections (internal/process/task_queues.js:93:5)
    at async Object.uploadFileAndPersist (/srv/app/node_modules/strapi-plugin-upload/services/Upload.js:154:5)
    at async Promise.all (index 0)
    at async Object.upload (/srv/app/node_modules/strapi-plugin-upload/services/Upload.js:140:12)
    at async uploadFiles (/srv/app/node_modules/strapi-plugin-upload/controllers/upload/admin.js:187:27)
    at async Object.upload (/srv/app/node_modules/strapi-plugin-upload/controllers/Upload.js:65:5)
    at async /srv/app/node_modules/strapi/lib/middlewares/router/utils/routerChecker.js:79:22
    at async /srv/app/node_modules/strapi-utils/lib/policy.js:68:5
    at async /srv/app/node_modules/strapi/lib/middlewares/parser/index.js:48:23
    at async /srv/app/node_modules/strapi/lib/middlewares/xss/index.js:26:9

Expected behavior

Assets are uploaded using the IAM role to the S3 bucket configured.

Screenshots

image

Code snippets

Our plugin config:

var AWS = require('aws-sdk');

module.exports = ({ env }) => ({
  upload: {
    provider: 'aws-s3',
    providerOptions: {
      credentials: new AWS.TokenFileWebIdentityCredentials(),
      region: env('AWS_REGION') || 'us-west-2',
      params: {
        Bucket: env('S3_ASSETS_BUCKET'),
      },
    },
  },
});

System

  • Node.js version: v14.15.3 (Based on strapi-base image)
  • NPM version: 6.14.9
  • Strapi version: 3.6.1
  • Database: Postgres
  • Operating system: Debian 9 (Based on strapi-base image)

Additional context

The AWS Node SDK seems to indicate these vars should be read in by virtue of using AWS.TokenFileWebIdentityCredentials(): https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/TokenFileWebIdentityCredentials.html

This class will read filename from AWS_WEB_IDENTITY_TOKEN_FILE environment variable or web_identity_token_file shared config variable, and get the OIDC token from filename. It will also read IAM role to be assumed from AWS_ROLE_ARN environment variable or role_arn shared config variable. This provider gets credetials using the AWS.STS.assumeRoleWithWebIdentity() service operation

For fun and profit, I also tried switching the credentials line to:

      credentialProvider: new AWS.TokenFileWebIdentityCredentials(),

That threw an even more ... interesting... error haha:

[2021-06-11T19:07:58.015Z] error TypeError: self.credentialProvider.resolve is not a function
    at Config.getCredentials (/srv/app/node_modules/strapi-provider-upload-aws-s3/node_modules/aws-sdk/lib/config.js:423:31)
    at Request.VALIDATE_CREDENTIALS (/srv/app/node_modules/strapi-provider-upload-aws-s3/node_modules/aws-sdk/lib/event_listeners.js:81:26)
    at Request.callListeners (/srv/app/node_modules/strapi-provider-upload-aws-s3/node_modules/aws-sdk/lib/sequential_executor.js:102:18)
    at Request.emit (/srv/app/node_modules/strapi-provider-upload-aws-s3/node_modules/aws-sdk/lib/sequential_executor.js:78:10)
    at Request.emit (/srv/app/node_modules/strapi-provider-upload-aws-s3/node_modules/aws-sdk/lib/request.js:688:14)
    at Request.transition (/srv/app/node_modules/strapi-provider-upload-aws-s3/node_modules/aws-sdk/lib/request.js:22:10)
    at AcceptorStateMachine.runTo (/srv/app/node_modules/strapi-provider-upload-aws-s3/node_modules/aws-sdk/lib/state_machine.js:14:12)
    at Request.runTo (/srv/app/node_modules/strapi-provider-upload-aws-s3/node_modules/aws-sdk/lib/request.js:408:15)
    at Request.send (/srv/app/node_modules/strapi-provider-upload-aws-s3/node_modules/aws-sdk/lib/request.js:372:10)
    at ManagedUpload.nextChunk (/srv/app/node_modules/strapi-provider-upload-aws-s3/node_modules/aws-sdk/lib/s3/managed_upload.js:487:51)
    at ManagedUpload.fillBuffer (/srv/app/node_modules/strapi-provider-upload-aws-s3/node_modules/aws-sdk/lib/s3/managed_upload.js:417:12)
    at ManagedUpload.send (/srv/app/node_modules/strapi-provider-upload-aws-s3/node_modules/aws-sdk/lib/s3/managed_upload.js:201:33)
    at features.constructor.upload (/srv/app/node_modules/strapi-provider-upload-aws-s3/node_modules/aws-sdk/lib/services/s3.js:1292:50)
    at /srv/app/node_modules/strapi-provider-upload-aws-s3/lib/index.js:24:14
    at new Promise (<anonymous>)
    at Object.upload (/srv/app/node_modules/strapi-provider-upload-aws-s3/lib/index.js:21:16)
[2021-06-11T19:07:58.016Z] error Error: Internal Server Error
    at convertToStrapiError (/srv/app/node_modules/strapi-plugin-upload/errors.js:38:26)
    at Object.upload (/srv/app/node_modules/strapi-plugin-upload/config/functions/bootstrap.js:35:11)
    at async Object.uploadFileAndPersist (/srv/app/node_modules/strapi-plugin-upload/services/Upload.js:154:5)

Metadata

Metadata

Assignees

No one assigned

    Labels

    issue: enhancementIssue suggesting an enhancement to an existing featuresource: core:uploadSource is core/upload package

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions