1
0
mirror of https://github.com/StackExchange/dnscontrol.git synced 2024-05-11 05:55:12 +00:00

Add R53_ZONE as an domain identifier (#1241)

Using R53_ZONE allows you to differentiate between split horizon
domains across zones.
This commit is contained in:
Vincent Hagen
2021-09-02 22:54:54 +02:00
committed by GitHub
parent 3fa5712232
commit 8c5db2e11c
5 changed files with 108 additions and 24 deletions

View File

@ -4,8 +4,12 @@ parameters:
- zone_id
---
R53_ZONE sets the required Route53 hosted zone id in a R53_ALIAS record.
R53_ZONE lets you specify the AWS Zone ID for an entire domain (D()) or a specific R53_ALIAS() record.
When used with D(), it sets the zone id of the domain. This can be used to differentiate between split horizon domains in public and private zones.
When used with R53_ALIAS() it sets the required Route53 hosted zone id in a R53_ALIAS record. See [https://stackexchange.github.io/dnscontrol/js#R53_ALIAS](R53_ALIAS's documentation) for details.
This directive has no impact when used in anything else than a R53_ALIAS.
Please refer to the R53_ALIAS directive for usage.

View File

@ -26,6 +26,10 @@ function initialize() {
defaultArgs = [];
}
function _isDomain(d) {
return _.isArray(d.nameservers) && _.isArray(d.records) && _.isString(d.name);
}
// Returns an array of domains which were registered so far during runtime
// Own function for compatibility reasons or if some day special processing would be required.
function getConfiguredDomains() {
@ -277,7 +281,9 @@ var R53_ALIAS = recordBuilder('R53_ALIAS', {
// R53_ZONE(zone_id)
function R53_ZONE(zone_id) {
return function (r) {
if (_.isObject(r.r53_alias)) {
if (_isDomain(r)) {
r.meta.zone_id = zone_id;
} else if (_.isObject(r.r53_alias)) {
r.r53_alias['zone_id'] = zone_id;
} else {
r.r53_alias = { zone_id: zone_id };

View File

@ -0,0 +1,7 @@
D('foo.com', 'none', R53_ZONE('Z2FTEDLFRTZ'));
D(
'foo.com!internal',
'none',
R53_ZONE('Z2FTEDLFRTF'),
R53_ALIAS('atest', 'A', 'foo.com.', R53_ZONE('Z2FTEDLFRTZ'))
);

View File

@ -0,0 +1,34 @@
{
"registrars": [],
"dns_providers": [],
"domains": [
{
"name": "foo.com",
"registrar": "none",
"dnsProviders": {},
"records": [],
"meta": {
"zone_id": "Z2FTEDLFRTZ"
}
},
{
"name": "foo.com!internal",
"registrar": "none",
"dnsProviders": {},
"records": [
{
"type": "R53_ALIAS",
"name": "atest",
"r53_alias": {
"type": "A",
"zone_id": "Z2FTEDLFRTZ"
},
"target": "foo.com."
}
],
"meta": {
"zone_id": "Z2FTEDLFRTF"
}
}
]
}

View File

@ -25,7 +25,8 @@ type route53Provider struct {
client *r53.Route53
registrar *r53d.Route53Domains
delegationSet *string
zones map[string]*r53.HostedZone
zonesById map[string]*r53.HostedZone
zonesByDomain map[string]*r53.HostedZone
originalRecords []*r53.ResourceRecordSet
}
@ -119,7 +120,7 @@ func withRetry(f func() error) {
func (r *route53Provider) ListZones() ([]string, error) {
var zones []string
// Assumes r.zones was filled already by newRoute53().
for i := range r.zones {
for i := range r.zonesByDomain {
zones = append(zones, i)
}
return zones, nil
@ -127,7 +128,8 @@ func (r *route53Provider) ListZones() ([]string, error) {
func (r *route53Provider) getZones() error {
var nextMarker *string
r.zones = make(map[string]*r53.HostedZone)
r.zonesByDomain = make(map[string]*r53.HostedZone)
r.zonesById = make(map[string]*r53.HostedZone)
for {
var out *r53.ListHostedZonesOutput
var err error
@ -143,7 +145,8 @@ func (r *route53Provider) getZones() error {
}
for _, z := range out.HostedZones {
domain := strings.TrimSuffix(*z.Name, ".")
r.zones[domain] = z
r.zonesByDomain[domain] = z
r.zonesById[parseZoneId(*z.Id)] = z
}
if out.NextMarker != nil {
nextMarker = out.NextMarker
@ -154,19 +157,27 @@ func (r *route53Provider) getZones() error {
return nil
}
type errNoExist struct {
type errDomainNoExist struct {
domain string
}
func (e errNoExist) Error() string {
type errZoneNoExist struct {
zoneId string
}
func (e errDomainNoExist) Error() string {
return fmt.Sprintf("Domain %s not found in your route 53 account", e.domain)
}
func (e errZoneNoExist) Error() string {
return fmt.Sprintf("Zone with id %s not found in your route 53 account", e.zoneId)
}
func (r *route53Provider) GetNameservers(domain string) ([]*models.Nameserver, error) {
zone, ok := r.zones[domain]
zone, ok := r.zonesByDomain[domain]
if !ok {
return nil, errNoExist{domain}
return nil, errDomainNoExist{domain}
}
var z *r53.GetHostedZoneOutput
var err error
@ -187,14 +198,31 @@ func (r *route53Provider) GetNameservers(domain string) ([]*models.Nameserver, e
return models.ToNameservers(nss)
}
// GetZoneRecords gets the records of a zone and returns them in RecordConfig format.
func (r *route53Provider) GetZoneRecords(domain string) (models.Records, error) {
zone, ok := r.zones[domain]
if !ok {
return nil, errNoExist{domain}
if zone, ok := r.zonesByDomain[domain]; ok {
return r.getZoneRecords(zone)
}
return nil, errDomainNoExist{domain}
}
func (r *route53Provider) getZone(dc *models.DomainConfig) (*r53.HostedZone, error) {
if zoneId, ok := dc.Metadata["zone_id"]; ok {
zone, ok := r.zonesById[zoneId]
if !ok {
return nil, errZoneNoExist{zoneId}
}
return zone, nil
}
if zone, ok := r.zonesByDomain[dc.Name]; ok {
return zone, nil
}
return nil, errDomainNoExist{dc.Name}
}
func (r *route53Provider) getZoneRecords(zone *r53.HostedZone) (models.Records, error) {
records, err := r.fetchRecordSets(zone.Id)
if err != nil {
return nil, err
@ -203,7 +231,7 @@ func (r *route53Provider) GetZoneRecords(domain string) (models.Records, error)
var existingRecords = []*models.RecordConfig{}
for _, set := range records {
rts, err := nativeToRecords(set, domain)
rts, err := nativeToRecords(set, unescape(zone.Name))
if err != nil {
return nil, err
}
@ -217,14 +245,14 @@ func (r *route53Provider) GetDomainCorrections(dc *models.DomainConfig) ([]*mode
var corrections = []*models.Correction{}
existingRecords, err := r.GetZoneRecords(dc.Name)
zone, err := r.getZone(dc)
if err != nil {
return nil, err
}
zone, ok := r.zones[dc.Name]
if !ok {
return nil, errNoExist{dc.Name}
existingRecords, err := r.getZoneRecords(zone)
if err != nil {
return nil, err
}
for _, want := range dc.Records {
@ -492,6 +520,11 @@ func getZoneID(zone *r53.HostedZone, r *models.RecordConfig) string {
if zoneID == "" {
zoneID = aws.StringValue(zone.Id)
}
return parseZoneId(zoneID)
}
/** Removes "/hostedzone/"" prefix from AWS ZoneId */
func parseZoneId(zoneID string) string {
if strings.HasPrefix(zoneID, "/hostedzone/") {
zoneID = strings.TrimPrefix(zoneID, "/hostedzone/")
}
@ -613,7 +646,7 @@ func unescape(s *string) string {
}
func (r *route53Provider) EnsureDomainExists(domain string) error {
if _, ok := r.zones[domain]; ok {
if _, ok := r.zonesByDomain[domain]; ok {
return nil
}
if r.delegationSet != nil {