Skip to content

Commit 2f77c81

Browse files
kllinzyprateekchaudhry
authored andcommitted
use the same provider precedence in linux/windows, make ECS-A prefer SSM over EC2 Creds
1 parent 4ca8d9d commit 2f77c81

File tree

7 files changed

+214
-316
lines changed

7 files changed

+214
-316
lines changed

agent/vendor/github.com/aws/amazon-ecs-agent/ecs-agent/credentials/providers/instance_credentials_provider.go

Lines changed: 90 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

agent/vendor/github.com/aws/amazon-ecs-agent/ecs-agent/credentials/providers/instance_credentials_provider_linux.go

Lines changed: 0 additions & 49 deletions
This file was deleted.

agent/vendor/github.com/aws/amazon-ecs-agent/ecs-agent/credentials/providers/instance_credentials_provider_windows.go

Lines changed: 0 additions & 107 deletions
This file was deleted.

ecs-agent/credentials/providers/instance_credentials_provider.go

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,70 @@ func (p *InstanceCredentialsProvider) Retrieve(ctx context.Context) (aws.Credent
3232
return aws.Credentials{}, err
3333
}
3434

35+
// NewInstanceCredentialsCache returns a chain of instance credentials providers wrapped in a credentials cache.
36+
// The instance credentials chain is the default credentials chain plus the "rotating shared credentials provider",
37+
// so credentials will be checked in this order:
38+
//
39+
// 1. Env vars (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY).
40+
//
41+
// 2. Shared credentials file (https://docs.aws.amazon.com/ses/latest/DeveloperGuide/create-shared-credentials-file.html) (file at ~/.aws/credentials containing access key id and secret access key).
42+
//
43+
// 3. EC2 role credentials. This is an IAM role that the user specifies when they launch their EC2 container instance (ie ecsInstanceRole (https://docs.aws.amazon.com/AmazonECS/latest/developerguide/instance_IAM_role.html)).
44+
//
45+
// 4. Rotating shared credentials file located at /rotatingcreds/credentials
46+
//
47+
// The default credential chain provided by the SDK includes:
48+
// * EnvProvider
49+
// * SharedCredentialsProvider
50+
// * RemoteCredProvider (EC2RoleProvider)
51+
//
52+
// In the case of ECS-A, there are a couple considerations:
53+
//
54+
// * The `SharedCredentialsProvider` takes
55+
// precedence over the `RotatingSharedCredentialsProvider` and this results
56+
// in the credentials not being refreshed. To mitigate this issue, we will
57+
// reorder the credential chain and ensure that `RotatingSharedCredentialsProvider`
58+
// takes precedence over the `SharedCredentialsProvider` for ECS-A.
59+
//
60+
// * On EC2, the `EC2RoleProvider` takes precedence over the `RotatingSharedCredentialsProvider`.
61+
// Prioritizing `RotatingSharedCredentialsProvider` over the
62+
// `EC2RoleProvider` ensures that SSM credentials will be used if they are available,
63+
// and the EC2 credentials will only be used as a last-resort.
64+
65+
func NewInstanceCredentialsCache(
66+
isExternal bool,
67+
rotatingSharedCreds aws.CredentialsProvider,
68+
imdsClient ec2rolecreds.GetMetadataAPIClient,
69+
) *aws.CredentialsCache {
70+
var providers []aws.CredentialsProvider
71+
72+
// If imdsClient is nil, the SDK will default to the EC2 IMDS client.
73+
// Pass a non-nil imdsClient to stub it out in tests.
74+
options := func(o *ec2rolecreds.Options) {
75+
o.Client = imdsClient
76+
}
77+
78+
if isExternal {
79+
providers = []aws.CredentialsProvider{
80+
envCreds,
81+
rotatingSharedCreds,
82+
sharedCreds,
83+
ec2rolecreds.New(options),
84+
}
85+
} else {
86+
providers = []aws.CredentialsProvider{
87+
defaultCreds(options),
88+
rotatingSharedCreds,
89+
}
90+
}
91+
92+
return aws.NewCredentialsCache(
93+
&InstanceCredentialsProvider{
94+
providers: providers,
95+
},
96+
)
97+
}
98+
3599
func defaultCreds(options func(*ec2rolecreds.Options)) aws.CredentialsProviderFunc {
36100
return func(ctx context.Context) (aws.Credentials, error) {
37101
cfg, err := config.LoadDefaultConfig(ctx, config.WithEC2RoleCredentialOptions(options))
@@ -43,3 +107,29 @@ func defaultCreds(options func(*ec2rolecreds.Options)) aws.CredentialsProviderFu
43107

44108
}
45109
}
110+
111+
var envCreds = aws.CredentialsProviderFunc(func(ctx context.Context) (aws.Credentials, error) {
112+
cfg, err := config.NewEnvConfig()
113+
return cfg.Credentials, err
114+
})
115+
116+
var sharedCreds = aws.CredentialsProviderFunc(func(ctx context.Context) (aws.Credentials, error) {
117+
// Load the env config to get shared config values from env vars (AWS_PROFILE and AWS_SHARED_CREDENTIALS_FILE).
118+
envCfg, err := config.NewEnvConfig()
119+
if err != nil {
120+
return aws.Credentials{}, err
121+
}
122+
123+
// If shared config env vars are unset, use the default values.
124+
if envCfg.SharedConfigProfile == "" {
125+
envCfg.SharedConfigProfile = config.DefaultSharedConfigProfile
126+
}
127+
if envCfg.SharedCredentialsFile == "" {
128+
envCfg.SharedCredentialsFile = config.DefaultSharedCredentialsFilename()
129+
}
130+
131+
cfg, err := config.LoadSharedConfigProfile(ctx, envCfg.SharedConfigProfile, func(option *config.LoadSharedConfigOptions) {
132+
option.CredentialsFiles = []string{envCfg.SharedCredentialsFile}
133+
})
134+
return cfg.Credentials, err
135+
})

0 commit comments

Comments
 (0)