-
Notifications
You must be signed in to change notification settings - Fork 0
/
route53.go
113 lines (97 loc) · 2.87 KB
/
route53.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
package dns
import (
"errors"
"fmt"
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/route53"
"github.com/rs/zerolog/log"
"github.com/soerenschneider/dyndns/internal/common"
)
type Route53Propagator struct {
client *route53.Route53
hostedZoneId string
ttl int64
}
func NewRoute53Propagator(hostedZoneId string, provider credentials.Provider) (*Route53Propagator, error) {
var awsSession *session.Session
if provider != nil {
log.Info().Msg("Building AWS client using given credentials provider")
awsSession = session.Must(session.NewSession(&aws.Config{
Credentials: credentials.NewCredentials(provider),
}))
} else {
log.Info().Msg("Building AWS client session using default provider")
awsSession = session.Must(session.NewSession())
}
svc := route53.New(awsSession)
return &Route53Propagator{
client: svc,
hostedZoneId: hostedZoneId,
ttl: defaultRecordTtl,
}, nil
}
func (dns *Route53Propagator) PropagateChange(resolvedIp common.DnsRecord) error {
changes := getChanges(resolvedIp, dns.ttl)
if len(changes) == 0 {
return errors.New("empty list of changes")
}
batch := &route53.ChangeBatch{
Changes: changes,
Comment: aws.String(fmt.Sprintf("Dyndns Change from %s", time.Now().Format("2006-01-02T15:04:05Z07:00"))),
}
in := &route53.ChangeResourceRecordSetsInput{
ChangeBatch: batch,
HostedZoneId: &dns.hostedZoneId,
}
_, err := dns.client.ChangeResourceRecordSets(in)
if err != nil {
return fmt.Errorf("updating resource failed '%s': %v", resolvedIp.Host, err)
}
return nil
}
func buildChange(host, value, recordType string, ttl int64) (*route53.Change, error) {
validTypeSupplied := false
for _, t := range route53.RRType_Values() {
if t == recordType {
validTypeSupplied = true
break
}
}
if !validTypeSupplied {
return nil, fmt.Errorf("invalid record type supplied: %s", recordType)
}
return &route53.Change{
Action: aws.String(route53.ChangeActionUpsert),
ResourceRecordSet: &route53.ResourceRecordSet{
Name: aws.String(host),
ResourceRecords: []*route53.ResourceRecord{
{Value: aws.String(value)},
},
TTL: aws.Int64(ttl),
Type: aws.String(recordType),
},
}, nil
}
func getChanges(resolved common.DnsRecord, ttl int64) []*route53.Change {
var records []*route53.Change
if resolved.HasIpV4() {
change, err := buildChange(resolved.Host, resolved.IpV4, route53.RRTypeA, ttl)
if err != nil {
log.Info().Msgf("couldn't build change for ipv4: %v", err)
} else {
records = append(records, change)
}
}
if resolved.HasIpV6() {
change, err := buildChange(resolved.Host, resolved.IpV6, route53.RRTypeAaaa, ttl)
if err != nil {
log.Info().Msgf("couldn't build change for ipv6: %v", err)
} else {
records = append(records, change)
}
}
return records
}