From 815ebe50f62f05e5f79e27b09a46861ce63875aa Mon Sep 17 00:00:00 2001 From: Bryan Boreham Date: Wed, 10 Sep 2025 11:48:24 +0100 Subject: [PATCH] [ENHANCEMENT] AWS SD: Add optional external_id field AWS recommends that roles use an external ID to avoid accidentally granting access to the wrong account. Signed-off-by: Bryan Boreham --- discovery/aws/ec2.go | 7 ++++++- discovery/aws/lightsail.go | 7 ++++++- docs/configuration/configuration.md | 6 ++++++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/discovery/aws/ec2.go b/discovery/aws/ec2.go index 539cd84c4f..6e14108077 100644 --- a/discovery/aws/ec2.go +++ b/discovery/aws/ec2.go @@ -93,6 +93,7 @@ type EC2SDConfig struct { SecretKey config.Secret `yaml:"secret_key,omitempty"` Profile string `yaml:"profile,omitempty"` RoleARN string `yaml:"role_arn,omitempty"` + ExternalID string `yaml:"external_id,omitempty"` RefreshInterval model.Duration `yaml:"refresh_interval,omitempty"` Port int `yaml:"port"` Filters []*EC2Filter `yaml:"filters"` @@ -219,7 +220,11 @@ func (d *EC2Discovery) ec2Client(ctx context.Context) (ec2Client, error) { // If the role ARN is set, assume the role to get credentials and set the credentials provider in the config. if d.cfg.RoleARN != "" { - assumeProvider := stscreds.NewAssumeRoleProvider(sts.NewFromConfig(cfg), d.cfg.RoleARN) + assumeProvider := stscreds.NewAssumeRoleProvider(sts.NewFromConfig(cfg), d.cfg.RoleARN, func(o *stscreds.AssumeRoleOptions) { + if d.cfg.ExternalID != "" { + o.ExternalID = aws.String(d.cfg.ExternalID) + } + }) cfg.Credentials = aws.NewCredentialsCache(assumeProvider) } diff --git a/discovery/aws/lightsail.go b/discovery/aws/lightsail.go index 5c356c8c45..a0a11603c1 100644 --- a/discovery/aws/lightsail.go +++ b/discovery/aws/lightsail.go @@ -76,6 +76,7 @@ type LightsailSDConfig struct { SecretKey config.Secret `yaml:"secret_key,omitempty"` Profile string `yaml:"profile,omitempty"` RoleARN string `yaml:"role_arn,omitempty"` + ExternalID string `yaml:"external_id,omitempty"` RefreshInterval model.Duration `yaml:"refresh_interval,omitempty"` Port int `yaml:"port"` @@ -183,7 +184,11 @@ func (d *LightsailDiscovery) lightsailClient(ctx context.Context) (*lightsail.Cl // If the role ARN is set, assume the role to get credentials and set the credentials provider in the config. if d.cfg.RoleARN != "" { - assumeProvider := stscreds.NewAssumeRoleProvider(sts.NewFromConfig(cfg), d.cfg.RoleARN) + assumeProvider := stscreds.NewAssumeRoleProvider(sts.NewFromConfig(cfg), d.cfg.RoleARN, func(o *stscreds.AssumeRoleOptions) { + if d.cfg.ExternalID != "" { + o.ExternalID = aws.String(d.cfg.ExternalID) + } + }) cfg.Credentials = aws.NewCredentialsCache(assumeProvider) } diff --git a/docs/configuration/configuration.md b/docs/configuration/configuration.md index b3ea571b80..a4f12a5bdd 100644 --- a/docs/configuration/configuration.md +++ b/docs/configuration/configuration.md @@ -1208,6 +1208,9 @@ See below for the configuration options for EC2 discovery: # AWS Role ARN, an alternative to using AWS API keys. [ role_arn: ] +# Optional External ID that can go along with role_arn. +[ external_id: ] + # Refresh interval to re-read the instance list. [ refresh_interval: | default = 60s ] @@ -2068,6 +2071,9 @@ See below for the configuration options for Lightsail discovery: # AWS Role ARN, an alternative to using AWS API keys. [ role_arn: ] +# Optional External ID that can go along with role_arn. +[ external_id: ] + # Refresh interval to re-read the instance list. [ refresh_interval: | default = 60s ]