From 62ce7086cb6b07a56f5df892f68e1081b808364d Mon Sep 17 00:00:00 2001 From: Kevin Neufeld Date: Fri, 31 Oct 2025 16:05:52 -0700 Subject: [PATCH] feat(Route53): Add support for RoleArn and ExternalId Issue #3816 --- documentation/provider/route53.md | 16 ++++++++++++++++ go.mod | 2 +- providers/route53/route53Provider.go | 18 +++++++++++++++++- 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/documentation/provider/route53.md b/documentation/provider/route53.md index aeddf83e1c..fd058ad17b 100644 --- a/documentation/provider/route53.md +++ b/documentation/provider/route53.md @@ -59,6 +59,22 @@ Example: ``` {% endcode %} +Alternatively, this provider also supports `RoleArn` with an optional `ExternalId` + +Example: + +{% code title="creds.json" %} +```json +{ + "r53_main": { + "TYPE": "ROUTE53", + "RoleArn": "arn:aws:iam::123456789012:role/ExampleRole", + "ExternalId": "123456789012" + } +} +``` +{% endcode %} + You can find some other ways to authenticate to Route53 in the [go sdk configuration](https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html). ## Metadata diff --git a/go.mod b/go.mod index e62a86342d..7e67c08fd1 100644 --- a/go.mod +++ b/go.mod @@ -59,6 +59,7 @@ require ( require ( github.com/Azure/azure-sdk-for-go/sdk/azcore v1.19.1 github.com/G-Core/gcore-dns-sdk-go v0.3.3 + github.com/aws/aws-sdk-go-v2/service/sts v1.38.6 github.com/centralnicgroup-opensource/rtldev-middleware-go-sdk/v5 v5.0.18 github.com/containrrr/shoutrrr v0.8.0 github.com/failsafe-go/failsafe-go v0.9.0 @@ -95,7 +96,6 @@ require ( github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.9 // indirect github.com/aws/aws-sdk-go-v2/service/sso v1.29.6 // indirect github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.1 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.38.6 // indirect github.com/aws/smithy-go v1.23.0 // indirect github.com/bits-and-blooms/bitset v1.24.0 // indirect github.com/boombuler/barcode v1.0.1 // indirect diff --git a/providers/route53/route53Provider.go b/providers/route53/route53Provider.go index 1c610eadd7..075ca79da0 100644 --- a/providers/route53/route53Provider.go +++ b/providers/route53/route53Provider.go @@ -20,10 +20,12 @@ import ( "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/config" "github.com/aws/aws-sdk-go-v2/credentials" + "github.com/aws/aws-sdk-go-v2/credentials/stscreds" r53 "github.com/aws/aws-sdk-go-v2/service/route53" r53Types "github.com/aws/aws-sdk-go-v2/service/route53/types" r53d "github.com/aws/aws-sdk-go-v2/service/route53domains" r53dTypes "github.com/aws/aws-sdk-go-v2/service/route53domains/types" + "github.com/aws/aws-sdk-go-v2/service/sts" ) type route53Provider struct { @@ -50,7 +52,7 @@ func newRoute53(m map[string]string, _ json.RawMessage) (*route53Provider, error config.WithRegion("us-east-1"), } - keyID, secretKey, tokenID := m["KeyId"], m["SecretKey"], m["Token"] + keyID, secretKey, tokenID, roleArn, externalId := m["KeyId"], m["SecretKey"], m["Token"], m["RoleArn"], m["ExternalId"] // Token is optional and left empty unless required if keyID != "" || secretKey != "" { optFns = append(optFns, config.WithCredentialsProvider(credentials.NewStaticCredentialsProvider(keyID, secretKey, tokenID))) @@ -61,6 +63,20 @@ func newRoute53(m map[string]string, _ json.RawMessage) (*route53Provider, error return nil, err } + if roleArn != "" { + stsClient := sts.NewFromConfig(config) + sessionName := fmt.Sprintf("dnscontrol-route53-%d", time.Now().Unix()) + + var assumeOpts []func(*stscreds.AssumeRoleOptions) + if externalId != "" { + assumeOpts = append(assumeOpts, func(o *stscreds.AssumeRoleOptions) { o.ExternalID = aws.String(externalId) }) + } + assumeOpts = append(assumeOpts, func(o *stscreds.AssumeRoleOptions) { o.RoleSessionName = sessionName }) + + stsCredsProvider := stscreds.NewAssumeRoleProvider(stsClient, roleArn, assumeOpts...) + config.Credentials = aws.NewCredentialsCache(stsCredsProvider) + } + var dls *string if val, ok := m["DelegationSet"]; ok { printer.Printf("ROUTE53 DelegationSet %s configured\n", val)