├── 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 | --------------------------------------------------------------------------------