Error 422 When Using Powershell to Update DNS Records on GoDaddy API

荒凉一梦 提交于 2019-12-07 18:52:13

问题


I am trying to update my DNS with GoDaddy via their API (My home network is on a Dynamic IP).

I am able to succesfully update when using the script found at http://teanazar.com/2016/05/godaddy-ddns-updater/ when run through cygwin.

However I am trying to simply things, and do this in powershell instead.

However when trying to use the following script:

$IP = Invoke-WebRequest http://api.ipify.org?format=json
$IP2 = ConvertFrom-JSON $ip
$domain = 'example.com'
$type = 'A'
$name = '@'

$key = 'key'
$secret = 'secret'


$Request = @{ttl='600';data=$ip2.ip;priority='1'}

$JSON = Convertto-Json $request

$headers = @{}
$headers["Authorization"] = 'sso-key ' + $key + ':' + $secret

Invoke-WebRequest    https://api.godaddy.com/v1/domains/$domain/records/$Type/$Name -contenttype "application/json" -method put -body $json -headers $headers

I have managed to work through each issue so far, and I know it is authenticating. But when I execute, i am getting "The Remote Server returned an error: (422) Unprocessable Entity


回答1:


I'd been using an implementation based on the solution provided by drizin... and it worked very well up until recently.

It seems that GoDaddy have tightened up on the JSON validation and it now fails with the following error:

{
  "code": "INVALID_BODY",
  "fields": [
    {
      "code": "UNEXPECTED_TYPE",
      "message": "is not a array",
      "path": "records"
    }
  ],
  "message": "Request body doesn't fulfill schema, see details in `fields`"
}

According to the specification for the APIs at https://developer.godaddy.com/doc/endpoint/domains#/v1/recordReplaceTypeName the JSON sent should be an array... i.e. [ { ... } ] where the code creates { ... }.

To fix this it requires a simple change to the line of code that build the JSON...

From:

$JSON = ConvertTo-Json @{data=$IP;ttl=3600}

To:

$JSON = ConvertTo-Json @(@{data=$IP;ttl=3600})



回答2:


Make a production key on godaddy. The test key did not work for me.

And your ttl need to be an integer. not string, remove the '' from it.

(and change your @ to %40)

$IP = Invoke-WebRequest http://api.ipify.org?format=json
$IP2 = ConvertFrom-JSON $ip
$domain = 'example.com'
$type = 'A'
$name = 'Test'

$key = 'key'
$secret = 'secret'


[array]$Request=@{data=$IP2.ip; "port"=1; "priority"=0; "protocol"="none"; "service"="none"; "ttl"=3600; "weight"=1}

$JSON = Convertto-Json $request

$headers = @{}
$headers["Authorization"] = 'sso-key ' + $key + ':' + $secret


Invoke-WebRequest    https://api.godaddy.com/v1/domains/$domain/records  -method get -headers $headers
Invoke-WebRequest    https://api.godaddy.com/v1/domains/$domain/records/A/Test  -method put -headers $headers -Body $json -ContentType "application/json"

Looks like GoDaddy updated the API. Updated the solution to include the "array" requirement for the JSON as well as additional fields that now appear to be required as well.




回答3:


To solve this problem, I would first recommend you start with a GET operation of the same endpoint. What do you see when you run this command?

Invoke-WebRequest   https://api.godaddy.com/v1/domains/$domain/records `
  -contenttype "application/json" -method GET -headers $headers

Let's validate what kind of Data GoDaddy will show you via this endpoint. Maybe they have a different terminology for making an @ record? There's a lot of ways we could be running into issues.

Let me know what you see here and we'll work to a solution.




回答4:


The A record is set in line 20 rather than being the VAR $name and the TTL is set to 1 at line 11, I think godaddy kicks it at this value. set the TTL to 3600 and insert the var to 20 it should work, it did for me anyway.

Thanks for the pointer :)

