10

My question is the same as this other question: How to run AWS SDK with credentials from variables? but I am using SDK version 2 which no longer uses Session (if I understand correctly).

So, I am creating a new client, and I have the credentials as variables. I need to use the IAM service. Here is the function:

func getIAMClient(ctx context.Context) (*iam.Client, error) {
    cfg, err := config.LoadDefaultConfig(ctx, config.WithRegion("no-region"))
    if err != nil {
        return nil, errors.Wrap(err)
    }

    cfg.HTTPClient, err = getHTTPClient(ctx)
    if err != nil {
        return nil, err
    }

    return iam.NewFromConfig(cfg), nil
}

Different users will use the app at the same time, so I can't just use ENV files, but I haven't been able to find a documentation page explaining how to pass these credentials to my Client. Any support will be appreciated!

blackgreen
  • 34,072
  • 23
  • 111
  • 129
Camilo Urán
  • 387
  • 4
  • 12

2 Answers2

7

This can be achieved with the StaticCredentialsProvider as described in section "Static Credentials" of the AWS SDK for Go V2 documentation:

cfg, err := config.LoadDefaultConfig(ctx, config.WithCredentialsProvider(credentials.NewStaticCredentialsProvider("AKID", "SECRET_KEY", "TOKEN")))
Gregor Zurowski
  • 2,222
  • 2
  • 9
  • 15
3

To init configs from runtime variables, it's fine to use credentials.NewStaticCredentialsProvider:

staticProvider := credentials.NewStaticCredentialsProvider(
    accessKey, 
    secretKey, 
    sessionToken,
)
cfg, err := config.LoadDefaultConfig(
    context.Background(), 
    config.WithCredentialsProvider(staticProvider),
)
if err != nil {
    return nil, err
}
client := iam.New(cfg)

However the AWS SDK documentation correctly reminds you that:

Do not embed credentials inside an application. Use this method only for testing purposes.

This is because typically code snippets that use static credentials pass hardcoded strings, which obviously is a security issue. In your case, you are attempting to pass runtime variables, so as long as those are not checked in with your application sources, you should be fine.


For the general use case, i.e. environment variables, you can use external.LoadDefaultAWSConfig, which automatically looks for, in this order:

  • Environment Variables
  • Shared Configuration and Shared Credentials files.
// import "github.com/aws/aws-sdk-go-v2/aws/external"

    cfg, err := external.LoadDefaultAWSConfig(external.WithRegion(region))
    if err != nil {
        return nil, err
    }

    client := iam.New(cfg)

The method under the hood calls external.NewEnvConfig which tries to fetch credentials from the environment variables:

  • AWS_SECRET_ACCESS_KEY or AWS_SECRET_KEY
  • AWS_ACCESS_KEY_ID or AWS_ACCESS_KEY

More details about the read priority of the env vars is given in EnvConfig documentation.

blackgreen
  • 34,072
  • 23
  • 111
  • 129
  • Thanks, but my question was precisely how to pass credentials manually and not have the SDK fetch them from environment or configuration files. – Camilo Urán Aug 11 '21 at 11:47
  • @CamiloUrán yes, TBH at first I misunderstood your question. However the term "variable" in your title may be found by people who look for "environment" variables. So I added the solution to your specific problem to my answer, and left the general part for other use cases – blackgreen Aug 11 '21 at 12:09
  • I see! Thanks, like you said, the general case is always useful too. – Camilo Urán Aug 12 '21 at 02:30