cloudydeno / deno-aws_api

From-scratch Typescript client for accessing AWS APIs
https://deno.land/x/aws_api
59 stars 3 forks source link

bug: AWS_PROFILE behavior broken #49

Open enote-kane opened 1 month ago

enote-kane commented 1 month ago

With the official AWS SDK, I can switch accounts/roles by defining profiles in ~/.aws/config. All these profiles may inherit from the same "credential" profile, specified through source_profile.

The Deno AWS API, however, only reads profiles from ~/.aws/credentials and doesn't seem to support role-arn or reading the config file at all.

Just ran into this:

error: Uncaught (in promise) Error: Failed to load any possible AWS credentials:
    - EnvironmentCredentials('AWS') Error: AWS environment variables not set
    - EnvironmentCredentials('AMAZON') Error: AMAZON environment variables not set
    - SharedIniFileCredentials() Error: Profile dev not found in credentials file
    - EcsTaskCredentials() Error: AWS_CONTAINER_CREDENTIALS_RELATIVE_URI not set
    - TokenFileWebIdentityCredentials() Error: No WebIdentityToken file path is set
    - EC2MetadataCredentials() Error: Instance Metadata Timeout: 1000ms
    return Promise.reject(new Error([
                          ^
    at CredentialsProviderChain.getCredentials (https://deno.land/x/aws_api@v0.8.1/client/credentials.ts:44:27)
    at eventLoopTick (ext:core/01_core.js:168:7)
    at async XmlServiceClient.signingFetcher [as signedFetcher] (https://deno.land/x/aws_api@v0.8.1/client/client.ts:89:29)
    at async XmlServiceClient.performRequest (https://deno.land/x/aws_api@v0.8.1/client/client.ts:179:22)
    at async S3.listObjectsV2 (https://aws-api.deno.dev/v0.4/services/s3.ts:1601:18)

An example:

~/.aws/credentials:

[default]
aws_access_key_id = ABCDEFG
aws_secret_access_key = abcdefg

~/.aws/config:

[profile dev]
region = eu-west-1
output = json
role_arn = arn:aws:iam::123456:role/abc
source_profile = default

[profile staging]
region = eu-west-1
output = json
role_arn = arn:aws:iam::654321:role/def
source_profile = default

Furthermore, the Deno AWS API implementation also violates the following:

Depending on the file, profile section names use the following format:

  • Config file: [default] [profile user1]
  • Credentials file: [default] [user1] Do not use the word profile when creating an entry in the credentials file.

Ref: https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html

danopia commented 1 month ago

First, to refresh on the coverage of my provided implementation, the README includes:

The following credential sources are supported:

  • Environment variables
  • Static credentials in ~/.aws/credentials
  • EKS Pod Identity (web identity token files)
  • ECS Task IAM roles
  • EC2 instance credentials

[...]

Multiple bits are missing:

  • AssumeRole credentials (#4)
  • [...]

It looks like you are looking to use an AssumeRole-based profile. Yes, this library currently lacks any support for the AWS config file, including profile chaining. (I should document this more clearly...)

This SharedIniFileCredentials implementation is the entirety of my AWS_PROFILE implementation and is clearly insufficient. TBH, CredentialsProvider is probably the wrong level of abstraction to implement ~/.aws/config. Perhaps profiles should be handled by ApiFactory instead.

Unfortunately, I have very little capacity for writing new code near-term due to summer plans. I suggest several options, maybe one can help you move forward:

  1. If you just want something that works in every scenario, you can try importing the real full-fat AWS SDK from NPM. It should work fine in modern Deno. I maintain this library as a lean Deno-native alternative.
  2. If you want to move forward with leveraging /x/aws_api in your app, you could implement a new CredentialsProvider which reads ~/.aws/config and supports assuming roles. You could then pass it to the ApiFactory and/or construct a customized CredentialsProviderChain including it. This might be upstreamable too.
  3. If you like /x/aws_api but want solid auth, you could import only npm:@aws-sdk/credential-providers and then wrap it with a CredentialsProvider interface for this library to use. This could be a helpful example to share.
  4. If this is a minor issue for you, you can hang in there with workarounds until I form a plan for how to properly integrate AWS_PROFILE logic 🤔 ⌛

Thanks for reaching out! I hope I can help with any further questions you may have.