├── README.md
├── dns.rb
└── etc
├── 1.1.1.in-addr.arpa.db
├── apple.com.db
└── named.conf
/README.md:
--------------------------------------------------------------------------------
1 | # bind-restapi
2 |
3 | A quick and simple RESTful API to BIND, written in Ruby / Sinatra. Provides the ability to add/remove entries with an existing BIND DNS architecture.
4 |
5 | I wrote this as a solution to enable our internal Cloud to add/remove machines to DNS by integrating with the DNS architecture that we have today.
6 |
7 | ## Instructions
8 | # cd etc/
9 | # named -c named.conf
10 | $ ruby dns.rb
11 |
12 | ### Add a record to DNS:
13 |
14 | $ curl -X POST -H 'Content-Type: application/json' -H 'X-Api-Key: secret' -d '{ "hostname": "host12.apple.com", "ip": "1.1.1.12" }' http://localhost:4567/dns
15 |
16 | ### Remove a record from DNS:
17 |
18 | $ curl -X DELETE -H 'Content-Type: application/json' -H 'X-Api-Key: secret' -d '{ "hostname": "host12.apple.com", "ip": "1.1.1.12" }' http://localhost:4567/dns
19 |
20 | ## API
21 | The API supports POST and DELETE methods to add and remove entries, respectively. On a successful POST a 201 is returned. On a successful DELETE a 200 is returned. Duplicate records are never created.
22 |
23 | The API can reside on a local *or* remote DNS server.
24 |
25 | On a POST request, the API adds **both** the *forward* zone **and** *reverse* in-addr.arpa zone entry as a convenience.
26 |
27 | On a DELETE request, the API removes **both** the *forward* zone **and** *reverse* in-addr.arpa zone entry as a connivence.
28 |
29 | The TTL and other DNS params are hard-coded inside of dns.rb
30 |
31 | ## Security
32 | The API is protected by way of an API-Key using a custom X-Api-Key
HTTP header. The API should also be served over a secure connection.
33 |
34 | ## etc
35 | Example named configuration files are included to help get started with integrating dns.rb
with BIND.
36 |
--------------------------------------------------------------------------------
/dns.rb:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 |
3 | require 'rubygems'
4 | require 'sinatra'
5 | require 'json'
6 | require 'ipaddr'
7 |
8 | # curl -X POST -H 'Content-Type: application/json' -H 'X-Api-Key: secret' -d '{ "hostname": "host12.apple.com", "ip": "1.1.1.12" }' http://localhost:4567/dns
9 | # curl -X DELETE -H 'Content-Type: application/json' -H 'X-Api-Key: secret' -d '{ "hostname": "host12.apple.com", "ip": "1.1.1.12" }' http://localhost:4567/dns
10 |
11 | dns_params = {
12 | :server => '127.0.0.1',
13 | :rndc_key => 'rndc-key',
14 | :rndc_secret => 'MHGIj19UPT5EmWeHWFJLOw==',
15 | :ttl => '300'
16 | }
17 |
18 | # Reverse the IP address for the in-addr.arpa zone
19 | def reverse_ip(ipaddress)
20 | reverse_ip = IPAddr.new ipaddress
21 | reverse_ip.reverse
22 | end
23 |
24 | # Authenticate all requests with an API key
25 | before do
26 | # X-Api-Key
27 | error 401 unless env['HTTP_X_API_KEY'] =~ /secret/
28 | end
29 |
30 | post '/dns' do
31 | request_params = JSON.parse(request.body.read)
32 | reverse_zone = reverse_ip(request_params["ip"])
33 | ttl = if request_params["ttl"].nil? then dns_params[:ttl] else request_params["ttl"] end
34 |
35 | # Add record to forward and reverse zones, via TCP
36 | IO.popen("nsupdate -y #{dns_params[:rndc_key]}:#{dns_params[:rndc_secret]} -v", 'r+') do |f|
37 | f << <<-EOF
38 | server #{dns_params[:server]}
39 | update add #{request_params["hostname"]} #{ttl} A #{request_params["ip"]}
40 | send
41 | update add #{reverse_zone} #{ttl} PTR #{request_params["hostname"]}
42 | send
43 | EOF
44 | f.close_write
45 | end
46 | error 500 unless $? == 0
47 | status 201
48 | end
49 |
50 | delete '/dns' do
51 | request_params = JSON.parse(request.body.read)
52 | reverse_zone = reverse_ip(request_params["ip"])
53 |
54 | # Remove record from forward and reverse zones, via TCP
55 | IO.popen("nsupdate -y #{dns_params[:rndc_key]}:#{dns_params[:rndc_secret]} -v", 'r+') do |f|
56 | f << <<-EOF
57 | server #{dns_params[:server]}
58 | update delete #{request_params["hostname"]} A
59 | send
60 | update delete #{reverse_zone} PTR
61 | send
62 | EOF
63 | f.close_write
64 | end
65 | error 500 unless $? == 0
66 | end
67 |
--------------------------------------------------------------------------------
/etc/1.1.1.in-addr.arpa.db:
--------------------------------------------------------------------------------
1 | $ORIGIN .
2 | $TTL 38400 ; 10 hours 40 minutes
3 | 1.1.1.in-addr.arpa IN SOA ns1.apple.com. hostmaster.apple.com. (
4 | 2012110933 ; serial
5 | 28800 ; refresh (8 hours)
6 | 3600 ; retry (1 hour)
7 | 604800 ; expire (1 week)
8 | 38400 ; minimum (10 hours 40 minutes)
9 | )
10 | NS ns1.apple.com.
11 |
--------------------------------------------------------------------------------
/etc/apple.com.db:
--------------------------------------------------------------------------------
1 | $ORIGIN .
2 | $TTL 38400 ; 10 hours 40 minutes
3 | apple.com IN SOA ns1.apple.com. hostmaster.apple.com. (
4 | 2012110934 ; serial
5 | 28800 ; refresh (8 hours)
6 | 3600 ; retry (1 hour)
7 | 604800 ; expire (1 week)
8 | 38400 ; minimum (10 hours 40 minutes)
9 | )
10 | NS ns1.apple.com.
11 | $ORIGIN apple.com.
12 | ns1 A 1.2.3.4
13 |
--------------------------------------------------------------------------------
/etc/named.conf:
--------------------------------------------------------------------------------
1 | key "rndc-key" {
2 | algorithm hmac-md5;
3 | secret "MHGIj19UPT5EmWeHWFJLOw==";
4 | };
5 |
6 | zone "apple.com" {
7 | type master;
8 | file "apple.com.db";
9 | allow-update { key "rndc-key"; };
10 | };
11 |
12 | zone "1.1.1.in-addr.arpa" IN {
13 | type master;
14 | file "1.1.1.in-addr.arpa.db";
15 | allow-update { key "rndc-key"; };
16 | };
17 |
--------------------------------------------------------------------------------