aws-sdk-go-v2
aws-sdk-go-v2 copied to clipboard
Better AssumeRole example
Is your feature request related to a problem? Please describe.
On the cli, it's aws sts assume-role --role-arn "arn:aws:iam::XYZ:role/ViewLogsPlease" --role-session-name ViewOne
And then you awkwardly need to setup AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN, however it's less awkward than wading through wierd non-sensical documentation like https://aws.github.io/aws-sdk-go-v2/docs/code-examples/sts/assumerole/
Describe the solution you'd like
Clear working instructions like
creds := stscreds.NewAssumeRoleProvider(stsclient, "arn:aws:iam::XYZ:role/ViewLogsPlease", func(p *stscreds.AssumeRoleOpti ons) {
p.RoleSessionName = "ViewLogsPlease"
})
// Magic sauce to get the current role
cfg.Credentials = aws.NewCredentialsCache(creds)
Describe alternatives you've considered Maybe I should go back to v1, because v2 hasn't made the cfg any easier!
Additional context
Additionally I went down the rabbit hole of assuming that something like:
cfg, err := config.LoadDefaultConfig(context.TODO(),
config.WithSharedConfigProfile("mine"),
config.WithAssumeRoleCredentialOptions(func(o *stscreds.AssumeRoleOptions) {
o.RoleARN = "arn:aws:iam::XYZ:role/ViewLogsPlease"
}),
)
It doesn't work, and I have no idea why. github.com/aws/aws-sdk-go-v2 v1.8.0
Thanks for reaching out @kaihendry . To help clarify the issue, could you provide if your SharedConfigProfile in this example has assume role configured in it?
As documented at https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/config#WithAssumeRoleCredentialOptions
WithAssumeRoleCredentialOptions is a helper function to construct functional options that sets a function to use stscreds.AssumeRoleOptions on config's LoadOptions. If assume role credentials options is set to nil, the assume role credentials value will be ignored. If multiple WithAssumeRoleCredentialOptions calls are made, the last call overrides the previous call values.
The WithAssumeRoleCredentialOptions works similar to how you are configuring p.RoleSessionName = "ViewLogsPlease" in your first code snippet.
In your example - if no assume role was present in "mine" shared config profile, the WithAssumeRoleCredentialOptions will not be invoked.
We will update our example docs to reflect this requirement.
I think the confusion here might be that @kaihendry is looking for programmatic role assumption. But what WithAssumeRoleCredentialOptions provides is configuring an assumed-role profile from configuration. That looks like the following in your ~/.aws/config:
# this is a pre-existing profile you already have
[profile profile-to-call-assume-role-with]
# maybe it's IAM User credentials
# or AWS SSO config
# or whatever else you may have
[profile view-logs]
role_arn = arn:aws:iam::XYZ:role/ViewLogsPlease
# optional: role_session_name = MyRoleSessionName
source_profile = profile-to-call-assume-role-with
# or instead of source_profile, you can tell it to
# use external credentials. one of:
# credential_source = Environment
# credential_source = Ec2InstanceMetadata
# credential_source = EcsContainer
With this config, you can reference the view-logs profile like any other. WithAssumeRoleCredentialOptions lets you modify the parameters of the AssumeRole call that is caused by this profile, but can't make it use an assumed role where none is present in the config file.
This is in contrast to the JavaScript SDK, which provides ChainableTemporaryCredentials as a way to configure the SDK with a role programmatically. For boto3, I had to make a library to accomplish this.
So, hopefully the above ~/.aws/config profile option accomplishes your need, but a separate issue for programmatic role assumption seems worth opening? This would probably be a new Config type that has a role ARN and base config?
func NewAssumeRoleConfig(ctx context.Context, baseCfg aws.Config, roleARN string, v func(*stscreds.AssumeRoleOptions)) (cfg aws.Config, err error)
this example is very good : https://flowerinthenight.com/blog/2021/04/30/authenticate-aws-sdk-golang-v2
assumecnf, _ := config.LoadDefaultConfig(...)
stsclient := sts.NewFromConfig(assumecnf)
cnf, _ := config.LoadDefaultConfig(
ctx, config.WithRegion("{aws-region}"),
config.WithCredentialsProvider(aws.NewCredentialsCache(
stscredsv2.NewAssumeRoleProvider(
stsclient,
"{rolearn-to-assume}",
)),
),
)
client := s3.NewFromConfig(cnf)
res, _ := client.GetObject(ctx, &s3.GetObjectInput{
Bucket: awsv2.String("{some-bucket}"),
Key: awsv2.String("{some-key}"),
})```
Came here to post a similar issue - I think the docs could be improved in this case (specifically this one: https://aws.github.io/aws-sdk-go-v2/docs/code-examples/sts/assumerole/) to show the use of the AssumeRole credentials as opposed to stopping at getting the role assumed. I also stumbled across the example above and that seems to work, but it would be good to see a working example with best practice code from AWS itself.
This seems like the best, simplest example I've seen for AssumeRole: https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/credentials/stscreds#hdr-Assume_Role
Assuming role without 'stscreds' (only using 'sts' and 'sts/types') and static credentials:
import (
"context"
"log"
"strconv"
"time"
"math/rand"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/credentials"
"github.com/aws/aws-sdk-go-v2/ec2"
"github.com/aws/aws-sdk-go-v2/sts"
stsTypes "github.com/aws/aws-sdk-go-v2/sts/types"
)
// Create config & sts client with source account
cfg, err := config.LoadDefaultConfig (ctx, config.WithRegion(region), config.WithSharedConfigProfile(profileName))
if err != nil {
log.Fatalf("unable to load shared profile for sts client config, %v", err)
}
sourceAccount := sts.NewFromConfig(cfg)
// Assume target role and store credentials
rand.Seed(time.Now().UnixNano())
response, err := sourceAccount.AssumeRole(ctx, &sts.AssumeRoleInput{
RoleArn: aws.String("arn:aws:iam::ACCOUNT_NUM:role/ROLE_NAME),
RoleSessionName: aws.String("some-identifier-" + strconv.Itoa(10000 + rand.Intn(25000))),
}
if err != nil {
log.Fatalf("unable to assume target role, %v", err)
}
var assumedRoleCreds *stsTypes.Credentials = response.Credentials
// Create config with target service client, using assumed role
cfg, err = config.LoadDefaultConfig(ctx, config.WithRegion(region), config.WithCredentialsProvider(credentials.NewStaticCredentialsProvider(*assumedRoleCreds.AccessKeyId, *assumedRoleCreds.SecretAccessKey, *assumedRoleCreds.SessionToken)))
if err != nil {
log.Fatalf("unable to load static credentials for service client config, %v", err)
}
// Use it
ec2.NewFromConfig(cfg)
reference: https://aws.github.io/aws-sdk-go-v2/docs/configuring-sdk/#static-credentials
Since I see many comments here with good examples I feel confident we can close this issue. If this is not sufficient please open a new issue.
Thanks, Ran~
⚠️COMMENT VISIBILITY WARNING⚠️
Comments on closed issues are hard for our team to see. If you need more assistance, please either tag a team member or open a new issue that references this one. If you wish to keep having a conversation with other community members under this issue feel free to do so.