import (
"fmt"
- "io/ioutil"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/aws/credentials"
- "github.com/go-ini/ini"
+
+ "github.com/aws/aws-sdk-go/internal/ini"
)
const (
sessionTokenKey = `aws_session_token` // optional
// Assume Role Credentials group
- roleArnKey = `role_arn` // group required
- sourceProfileKey = `source_profile` // group required
- externalIDKey = `external_id` // optional
- mfaSerialKey = `mfa_serial` // optional
- roleSessionNameKey = `role_session_name` // optional
+ roleArnKey = `role_arn` // group required
+ sourceProfileKey = `source_profile` // group required (or credential_source)
+ credentialSourceKey = `credential_source` // group required (or source_profile)
+ externalIDKey = `external_id` // optional
+ mfaSerialKey = `mfa_serial` // optional
+ roleSessionNameKey = `role_session_name` // optional
// Additional Config fields
regionKey = `region`
+ // endpoint discovery group
+ enableEndpointDiscoveryKey = `endpoint_discovery_enabled` // optional
+ // External Credential Process
+ credentialProcessKey = `credential_process`
+
// DefaultSharedConfigProfile is the default profile to be used when
// loading configuration from the config files if another profile name
// is not provided.
)
type assumeRoleConfig struct {
- RoleARN string
- SourceProfile string
- ExternalID string
- MFASerial string
- RoleSessionName string
+ RoleARN string
+ SourceProfile string
+ CredentialSource string
+ ExternalID string
+ MFASerial string
+ RoleSessionName string
}
// sharedConfig represents the configuration fields of the SDK config files.
AssumeRole assumeRoleConfig
AssumeRoleSource *sharedConfig
+ // An external process to request credentials
+ CredentialProcess string
+
// Region is the region the SDK should use for looking up AWS service endpoints
// and signing requests.
//
// region
Region string
+
+ // EnableEndpointDiscovery can be enabled in the shared config by setting
+ // endpoint_discovery_enabled to true
+ //
+ // endpoint_discovery_enabled = true
+ EnableEndpointDiscovery *bool
}
type sharedConfigFile struct {
Filename string
- IniData *ini.File
+ IniData ini.Sections
}
// loadSharedConfig retrieves the configuration from the list of files
files := make([]sharedConfigFile, 0, len(filenames))
for _, filename := range filenames {
- b, err := ioutil.ReadFile(filename)
- if err != nil {
+ sections, err := ini.OpenFile(filename)
+ if aerr, ok := err.(awserr.Error); ok && aerr.Code() == ini.ErrCodeUnableToReadFile {
// Skip files which can't be opened and read for whatever reason
continue
- }
-
- f, err := ini.Load(b)
- if err != nil {
+ } else if err != nil {
return nil, SharedConfigLoadError{Filename: filename, Err: err}
}
files = append(files, sharedConfigFile{
- Filename: filename, IniData: f,
+ Filename: filename, IniData: sections,
})
}
func (cfg *sharedConfig) setAssumeRoleSource(origProfile string, files []sharedConfigFile) error {
var assumeRoleSrc sharedConfig
+ if len(cfg.AssumeRole.CredentialSource) > 0 {
+ // setAssumeRoleSource is only called when source_profile is found.
+ // If both source_profile and credential_source are set, then
+ // ErrSharedConfigSourceCollision will be returned
+ return ErrSharedConfigSourceCollision
+ }
+
// Multiple level assume role chains are not support
if cfg.AssumeRole.SourceProfile == origProfile {
assumeRoleSrc = *cfg
// if a config file only includes aws_access_key_id but no aws_secret_access_key
// the aws_access_key_id will be ignored.
func (cfg *sharedConfig) setFromIniFile(profile string, file sharedConfigFile) error {
- section, err := file.IniData.GetSection(profile)
- if err != nil {
+ section, ok := file.IniData.GetSection(profile)
+ if !ok {
// Fallback to to alternate profile name: profile <name>
- section, err = file.IniData.GetSection(fmt.Sprintf("profile %s", profile))
- if err != nil {
- return SharedConfigProfileNotExistsError{Profile: profile, Err: err}
+ section, ok = file.IniData.GetSection(fmt.Sprintf("profile %s", profile))
+ if !ok {
+ return SharedConfigProfileNotExistsError{Profile: profile, Err: nil}
}
}
// Shared Credentials
- akid := section.Key(accessKeyIDKey).String()
- secret := section.Key(secretAccessKey).String()
+ akid := section.String(accessKeyIDKey)
+ secret := section.String(secretAccessKey)
if len(akid) > 0 && len(secret) > 0 {
cfg.Creds = credentials.Value{
AccessKeyID: akid,
SecretAccessKey: secret,
- SessionToken: section.Key(sessionTokenKey).String(),
+ SessionToken: section.String(sessionTokenKey),
ProviderName: fmt.Sprintf("SharedConfigCredentials: %s", file.Filename),
}
}
// Assume Role
- roleArn := section.Key(roleArnKey).String()
- srcProfile := section.Key(sourceProfileKey).String()
- if len(roleArn) > 0 && len(srcProfile) > 0 {
+ roleArn := section.String(roleArnKey)
+ srcProfile := section.String(sourceProfileKey)
+ credentialSource := section.String(credentialSourceKey)
+ hasSource := len(srcProfile) > 0 || len(credentialSource) > 0
+ if len(roleArn) > 0 && hasSource {
cfg.AssumeRole = assumeRoleConfig{
- RoleARN: roleArn,
- SourceProfile: srcProfile,
- ExternalID: section.Key(externalIDKey).String(),
- MFASerial: section.Key(mfaSerialKey).String(),
- RoleSessionName: section.Key(roleSessionNameKey).String(),
+ RoleARN: roleArn,
+ SourceProfile: srcProfile,
+ CredentialSource: credentialSource,
+ ExternalID: section.String(externalIDKey),
+ MFASerial: section.String(mfaSerialKey),
+ RoleSessionName: section.String(roleSessionNameKey),
}
}
+ // `credential_process`
+ if credProc := section.String(credentialProcessKey); len(credProc) > 0 {
+ cfg.CredentialProcess = credProc
+ }
+
// Region
- if v := section.Key(regionKey).String(); len(v) > 0 {
+ if v := section.String(regionKey); len(v) > 0 {
cfg.Region = v
}
+ // Endpoint discovery
+ if section.Has(enableEndpointDiscoveryKey) {
+ v := section.Bool(enableEndpointDiscoveryKey)
+ cfg.EnableEndpointDiscovery = &v
+ }
+
return nil
}