Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds logging for authentication flow #146

Merged
merged 4 commits into from
Feb 25, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions aws_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,12 @@ func GetAwsConfig(ctx context.Context, c *Config) (aws.Config, error) {
}
}

credentialsProvider, source, err := getCredentialsProvider(ctx, c)
credentialsProvider, initialSource, err := getCredentialsProvider(ctx, c)
if err != nil {
return aws.Config{}, err
}
creds, _ := credentialsProvider.Retrieve(ctx)
log.Printf("[INFO] Retrieved credentials from %q", creds.Source)

var retryer aws.Retryer
retryer = retry.NewStandard()
Expand All @@ -65,7 +67,7 @@ func GetAwsConfig(ctx context.Context, c *Config) (aws.Config, error) {
return retryer
}),
)
if source == ec2rolecreds.ProviderName {
if initialSource == ec2rolecreds.ProviderName {
loadOptions = append(
loadOptions,
config.WithEC2IMDSRegion(),
Expand Down
42 changes: 42 additions & 0 deletions aws_config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -845,6 +845,48 @@ aws_secret_access_key = DefaultSharedCredentialsSecretKey
[some-profile]
aws_access_key_id = DefaultSharedCredentialsAccessKey
aws_secret_access_key = DefaultSharedCredentialsSecretKey
`,
},
{
Config: &Config{},
Description: "AWS_ACCESS_KEY_ID overrides AWS_PROFILE",
EnvironmentVariables: map[string]string{
"AWS_ACCESS_KEY_ID": servicemocks.MockEnvAccessKey,
"AWS_SECRET_ACCESS_KEY": servicemocks.MockEnvSecretKey,
"AWS_PROFILE": "SharedCredentialsProfile",
},
SharedCredentialsFile: `
[default]
aws_access_key_id = DefaultSharedCredentialsAccessKey
aws_secret_access_key = DefaultSharedCredentialsSecretKey

[SharedCredentialsProfile]
aws_access_key_id = ProfileSharedCredentialsAccessKey
aws_secret_access_key = ProfileSharedCredentialsSecretKey
`,
MockStsEndpoints: []*servicemocks.MockEndpoint{
servicemocks.MockStsGetCallerIdentityValidEndpoint,
},
ExpectedCredentialsValue: mockdata.MockEnvCredentials,
},
{
Config: &Config{
Region: "us-east-1",
},
Description: "AWS_ACCESS_KEY_ID does not override invalid profile name from envvar",
EnvironmentVariables: map[string]string{
"AWS_ACCESS_KEY_ID": servicemocks.MockEnvAccessKey,
"AWS_SECRET_ACCESS_KEY": servicemocks.MockEnvSecretKey,
"AWS_PROFILE": "no-such-profile",
},
ExpectedError: func(err error) bool {
var e config.SharedConfigProfileNotExistError
return errors.As(err, &e)
},
SharedCredentialsFile: `
[some-profile]
aws_access_key_id = DefaultSharedCredentialsAccessKey
aws_secret_access_key = DefaultSharedCredentialsSecretKey
`,
},
}
Expand Down
87 changes: 66 additions & 21 deletions credentials.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"context"
"fmt"
"log"
"os"
"strings"

"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/config"
Expand Down Expand Up @@ -33,45 +35,83 @@ func getCredentialsProvider(ctx context.Context, c *Config) (aws.CredentialsProv
return nil, "", err
}

if c.Profile != "" && os.Getenv("AWS_ACCESS_KEY_ID") != "" && os.Getenv("AWS_SECRET_ACCESS_KEY") != "" {
log.Printf(`[WARN] A Profile was specified along with the environment variables "AWS_ACCESS_KEY_ID" and "AWS_SECRET_ACCESS_KEY". ` +
"The Profile is now used instead of the environment variable credentials. This may lead to unexpected behavior.")
}

// The default AWS SDK authentication flow silently ignores invalid Profiles. Pre-validate that the Profile exists
// https://github.com/aws/aws-sdk-go-v2/issues/1591
profile := c.Profile
if profile == "" {
profile = envConfig.SharedConfigProfile
}

sharedCredentialsFiles, err := c.ResolveSharedCredentialsFiles()
if err != nil {
return nil, "", err
}
if len(sharedCredentialsFiles) == 0 {
sharedCredentialsFiles = []string{envConfig.SharedCredentialsFile}
}
if profile != "" {
sharedCredentialsFiles, err := c.ResolveSharedCredentialsFiles()
if err != nil {
return nil, "", err
}
if len(sharedCredentialsFiles) != 0 {
f := make([]string, len(sharedCredentialsFiles))
for i, v := range sharedCredentialsFiles {
f[i] = fmt.Sprintf(`"%s"`, v)
}
log.Printf("[DEBUG] Using shared credentials files from configuration: [%s]", strings.Join(f, ", "))
} else {
if envConfig.SharedCredentialsFile != "" {
log.Printf("[DEBUG] Using shared credentials file environment variables: %q", envConfig.SharedCredentialsFile)
sharedCredentialsFiles = []string{envConfig.SharedCredentialsFile}
}
}

sharedConfigFiles, err := c.ResolveSharedConfigFiles()
if err != nil {
return nil, "", err
}
if len(sharedConfigFiles) == 0 {
sharedConfigFiles = []string{envConfig.SharedConfigFile}
}
sharedConfigFiles, err := c.ResolveSharedConfigFiles()
if err != nil {
return nil, "", err
}
if len(sharedConfigFiles) != 0 {
f := make([]string, len(sharedConfigFiles))
for i, v := range sharedConfigFiles {
f[i] = fmt.Sprintf(`"%s"`, v)
}
log.Printf("[DEBUG] Using shared configuration files from configuration: %v", strings.Join(f, ", "))
} else {
if envConfig.SharedConfigFile != "" {
log.Printf("[DEBUG] Using shared configuration file environment variables: %s", envConfig.SharedConfigFile)
sharedConfigFiles = []string{envConfig.SharedConfigFile}
}
}

// The default AWS SDK authentication flow silently ignores invalid Profiles. Pre-validate that the Profile exists
// https://github.com/aws/aws-sdk-go-v2/issues/1591
if profile != "" {
_, err := config.LoadSharedConfigProfile(ctx, profile, func(opts *config.LoadSharedConfigOptions) {
_, err = config.LoadSharedConfigProfile(ctx, profile, func(opts *config.LoadSharedConfigOptions) {
opts.CredentialsFiles = sharedCredentialsFiles
opts.ConfigFiles = sharedConfigFiles
})
if err != nil {
return nil, "", err
}
}
// We need to validate both the configured and envvar named profiles for validity,
// but to use proper precedence, we only set the configured named profile
if c.Profile != "" {
log.Printf("[DEBUG] Using profile from configuration: %q", c.Profile)
loadOptions = append(
loadOptions,
config.WithSharedConfigProfile(c.Profile),
)

}

if c.AccessKey != "" || c.SecretKey != "" || c.Token != "" {
params := make([]string, 0, 3) //nolint:gomnd
if c.AccessKey != "" {
params = append(params, "access key")
}
if c.SecretKey != "" {
params = append(params, "secret key")
}
if c.Token != "" {
params = append(params, "token")
}
log.Printf("[DEBUG] Using %s from configuration", strings.Join(params, ", "))
loadOptions = append(
loadOptions,
config.WithCredentialsProvider(
Expand All @@ -91,13 +131,19 @@ func getCredentialsProvider(ctx context.Context, c *Config) (aws.CredentialsProv

creds, err := cfg.Credentials.Retrieve(ctx)
if err != nil {
if c.Profile != "" && os.Getenv("AWS_ACCESS_KEY_ID") != "" && os.Getenv("AWS_SECRET_ACCESS_KEY") != "" {
err = fmt.Errorf(`A Profile was specified along with the environment variables "AWS_ACCESS_KEY_ID" and "AWS_SECRET_ACCESS_KEY". The Profile is now used instead of the environment variable credentials.

Error: %w`, err)
}
return nil, "", c.NewNoValidCredentialSourcesError(err)
}

if c.AssumeRole == nil || c.AssumeRole.RoleARN == "" {
return cfg.Credentials, creds.Source, nil
}

log.Printf("[INFO] Retrieved initial credentials from %q", creds.Source)
provider, err := assumeRoleCredentialsProvider(ctx, cfg, c)

return provider, creds.Source, err
Expand All @@ -106,8 +152,7 @@ func getCredentialsProvider(ctx context.Context, c *Config) (aws.CredentialsProv
func assumeRoleCredentialsProvider(ctx context.Context, awsConfig aws.Config, c *Config) (aws.CredentialsProvider, error) {
ar := c.AssumeRole
// When assuming a role, we need to first authenticate the base credentials above, then assume the desired role
log.Printf("[INFO] Attempting to AssumeRole %s (SessionName: %q, ExternalId: %q)",
ar.RoleARN, ar.SessionName, ar.ExternalID)
log.Printf("[INFO] Assuming IAM Role %q (SessionName: %q, ExternalId: %q)", ar.RoleARN, ar.SessionName, ar.ExternalID)

client := stsClient(awsConfig, c)

Expand Down
42 changes: 42 additions & 0 deletions v2/awsv1shim/session_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -890,6 +890,48 @@ aws_secret_access_key = DefaultSharedCredentialsSecretKey
[some-profile]
aws_access_key_id = DefaultSharedCredentialsAccessKey
aws_secret_access_key = DefaultSharedCredentialsSecretKey
`,
},
{
Config: &awsbase.Config{},
Description: "AWS_ACCESS_KEY_ID overrides AWS_PROFILE",
EnvironmentVariables: map[string]string{
"AWS_ACCESS_KEY_ID": servicemocks.MockEnvAccessKey,
"AWS_SECRET_ACCESS_KEY": servicemocks.MockEnvSecretKey,
"AWS_PROFILE": "SharedCredentialsProfile",
},
SharedCredentialsFile: `
[default]
aws_access_key_id = DefaultSharedCredentialsAccessKey
aws_secret_access_key = DefaultSharedCredentialsSecretKey

[SharedCredentialsProfile]
aws_access_key_id = ProfileSharedCredentialsAccessKey
aws_secret_access_key = ProfileSharedCredentialsSecretKey
`,
MockStsEndpoints: []*servicemocks.MockEndpoint{
servicemocks.MockStsGetCallerIdentityValidEndpoint,
},
ExpectedCredentialsValue: mockdata.MockEnvCredentials,
},
{
Config: &awsbase.Config{
Region: "us-east-1",
},
Description: "AWS_ACCESS_KEY_ID does not override invalid profile name from envvar",
EnvironmentVariables: map[string]string{
"AWS_ACCESS_KEY_ID": servicemocks.MockEnvAccessKey,
"AWS_SECRET_ACCESS_KEY": servicemocks.MockEnvSecretKey,
"AWS_PROFILE": "no-such-profile",
},
ExpectedError: func(err error) bool {
var e configv2.SharedConfigProfileNotExistError
return errors.As(err, &e)
},
SharedCredentialsFile: `
[some-profile]
aws_access_key_id = DefaultSharedCredentialsAccessKey
aws_secret_access_key = DefaultSharedCredentialsSecretKey
`,
},
}
Expand Down