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

add configs to disable imdsv1 fallback #5015

Merged
merged 2 commits into from
Nov 1, 2023
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
2 changes: 2 additions & 0 deletions CHANGELOG_PENDING.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
### SDK Features

### SDK Enhancements
* `aws/ec2metadata`: Added environment and shared config support for disabling IMDSv1 fallback.
* Use env `AWS_EC2_METADATA_V1_DISABLED` or shared config `ec2_metadata_v1_disabled` accordingly.

### SDK Bugs
28 changes: 28 additions & 0 deletions aws/session/env_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,12 @@ type envConfig struct {
// AWS_EC2_METADATA_SERVICE_ENDPOINT_MODE=IPv6
EC2IMDSEndpointMode endpoints.EC2IMDSEndpointModeState

// Specifies that IMDS clients should not fallback to IMDSv1 if token
// requests fail.
//
// AWS_EC2_METADATA_V1_DISABLED=true
EC2IMDSv1Disabled *bool

// Specifies that SDK clients must resolve a dual-stack endpoint for
// services.
//
Expand Down Expand Up @@ -251,6 +257,9 @@ var (
ec2IMDSEndpointModeEnvKey = []string{
"AWS_EC2_METADATA_SERVICE_ENDPOINT_MODE",
}
ec2MetadataV1DisabledEnvKey = []string{
"AWS_EC2_METADATA_V1_DISABLED",
}
useCABundleKey = []string{
"AWS_CA_BUNDLE",
}
Expand Down Expand Up @@ -393,6 +402,7 @@ func envConfigLoad(enableSharedConfig bool) (envConfig, error) {
if err := setEC2IMDSEndpointMode(&cfg.EC2IMDSEndpointMode, ec2IMDSEndpointModeEnvKey); err != nil {
return envConfig{}, err
}
setBoolPtrFromEnvVal(&cfg.EC2IMDSv1Disabled, ec2MetadataV1DisabledEnvKey)

if err := setUseDualStackEndpointFromEnvVal(&cfg.UseDualStackEndpoint, awsUseDualStackEndpoint); err != nil {
return cfg, err
Expand All @@ -414,6 +424,24 @@ func setFromEnvVal(dst *string, keys []string) {
}
}

func setBoolPtrFromEnvVal(dst **bool, keys []string) {
for _, k := range keys {
value := os.Getenv(k)
if len(value) == 0 {
continue
}

switch {
case strings.EqualFold(value, "false"):
*dst = new(bool)
**dst = false
case strings.EqualFold(value, "true"):
*dst = new(bool)
**dst = true
}
}
}

func setEC2IMDSEndpointMode(mode *endpoints.EC2IMDSEndpointModeState, keys []string) error {
for _, k := range keys {
value := os.Getenv(k)
Expand Down
30 changes: 30 additions & 0 deletions aws/session/env_config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"strconv"
"testing"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/endpoints"
"github.com/aws/aws-sdk-go/awstesting"
Expand Down Expand Up @@ -467,6 +468,35 @@ func TestLoadEnvConfig(t *testing.T) {
},
WantErr: true,
},
33: {
Env: map[string]string{
"AWS_EC2_METADATA_V1_DISABLED": "fAlSe",
},
Config: envConfig{
SharedCredentialsFile: shareddefaults.SharedCredentialsFilename(),
SharedConfigFile: shareddefaults.SharedConfigFilename(),
EC2IMDSv1Disabled: aws.Bool(false),
},
},
34: {
Env: map[string]string{
"AWS_EC2_METADATA_V1_DISABLED": "tRuE",
},
Config: envConfig{
SharedCredentialsFile: shareddefaults.SharedCredentialsFilename(),
SharedConfigFile: shareddefaults.SharedConfigFilename(),
EC2IMDSv1Disabled: aws.Bool(true),
},
},
35: {
Env: map[string]string{
"AWS_EC2_METADATA_V1_DISABLED": "invalid",
},
Config: envConfig{
SharedCredentialsFile: shareddefaults.SharedCredentialsFilename(),
SharedConfigFile: shareddefaults.SharedConfigFilename(),
},
},
}

for i, c := range cases {
Expand Down
8 changes: 8 additions & 0 deletions aws/session/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -779,6 +779,14 @@ func mergeConfigSrcs(cfg, userCfg *aws.Config,
cfg.EndpointResolver = wrapEC2IMDSEndpoint(cfg.EndpointResolver, ec2IMDSEndpoint, endpointMode)
}

cfg.EC2MetadataEnableFallback = userCfg.EC2MetadataEnableFallback
if cfg.EC2MetadataEnableFallback == nil && envCfg.EC2IMDSv1Disabled != nil {
cfg.EC2MetadataEnableFallback = aws.Bool(!*envCfg.EC2IMDSv1Disabled)
}
if cfg.EC2MetadataEnableFallback == nil && sharedCfg.EC2IMDSv1Disabled != nil {
cfg.EC2MetadataEnableFallback = aws.Bool(!*sharedCfg.EC2IMDSv1Disabled)
}

cfg.S3UseARNRegion = userCfg.S3UseARNRegion
if cfg.S3UseARNRegion == nil {
cfg.S3UseARNRegion = &envCfg.S3UseARNRegion
Expand Down
10 changes: 10 additions & 0 deletions aws/session/shared_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@ const (
// EC2 IMDS Endpoint
ec2MetadataServiceEndpointKey = "ec2_metadata_service_endpoint"

// ECS IMDSv1 disable fallback
ec2MetadataV1DisabledKey = "ec2_metadata_v1_disabled"

// Use DualStack Endpoint Resolution
useDualStackEndpoint = "use_dualstack_endpoint"

Expand Down Expand Up @@ -179,6 +182,12 @@ type sharedConfig struct {
// ec2_metadata_service_endpoint=http://fd00:ec2::254
EC2IMDSEndpoint string

// Specifies that IMDS clients should not fallback to IMDSv1 if token
// requests fail.
//
// ec2_metadata_v1_disabled=true
EC2IMDSv1Disabled *bool

// Specifies that SDK clients must resolve a dual-stack endpoint for
// services.
//
Expand Down Expand Up @@ -434,6 +443,7 @@ func (cfg *sharedConfig) setFromIniFile(profile string, file sharedConfigFile, e
ec2MetadataServiceEndpointModeKey, file.Filename, err)
}
updateString(&cfg.EC2IMDSEndpoint, section, ec2MetadataServiceEndpointKey)
updateBoolPtr(&cfg.EC2IMDSv1Disabled, section, ec2MetadataV1DisabledKey)

updateUseDualStackEndpoint(&cfg.UseDualStackEndpoint, section, useDualStackEndpoint)

Expand Down
25 changes: 25 additions & 0 deletions aws/session/shared_config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"strings"
"testing"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/endpoints"
"github.com/aws/aws-sdk-go/internal/ini"
Expand Down Expand Up @@ -411,6 +412,30 @@ func TestLoadSharedConfig(t *testing.T) {
Profile: "sso-session-not-exist",
Err: fmt.Errorf("failed to find SSO session section, sso-session-lost"),
},
{
Filenames: []string{testConfigFilename},
Profile: "ec2-metadata-v1-disabled-false",
Expected: sharedConfig{
Profile: "ec2-metadata-v1-disabled-false",
EC2IMDSv1Disabled: aws.Bool(false),
},
},
{
Filenames: []string{testConfigFilename},
Profile: "ec2-metadata-v1-disabled-true",
Expected: sharedConfig{
Profile: "ec2-metadata-v1-disabled-true",
EC2IMDSv1Disabled: aws.Bool(true),
},
},
{
Filenames: []string{testConfigFilename},
Profile: "ec2-metadata-v1-disabled-invalid",
Expected: sharedConfig{
Profile: "ec2-metadata-v1-disabled-invalid",
EC2IMDSv1Disabled: aws.Bool(false),
},
},
}

for i, c := range cases {
Expand Down
11 changes: 10 additions & 1 deletion aws/session/testdata/shared_config
Original file line number Diff line number Diff line change
Expand Up @@ -203,4 +203,13 @@ sso_registration_scopes = sso:account:access
region = us-east-1
sso_session = sso-session-lost
sso_account_id = 123456789012
sso_role_name = testRole
sso_role_name = testRole

[profile ec2-metadata-v1-disabled-false]
ec2_metadata_v1_disabled=False

[profile ec2-metadata-v1-disabled-true]
ec2_metadata_v1_disabled=True

[profile ec2-metadata-v1-disabled-invalid]
ec2_metadata_v1_disabled=invalid