Skip to content

Commit

Permalink
Fix SkipMetadataApiCheck and remove now extraneous GetCredentialsFrom…
Browse files Browse the repository at this point in the history
…Metadata

Reference: #43

`GetCredentialsFromMetadata` is superseded by default AWS Go SDK credential handling, which is now called beforehand.
  • Loading branch information
bflad committed Jun 3, 2020
1 parent a5d46a2 commit a687c0d
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 86 deletions.
84 changes: 1 addition & 83 deletions awsauth.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import (
awsCredentials "github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds"
"github.com/aws/aws-sdk-go/aws/credentials/stscreds"
"github.com/aws/aws-sdk-go/aws/defaults"
"github.com/aws/aws-sdk-go/aws/ec2metadata"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/iam"
Expand Down Expand Up @@ -220,84 +219,6 @@ func GetCredentialsFromSession(c *Config) (*awsCredentials.Credentials, error) {
return creds, nil
}

// GetCredentialsFromMetadata returns credentials derived from and ECS or ECS
// metadata endpoint.
func GetCredentialsFromMetadata(c *Config) (*awsCredentials.Credentials, error) {
log.Printf("[INFO] Attempting to use metadata-derived credentials")
providers := []awsCredentials.Provider{}

// Build isolated HTTP client to avoid issues with globally-shared settings
client := cleanhttp.DefaultClient()
client.Timeout = DefaultMetadataClientTimeout

const userTimeoutEnvVar = "AWS_METADATA_TIMEOUT"
userTimeout := os.Getenv(userTimeoutEnvVar)
if userTimeout != "" {
newTimeout, err := time.ParseDuration(userTimeout)
if err == nil {
if newTimeout.Nanoseconds() > 0 {
client.Timeout = newTimeout
} else {
log.Printf("[WARN] Non-positive value of %s (%s) is meaningless, ignoring", userTimeoutEnvVar, newTimeout.String())
}
} else {
log.Printf("[WARN] Error converting %s to time.Duration: %s", userTimeoutEnvVar, err)
}
}

log.Printf("[INFO] Setting AWS metadata API timeout to %s", client.Timeout.String())
cfg := &aws.Config{
HTTPClient: client,
}
usedEndpoint := setOptionalEndpoint(cfg)

// Add the default AWS provider for ECS Task Roles if the relevant env variable is set
if uri := os.Getenv("AWS_CONTAINER_CREDENTIALS_RELATIVE_URI"); len(uri) > 0 {
providers = append(providers, defaults.RemoteCredProvider(*cfg, defaults.Handlers()))
log.Print("[INFO] ECS container credentials detected, RemoteCredProvider added to auth chain")
}

if !c.SkipMetadataApiCheck {
// Real AWS should reply to a simple metadata request.
// We check it actually does to ensure something else didn't just
// happen to be listening on the same IP:Port
ec2Session, err := session.NewSession(cfg)

if err != nil {
return nil, fmt.Errorf("error creating EC2 Metadata session: %w", err)
}

metadataClient := ec2metadata.New(ec2Session)
if metadataClient.Available() {
providers = append(providers, &ec2rolecreds.EC2RoleProvider{
Client: metadataClient,
})
log.Print("[INFO] AWS EC2 instance detected via default metadata" +
" API endpoint, EC2RoleProvider added to the auth chain")
} else {
if usedEndpoint == "" {
usedEndpoint = "default location"
}
log.Printf("[INFO] Ignoring AWS metadata API endpoint at %s "+
"as it doesn't return any instance-id", usedEndpoint)
}
}

// Validate the credentials before returning them
creds := awsCredentials.NewChainCredentials(providers)
cp, err := creds.Get()
if err != nil {
if IsAWSErr(err, "NoCredentialProviders", "") {
return nil, ErrNoValidCredentialSources
}
return nil, fmt.Errorf("Error deriving credentials from metadata: %s", err)
}

log.Printf("[INFO] Successfully derived credentials from metadata")
log.Printf("[INFO] AWS Auth provider used: %q", cp.ProviderName)
return creds, nil
}

// GetCredentials gets credentials from the environment, shared credentials,
// the session (which may include a credential process), or ECS/EC2 metadata endpoints.
// GetCredentials also validates the credentials and the ability to assume a role
Expand All @@ -324,10 +245,7 @@ func GetCredentials(c *Config) (*awsCredentials.Credentials, error) {
if IsAWSErr(err, "NoCredentialProviders", "") {
creds, err = GetCredentialsFromSession(c)
if err != nil {
creds, err = GetCredentialsFromMetadata(c)
if err != nil {
return nil, err
}
return nil, err
}
} else {
return nil, fmt.Errorf("Error loading credentials for AWS Provider: %w", err)
Expand Down
5 changes: 5 additions & 0 deletions session.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"log"
"net/http"
"os"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/endpoints"
Expand Down Expand Up @@ -64,6 +65,10 @@ func GetSessionOptions(c *Config) (*session.Options, error) {

// GetSession attempts to return valid AWS Go SDK session.
func GetSession(c *Config) (*session.Session, error) {
if c.SkipMetadataApiCheck {
os.Setenv("AWS_EC2_METADATA_DISABLED", "true")
}

options, err := GetSessionOptions(c)

if err != nil {
Expand Down
17 changes: 14 additions & 3 deletions session_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -910,9 +910,7 @@ aws_secret_access_key = DefaultSharedCredentialsSecretKey
"AWS_SDK_LOAD_CONFIG": "1",
},
ExpectedError: func(err error) bool {
// TODO: Return wrapped error
//return IsAWSErr(err, "CredentialRequiresARNError", "")
return err.Error() == errMsgNoValidCredentialSources
return IsAWSErr(err, "CredentialRequiresARNError", "")
},
SharedConfigurationFile: `
[profile SharedConfigurationProfile]
Expand All @@ -934,6 +932,19 @@ source_profile = SourceSharedCredentials
},
ExpectedRegion: "us-east-1",
},
{
Config: &Config{
Region: "us-east-1",
SkipMetadataApiCheck: true,
},
Description: "skip EC2 metadata API check",
EnableEc2MetadataServer: true,
ExpectedError: func(err error) bool {
// TODO: https://github.com/hashicorp/aws-sdk-go-base/pull/42
return err.Error() == errMsgNoValidCredentialSources
},
ExpectedRegion: "us-east-1",
},
}

for _, testCase := range testCases {
Expand Down

0 comments on commit a687c0d

Please sign in to comment.