diff --git a/provider/aws.go b/provider/aws.go index 4a5ee5cf70..00f08bb9e5 100644 --- a/provider/aws.go +++ b/provider/aws.go @@ -26,6 +26,7 @@ import ( "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/route53" + "github.com/aws/aws-sdk-go/aws/awserr" "github.com/kubernetes-incubator/external-dns/endpoint" "github.com/kubernetes-incubator/external-dns/plan" ) @@ -63,6 +64,7 @@ type Route53API interface { ChangeResourceRecordSets(*route53.ChangeResourceRecordSetsInput) (*route53.ChangeResourceRecordSetsOutput, error) CreateHostedZone(*route53.CreateHostedZoneInput) (*route53.CreateHostedZoneOutput, error) ListHostedZonesPages(input *route53.ListHostedZonesInput, fn func(resp *route53.ListHostedZonesOutput, lastPage bool) (shouldContinue bool)) error + GetHostedZone(input *route53.GetHostedZoneInput) (*route53.GetHostedZoneOutput, error) } // AWSProvider is an implementation of Provider for AWS Route53. @@ -110,7 +112,36 @@ func (p *AWSProvider) Zones() (map[string]*route53.HostedZone, error) { f := func(resp *route53.ListHostedZonesOutput, lastPage bool) (shouldContinue bool) { for _, zone := range resp.HostedZones { if p.domainFilter.Match(aws.StringValue(zone.Name)) { + + hostedZoneOutput, err := p.client.GetHostedZone(&route53.GetHostedZoneInput{ + Id: zone.Id, + }) + + if err != nil { + if awsErr, ok := err.(awserr.Error); ok { + + if awsErr.Code() == "AccessDenied" { + log.WithField("ID", aws.StringValue(zone.Id)). + WithField("Name", aws.StringValue(zone.Name)). + WithField("Private", aws.BoolValue(zone.Config.PrivateZone)). + Debugf("Skipping the Zone, because access is denied.") + continue + } else { + log.WithField("Code", awsErr.Code()).WithField("Message", awsErr.Message()).WithField("Err", awsErr.OrigErr()).Errorf("AWS Route53 API Error") + return false + } + } + } + + log. + WithField("ID", aws.StringValue(hostedZoneOutput.HostedZone.Id)). + WithField("Name", aws.StringValue(hostedZoneOutput.HostedZone.Name)). + WithField("ResourceRecordSetCount", aws.Int64Value(hostedZoneOutput.HostedZone.ResourceRecordSetCount)). + WithField("Private", aws.BoolValue(hostedZoneOutput.HostedZone.Config.PrivateZone)). + Debugf("Zone Info") + zones[aws.StringValue(zone.Id)] = zone + } } diff --git a/provider/aws_test.go b/provider/aws_test.go index 72e1aa2916..66262914d4 100644 --- a/provider/aws_test.go +++ b/provider/aws_test.go @@ -27,6 +27,9 @@ import ( "github.com/kubernetes-incubator/external-dns/internal/testutils" "github.com/kubernetes-incubator/external-dns/plan" + "errors" + + "github.com/aws/aws-sdk-go/aws/awserr" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -137,12 +140,31 @@ func (r *Route53APIStub) CreateHostedZone(input *route53.CreateHostedZoneInput) return nil, fmt.Errorf("Error creating hosted DNS zone: %s already exists", id) } r.zones[id] = &route53.HostedZone{ - Id: aws.String(id), - Name: aws.String(name), + Id: aws.String(id), + Name: aws.String(name), + Config: input.HostedZoneConfig, } return &route53.CreateHostedZoneOutput{HostedZone: r.zones[id]}, nil } +func (r *Route53APIStub) GetHostedZone(input *route53.GetHostedZoneInput) (*route53.GetHostedZoneOutput, error) { + + if aws.StringValue(input.Id) == "/hostedzone/accessdenied.com." { + return nil, awserr.New("AccessDenied", "AccessDenied", errors.New("AccessDenied")) + + } + id := "/hostedzone/" + aws.StringValue(input.Id) + + return &route53.GetHostedZoneOutput{HostedZone: &route53.HostedZone{ + Id: aws.String(id), + Name: aws.String("testing"), // value is not important here + Config: &route53.HostedZoneConfig{ + PrivateZone: aws.Bool(false), + }, + ResourceRecordSetCount: aws.Int64(1), + }}, nil +} + func TestAWSZones(t *testing.T) { provider := newAWSProvider(t, NewDomainFilter([]string{"ext-dns-test-2.teapot.zalan.do."}), false, []*endpoint.Endpoint{}) @@ -597,6 +619,9 @@ func createAWSZone(t *testing.T, provider *AWSProvider, zone *route53.HostedZone params := &route53.CreateHostedZoneInput{ CallerReference: aws.String("external-dns.alpha.kubernetes.io/test-zone"), Name: zone.Name, + HostedZoneConfig: &route53.HostedZoneConfig{ + PrivateZone: zone.Config.PrivateZone, + }, } if _, err := provider.client.CreateHostedZone(params); err != nil { @@ -673,16 +698,33 @@ func newAWSProvider(t *testing.T, domainFilter DomainFilter, dryRun bool, record createAWSZone(t, provider, &route53.HostedZone{ Id: aws.String("/hostedzone/zone-1.ext-dns-test-2.teapot.zalan.do."), Name: aws.String("zone-1.ext-dns-test-2.teapot.zalan.do."), + Config: &route53.HostedZoneConfig{ + PrivateZone: aws.Bool(false), + }, }) createAWSZone(t, provider, &route53.HostedZone{ Id: aws.String("/hostedzone/zone-2.ext-dns-test-2.teapot.zalan.do."), Name: aws.String("zone-2.ext-dns-test-2.teapot.zalan.do."), + Config: &route53.HostedZoneConfig{ + PrivateZone: aws.Bool(false), + }, }) createAWSZone(t, provider, &route53.HostedZone{ Id: aws.String("/hostedzone/zone-3.ext-dns-test-2.teapot.zalan.do."), Name: aws.String("zone-3.ext-dns-test-2.teapot.zalan.do."), + Config: &route53.HostedZoneConfig{ + PrivateZone: aws.Bool(false), + }, + }) + + createAWSZone(t, provider, &route53.HostedZone{ + Id: aws.String("/hostedzone/accessdenied.com."), + Name: aws.String("accessdenied.com."), + Config: &route53.HostedZoneConfig{ + PrivateZone: aws.Bool(false), + }, }) setupAWSRecords(t, provider, records)