support ExternalID in AWS Provider when assuming a role

This commit is contained in:
pg2000 2022-06-15 17:52:05 +02:00
parent c5fc57f977
commit 4ace07f0a2
No known key found for this signature in database
GPG Key ID: AD3472A5DEB9109B
5 changed files with 27 additions and 5 deletions

View File

@ -196,6 +196,7 @@ func main() {
BatchChangeInterval: cfg.AWSBatchChangeInterval, BatchChangeInterval: cfg.AWSBatchChangeInterval,
EvaluateTargetHealth: cfg.AWSEvaluateTargetHealth, EvaluateTargetHealth: cfg.AWSEvaluateTargetHealth,
AssumeRole: cfg.AWSAssumeRole, AssumeRole: cfg.AWSAssumeRole,
AssumeRoleExternalId: cfg.AWSAssumeRoleExternalId,
APIRetries: cfg.AWSAPIRetries, APIRetries: cfg.AWSAPIRetries,
PreferCNAME: cfg.AWSPreferCNAME, PreferCNAME: cfg.AWSPreferCNAME,
DryRun: cfg.DryRun, DryRun: cfg.DryRun,
@ -208,7 +209,7 @@ func main() {
log.Infof("Registry \"%s\" cannot be used with AWS Cloud Map. Switching to \"aws-sd\".", cfg.Registry) log.Infof("Registry \"%s\" cannot be used with AWS Cloud Map. Switching to \"aws-sd\".", cfg.Registry)
cfg.Registry = "aws-sd" cfg.Registry = "aws-sd"
} }
p, err = awssd.NewAWSSDProvider(domainFilter, cfg.AWSZoneType, cfg.AWSAssumeRole, cfg.DryRun, cfg.AWSSDServiceCleanup, cfg.TXTOwnerID) p, err = awssd.NewAWSSDProvider(domainFilter, cfg.AWSZoneType, cfg.AWSAssumeRole, cfg.AWSAssumeRoleExternalId, cfg.DryRun, cfg.AWSSDServiceCleanup, cfg.TXTOwnerID)
case "azure-dns", "azure": case "azure-dns", "azure":
p, err = azure.NewAzureProvider(cfg.AzureConfigFile, domainFilter, zoneNameFilter, zoneIDFilter, cfg.AzureResourceGroup, cfg.AzureUserAssignedIdentityClientID, cfg.DryRun) p, err = azure.NewAzureProvider(cfg.AzureConfigFile, domainFilter, zoneNameFilter, zoneIDFilter, cfg.AzureResourceGroup, cfg.AzureUserAssignedIdentityClientID, cfg.DryRun)
case "azure-private-dns": case "azure-private-dns":

View File

