-
-
Save anselm-helbig/fe5c2db97b4f2d897b3e5ff02887e1b0 to your computer and use it in GitHub Desktop.
Copy DNS zones from CloudFlare to Route53
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
require "bundler/inline" | |
gemfile do | |
gem "rubyflare" | |
gem "route53" | |
end | |
require "yaml" | |
credentials = YAML.load(File.read("credentials.yml")) | |
cloudflare_conn = Rubyflare.connect_with( | |
credentials['cloudflare']['email'], | |
credentials['cloudflare']['api_key'] | |
) | |
r53_conn = Route53::Connection.new( | |
credentials['aws']['access_key'], | |
credentials['aws']['secret_key'] | |
) | |
module CloudFlare | |
# Get all zones (domains) | |
def self.zones(connection) | |
connection.get("zones", per_page: 1).results.map { |record| | |
Zone.new(record, connection) | |
} | |
end | |
Zone = Struct.new(:record, :connection) do | |
def name | |
record[:name] | |
end | |
def id | |
record[:id] | |
end | |
def dns_records | |
connection.get("zones/#{id}/dns_records", per_page: 1000).results.map { |r| | |
DnsRecord.new(r, connection) | |
} | |
end | |
end | |
DnsRecord = Struct.new(:record, :connection) do | |
def self.build(record, connection) | |
case record[:type] | |
when "MX" | |
MxRecord | |
else | |
DnsRecord | |
end.new(record, connection) | |
end | |
def name | |
record[:name] + "." | |
end | |
def type | |
record[:type] | |
end | |
def content | |
record[:content] | |
end | |
def matches?(other) | |
self.name == other.name && | |
self.type == other.type && | |
self.content == other.content | |
end | |
def to_route53(r53_zone) | |
Route53::DNSRecord.new(name, type, "60", [content], r53_zone) | |
end | |
end | |
class MxRecord < DnsRecord | |
def name | |
"#{cf_record[:priority]} #{cf_record[:name]}." | |
end | |
end | |
end | |
# Iterate over zones, and their records and create them in r53 | |
CloudFlare.zones.each do |cf_zone| | |
mx_content = Hash.new { |h, k| h[k] = [] } | |
# Check if the zone exists already | |
puts "checking if #{cf_zone.name} zone exists in r53 - will create it only if it doesn't" | |
r53_zone = Array(r53_conn.get_zones(cf_zone.name)).first | |
unless r53_zone | |
r53_zone = Route53::Zone.new("#{cf_zone.name}.", nil, r53_conn) | |
# Create a zone in route53 | |
puts "creating new zone in r53: #{cf_zone.name}." | |
resp = r53_zone.create_zone | |
exit 1 if resp.error? | |
while resp.pending? | |
sleep 1 | |
end | |
end | |
# get the zone records | |
r53_zone_records = r53_zone.get_records | |
cf_zone_dns_records = cloudflare_conn.get("zones/#{cf_zone[:id]}/dns_records", per_page: 1000) | |
cf_zone_dns_records.results.each do |cf_record| | |
unless r53_zone.get_records.find { |r53_record| | |
r53_record.name == "#{cf_record[:name]}." && | |
r53_record.type == cf_record[:type] && | |
r53_record.values == cf_record[:content] | |
} | |
case cf_record[:type] | |
when "SOA", "NS" | |
next | |
when "MX" | |
mx_content[cf_record[:name]] << "#{cf_record[:priority]} #{cf_record[:name]}." | |
else | |
# Check if it doesn't exist in Route53 yet | |
puts "checking if #{cf_record[:name]} #{cf_record[:type]} record exists in r53 - will create it only if it doesn't" | |
unless r53_zone_records.find { |r53_record| | |
r53_record.name == "#{cf_record[:name]}." && | |
r53_record.type == cf_record[:type] && | |
r53_record.values.include?(cf_record[:content]) | |
} | |
puts "creating #{cf_record[:type]} record named #{cf_record[:name]} in #{cf_zone[:name]} zone with content #{cf_record[:content]}" | |
# Create a new record within our newly created r53 zone. | |
new_record = Route53::DNSRecord.new("#{cf_record[:name]}.",cf_record[:type],"60",["#{cf_record[:content]}"],r53_zone) | |
new_record.create | |
end | |
end | |
end | |
end | |
mx_content.each do |mx_record_name, mx_record_content| | |
# Check if it doesn't exist in Route53 yet | |
puts "checking if #{mx_record_name} MX record exists in r53 - will create it only if it doesn't" | |
unless r53_zone_records.find { |r53_record| | |
r53_record.name == "#{mx_record_name}." && | |
r53_record.type == "MX" && | |
r53_record.values == mx_record_content.uniq | |
} | |
puts "creating MX record named #{mx_record_name} with in #{cf_zone[:name]} zone with content #{mx_record_content}" | |
# Create a new MX record within our newly created r53 zone. | |
new_mx_record = Route53::DNSRecord.new("#{mx_record_name}.","MX","60",mx_record_content.uniq,r53_zone) | |
new_mx_record.create | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment