github.com/aavshr/aws-sdk-go@v1.41.3/aws/session/shared_config.go (about)

     1  package session
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  	"time"
     7  
     8  	"github.com/aavshr/aws-sdk-go/aws/awserr"
     9  	"github.com/aavshr/aws-sdk-go/aws/credentials"
    10  	"github.com/aavshr/aws-sdk-go/aws/endpoints"
    11  	"github.com/aavshr/aws-sdk-go/internal/ini"
    12  )
    13  
    14  const (
    15  	// Static Credentials group
    16  	accessKeyIDKey  = `aws_access_key_id`     // group required
    17  	secretAccessKey = `aws_secret_access_key` // group required
    18  	sessionTokenKey = `aws_session_token`     // optional
    19  
    20  	// Assume Role Credentials group
    21  	roleArnKey             = `role_arn`          // group required
    22  	sourceProfileKey       = `source_profile`    // group required (or credential_source)
    23  	credentialSourceKey    = `credential_source` // group required (or source_profile)
    24  	externalIDKey          = `external_id`       // optional
    25  	mfaSerialKey           = `mfa_serial`        // optional
    26  	roleSessionNameKey     = `role_session_name` // optional
    27  	roleDurationSecondsKey = "duration_seconds"  // optional
    28  
    29  	// AWS Single Sign-On (AWS SSO) group
    30  	ssoAccountIDKey = "sso_account_id"
    31  	ssoRegionKey    = "sso_region"
    32  	ssoRoleNameKey  = "sso_role_name"
    33  	ssoStartURL     = "sso_start_url"
    34  
    35  	// CSM options
    36  	csmEnabledKey  = `csm_enabled`
    37  	csmHostKey     = `csm_host`
    38  	csmPortKey     = `csm_port`
    39  	csmClientIDKey = `csm_client_id`
    40  
    41  	// Additional Config fields
    42  	regionKey = `region`
    43  
    44  	// custom CA Bundle filename
    45  	customCABundleKey = `ca_bundle`
    46  
    47  	// endpoint discovery group
    48  	enableEndpointDiscoveryKey = `endpoint_discovery_enabled` // optional
    49  
    50  	// External Credential Process
    51  	credentialProcessKey = `credential_process` // optional
    52  
    53  	// Web Identity Token File
    54  	webIdentityTokenFileKey = `web_identity_token_file` // optional
    55  
    56  	// Additional config fields for regional or legacy endpoints
    57  	stsRegionalEndpointSharedKey = `sts_regional_endpoints`
    58  
    59  	// Additional config fields for regional or legacy endpoints
    60  	s3UsEast1RegionalSharedKey = `s3_us_east_1_regional_endpoint`
    61  
    62  	// DefaultSharedConfigProfile is the default profile to be used when
    63  	// loading configuration from the config files if another profile name
    64  	// is not provided.
    65  	DefaultSharedConfigProfile = `default`
    66  
    67  	// S3 ARN Region Usage
    68  	s3UseARNRegionKey = "s3_use_arn_region"
    69  
    70  	// EC2 IMDS Endpoint Mode
    71  	ec2MetadataServiceEndpointModeKey = "ec2_metadata_service_endpoint_mode"
    72  
    73  	// EC2 IMDS Endpoint
    74  	ec2MetadataServiceEndpointKey = "ec2_metadata_service_endpoint"
    75  )
    76  
    77  // sharedConfig represents the configuration fields of the SDK config files.
    78  type sharedConfig struct {
    79  	Profile string
    80  
    81  	// Credentials values from the config file. Both aws_access_key_id and
    82  	// aws_secret_access_key must be provided together in the same file to be
    83  	// considered valid. The values will be ignored if not a complete group.
    84  	// aws_session_token is an optional field that can be provided if both of
    85  	// the other two fields are also provided.
    86  	//
    87  	//	aws_access_key_id
    88  	//	aws_secret_access_key
    89  	//	aws_session_token
    90  	Creds credentials.Value
    91  
    92  	CredentialSource     string
    93  	CredentialProcess    string
    94  	WebIdentityTokenFile string
    95  
    96  	SSOAccountID string
    97  	SSORegion    string
    98  	SSORoleName  string
    99  	SSOStartURL  string
   100  
   101  	RoleARN            string
   102  	RoleSessionName    string
   103  	ExternalID         string
   104  	MFASerial          string
   105  	AssumeRoleDuration *time.Duration
   106  
   107  	SourceProfileName string
   108  	SourceProfile     *sharedConfig
   109  
   110  	// Region is the region the SDK should use for looking up AWS service
   111  	// endpoints and signing requests.
   112  	//
   113  	//	region
   114  	Region string
   115  
   116  	// CustomCABundle is the file path to a PEM file the SDK will read and
   117  	// use to configure the HTTP transport with additional CA certs that are
   118  	// not present in the platforms default CA store.
   119  	//
   120  	// This value will be ignored if the file does not exist.
   121  	//
   122  	//  ca_bundle
   123  	CustomCABundle string
   124  
   125  	// EnableEndpointDiscovery can be enabled in the shared config by setting
   126  	// endpoint_discovery_enabled to true
   127  	//
   128  	//	endpoint_discovery_enabled = true
   129  	EnableEndpointDiscovery *bool
   130  
   131  	// CSM Options
   132  	CSMEnabled  *bool
   133  	CSMHost     string
   134  	CSMPort     string
   135  	CSMClientID string
   136  
   137  	// Specifies the Regional Endpoint flag for the SDK to resolve the endpoint for a service
   138  	//
   139  	// sts_regional_endpoints = regional
   140  	// This can take value as `LegacySTSEndpoint` or `RegionalSTSEndpoint`
   141  	STSRegionalEndpoint endpoints.STSRegionalEndpoint
   142  
   143  	// Specifies the Regional Endpoint flag for the SDK to resolve the endpoint for a service
   144  	//
   145  	// s3_us_east_1_regional_endpoint = regional
   146  	// This can take value as `LegacyS3UsEast1Endpoint` or `RegionalS3UsEast1Endpoint`
   147  	S3UsEast1RegionalEndpoint endpoints.S3UsEast1RegionalEndpoint
   148  
   149  	// Specifies if the S3 service should allow ARNs to direct the region
   150  	// the client's requests are sent to.
   151  	//
   152  	// s3_use_arn_region=true
   153  	S3UseARNRegion bool
   154  
   155  	// Specifies the EC2 Instance Metadata Service default endpoint selection mode (IPv4 or IPv6)
   156  	//
   157  	// ec2_metadata_service_endpoint_mode=IPv6
   158  	EC2IMDSEndpointMode endpoints.EC2IMDSEndpointModeState
   159  
   160  	// Specifies the EC2 Instance Metadata Service endpoint to use. If specified it overrides EC2IMDSEndpointMode.
   161  	//
   162  	// ec2_metadata_service_endpoint=http://fd00:ec2::254
   163  	EC2IMDSEndpoint string
   164  }
   165  
   166  type sharedConfigFile struct {
   167  	Filename string
   168  	IniData  ini.Sections
   169  }
   170  
   171  // loadSharedConfig retrieves the configuration from the list of files using
   172  // the profile provided. The order the files are listed will determine
   173  // precedence. Values in subsequent files will overwrite values defined in
   174  // earlier files.
   175  //
   176  // For example, given two files A and B. Both define credentials. If the order
   177  // of the files are A then B, B's credential values will be used instead of
   178  // A's.
   179  //
   180  // See sharedConfig.setFromFile for information how the config files
   181  // will be loaded.
   182  func loadSharedConfig(profile string, filenames []string, exOpts bool) (sharedConfig, error) {
   183  	if len(profile) == 0 {
   184  		profile = DefaultSharedConfigProfile
   185  	}
   186  
   187  	files, err := loadSharedConfigIniFiles(filenames)
   188  	if err != nil {
   189  		return sharedConfig{}, err
   190  	}
   191  
   192  	cfg := sharedConfig{}
   193  	profiles := map[string]struct{}{}
   194  	if err = cfg.setFromIniFiles(profiles, profile, files, exOpts); err != nil {
   195  		return sharedConfig{}, err
   196  	}
   197  
   198  	return cfg, nil
   199  }
   200  
   201  func loadSharedConfigIniFiles(filenames []string) ([]sharedConfigFile, error) {
   202  	files := make([]sharedConfigFile, 0, len(filenames))
   203  
   204  	for _, filename := range filenames {
   205  		sections, err := ini.OpenFile(filename)
   206  		if aerr, ok := err.(awserr.Error); ok && aerr.Code() == ini.ErrCodeUnableToReadFile {
   207  			// Skip files which can't be opened and read for whatever reason
   208  			continue
   209  		} else if err != nil {
   210  			return nil, SharedConfigLoadError{Filename: filename, Err: err}
   211  		}
   212  
   213  		files = append(files, sharedConfigFile{
   214  			Filename: filename, IniData: sections,
   215  		})
   216  	}
   217  
   218  	return files, nil
   219  }
   220  
   221  func (cfg *sharedConfig) setFromIniFiles(profiles map[string]struct{}, profile string, files []sharedConfigFile, exOpts bool) error {
   222  	cfg.Profile = profile
   223  
   224  	// Trim files from the list that don't exist.
   225  	var skippedFiles int
   226  	var profileNotFoundErr error
   227  	for _, f := range files {
   228  		if err := cfg.setFromIniFile(profile, f, exOpts); err != nil {
   229  			if _, ok := err.(SharedConfigProfileNotExistsError); ok {
   230  				// Ignore profiles not defined in individual files.
   231  				profileNotFoundErr = err
   232  				skippedFiles++
   233  				continue
   234  			}
   235  			return err
   236  		}
   237  	}
   238  	if skippedFiles == len(files) {
   239  		// If all files were skipped because the profile is not found, return
   240  		// the original profile not found error.
   241  		return profileNotFoundErr
   242  	}
   243  
   244  	if _, ok := profiles[profile]; ok {
   245  		// if this is the second instance of the profile the Assume Role
   246  		// options must be cleared because they are only valid for the
   247  		// first reference of a profile. The self linked instance of the
   248  		// profile only have credential provider options.
   249  		cfg.clearAssumeRoleOptions()
   250  	} else {
   251  		// First time a profile has been seen, It must either be a assume role
   252  		// credentials, or SSO. Assert if the credential type requires a role ARN,
   253  		// the ARN is also set, or validate that the SSO configuration is complete.
   254  		if err := cfg.validateCredentialsConfig(profile); err != nil {
   255  			return err
   256  		}
   257  	}
   258  	profiles[profile] = struct{}{}
   259  
   260  	if err := cfg.validateCredentialType(); err != nil {
   261  		return err
   262  	}
   263  
   264  	// Link source profiles for assume roles
   265  	if len(cfg.SourceProfileName) != 0 {
   266  		// Linked profile via source_profile ignore credential provider
   267  		// options, the source profile must provide the credentials.
   268  		cfg.clearCredentialOptions()
   269  
   270  		srcCfg := &sharedConfig{}
   271  		err := srcCfg.setFromIniFiles(profiles, cfg.SourceProfileName, files, exOpts)
   272  		if err != nil {
   273  			// SourceProfile that doesn't exist is an error in configuration.
   274  			if _, ok := err.(SharedConfigProfileNotExistsError); ok {
   275  				err = SharedConfigAssumeRoleError{
   276  					RoleARN:       cfg.RoleARN,
   277  					SourceProfile: cfg.SourceProfileName,
   278  				}
   279  			}
   280  			return err
   281  		}
   282  
   283  		if !srcCfg.hasCredentials() {
   284  			return SharedConfigAssumeRoleError{
   285  				RoleARN:       cfg.RoleARN,
   286  				SourceProfile: cfg.SourceProfileName,
   287  			}
   288  		}
   289  
   290  		cfg.SourceProfile = srcCfg
   291  	}
   292  
   293  	return nil
   294  }
   295  
   296  // setFromFile loads the configuration from the file using the profile
   297  // provided. A sharedConfig pointer type value is used so that multiple config
   298  // file loadings can be chained.
   299  //
   300  // Only loads complete logically grouped values, and will not set fields in cfg
   301  // for incomplete grouped values in the config. Such as credentials. For
   302  // example if a config file only includes aws_access_key_id but no
   303  // aws_secret_access_key the aws_access_key_id will be ignored.
   304  func (cfg *sharedConfig) setFromIniFile(profile string, file sharedConfigFile, exOpts bool) error {
   305  	section, ok := file.IniData.GetSection(profile)
   306  	if !ok {
   307  		// Fallback to to alternate profile name: profile <name>
   308  		section, ok = file.IniData.GetSection(fmt.Sprintf("profile %s", profile))
   309  		if !ok {
   310  			return SharedConfigProfileNotExistsError{Profile: profile, Err: nil}
   311  		}
   312  	}
   313  
   314  	if exOpts {
   315  		// Assume Role Parameters
   316  		updateString(&cfg.RoleARN, section, roleArnKey)
   317  		updateString(&cfg.ExternalID, section, externalIDKey)
   318  		updateString(&cfg.MFASerial, section, mfaSerialKey)
   319  		updateString(&cfg.RoleSessionName, section, roleSessionNameKey)
   320  		updateString(&cfg.SourceProfileName, section, sourceProfileKey)
   321  		updateString(&cfg.CredentialSource, section, credentialSourceKey)
   322  		updateString(&cfg.Region, section, regionKey)
   323  		updateString(&cfg.CustomCABundle, section, customCABundleKey)
   324  
   325  		if section.Has(roleDurationSecondsKey) {
   326  			d := time.Duration(section.Int(roleDurationSecondsKey)) * time.Second
   327  			cfg.AssumeRoleDuration = &d
   328  		}
   329  
   330  		if v := section.String(stsRegionalEndpointSharedKey); len(v) != 0 {
   331  			sre, err := endpoints.GetSTSRegionalEndpoint(v)
   332  			if err != nil {
   333  				return fmt.Errorf("failed to load %s from shared config, %s, %v",
   334  					stsRegionalEndpointSharedKey, file.Filename, err)
   335  			}
   336  			cfg.STSRegionalEndpoint = sre
   337  		}
   338  
   339  		if v := section.String(s3UsEast1RegionalSharedKey); len(v) != 0 {
   340  			sre, err := endpoints.GetS3UsEast1RegionalEndpoint(v)
   341  			if err != nil {
   342  				return fmt.Errorf("failed to load %s from shared config, %s, %v",
   343  					s3UsEast1RegionalSharedKey, file.Filename, err)
   344  			}
   345  			cfg.S3UsEast1RegionalEndpoint = sre
   346  		}
   347  
   348  		// AWS Single Sign-On (AWS SSO)
   349  		updateString(&cfg.SSOAccountID, section, ssoAccountIDKey)
   350  		updateString(&cfg.SSORegion, section, ssoRegionKey)
   351  		updateString(&cfg.SSORoleName, section, ssoRoleNameKey)
   352  		updateString(&cfg.SSOStartURL, section, ssoStartURL)
   353  
   354  		if err := updateEC2MetadataServiceEndpointMode(&cfg.EC2IMDSEndpointMode, section, ec2MetadataServiceEndpointModeKey); err != nil {
   355  			return fmt.Errorf("failed to load %s from shared config, %s, %v",
   356  				ec2MetadataServiceEndpointModeKey, file.Filename, err)
   357  		}
   358  		updateString(&cfg.EC2IMDSEndpoint, section, ec2MetadataServiceEndpointKey)
   359  	}
   360  
   361  	updateString(&cfg.CredentialProcess, section, credentialProcessKey)
   362  	updateString(&cfg.WebIdentityTokenFile, section, webIdentityTokenFileKey)
   363  
   364  	// Shared Credentials
   365  	creds := credentials.Value{
   366  		AccessKeyID:     section.String(accessKeyIDKey),
   367  		SecretAccessKey: section.String(secretAccessKey),
   368  		SessionToken:    section.String(sessionTokenKey),
   369  		ProviderName:    fmt.Sprintf("SharedConfigCredentials: %s", file.Filename),
   370  	}
   371  	if creds.HasKeys() {
   372  		cfg.Creds = creds
   373  	}
   374  
   375  	// Endpoint discovery
   376  	updateBoolPtr(&cfg.EnableEndpointDiscovery, section, enableEndpointDiscoveryKey)
   377  
   378  	// CSM options
   379  	updateBoolPtr(&cfg.CSMEnabled, section, csmEnabledKey)
   380  	updateString(&cfg.CSMHost, section, csmHostKey)
   381  	updateString(&cfg.CSMPort, section, csmPortKey)
   382  	updateString(&cfg.CSMClientID, section, csmClientIDKey)
   383  
   384  	updateBool(&cfg.S3UseARNRegion, section, s3UseARNRegionKey)
   385  
   386  	return nil
   387  }
   388  
   389  func updateEC2MetadataServiceEndpointMode(endpointMode *endpoints.EC2IMDSEndpointModeState, section ini.Section, key string) error {
   390  	if !section.Has(key) {
   391  		return nil
   392  	}
   393  	value := section.String(key)
   394  	return endpointMode.SetFromString(value)
   395  }
   396  
   397  func (cfg *sharedConfig) validateCredentialsConfig(profile string) error {
   398  	if err := cfg.validateCredentialsRequireARN(profile); err != nil {
   399  		return err
   400  	}
   401  
   402  	return nil
   403  }
   404  
   405  func (cfg *sharedConfig) validateCredentialsRequireARN(profile string) error {
   406  	var credSource string
   407  
   408  	switch {
   409  	case len(cfg.SourceProfileName) != 0:
   410  		credSource = sourceProfileKey
   411  	case len(cfg.CredentialSource) != 0:
   412  		credSource = credentialSourceKey
   413  	case len(cfg.WebIdentityTokenFile) != 0:
   414  		credSource = webIdentityTokenFileKey
   415  	}
   416  
   417  	if len(credSource) != 0 && len(cfg.RoleARN) == 0 {
   418  		return CredentialRequiresARNError{
   419  			Type:    credSource,
   420  			Profile: profile,
   421  		}
   422  	}
   423  
   424  	return nil
   425  }
   426  
   427  func (cfg *sharedConfig) validateCredentialType() error {
   428  	// Only one or no credential type can be defined.
   429  	if !oneOrNone(
   430  		len(cfg.SourceProfileName) != 0,
   431  		len(cfg.CredentialSource) != 0,
   432  		len(cfg.CredentialProcess) != 0,
   433  		len(cfg.WebIdentityTokenFile) != 0,
   434  	) {
   435  		return ErrSharedConfigSourceCollision
   436  	}
   437  
   438  	return nil
   439  }
   440  
   441  func (cfg *sharedConfig) validateSSOConfiguration() error {
   442  	if !cfg.hasSSOConfiguration() {
   443  		return nil
   444  	}
   445  
   446  	var missing []string
   447  	if len(cfg.SSOAccountID) == 0 {
   448  		missing = append(missing, ssoAccountIDKey)
   449  	}
   450  
   451  	if len(cfg.SSORegion) == 0 {
   452  		missing = append(missing, ssoRegionKey)
   453  	}
   454  
   455  	if len(cfg.SSORoleName) == 0 {
   456  		missing = append(missing, ssoRoleNameKey)
   457  	}
   458  
   459  	if len(cfg.SSOStartURL) == 0 {
   460  		missing = append(missing, ssoStartURL)
   461  	}
   462  
   463  	if len(missing) > 0 {
   464  		return fmt.Errorf("profile %q is configured to use SSO but is missing required configuration: %s",
   465  			cfg.Profile, strings.Join(missing, ", "))
   466  	}
   467  
   468  	return nil
   469  }
   470  
   471  func (cfg *sharedConfig) hasCredentials() bool {
   472  	switch {
   473  	case len(cfg.SourceProfileName) != 0:
   474  	case len(cfg.CredentialSource) != 0:
   475  	case len(cfg.CredentialProcess) != 0:
   476  	case len(cfg.WebIdentityTokenFile) != 0:
   477  	case cfg.hasSSOConfiguration():
   478  	case cfg.Creds.HasKeys():
   479  	default:
   480  		return false
   481  	}
   482  
   483  	return true
   484  }
   485  
   486  func (cfg *sharedConfig) clearCredentialOptions() {
   487  	cfg.CredentialSource = ""
   488  	cfg.CredentialProcess = ""
   489  	cfg.WebIdentityTokenFile = ""
   490  	cfg.Creds = credentials.Value{}
   491  	cfg.SSOAccountID = ""
   492  	cfg.SSORegion = ""
   493  	cfg.SSORoleName = ""
   494  	cfg.SSOStartURL = ""
   495  }
   496  
   497  func (cfg *sharedConfig) clearAssumeRoleOptions() {
   498  	cfg.RoleARN = ""
   499  	cfg.ExternalID = ""
   500  	cfg.MFASerial = ""
   501  	cfg.RoleSessionName = ""
   502  	cfg.SourceProfileName = ""
   503  }
   504  
   505  func (cfg *sharedConfig) hasSSOConfiguration() bool {
   506  	switch {
   507  	case len(cfg.SSOAccountID) != 0:
   508  	case len(cfg.SSORegion) != 0:
   509  	case len(cfg.SSORoleName) != 0:
   510  	case len(cfg.SSOStartURL) != 0:
   511  	default:
   512  		return false
   513  	}
   514  	return true
   515  }
   516  
   517  func oneOrNone(bs ...bool) bool {
   518  	var count int
   519  
   520  	for _, b := range bs {
   521  		if b {
   522  			count++
   523  			if count > 1 {
   524  				return false
   525  			}
   526  		}
   527  	}
   528  
   529  	return true
   530  }
   531  
   532  // updateString will only update the dst with the value in the section key, key
   533  // is present in the section.
   534  func updateString(dst *string, section ini.Section, key string) {
   535  	if !section.Has(key) {
   536  		return
   537  	}
   538  	*dst = section.String(key)
   539  }
   540  
   541  // updateBool will only update the dst with the value in the section key, key
   542  // is present in the section.
   543  func updateBool(dst *bool, section ini.Section, key string) {
   544  	if !section.Has(key) {
   545  		return
   546  	}
   547  	*dst = section.Bool(key)
   548  }
   549  
   550  // updateBoolPtr will only update the dst with the value in the section key,
   551  // key is present in the section.
   552  func updateBoolPtr(dst **bool, section ini.Section, key string) {
   553  	if !section.Has(key) {
   554  		return
   555  	}
   556  	*dst = new(bool)
   557  	**dst = section.Bool(key)
   558  }
   559  
   560  // SharedConfigLoadError is an error for the shared config file failed to load.
   561  type SharedConfigLoadError struct {
   562  	Filename string
   563  	Err      error
   564  }
   565  
   566  // Code is the short id of the error.
   567  func (e SharedConfigLoadError) Code() string {
   568  	return "SharedConfigLoadError"
   569  }
   570  
   571  // Message is the description of the error
   572  func (e SharedConfigLoadError) Message() string {
   573  	return fmt.Sprintf("failed to load config file, %s", e.Filename)
   574  }
   575  
   576  // OrigErr is the underlying error that caused the failure.
   577  func (e SharedConfigLoadError) OrigErr() error {
   578  	return e.Err
   579  }
   580  
   581  // Error satisfies the error interface.
   582  func (e SharedConfigLoadError) Error() string {
   583  	return awserr.SprintError(e.Code(), e.Message(), "", e.Err)
   584  }
   585  
   586  // SharedConfigProfileNotExistsError is an error for the shared config when
   587  // the profile was not find in the config file.
   588  type SharedConfigProfileNotExistsError struct {
   589  	Profile string
   590  	Err     error
   591  }
   592  
   593  // Code is the short id of the error.
   594  func (e SharedConfigProfileNotExistsError) Code() string {
   595  	return "SharedConfigProfileNotExistsError"
   596  }
   597  
   598  // Message is the description of the error
   599  func (e SharedConfigProfileNotExistsError) Message() string {
   600  	return fmt.Sprintf("failed to get profile, %s", e.Profile)
   601  }
   602  
   603  // OrigErr is the underlying error that caused the failure.
   604  func (e SharedConfigProfileNotExistsError) OrigErr() error {
   605  	return e.Err
   606  }
   607  
   608  // Error satisfies the error interface.
   609  func (e SharedConfigProfileNotExistsError) Error() string {
   610  	return awserr.SprintError(e.Code(), e.Message(), "", e.Err)
   611  }
   612  
   613  // SharedConfigAssumeRoleError is an error for the shared config when the
   614  // profile contains assume role information, but that information is invalid
   615  // or not complete.
   616  type SharedConfigAssumeRoleError struct {
   617  	RoleARN       string
   618  	SourceProfile string
   619  }
   620  
   621  // Code is the short id of the error.
   622  func (e SharedConfigAssumeRoleError) Code() string {
   623  	return "SharedConfigAssumeRoleError"
   624  }
   625  
   626  // Message is the description of the error
   627  func (e SharedConfigAssumeRoleError) Message() string {
   628  	return fmt.Sprintf(
   629  		"failed to load assume role for %s, source profile %s has no shared credentials",
   630  		e.RoleARN, e.SourceProfile,
   631  	)
   632  }
   633  
   634  // OrigErr is the underlying error that caused the failure.
   635  func (e SharedConfigAssumeRoleError) OrigErr() error {
   636  	return nil
   637  }
   638  
   639  // Error satisfies the error interface.
   640  func (e SharedConfigAssumeRoleError) Error() string {
   641  	return awserr.SprintError(e.Code(), e.Message(), "", nil)
   642  }
   643  
   644  // CredentialRequiresARNError provides the error for shared config credentials
   645  // that are incorrectly configured in the shared config or credentials file.
   646  type CredentialRequiresARNError struct {
   647  	// type of credentials that were configured.
   648  	Type string
   649  
   650  	// Profile name the credentials were in.
   651  	Profile string
   652  }
   653  
   654  // Code is the short id of the error.
   655  func (e CredentialRequiresARNError) Code() string {
   656  	return "CredentialRequiresARNError"
   657  }
   658  
   659  // Message is the description of the error
   660  func (e CredentialRequiresARNError) Message() string {
   661  	return fmt.Sprintf(
   662  		"credential type %s requires role_arn, profile %s",
   663  		e.Type, e.Profile,
   664  	)
   665  }
   666  
   667  // OrigErr is the underlying error that caused the failure.
   668  func (e CredentialRequiresARNError) OrigErr() error {
   669  	return nil
   670  }
   671  
   672  // Error satisfies the error interface.
   673  func (e CredentialRequiresARNError) Error() string {
   674  	return awserr.SprintError(e.Code(), e.Message(), "", nil)
   675  }