]> granicus.if.org Git - pdns/commitdiff
add example.rb sample script for remotebackend, thanks Aki
authorPeter van Dijk <peter.van.dijk@netherlabs.nl>
Tue, 19 Mar 2013 08:47:58 +0000 (08:47 +0000)
committerPeter van Dijk <peter.van.dijk@netherlabs.nl>
Tue, 19 Mar 2013 08:47:58 +0000 (08:47 +0000)
git-svn-id: svn://svn.powerdns.com/pdns/trunk/pdns@3130 d19b8d6e-7fed-0310-83ef-9ca221ded41b

modules/remotebackend/example.rb [new file with mode: 0644]

diff --git a/modules/remotebackend/example.rb b/modules/remotebackend/example.rb
new file mode 100644 (file)
index 0000000..031774a
--- /dev/null
@@ -0,0 +1,203 @@
+#!/usr/bin/ruby
+
+require 'rubygems'
+require 'json'
+
+## this is an example stub for remote backend
+## to add more methods, just write
+## def do_<methodname>(args)
+## end
+## look at the existing methods to find out 
+## how to customize this. 
+
+## WARNING: this contains some code that 
+## should never be used in production, but 
+## is provided to give a more comprehensive
+## example code. 
+
+## Code provided only as example, not suitable
+## for production. 
+
+## Usage: 
+##  launch=remote
+##  remote-dnssec=yes
+##  remote-connection-string=pipe:command=/path/to/example.rb,timeout=2000
+
+class RequestHandler
+
+public
+  def initialize
+    @_log = []
+    @initialized = false
+    @default_ttl = 3600
+  end
+
+protected
+
+  ## YOUR METHODS GO AFTER THIS LINE
+
+  def do_initialize(args)
+     if @initialized
+       raise "Cannot reinitialize"
+     end 
+     log "Example backend v1.0 starting"
+     @initialized = true
+     true
+  end
+
+  ## used to tell that we do NSEC3 NARROW
+  def do_getdomainmetadata(args)
+     if args["name"] == "example.com"
+       if args["kind"] == "NSEC3NARROW"
+           return "1"
+       elsif args["kind"] == "NSEC3PARAM"
+           return "1 1 1 fe"
+       end
+     end
+     false
+  end
+
+  ## returns keys, do not use in production
+  def do_getdomainkeys(args)
+     if args["name"] == "example.com"
+        return [ 
+          {
+             "id" => 1,
+             "flags" => 257,
+             "active" => true,
+             "content" => "Private-key-format: v1.2
+Algorithm: 8 (RSASHA256)
+Modulus: ovvzf1fHdptdXsBrBLSqmGqdEKwR2B9st/KBgh8xQKoQzTGUG00CsPjF/J59IBU+EU/IIInMn0MxLLTyUKa2DJUkR6i7UKif5jKX1c7yvWzrFKLGOHjugUX2++r+o789biUte1qpWp3Kc2RYL18oPco4zpo6JcsPmhOK3aUCDJXmuWgHl1KudCQIiPkISArXVn4oOp+skQq+mUBl1Pysc4D+6sl77ERR2fW6xJ4ZRPOIKr445RJJmKgoMG8yRrR3it1RmV49hZlvMosQjBUoNcqhqOI0n4l8HOLyna7KIzoNKG62GtUCZh8uy8IjdUiWPYGEtkZ9zE0bnnF+R7HGvQ==
+PublicExponent: AQAB
+PrivateExponent: Lp/c3IUD7o4re7uX4dS9KLT3EZnn0OfMdiLNoafCszjzbX/NWrIBHxdLrCS6rr7k7pbgLU6+VqEmJB/vYdsPITJZGpbOXxieBYBbpzJ4hm/uIA0gn28Y66pUKWTkS3ud2zCPfkZFREL3c2M1Rvf1zxdWgOPl1oHsiKsmgpl9qJOSKHMWFC+m/pUMJ7iOMgyDRV+PNeb/8P1jVOAYyQMEnu+enw2ro2NiWXNikbnaWrIv3IxVZAyZG4/H8+1vfQFPDWztosOy7OhV3WyMJkfwcXrlGoyLlxyAgkh/jeCnmPllxlJZGTgCtoVYd/n8osMXCDKxpAhsfdfCPeNOcjocgQ==
+Prime1: +T+s7wv+zVqONJqkAKw4OCVzxBc5FWrmDPcjPCUeKIK/K/3+XjmIqTlbvBKf+7rm+AGVnXAbqk90+jzE3mKI8HMG/rM2cx01986xNQsIqwi2VAt25huPhEyrtNzos6lmrCYaioaQnNpMvMLun3DvcaygkDUXxH7Dg+6BTHeUfnk=
+Prime2: p2YbBveBK3XyGMuVrDH9CvvpgKEoko+mPwLoKNpBoHrGxeOdCQmlPbnr0GrtZpy4sBNc5+shz2c6c1J3GlgPndT7zi2+MFGfWIGV48SAknVLfOU4iUpaGllnxcbjZeytG6WHdy2RaR3ReeGvdWxmxeuv084c2zC/7/vkcmgOqWU=
+Exponent1: EdVFeUEBdQ3imM7rpwSrbRD47HHA6tBgL1NLWRVKyBk6tloQ5gr1xS3Oa3FlsuwXdG0gmEgaIqBWvUS1zTd9lr6UJIsL/UZ8wwMt2J62ew4/hVngouwb45pcuq8HkzsulmiPg5PHKwHPdb34tr2s1BRG1KqHzc5IDNt2stLnc/k=
+Exponent2: oT+Iv1BAu7WUa/AHj+RjJGZ+iaozo+H9uOq66Uc8OjKqMErNpLwG0Qu7rHqjjdlfSjSMpNXpLpj4Q8fm9JhpCpbzq6qCbpbhUGcbFFjfpLSZ74f5yr21R3ZhsLChsTenlF8Bu3pIfKH9e1M7KXgvE22xY+xB/Z3a9XeFmfLEVMU=
+Coefficient: vG8tLZBE4s3bftN5INv2/o3knEcaoUAPfakSsjM2uLwQCGiUbBOOlp3QSdTU4MiLjDsza3fKIptdwYP9PvSkhGhtLPjBpKjRk1J1+sct3dfT66JPClJc1A8bLQPj4ZpO/BkJe6ji4HYfOp7Rjn9z8rTqwEfbP64CZV3/frUzIkQ="
+          },
+          {
+             "id" => 2,
+             "flags" => 256,
+             "active" => true,
+             "content" => "Private-key-format: v1.2
+Algorithm: 8 (RSASHA256)
+Modulus: wKPNcDwkCd2DKxfdkMqTFOV2ITdgxIDaOd4vQ2QtphMBY9yYwmEkNsVdVFz7VVuQHdls20JUe+brFUhs1zEMMbokulFP/qVAItAeEWcqtkPULT+mmX5HsexpFVAZ5+UXuerObk/HMiIMt1CvkIWhmjSIkAI6dFRlf/93zTjy0+vwrNWZPXSzLccK5TfJmxdYdGPcsHkg6UmqEFPQuyZpmlmpg3IwjL5YddTDobAoABz/BrH7WsW0q/PyVubITo8JuFiBI5Fmw+3ef3PVUt1jtUCGASvtqNXW4wtWrgqvQKg/odthpceQ4QagV9XSlOdml527thnf9cMpm0Gh4Ox5HQ==
+PublicExponent: AQAB
+PrivateExponent: f+M+26fRdQstrUomuZ0Cj/jVt69/+nRga9JpJiA3fe1YGue0MjczR3k3QG6KHFyxDF/vuJAMbkUbBAIU37ecFNcy0s5wgOlL7tCjZYJMBLx6+58qBvSivCfqi0+mIyEf4zlS2kD0SP/52SkjpJpScoE1uAUCsX/l8lezPPb1nmH3RDwJwX1NVhsErHCAmxGDoj4nPCEhKgHkdbR0i8geXGdWR4slyq1EhuGJal4p5sNvzDQTYRy6r49rpbNHw9F7ojomIhTUCUjOXAX0X1HB5UTXRMpgpCNEjRG1a+aqxp/ZSMHSEGCv67fua5Qrd/qX1Ppns/oqZfCfTpTD3v/sMQ==
+Prime1: +0zQuFi7rZDTMGMIKiF6UOG5+pKwGxHmgKPOGF6fk3tIuSomgiVD3DLz5Y6kYk0kKls6IiA6X2esYwNXAaLe0dyMzpAnU4URXhFW7fUnHP0zA7NmaFRYPHstPeU59/JS+zmVlj4Ok1oeGocSGAFYGxXa+Sot0fyCXpAjZboDWg8=
+Prime2: xD4hprQmcn5gmLqYO9+nEEJTNyNccbAciiKjRJxIE7w6muuKESx0uUn5XdnzSxhbVkK16kkEqW3s+Y+VoLxwRj2fuvoPfx8nTQXY1esgcIZCG8ubvHW5T0bzee5gyX3cMvaxkoeM7euYgvh0UwR/FG910SwAlmMZjSwXay2YlhM=
+Exponent1: 6vcWzNcCnDWmkT53WtU0hb2Y4+YVzSm+iRcf039d20rRY3g6y0NGoPPvQftOTi9smkH0KAZULfJEp8tupbQAfN6ntVfpvVjVNUwnKJUo/hzsfxBVt0Ttv5c4ZQAYZHHqDsX3zKO3gyUmso0KaPGQzLpxpLlAYG+mAf7paeszyRc=
+Exponent2: ouvWMjk0Bi/ncETRqDuYzkXSIl+oGvaT6xawp4B70m6d1QohWPqoeT/x2Dne44R4J9hAgR5X0XXinJnZJlXrfFUi7C84eFhb33UwPQD0sJa2Aa97Pu4Zh7im4J7IGd/01Ra7+6Ovm8LRnkI5CMcd3dBfZuX6IuBpUSu+0YtMN6M=
+Coefficient: 5lP9IFknvFgaXKCs8MproehHSFhFTWac4557HIn03KrnlGOKDcY6DC/vgu1e42bEZ4J0RU0EELp5u4tAEYcumIaIVhfzRsajYRGln2mHe6o6nTO+FbANKuhyVmBEvTVczPOcYLrFXKVTglKAs+8W96dYIMDhiAwxi9zijLKKQ1k="
+          }
+        ]
+     end
+     false
+  end
+
+  ## Example lookup
+  ## Returns SOA, MX, NS and A records for example.com
+  ## also static A record for test.example.com
+  ## and dynamic A record for anything else in example.com domain 
+  def do_lookup(args)
+     if args["qname"] == "example.com" and args["qtype"].downcase == "soa"
+       return [
+          record("SOA","example.com", "sns.dns.icann.org noc.dns.icann.org 2013012485 7200 3600 1209600 3600"),
+              ]
+     elsif args["qname"] == "example.com" and args["qtype"].downcase == "any"
+       return [ 
+          record("SOA","example.com", "sns.dns.icann.org noc.dns.icann.org 2013012485 7200 3600 1209600 3600"),
+          record("NS","example.com","sns.dns.icann.org"),
+          record_prio("MX","example.com","test.example.com",10)
+              ]
+     elsif args["qname"] == "test.example.com" and args["qtype"].downcase == "any"
+       return [
+          record("A","test.example.com","127.0.0.1")
+       ]
+     elsif args["qname"] =~ /(.*)\.example\.com$/ and args["qtype"].downcase == "any"
+       ip = 0
+       $1.downcase.each_byte do |b| ip = ip + b end
+       ip_2 = ip/256
+       ip = ip%256
+       return [
+          record("A",args["qname"], "127.0.#{ip_2}.#{ip}")
+       ]
+     end
+     false
+  end
+
+  ## AXFR support
+  ## Do note that having AXFR here is somewhat stupid since
+  ## we generate records above. But it is still included
+  ## for sake of having an example. Do not do ths in production.
+  def do_list(args)
+     if args["zonename"] == "example.com"
+       return [
+          record("SOA","example.com", "sns.dns.icann.org noc.dns.icann.org 2013012485 7200 3600 1209600 3600"),
+          record("NS","example.com","sns.dns.icann.org"),
+          record_prio("MX","example.com","test.example.com",10),
+          record("A","test.example.com","127.0.0.1")
+       ]
+     end
+     false          
+  end
+
+  ## Please see http://doc.powerdns.com/remotebackend.html for methods to add here
+  ## Just remember to prefix them with do_
+
+  ## Some helpers after this 
+
+  def record_prio_ttl(qtype,qname,content,prio,ttl)
+    {:qtype => qtype, :qname => qname, :content => content, :priority => prio, :ttl => ttl, :auth => 1}
+  end
+
+  def record_prio(qtype,qname,content,prio)
+    record_prio_ttl(qtype,qname,content,prio,@default_ttl)
+  end
+
+  def record(qtype,qname,content)
+    record_prio_ttl(qtype,qname,content,0,@default_ttl)
+  end
+
+  def log(message)
+    @_log << message
+  end
+
+  ## Flushes log array and returns it.
+  def consume_log
+    ret = @_log
+    @_log = []
+    ret
+  end
+
+public
+  def run
+     STDOUT.sync=true
+     STDIN.each_line do |line|
+        # So far rapidjson has managed to follow RFC4627
+        # and hasn't done formatted json so there should be
+        # no newlines. 
+        msg = JSON.parse(line)
+       
+        # it's a good idea to prefix methods with do_ to prevent
+        # clashes with initialize et al, and downcase it for simplicity
+        method = "do_#{msg["method"].downcase}".to_sym
+        if self.respond_to? method
+          result = self.send method, msg["parameters"]
+        else
+          log "Method #{msg["method"]} not implemented"
+          result = false
+        end
+        # build and emit result
+        reply = { :result => result, :log => consume_log }
+        puts reply.to_json
+     end
+  end
+end
+
+begin 
+  RequestHandler.new.run
+rescue Interrupt
+  # ignore this exception, caused by ctrl+c in foreground mode
+end