sprinkle_dns

Make handling DNS easier by using simple Ruby constructs


Licenses
MIT/GPL-2.0
Install
gem install sprinkle_dns -v 1.0.2

Documentation

SprinkleDNS logo

SprinkleDNS

A diff-based way of managing DNS for people with lots of domains for AWS Route53.

How

Use plain old Ruby to define your DNS configuration:

require 'sprinkle_dns'

client = SprinkleDNS::Route53Client.new(ACCESS_KEY_ID, SECRET_ACCESS_KEY)
sdns   = SprinkleDNS::Client.new(client)

sdns.entry('A', 'www.billetto.com', '88.80.188.142', 360)
sdns.entry('A', 'staging.billetto.com', '88.80.188.143', 360)

sdns.sprinkle!

Or a more advanced example using loops and interpolation:

require 'sprinkle_dns'

client = SprinkleDNS::Route53Client.new(ACCESS_KEY_ID, SECRET_ACCESS_KEY)
sdns   = SprinkleDNS::Client.new(client)

domains = ['billetto.dk', 'billetto.co.uk', 'billetto.com',  'billetto.se']

domains.each do |domain|
  sdns.entry('A', domain, '88.80.188.142', 360)
  sdns.entry('A', "www.#{domain}", '88.80.188.142', 360)

  s.entry("CNAME", "docs.#{domain}",  'ghs.googlehosted.com', 43200)
  s.entry("CNAME", "mail.#{domain}",  'ghs.googlehosted.com', 43200)
  s.entry("CNAME", "drive.#{domain}", 'ghs.googlehosted.com', 43200)

  s.entry("MX",    domain, ['1 aspmx.l.google.com',
                            '5 alt1.aspmx.l.google.com',
                            '5 alt2.aspmx.l.google.com',
                            '10 aspmx2.googlemail.com',
                            '10 aspmx3.googlemail.com'], 60)
end

# Overwrite one of the domains, to test our new loadbalancer:
sdns.entry('A', 'billetto.com', '89.81.189.143', 360)

sdns.sprinkle!

Configuration

You can configure the SprinkleDNS::Client like so:

client = SprinkleDNS::Route53Client.new(ACCESS_KEY_ID, SECRET_ACCESS_KEY)
sdns = SprinkleDNS::Client.new(client,
  dry_run: false,
  diff: true,
  show_untouched: false,
  force: true,
  delete: false,
  interactive_progress: true,
  create_hosted_zones: false,
)

Here is a table that shows the different configuration options:

Name Description Default value
dry_run Do not make any changes, just compare and exit, useful with diff: true. true
diff Prints a diff to list the changes that are going to be made. true
show_untouched Specifies whether or not the diff should show untouched records or not. false
force Do not ask before changes are made, just apply. false
delete Specifies whether unreferenced entries should be deleted. false
interactive_progress Shows interactive progress whilst changes are being applied, nice for your terminal, not for your CI-job. true
create_hosted_zones Specifies whether or not hosted zones should be created. false

dry_run and diff

dry_run is useful combined with diff because it will let you see the changes in a safe manner without any changes being applied:

dry_run and diff

force: false

With force being set to false you will be asked whether or not you want to apply the changes:

force set to false

delete: true

With delete being set to true SprinkleDNS will delete any entries not being referenced, these will also show up in the diff (if it is enabled):

delete true shows up in diffs

create_hosted_zones: true

With create_hosted_zones set to true, SprinkleDNS will create a hosted zone if not existing, it requires the route53:CreateHostedZone permission.

Support for ALIAS-records

Route53 supports ALIAS-records to achieve CNAME-flattening, SprinkleDNS also supports that, here we point our root domain to an ELB:

require 'sprinkle_dns'

client = SprinkleDNS::Route53Client.new(ACCESS_KEY_ID, SECRET_ACCESS_KEY)
sdns   = SprinkleDNS::Client.new(client)

sdns.alias('A', 'billetto.com', 'Z215JYRZR1TBD5', 'dualstack.mothership-test-elb-546580691.eu-central-1.elb.amazonaws.com')

sdns.sprinkle!

Amazon policy

This gem uses the following permissions to manage hosted zones:

  • route53:ListHostedZones, for getting the list of hosted zones.
  • route53:ListResourceRecordSets, to read the records for a hosted zone.
  • route53:ChangeResourceRecordSets, to change records for a hosted zone.
  • route53:GetChange, for reading when a change have been applied.

Additionally, you can consider adding the following permissions:

  • route53:CreateHostedZone, for allowing the gem to create hosted zones.

You can allow it for all of your hosted zones:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "route53:ListResourceRecordSets",
                "route53:ChangeResourceRecordSets",
                "route53:GetChange",
                "route53:ListHostedZones"
            ],
            "Resource": [
                "*"
            ]
        }
    ]
}

For a more "locked down" policy you can use this (remember to update the resource array):

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "route53:ListResourceRecordSets",
                "route53:ChangeResourceRecordSets"
            ],
            "Resource": [
                "arn:aws:route53:::hostedzone/Z3EATJAGJWXQE8"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "route53:GetChange",
                "route53:ListHostedZones"
            ],
            "Resource": [
                "*"
            ]
        }
    ]
}