Skip to content

Commit

Permalink
load and test imdsv1 disable in cfgs
Browse files Browse the repository at this point in the history
  • Loading branch information
lucix-aws committed Oct 6, 2023
1 parent 592707c commit de57389
Show file tree
Hide file tree
Showing 7 changed files with 113 additions and 1 deletion.
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

0 comments on commit de57389

Please sign in to comment.