@ -83,6 +83,7 @@ type Config struct {
AWSZoneType string AWSZoneType string
AWSZoneTagFilter []string AWSZoneTagFilter []string
AWSAssumeRole string AWSAssumeRole string
AWSAssumeRoleExternalId string
AWSBatchChangeSize int AWSBatchChangeSize int
AWSBatchChangeInterval time.Duration AWSBatchChangeInterval time.Duration
AWSEvaluateTargetHealth bool AWSEvaluateTargetHealth bool
@ -227,6 +228,7 @@ var defaultConfig = &Config{
AWSZoneType: "", AWSZoneType: "",
AWSZoneTagFilter: []string{}, AWSZoneTagFilter: []string{},
AWSAssumeRole: "", AWSAssumeRole: "",
AWSAssumeRoleExternalId: "",
AWSBatchChangeSize: 1000, AWSBatchChangeSize: 1000,
AWSBatchChangeInterval: time.Second, AWSBatchChangeInterval: time.Second,
AWSEvaluateTargetHealth: true, AWSEvaluateTargetHealth: true,
@ -423,6 +425,7 @@ func (cfg *Config) ParseFlags(args []string) error {
app.Flag("aws-zone-type", "When using the AWS provider, filter for zones of this type (optional, options: public, private)").Default(defaultConfig.AWSZoneType).EnumVar(&cfg.AWSZoneType, "", "public", "private") app.Flag("aws-zone-type", "When using the AWS provider, filter for zones of this type (optional, options: public, private)").Default(defaultConfig.AWSZoneType).EnumVar(&cfg.AWSZoneType, "", "public", "private")
app.Flag("aws-zone-tags", "When using the AWS provider, filter for zones with these tags").Default("").StringsVar(&cfg.AWSZoneTagFilter) app.Flag("aws-zone-tags", "When using the AWS provider, filter for zones with these tags").Default("").StringsVar(&cfg.AWSZoneTagFilter)
app.Flag("aws-assume-role", "When using the AWS provider, assume this IAM role. Useful for hosted zones in another AWS account. Specify the full ARN, e.g. `arn:aws:iam::123455567:role/external-dns` (optional)").Default(defaultConfig.AWSAssumeRole).StringVar(&cfg.AWSAssumeRole) app.Flag("aws-assume-role", "When using the AWS provider, assume this IAM role. Useful for hosted zones in another AWS account. Specify the full ARN, e.g. `arn:aws:iam::123455567:role/external-dns` (optional)").Default(defaultConfig.AWSAssumeRole).StringVar(&cfg.AWSAssumeRole)
app.Flag("aws-assume-role-external-id", "When using the AWS provider and assuming a role then specify this external id` (optional)").Default(defaultConfig.AWSAssumeRoleExternalId).StringVar(&cfg.AWSAssumeRoleExternalId)
app.Flag("aws-batch-change-size", "When using the AWS provider, set the maximum number of changes that will be applied in each batch.").Default(strconv.Itoa(defaultConfig.AWSBatchChangeSize)).IntVar(&cfg.AWSBatchChangeSize) app.Flag("aws-batch-change-size", "When using the AWS provider, set the maximum number of changes that will be applied in each batch.").Default(strconv.Itoa(defaultConfig.AWSBatchChangeSize)).IntVar(&cfg.AWSBatchChangeSize)
app.Flag("aws-batch-change-interval", "When using the AWS provider, set the interval between batch changes.").Default(defaultConfig.AWSBatchChangeInterval.String()).DurationVar(&cfg.AWSBatchChangeInterval) app.Flag("aws-batch-change-interval", "When using the AWS provider, set the interval between batch changes.").Default(defaultConfig.AWSBatchChangeInterval.String()).DurationVar(&cfg.AWSBatchChangeInterval)
app.Flag("aws-evaluate-target-health", "When using the AWS provider, set whether to evaluate the health of a DNS target (default: enabled, disable with --no-aws-evaluate-target-health)").Default(strconv.FormatBool(defaultConfig.AWSEvaluateTargetHealth)).BoolVar(&cfg.AWSEvaluateTargetHealth) app.Flag("aws-evaluate-target-health", "When using the AWS provider, set whether to evaluate the health of a DNS target (default: enabled, disable with --no-aws-evaluate-target-health)").Default(strconv.FormatBool(defaultConfig.AWSEvaluateTargetHealth)).BoolVar(&cfg.AWSEvaluateTargetHealth)

View File

@ -57,6 +57,7 @@ var (
AWSZoneType: "", AWSZoneType: "",
AWSZoneTagFilter: []string{""}, AWSZoneTagFilter: []string{""},
AWSAssumeRole: "", AWSAssumeRole: "",
AWSAssumeRoleExternalId: "",
AWSBatchChangeSize: 1000, AWSBatchChangeSize: 1000,
AWSBatchChangeInterval: time.Second, AWSBatchChangeInterval: time.Second,
AWSEvaluateTargetHealth: true, AWSEvaluateTargetHealth: true,
@ -157,6 +158,7 @@ var (
AWSZoneType: "private", AWSZoneType: "private",
AWSZoneTagFilter: []string{"tag=foo"}, AWSZoneTagFilter: []string{"tag=foo"},
AWSAssumeRole: "some-other-role", AWSAssumeRole: "some-other-role",
AWSAssumeRoleExternalId: "pg2000",
AWSBatchChangeSize: 100, AWSBatchChangeSize: 100,
AWSBatchChangeInterval: time.Second * 2, AWSBatchChangeInterval: time.Second * 2,
AWSEvaluateTargetHealth: false, AWSEvaluateTargetHealth: false,
@ -326,6 +328,7 @@ func TestParseFlags(t *testing.T) {
"--aws-zone-type=private", "--aws-zone-type=private",
"--aws-zone-tags=tag=foo", "--aws-zone-tags=tag=foo",
"--aws-assume-role=some-other-role", "--aws-assume-role=some-other-role",
"--aws-assume-role-external-id=pg2000",
"--aws-batch-change-size=100", "--aws-batch-change-size=100",
"--aws-batch-change-interval=2s", "--aws-batch-change-interval=2s",
"--aws-api-retries=13", "--aws-api-retries=13",
@ -438,6 +441,7 @@ func TestParseFlags(t *testing.T) {
"EXTERNAL_DNS_AWS_ZONE_TYPE": "private", "EXTERNAL_DNS_AWS_ZONE_TYPE": "private",
"EXTERNAL_DNS_AWS_ZONE_TAGS": "tag=foo", "EXTERNAL_DNS_AWS_ZONE_TAGS": "tag=foo",
"EXTERNAL_DNS_AWS_ASSUME_ROLE": "some-other-role", "EXTERNAL_DNS_AWS_ASSUME_ROLE": "some-other-role",
"EXTERNAL_DNS_AWS_ASSUME_ROLE_EXTERNAL_ID": "pg2000",
"EXTERNAL_DNS_AWS_BATCH_CHANGE_SIZE": "100", "EXTERNAL_DNS_AWS_BATCH_CHANGE_SIZE": "100",
"EXTERNAL_DNS_AWS_BATCH_CHANGE_INTERVAL": "2s", "EXTERNAL_DNS_AWS_BATCH_CHANGE_INTERVAL": "2s",
"EXTERNAL_DNS_AWS_EVALUATE_TARGET_HEALTH": "0", "EXTERNAL_DNS_AWS_EVALUATE_TARGET_HEALTH": "0",

View File

@ -170,6 +170,7 @@ type AWSConfig struct {
BatchChangeInterval time.Duration BatchChangeInterval time.Duration
EvaluateTargetHealth bool EvaluateTargetHealth bool
AssumeRole string AssumeRole string
AssumeRoleExternalId string
APIRetries int APIRetries int
PreferCNAME bool PreferCNAME bool
DryRun bool DryRun bool
@ -199,7 +200,13 @@ func NewAWSProvider(awsConfig AWSConfig) (*AWSProvider, error) {
if awsConfig.AssumeRole != "" { if awsConfig.AssumeRole != "" {
log.Infof("Assuming role: %s", awsConfig.AssumeRole) log.Infof("Assuming role: %s", awsConfig.AssumeRole)
session.Config.WithCredentials(stscreds.NewCredentials(session, awsConfig.AssumeRole)) if awsConfig.AssumeRole != "" {
session.Config.WithCredentials(stscreds.NewCredentials(session, awsConfig.AssumeRole, func(p *stscreds.AssumeRoleProvider) {
p.ExternalID = &awsConfig.AssumeRoleExternalId
}))
} else {
session.Config.WithCredentials(stscreds.NewCredentials(session, awsConfig.AssumeRole))
}
} }
provider := &AWSProvider{ provider := &AWSProvider{

View File

@ -88,7 +88,7 @@ type AWSSDProvider struct {
} }
// NewAWSSDProvider initializes a new AWS Cloud Map based Provider. // NewAWSSDProvider initializes a new AWS Cloud Map based Provider.
func NewAWSSDProvider(domainFilter endpoint.DomainFilter, namespaceType string, assumeRole string, dryRun, cleanEmptyService bool, ownerID string) (*AWSSDProvider, error) { func NewAWSSDProvider(domainFilter endpoint.DomainFilter, namespaceType string, assumeRole string, assumeRoleExternalId string, dryRun, cleanEmptyService bool, ownerID string) (*AWSSDProvider, error) {
config := aws.NewConfig() config := aws.NewConfig()
config = config.WithHTTPClient( config = config.WithHTTPClient(
@ -109,8 +109,15 @@ func NewAWSSDProvider(domainFilter endpoint.DomainFilter, namespaceType string,
} }
if assumeRole != "" { if assumeRole != "" {
log.Infof("Assuming role: %s", assumeRole) if assumeRoleExternalId != "" {
sess.Config.WithCredentials(stscreds.NewCredentials(sess, assumeRole)) log.Infof("Assuming role: %s with external id", assumeRole)
sess.Config.WithCredentials(stscreds.NewCredentials(sess, assumeRole, func(p *stscreds.AssumeRoleProvider) {
p.ExternalID = &assumeRoleExternalId
}))
} else {
log.Infof("Assuming role: %s", assumeRole)
sess.Config.WithCredentials(stscreds.NewCredentials(sess, assumeRole))
}
} }
sess.Handlers.Build.PushBack(request.MakeAddToUserAgentHandler("ExternalDNS", externaldns.Version)) sess.Handlers.Build.PushBack(request.MakeAddToUserAgentHandler("ExternalDNS", externaldns.Version))