in app.go [90:197]
func (app *App) AssumeRole(options AssumeRoleParameters) (*TemporaryCredentials, error) {
profileName, err := app.profileName(options.UserRole)
if err != nil {
return nil, err
}
profile, err := app.awsConfig.GetProfile(profileName)
if err != nil {
return nil, err
}
if profile == nil {
profile = &ProfileConfiguration{}
}
currentPrincipalIsAssumedRole, err := app.CurrentPrincipalIsAssumedRole()
if err != nil {
return nil, fmt.Errorf("unable to check IAM principal type: %v", err)
}
// If force refresh was requested, or the credentials from a previous session
// are still valid return those
if !app.credentialsExpired(profile.Expires) && !options.ForceRefresh {
return app.awsConfig.GetCredentials(profileName)
}
// Get the full role ARN by combining the role prefix with the
// user-provided role name
roleARN := fmt.Sprintf("%s%s", app.config.RolePrefix, options.UserRole)
profile.RoleARN = roleARN
sessionName := profile.RoleSessionName
if sessionName == "" {
if options.RoleSessionName != "" {
sessionName = options.RoleSessionName
} else {
if currentPrincipalIsAssumedRole {
return nil, errAssumedRoleNeedsSessionName
}
sessionName, err = app.aws.Username()
if err != nil {
return nil, fmt.Errorf("unable to get username from AWS: %v", err)
}
}
profile.RoleSessionName = sessionName
}
// We first try to assume role without MFA and if that doesn't work then we
// try to assume role with MFA. Along the way, we collect errors in a
// multierr, so that if there is a fatal problem then we can output all
// errors so the user can see what happened along the way.
var finalErr error
// Try to assume role without MFA
creds, err := app.aws.AssumeRole(roleARN, sessionName)
if err != nil {
if IsAWSAccessDeniedError(err) {
finalErr = multierror.Append(finalErr, fmt.Errorf("error trying to AssumeRole without MFA: %v", err))
} else {
// Fail immediately if the error was something other than "access denied"
return nil, err
}
}
if creds != nil {
profile.Expires = creds.Expires
// Save credentials
if err := app.save(profileName, profile, creds); err != nil {
return nil, err
}
return creds, nil
}
if currentPrincipalIsAssumedRole {
// assumed roles don't have an user name or MFA device associated with them
return nil, finalErr
}
// Get user's MFA device
mfaDeviceARN, err := app.mfaDevice()
if err != nil {
finalErr = multierror.Append(finalErr, fmt.Errorf("error trying to AssumeRole with MFA: %v", err))
return nil, finalErr
}
profile.MFASerial = mfaDeviceARN
// Get token
mfaToken, err := app.mfaToken()
if err != nil {
finalErr = multierror.Append(finalErr, fmt.Errorf("error trying to AssumeRole with MFA: %v", err))
return nil, finalErr
}
// Assume role
creds, err = app.aws.AssumeRoleWithMFA(roleARN, sessionName, mfaDeviceARN, mfaToken)
if err != nil {
finalErr = multierror.Append(finalErr, fmt.Errorf("error trying to AssumeRole with MFA: %v; giving up", err))
return nil, finalErr
}
profile.Expires = creds.Expires
// Save credentials
if err := app.save(profileName, profile, creds); err != nil {
return nil, err
}
return creds, nil
}