Ошибка 422 при использовании Powershell для обновления записей DNS в API GoDaddy
Я пытаюсь обновить свой DNS с помощью GoDaddy через их API (моя домашняя сеть имеет динамический IP-адрес).
Я могу успешно обновлять при использовании скрипта, найденного на http://teanazar.com/2016/05/godaddy-ddns-updater/ при запуске через cygwin.
Однако я пытаюсь просто вещи, и сделать это в PowerShell вместо этого.
Однако при попытке использовать следующий скрипт:
$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
До сих пор мне удавалось проработать каждую проблему, и я знаю, что это проверка подлинности. Но когда я выполняюсь, я получаю "Удаленный сервер возвратил ошибку: (422) Unprocessable Entity
6 ответов
Я использовал реализацию, основанную на решении, предоставленном drizin... и до недавнего времени она работала очень хорошо.
Кажется, что GoDaddy ужесточил проверку JSON, и теперь он завершается ошибкой со следующей ошибкой:
{
"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`"
}
Согласно спецификации для API по адресу https://developer.godaddy.com/doc/endpoint/domains отправляемый JSON должен быть массивом... т.е. [ { ... } ]
где код создает { ... }
,
Чтобы это исправить, требуется простое изменение строки кода, которая создает JSON...
От:
$JSON = ConvertTo-Json @{data=$IP;ttl=3600}
Для того, чтобы:
$JSON = ConvertTo-Json @(@{data=$IP;ttl=3600})
Сделайте ключ производства на Годди. Тестовый ключ у меня не работал.
И ваш ттл должен быть целым числом. не строка, удалите '' из него.
(и измените свой @ на%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"
Похоже, GoDaddy обновил API. Обновлено решение, включив требование "массив" для JSON, а также дополнительные поля, которые теперь, по-видимому, также являются обязательными.
Чтобы решить эту проблему, я бы сначала порекомендовал вам начать с GET
работа той же конечной точки. Что вы видите, когда запускаете эту команду?
Invoke-WebRequest https://api.godaddy.com/v1/domains/$domain/records `
-contenttype "application/json" -method GET -headers $headers
Давайте проверим, какие данные GoDaddy покажет вам через эту конечную точку. Может быть, у них другая терминология для создания @
запись? Есть много способов, которыми мы могли бы столкнуться с проблемами.
Дайте мне знать, что вы видите здесь, и мы будем работать над решением.
Я смог заставить его работать со следующим:
$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
Запись A устанавливается в строке 20, а не является именем VAR $, а TTL устанавливается в 1 в строке 11, я думаю, что godaddy пинает ее при этом значении. установите TTL на 3600 и вставьте переменную на 20, это должно работать, в любом случае, у меня получилось.
Спасибо за указатель:)
$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"
Go Daddy имеет некоторые ограничения по типу (TTL должен быть числовым, Priority должен быть числовым [обратите внимание, что приоритет должен использоваться только для записей SRV]), а также некоторые бизнес-ограничения (например, заставить TTL быть не менее 600, что составляет 10 минут) и т. Д.,
Вы можете обратиться к их API здесь, где вы можете увидеть примеры данных, а также попробовать команды и увидеть сообщения об ошибках.
С другой стороны, если вы предпочитаете видеть сообщения об ошибках непосредственно в powershell, поскольку свойство Content недоступно при получении ошибки HTTP, вы должны извлечь сообщение об ошибке из потока ответов, как описано здесь.
Полный образец с обработкой ошибок:
$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
}