$IP = Invoke-WebRequest http://api.ipify.org?format=json
$IP2 = ConvertFrom-JSON $ip
$domain = 'domain.co.uk'
$type = 'A'
$name = 'record'

$key = 'blahhhhh'
$secret = 'blahhh'


$Request = @{ttl=3600;data=$ip2.ip}

$JSON = Convertto-Json $request

$headers = @{}
$headers["Authorization"] = 'sso-key ' + $key + ':' + $secret


Invoke-WebRequest    https://api.godaddy.com/v1/domains/$domain/records  -method get -headers $headers
Invoke-WebRequest    https://api.godaddy.com/v1/domains/$domain/records/A/$name  -method put -headers $headers -Body $json -ContentType "application/json"



回答5:


Go Daddy has some type constraints (TTL should be numeric, Priority should be numeric [please note that priority should only used for SRV records]), and some business constraints (like forcing TTL to be at least 600, which is 10min), etc.

You can refer to their API here, where you can see data examples, and also try out commands and see the error messages.

On the other hand if you prefer to see the error messages directly in powershell, since Content property is not available when you get an HTTP error, you should extract the error message from the response stream like described here

Full sample with error handling:

$IPj = Invoke-WebRequest http://api.ipify.org?format=json
$IP = (ConvertFrom-JSON $IPj).ip
$domain = 'mydomain.com'
$type = 'A'
$alias = 'myalias' # myalias.mydomain.com

$key = 'etc'
$secret = 'etc'

$JSON = ConvertTo-Json @{data=$IP;ttl=3600}
# you can also use an array of values: @(@{data=$IP1;ttl=3600},@{data=$IP2;ttl=3600},etc...)

$headers = @{}
$headers["Authorization"] = 'sso-key ' + $key + ':' + $secret

try {
    $ret = Invoke-WebRequest https://api.godaddy.com/v1/domains/$domain/records/$type/$alias  -method put -headers $headers -Body $json -ContentType "application/json"
    if ($ret.StatusCode -eq 200) { Write-Host "Success!" -for yellow } else { Write-Host "ERROR" -for red }
}
catch {
    $result = $_.Exception.Response.GetResponseStream()
    $reader = New-Object System.IO.StreamReader($result)
    $reader.BaseStream.Position = 0
    $reader.DiscardBufferedData()
    $responseBody = $reader.ReadToEnd();
    $responseBody = $responseBody | ConvertFrom-Json | Format-Custom | Out-String
    Write-Host "ERROR: $responseBody" -for red
}



回答6:


I was able to get it working with the following:

$apiKey = 'YOUR API KEY'
$apiSecret = 'YOUR API SECRET'
$domain = 'YOUR DOMAIN NAME'
#ENTER THE NAME OF THE RECORD YOU WISH TO UPDATE#
$name = '@'
$Headers = @{}
$Headers["Authorization"] = 'sso-key ' + $apiKey + ':' + $apiSecret
$result = Invoke-WebRequest https://api.godaddy.com/v1/domains/$domain/records/A/$name -method get -headers $headers
$content = ConvertFrom-Json $result.content
$dnsIp = $content.data
$currentIp = Invoke-RestMethod http://ipinfo.io/json | Select -exp ip
#THIS SECTION CHECKS THE CURRENT IP ADDRESS AGAINST THE PULL AND WILL UPDATE IF NOT CORRECT#
if ( $currentIp -ne $dnsIp) {
    #$Request = @{ttl=600;data=$currentIp }
    $JSON = ConvertTo-Json @(@{data=$currentIp;ttl=600})
    Invoke-WebRequest https://api.godaddy.com/v1/domains/$domain/records/A/$name -method put -headers $headers -Body $json -ContentType "application/json"

}
#SHOWS RESULTS OF THE HEADER PULL
Invoke-WebRequest https://api.godaddy.com/v1/domains/$domain/records/ -Method Get -Headers $Headers | ConvertFrom-Json


来源:https://stackoverflow.com/questions/39123202/error-422-when-using-powershell-to-update-dns-records-on-godaddy-api

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!