Closed meyuviofficial closed 2 months ago
I noticed something similar, may or may not be the same issue.
In my case the user and its MFA are defined in an account aaaaaaaaaaaaa and the assumed role is in another account, bbbbbbbbbbbb.
cfg, err := config.LoadDefaultConfig(context.TODO(),
config.WithRegion(region),
)
if err != nil {
log.Println("Error loading configuration profile:", err.Error())
}
gives Error loading configuration profile: assume role with MFA enabled, but AssumeRoleTokenProvider session option not set.
My AWS config looks like this, and it works well with AWS CLI:
[profile my-profile]
source_profile = users
role_arn=arn:aws:iam::bbbbbbbbbbbb:role/MyAssumedRole
mfa_serial = arn:aws:iam::aaaaaaaaaaaaa:mfa/my-mfa
region=us-east-1
Hi @yuvarajselva .
Thank your for your patience. Admittedly I've never used this flow before, so this took some time to try and reproduce. Unfortunately Im not able to replicate the error. Im able to successfully use the MFA token to assume a role.
Here is my setup for comparison:
main.go:
package main
import (
"context"
"log"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/sts"
)
func main() {
cfg, err := config.LoadDefaultConfig(context.TODO(),
config.WithClientLogMode(aws.LogRequestWithBody|aws.LogResponseWithBody),
config.WithSharedConfigProfile("RanVakMfa"),
)
if err != nil {
log.Fatalf("unable to load SDK config, %v", err)
}
stsClient := sts.NewFromConfig(cfg)
roleArn := "arn:aws:iam::REDACTED:role/mfa-role"
mfaSerialNumber := "arn:aws:iam::REDACTED:mfa/Pixel7"
tokenCode := "123456" // 6 digit code supplied by google Authenticator app
assumeRoleInput := &sts.AssumeRoleInput{
RoleArn: &roleArn,
RoleSessionName: aws.String("session-name"),
SerialNumber: &mfaSerialNumber,
TokenCode: &tokenCode,
}
out, err := stsClient.AssumeRole(context.TODO(), assumeRoleInput)
if err != nil {
log.Fatalf("unable to assume role, %v", err)
}
fmt.Println(*out.AssumedRoleUser.Arn) // logs arn:aws:sts::REDACTED:assumed-role/mfa-role/session-name
aws.config:
[profile RanVakMfa]
region = us-east-1
output = json
mfa_serial = arn:aws:iam::REDACTED:mfa/Pixel7
aws.credentials:
[RanVak]
aws_access_key_id = REDACTED
aws_secret_access_key = REDACTED
Using the CLI I can quickly inspect my role and the the assume role policy document attached to it.
$ aws iam get-role --role-name mfa-role
{
"Role": {
"Path": "/",
"RoleName": "mfa-role",
"RoleId": "REDACTED",
"Arn": "arn:aws:iam::REDACTED:role/mfa-role",
"CreateDate": "2023-12-06T00:22:58+00:00",
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::REDACTED:user/RanVak"
},
"Action": "sts:AssumeRole",
"Condition": {
"Bool": {
"aws:MultiFactorAuthPresent": "true"
}
}
}
]
},
"MaxSessionDuration": 3600,
"RoleLastUsed": {}
}
}
My IAM user has MFA enabled and Google Authenticator on my actual mobile phone configured to be the MFA provider:
Raw Request and response logs:
SDK 2023/12/05 17:14:49 DEBUG Request
POST / HTTP/1.1
Host: sts.us-east-1.amazonaws.com
User-Agent: aws-sdk-go-v2/1.23.1 os/macos lang/go#1.19.1 md/GOOS#darwin md/GOARCH#arm64 api/sts#1.25.4
Content-Length: 204
Amz-Sdk-Invocation-Id: REDACTED
Amz-Sdk-Request: attempt=1; max=3
Authorization: AWS4-HMAC-SHA256 Credential={{aws_access_key_id of user RanVak}}/20231206/us-east-1/sts/aws4_request, SignedHeaders=amz-sdk-invocation-id;content-length;content-type;host;x-amz-date, Signature=REDACTED
Content-Type: application/x-www-form-urlencoded
X-Amz-Date: 20231206T011449Z
Accept-Encoding: gzip
Action=AssumeRole&
RoleArn=arn:aws:iam::REDACTED:role/mfa-role&
RoleSessionName=session-name&
SerialNumber=arn:aws:iam::REDACTED:mfa/Pixel7&
TokenCode=REDACTED&
Version=2011-06-15
SDK 2023/12/05 17:14:49 DEBUG Response
HTTP/1.1 200 OK
Content-Length: 1443
Content-Type: text/xml
Date: Wed, 06 Dec 2023 01:14:49 GMT
X-Amzn-Requestid: REDACTED
<AssumeRoleResponse xmlns="https://sts.amazonaws.com/doc/2011-06-15/">
<AssumeRoleResult>
<AssumedRoleUser>
<AssumedRoleId>REDACTED:session-name</AssumedRoleId>
<Arn>arn:aws:sts::REDACTED:assumed-role/mfa-role/session-name</Arn>
</AssumedRoleUser>
<Credentials>
<AccessKeyId>REDACTED</AccessKeyId>
<SecretAccessKey>REDACTED</SecretAccessKey>
<SessionToken>REDACTED</SessionToken>
<Expiration>2023-12-06T02:14:50Z</Expiration>
</Credentials>
</AssumeRoleResult>
<ResponseMetadata>
<RequestId>REDACTED</RequestId>
</ResponseMetadata>
</AssumeRoleResponse>
arn:aws:sts::REDACTED:assumed-role/mfa-role/session-name
My guess is that one of the steps was not done correctly, or you did not setup your authentication device correctly. Can you please go over my code, and setup and see if it matches yours? Additionally, my code enables the raw request and response logger. You can use that to get an idea of the values you are sending over the wire and see at which part your application fails.
The part I see you were missing is to instruct the SDK to use a specific profile from your config file, but maybe you are doing so from an environment variable that is not visible in your code?
Thanks again, Ran~
In my setup I didn't specify the MFA serial in the Go code, since I had it in my profile.
And I think most people use profiles set in the environment rather than hardcoding them in code anyway.
So my code was something like this:
func connectEC2(region string) (*ec2.Client, error) {
cfg, err := config.LoadDefaultConfig(context.TODO(),
config.WithRegion(region),
)
if err != nil {
log.Println("Error loading configuration profile:", err.Error())
return nil, err
}
return ec2.NewFromConfig(cfg), nil
}
And got errors with a profile that has both mfa_serial and another source_profile assumed with IAM role
[profile test]
source_profile = default
role_arn = arn:aws:iam::xxxxxxx:role/DeveloperAccess
mfa_serial = arn:aws:iam::yyyyyyy:mfa/mfa
As a workaround I built this alternative MFA tool that runs as a credentials provider for my profile: https://github.com/LeanerCloud/assume_role_with_mfa
Hi @RanVaknin, Thanks for picking this up. I have tried your code but I'm getting the same error as before.
package main
import (
"context"
"fmt"
"log"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/sts"
)
func main() {
cfg, err := config.LoadDefaultConfig(context.TODO(),
config.WithClientLogMode(aws.LogRequestWithBody|aws.LogResponseWithBody),
config.WithSharedConfigProfile("sdu-dev-infra"),
)
if err != nil {
log.Fatalf("unable to load SDK config, %v", err)
}
stsClient := sts.NewFromConfig(cfg)
roleArn := "arn:aws:iam::765139991506:role/bea-platform-sre-iam-role"
mfaSerialNumber := "arn:aws:iam::393751483396:mfa/Yuvi-Mobile"
tokenCode := "022049" // 6 digit code supplied by google Authenticator app
assumeRoleInput := &sts.AssumeRoleInput{
RoleArn: &roleArn,
RoleSessionName: aws.String("session-name"),
SerialNumber: &mfaSerialNumber,
TokenCode: &tokenCode,
}
out, err := stsClient.AssumeRole(context.TODO(), assumeRoleInput)
if err != nil {
log.Fatalf("unable to assume role, %v", err)
}
fmt.Println(*out.AssumedRoleUser.Arn) // logs arn:aws:sts::REDACTED:assumed-role/mfa-role/session-name
}
2023/12/11 15:53:57 unable to load SDK config, assume role with MFA enabled, but AssumeRoleTokenProvider session option not set. exit status 1
[profile PARENT]
region = us-east-1
mfa_serial = arn:aws:iam::ACCOUNT_NUMBER:mfa/MY_DEVICE
[profile CHILD]
region = eu-west-1
role_arn = arn:aws:iam::ROLE_NUMBER:role/ROLE_NAME
mfa_serial = arn:aws:iam::ACCOUNT_NUMBER:mfa/MY_DEVICE
source_profile = PARENT
As you can see, I'm trying to login to the
CHILD
Profile as mentioned above where our resources are provisioned. These child profiles are nothing but child accounts used as DTAP environments (DEV, TST, PROD etc.)This setup works perfectly fine in Python Boto3 and AWS CLI whereas the issue only lies with Go Lang SDK v2. Not sure, whether it works in v1. I haven't tried it yet.
cat ~/.aws/credentials
[PARENT]
aws_access_key_id = REDACTED
aws_secret_access_key = REDACTED
I also tested with AWS CLI as you mentioned but I passed the profile along with it. And, it worked perfectly fine.
aws iam get-role --role-name $role_name --profile $profile
{
"Role": {
"Path": "/",
"RoleName": "ROLE_NAME",
"RoleId": "ROLE_ID",
"Arn": "arn:aws:iam::ROLE_NUMBER:role/ROLE_NAME",
"CreateDate": "YYYY-MM-DDTHH:MM:SS+00:00",
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Sid": "idassume",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::ACCOUNT_NUMBER:root"
},
"Action": "sts:AssumeRole",
"Condition": {
"Bool": {
"aws:MultiFactorAuthPresent": "true"
}
}
}
]
},
"Description": "ROLE DESCRIPTION",
"MaxSessionDuration": 3600,
"RoleLastUsed": {
"LastUsedDate": "YYYY-MM-DDTHH:MM:SS+00:00",
"Region": "eu-west-1"
}
}
}
The same above setup works fine with boto3 as well using the below code.
# aws_service.py
import boto3
from botocore.config import Config
class aws_service:
def __init__(self, service, region, profile):
self.session = boto3.Session(profile_name=profile, region_name=region)
self.client = self.session.client(
service_name=service,
config=Config(retries=dict(max_attempts=10, mode="standard")),
)
The above python method can be called and it is working like a charm.
Do you have any updates on this?
Hi Team, Do you have any updates on this?
Hi @meyuviofficial,
Thanks for your patience,
Referring to your last comment here, I tried replicating the behavior you described.
For example:
Credentials file
[RanVakMfa]
aws_access_key_id = REDACTED
aws_secret_access_key = REDACTED
Config file:
[profile RanVakMfa]
region = us-east-1
mfa_serial = arn:aws:iam::REDACTED:mfa/newpixel7
[profile RanVakMfaChild]
region = us-east-1
output = json
role_arn = arn:aws:iam::REDACTED:role/mfa-role
mfa_serial = arn:aws:iam::REDACTED:mfa/newpixel7
source_profile = RanVakMfa
But I'm not able to use assumeRole with the CLI using this setup:
$ aws sts assume-role --role-arn "arn:aws:iam::REDACTED:role/mfa-role" --role-session-name TestSession --serial-number "arn:aws:iam::REDACTED:mfa/newpixel7" --token-code 028266 --profile RanVakMfaChild
An error occurred (AccessDenied) when calling the AssumeRole operation: MultiFactorAuthentication failed, unable to validate MFA code. Please verify your MFA serial number is valid and associated with this user.
As you can see, I'm trying to login to the CHILD Profile as mentioned above where our resources are provisioned. These child profiles are nothing but child accounts used as DTAP environments (DEV, TST, PROD etc.)
This setup works perfectly fine in Python Boto3 and AWS CLI whereas the issue only lies with Go Lang SDK v2. Not sure, whether it works in v1. I haven't tried it yet.
In your example you are not doing an assume role as you tried doing using the Go SDK in your issue description. Instead you are making a get role which is not really the right comparison:
aws iam get-role --role-name $role_name --profile $profile
its not clear which role you are getting here, and which profile you are using and its also not clear how this shows that your setup with a CHILD profile is actually working.
For all I know this is an equivalent of a general get-role command that is independent of how your config file is setup:
$ aws iam get-role --role-name mfa-role
{
"Role": {
"Path": "/",
"RoleName": "mfa-role",
"RoleId": "REDACTED",
"Arn": "arn:aws:iam::REDACTED:role/mfa-role",
"CreateDate": "2023-12-06T00:22:58+00:00",
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::REDACTED:user/RanVakMfa"
},
"Action": "sts:AssumeRole",
"Condition": {
"Bool": {
"aws:MultiFactorAuthPresent": "true"
}
}
}
]
},
"MaxSessionDuration": 3600,
"RoleLastUsed": {
"LastUsedDate": "2023-12-06T00:38:07+00:00",
"Region": "us-east-1"
}
}
}
Are you able to use assumerole using this config file setup? Any other information you can provide would be helpful.
Thanks, Ran~
This issue has not received a response in 1 week. If you want to keep this issue open, please just leave a comment below and auto-close will be canceled.
Describe the bug
I'm trying to authenticate to an AWS account that has MFA enabled. But, I'm not able to do so because it's throwing error. Also, I'm not getting any examples or clear documentation for performing it.
I'm following the example mentioned in the official docs.
But, I'm not able to authenticate and I'm getting the below error always despite passing the MFA code.
Expected Behavior
Successfully authenticated to the AWS account.
Current Behavior
I'm not able to authenticate and I'm getting the below error always despite passing the MFA code.
Reproduction Steps
Possible Solution
Additional Information/Context
No response
AWS Go SDK V2 Module Versions Used
Compiler and Version used
go version go1.21.3 darwin/arm64
Operating System and version
Mac OS - Ventura - 13.6.1