skip to Main Content

I always getting the same error (Create domain ‘example.com’ failed) (or any domain) when trying to create new DNS zone with Powerdns API call.

My request:

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,'http://127.0.0.1:953/api/v1/servers/localhost/zones');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, "{"name":"example.com.", "kind":"Native", "masters": [], "nameservers":["ns1.example.com.", "ns2.example.com."]}");
$headers = array();
$headers[] = 'X-Api-Key: MY-KEY';
$headers[] = 'Accept: application/json';
$headers[] = 'Content-Type: application/json';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$result = curl_exec($ch);
if (curl_errno($ch)) {
    echo 'Error:' . curl_error($ch);
}
curl_close($ch);

Similar api call to get a list of DNS zones is working. GET request work properly but not POST.
Can anyone help, please?

My pdns.conf file is:

api=yes
api-key=MY-KEY

Maybe i have to change something in settings of my powerdns, idk really.
I would be very grateful for any help!

Server response after POST request is 422 error (Unprocessable Entity)

HTTP/1.1 422 Unprocessable Entity
Access-Control-Allow-Origin: *
Connection: close
Content-Length: 52
Content-Security-Policy: default-src ‘self’; style-src ‘self’ ‘unsafe-inline’
Content-Type: application/json
Server: PowerDNS/4.4.1
X-Content-Type-Options: nosniff
X-Frame-Options: deny
X-Permitted-Cross-Domain-Policies: none
X-Xss-Protection: 1; mode=block

This is my pdns.conf file
cat /etc/pdns/pdns.conf
bind-ignore-broken-records=yes
setuid=named
setgid=named
launch=bind
log-dns-queries=yes
loglevel=5
bind-config=/etc/named.conf
bind-dnssec-db=/var/cpanel/pdns/dnssec.db
local-address-nonexist-fail=no
distributor-threads=1
disable-axfr=yes
webserver=yes
api=yes
webserver-address=127.0.0.1
webserver-allow-from=0.0.0.0/0
webserver-password=SERVER-KEY
#gmysql-dnssec=no
webserver-port=953
api-key=MY-KEY
upgrade-unknown-types=1

2

Answers


  1. Your code looks correct.

    One big problem with your response.
    Content-Length: 52
    It should be Content-Length: 111.

    I have been testing your code with two apps
    One to send the curl request
    One to receive it and respond with the request details.

    Early on in my testing when I removed the Content-Type: application/json,
    I would see a content length of just over 50 bytes.

    Below is my app. It gets 111 bytes.
    If you change your curl url to http://eatled.com/receiveheader.php
    You should get this:

    Response
    Content-Length: 111
    Content-Type: application/json
    Accept: application/json
    Accept-Encoding: deflate, gzip, br
    Host: eatled.com
    X-Api-Key: MY-KEY
    
    BODY
    
    {"name":"example.com.", "kind":"Native", "masters": [], "nameservers":["ns1.example.com.", "ns2.example.com."]}
    
    
    array (
      'name' => 'example.com.',
      'kind' => 'Native',
      'masters' => 
      array (
      ),
      'nameservers' => 
      array (
        0 => 'ns1.example.com.',
        1 => 'ns2.example.com.',
      ),
    )
    

    LINK TO MY CURL SANDBOX

    The source code:
    sandbox.php

    <?php
    header('Content-Type: text/plain; charset=UTF-8');
    $jsn = "{"name":"example.com.", "kind":"Native", "masters": [], "nameservers":["ns1.example.com.", "ns2.example.com."]}";
    $data = json_decode($post,1);
    $post = $jsn;
    $request = array();
    $request[] = "Content-Type: application/json";
    $request[] = "Accept: application/json";
    $request[] = "X-Api-Key: MY-KEY";
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_HTTPHEADER, $request);
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);    
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);   
    curl_setopt($ch, CURLOPT_URL, 'http://eatled.com/receiveheader.php'); 
    curl_setopt($ch, CURLOPT_HEADER, false);
    curl_setopt($ch, CURLOPT_TIMEOUT,10);
    curl_setopt($ch, CURLOPT_FAILONERROR,true);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_ENCODING,"");
    curl_setopt($ch, CURLOPT_VERBOSE, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS,$post);
    $data = curl_exec($ch);
    $info = rawurldecode(var_export(curl_getinfo($ch),true));
    echo "nResponsen$data";
    echo "ncurl_getinfo =n$info";
    ?>
    

    receiveheaders.php

    <?php
    header('Content-Type: text/plain; charset=UTF-8');
    
    foreach (getallheaders() as $name => $value) {
        echo "$name: $valuen";
    }
    echo "nBODYn";
    $jsn = file_get_contents('php://input');
    echo "n$jsnnnn";
    $data = json_decode($jsn,1);
    var_export($data);
    echo "n$_POSTn";
    var_export($_POST);
    echo "n$_FILESn";
    var_export($_FILES);
    echo "n$_SERVERn";
    var_export($_SERVER);
    ?>
    

    END OF UPDATE



    Add these two headers.

    $headers[] = 'Accept: application/json';
    $headers[] = 'Content-Type: application/json';
    

    Right now the error you are getting is because the request content-type is

    'CONTENT_TYPE' => 'application/x-www-form-urlencoded',
    

    If use just used the content-type header and not accept, you’d get a different error. The API manual says you cannot use curl’s default Accept: */*

    Login or Signup to reply.
  2. Can you try call the API using curl command on the maching running pDNS webserver?

    curl -v 
     -H 'Content-Type: application/json' 
     -H 'X-Api-Key: MY-KEY' 
     -H 'Accept: application/json' 
     -X POST -d '{"name":"example.com.", "kind":"Native", "masters": [], "nameservers":["ns1.example.com.", "ns2.example.com."]}' 
     http://127.0.0.1:953/api/v1/servers/localhost/zones
    

    Because I don’t know your setup, so I guess that it had something relate to network. If curl request work, you should check webserver-allow-from configuration, you may try to set it to accept from all (0.0.0.0,::).

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search