GoDaddy DNS API - Building a module with numerous commands - rest

EDIT: I am looking for assistance on the GoDaddy API and how to form the request so I can delete a record. I can replace records and add new records and, of course, read records. I do not need assistance on building the module. Just having a problem figuring out the REST API piece for doing a delete on GoDaddy with the API.
I found this: Error 422 When Using Powershell to Update DNS Records on GoDaddy API
This gave me a good start. I have a number of functions I have already written to create or modify various different types of record. I have learned a lot along the way. Something that I have been unable to figure out so far is how to use the API to delete an existing record that is no longer needed.
I discovered that if I had an existing record of the same name and type and I tried to create a new, it would replace what was there with the new value. If it is just an A record and that is your desire, that's great. But if it is an MX or NS record, that is probably not the desired result. I am working on the helper functions to make sure that I don't blow away existing records before I publish to my module.
I am relatively new to reading API documentation and working with REST API's so I am probably just missing something basic, but if anyone could provide me with some guidance on how to configure my call so that I can clean up records that are no longer needed.
I am also having some issues formatting the SRV record properly so that it doesn't error out when I make the call. I am not sure where my problem is and I am not seeing anything in the documentation of allowed/expected values for Protocol, Service, etc.
Here is an excerpt of my code where I am calling:
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-Verbose -Message "Success!" }
else { Write-Warning -Message "ERROR" }
} 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-Warning -Message "ERROR: $responseBody"
}
You will recognize this code block as it is largely taken intact from the aforementioned post. I am passing in $type as a valid record type (A, CNAME, etc.). $alias is the name of an existing record. $headers is a properly formatted header with a valid key/secret pair (I am able to Get and Put other records). I have tried omitting the body altogether to delete a value and that fails. I have tried doing the body with a JSON empty set ([], [{}]) as well as passing in data and TTL values with no value in the JSON. I can't get a successful query to work. I am testing with the following:
Invoke-WebRequest "https://api.godaddy.com/v1/domains/mydomain/records/A/test2" -method put -headers $header -ContentType "application/json" -Body '[{}]'
Any guidance or pointers to documentation that I haven't found would be greatly appreciated.

I had the same problem, it's about JSON encoding. I will show you a PHP example you can adapt to anything. The format that GoDaddy will provide is like this:
[{"":"","":"","":"",.....}]
I don't know from where comes the [] but I remove them, the parse json with regular PHP functions:
$json = str_replace("]","",$json);
//print_r($json);
$json = json_decode($json,true);
Now you will get the usable object to work with.
When send data to GoDaddy, do the same (I use curl)
$data = '[{"type":"'.$type.'","name":"'.$name.'","data":"'.$data.'","ttl":'.$ttl.'}]';
A full example that I build for updating my home server dynamic IP :) Check the functions Update() and get()
https://github.com/yo3hcv/Dynamic-DNS-hosting-home-or-mobile-with-GoDaddy/blob/master/pip.php

This maybe useful for others as I ran into the same unclarity about deleting a DNS record from a Godaddy domain using their API.
Godaddy doesn't support deleting an individual record.
From their support on the question whether it was possible to delete a record:
Dear Sir/Madam,
This API call does not exist at this time and it is something on our backlog to build out but there is no ETA to have it created. Current you can use the Put endpoint on the record type to replace all but the one you do not want to keep or you may go into our UI to remove it that way.
See their api documentation for what is available (at this date July 2020).
However, what you can do is replace all the existing records with a new set.
So suppose you have three A records with subdomain SD1, SD2 and SD3 and you want to remove SD2. You could sent an update command using:
curl -X PUT "https://api.godaddy.com/v1/domains/<yourdomain>/records/A" -H "accept: application/json" -H "Content-Type: application/json" -H "Authorization: <yourAPIKEY>" -d "[ { \"data\": \"<IP for SD1>\", \"name\": \"SD1\", \"ttl\": 3600 }, { \"data\": \"<IP for SD3>\", \"name\": \"SD3\", \"ttl\": 3600 }]"
Which will result in two A records one for SD1 and one for SD3. As long as you have at least one recordtype left (this also works for MX, MS, TXT) you will be able to remove others.
If you want to remove the last you have to go back to the Godaddy GUI, unfortunately.

Related

Graphi API - Creating Document Set with Invoke-RestMethod

I need some help to get my code to create a Document Set in SharePoint Online using Graph API directly from a PowerShell script using Invoke-RestMethod.
I tested the request under the Graph Explorer portal and it works fine and I get a nice HTTP 201 (OK) as seen on the picture below:
Trying the very same request from my PowerShell script fails and returns HTTP 400 (Bad Request), I can't get the folder created and that is the first step to get the document set created, according to my research and an example found here:
Is it possible to create a project documentset using graph API?
As the first step mentioned in the example above, I need to first create the folder and then proceed to the following steps to achieve the creation of the document set but I can't get this first step done.
My application has the necessary permissions as I tested in the Graph Explorer:
Files.ReadAndWrite.All
Sites.ReadAndWrite.All
Sites.FullControl.All (not required but I had to try this one to make sure!)
I'm on the second step (folder creation) and I can't get past this point, according to the link above, once I get this working I will need to get the new folder ID, and then send a new PATCH to alter its content type to match the desire document set, I hope I can get some help, all the examples are vague and pretty much describe only on what to do but no actual functional code to sample from.
Thanks in advance!
$uri = "https://graph.microsoft.com/v1.0/drives/b!yVnguUBzyUC1PxgTM0JP-_ERFp1PTZFCjycaWZK6yKulBi9Ce_J8RIfF-OkWKE4B/root/children"
$headers = #{
"Authorization" = "$($token.token_type) $($token.access_token)"
"Content-Type" = "application/json"
}
$body = #{
"name" = "Test"
"folder" = {}
"#microsoft.graph.conflictBehavior" = "rename"
}
$request = Invoke-RestMethod -Headers $headers -Body $body -Method Post -Uri $uri
It should work when you modify $body like this
$body = #{
"name" = "Test"
"folder" = #{}
"#microsoft.graph.conflictBehavior" = "rename"
} | ConvertTo-Json
$body is a JSON object and you need to convert it to JSON. For initialing an empty folder object you have to use #{} instead of {}.
Thanks #user2250152, you gave me a great idea by solving part of the problem!
I did add the conversion to JSON as you recommended and decided to add the content-type back to my original header and it did the trick!
Adding the content-type solved the issue but your collaboration was essential, so thank you very much!
Now wish me luck to get the other steps done and achieve the conclusion of this thing!
$headers = #{
"Authorization" = "$($token.token_type) $($token.access_token)"
"Content-Type" = "application/json"
}

Powershell Invoke-Response Where Clause

I have the following Powershell script that runs without issue. I am being told that I need to add "&onlyCurrent=false" to get it to pull information for employees with a future start date. I have no idea how to do this....
$response = Invoke-RestMethod 'https://api._________.com/api/gateway.php/gemco/v1/reports/120' -Method 'GET' -Headers $headers
When I add this to the end, I get invalid parameter error message:
-Where-Object onlyCurrent eq "false"
The support for they system I'm pulling this from has no information on how to do this. Absolutely any help would be very greatly appreciated.
&onlyCurrent=false is probably a query string. You can append it at the end of the URL after ?. Note that & is used to separate multiple parameters, since you have just one it's not needed. Try changing the URL to:
https://api._________.com/api/gateway.php/gemco/v1/reports/120?onlyCurrent=false
Figured it out. You have to add ?onlyCurrent=false after the 120 (inside the single quote).

Powershell - Invoke-RestMethod with multiple headers

I am trying to use Invoke-Restmethod in Powershell to call an API (I'm fairly new to this). I can get it to POST and return the jwt access token. I can also use that token to return an id via GET, however I'm then having trouble with the next step of returning the next set of data. I can get it to work manually via curl. I believe the issue may be because multiple headers are required to return the tenant list and I'm unsure of the format to get this to work.
The curl script looks as follows, and works as expected:
curl -XGET -H "Authorization: Bearer <jwt access token>" -H "ID: <id>" https://theapiurl.com/.......
I've tried multiple ways to do this in powershell, most recently as below, but nothing I'm trying works. I've tried returning the individual $headers contents and building a string (i.e. $headers2 = $.headers.Item(Authorization) + ......) but that doesn't work either. To be honest, I've tried so many different things I've forgotten what I have and haven't tried
$headers = #{
'ID' = $id
'Authorization' = $auth_string
}
$response = Invoke-RestMethod -Method Get -Headers $headers -Uri $url
Please could you let me know the correct way to add multiple headers (which I think is the problem and what I'm getting wrong)?
In case it's useful to anyone else, another syntax for setting the parameters of this commandlet is as follows (real working example for uploading to the GitHub release repository). It's usful to set all the switches (without prepending a hyphen) in the parameters object like so:
$upload_params = #{
Uri = $upload_uri + "?name=$asset_name"
Method = 'POST'
Headers = #{
'Authorization' = "token $github_token"
'Accept' = 'application/vnd.github.everest-preview+json'
}
InFile = $asset
ContentType = 'application/octet-stream'
}
"Uploading $asset..."
$upload = Invoke-RestMethod #upload_params
"The server returned:"
echo $upload
The variable $upload contains the full object returned from the server (converted from json to a PowerShell object). So, for example, you can also get properties of this obect like so:
"Upload successfully posted as " + $upload.url
Thanks for all the responses - none of them were really the answer but they did give me the confidence I was doing it the right way.
I'd been using PS Write-Host to check the data returned - this was working for the tokens and ID's, but wasn't working for next step. I wasn't getting an error, just no data. (I did see the returned data when testing manually in a command prompt window).
As soon as I added an -OutFile to the PS and checked the file, I realised it was working all along and PS just wasn't showing me the results. 2 hours wasted, although I've learnt more as a result!

Powershell - Invoke-WebRequest - Issue with submit

I'm working on a powershell script that will create a printer on my Company Print Server, which is all done and working.
But we have however a location where we list all used IP's, which is a webpage.
So I'm trying to use Invoke-WebRequest to do this. Login to the page works but then when it tries to use the form to add the IP it doesn't.
Login only has one submit button in the form and to add the IP there is three buttons. I will list them in the order they are on the page
Clear the form
Apply
Cancel
So I'm thinking when I Invoke-Webrequest it is using the "clear form" function.
Is there any way I could specify which function to use when sending a webrequest?
I cant remove the "Clear form" button since it is being used frequently, just to get that clear.
$R = Invoke-WebRequest -URI http://localhost -SessionVariable IP
$Form = $R.Forms[0]
$Form.fields["ctlUsername"]=User
$Form.fields["ctlPassword"]=Pass
$R=Invoke-WebRequest -Uri ("http://localhost/" + $Form.Action) -WebSession
$IP -Method POST -Body $Form.Fields
$D = Invoke-WebRequest -URI http://localhost/addIP.php -WebSession $Test
$Form2 = $D.Forms[0]
$Form2.fields["IP"]="172.10.0.1"
$Form2.fields["name"]="Printer300"
$Form2.fields["location"]="Room407"
$Form2.fields["MAC"]="000"
$Form2.fields["ID"]="000"
Invoke-WebRequest -Uri http://localhost/addIP.php -WebSession $IP -Method POST -Body $Form2.Fields
Don't think in terms of "filling in web pages" when it comes to sending those requests. Web pages for a human user. Filling in a form and clicking a button is the manual way of creating an HTTP message with data.
When you post this form:
IP: [172.10.0.1 ]
Name: [Printer300 ]
Location: [Room407 ]
[Apply] [Cancel]
the browser creates a text string like this:
IP=172.10.0.1&Name=Printer300&Location=Room407
and sends it to the target URL.
Invoke-WebRequest can create this format directly from your data. This means, you don't need to "fill in" anything. Just pass a hashtable with the proper keys and values:
Invoke-WebRequest "http://localhost/addIP.php" -WebSession $IP -Method POST -Body #{
IP = "172.10.0.1"
Name = "Printer300"
Location = "Room407"
MAC = "000"
ID = "000"
}
Of course the keys must correspond to the form field names.
That being said, I don't see much of a need for authentication with requests coming from the localhost. You can save yourself some busywork by disabling authentication for all local requests, and requiring it only for remote requests.
Anyway, making a website request a password and then storing that password in clear text in a script is not exactly secure to begin with.
Invoke-WebRequest supports Windows integrated authentication, so that you don't have to bother with usernames and passwords at all. This would be my preferred authentication solution for such tasks.
Found the issue, it needed a hidden value that was not being sent via the form but was added in php function later.
Thanks for all your help.

How to query Azure AppInsights custom metric from Powershell

I'm publishing a custom metric called "ConnectionCount" on my AppInsights component.
I'm looking for a way to query the last values for that metric in a PowerShell script.
I've used this command in the past:
$resourceId = "/subscriptions/$subscriptionId/resourceGroups/MyResourceGroup/providers/microsoft.insights/components/MyAppInsight"
Get-AzureRmMetric -ResourceId $resourceId -TimeGrain $timeGrain -StartTime $startTime -MetricNames $metric`
But when run this, I just get an error back:
Get-AzureRmMetric : Operation returned an invalid status code 'NotFound'
I also tried the REST API, using this code:
$resourceGroupId = "subscriptions/$subscriptionId/resourceGroups/$resourceGroupName"
$filter = "(name.value eq 'ConnectionCount') and timeGrain eq duration'PT5M' and " +
"startTime eq 2017-07-20T17:00:47.8791884Z and endTime eq 2017-07-25T17:30:47.8832111Z"
$apiVersion = "2015-05-01"
$uri = "https://management.azure.com/$resourceGroupId/providers/microsoft.insights/components/$appInsightName/metrics?api-version=$apiVersion&`$filter=$filter"
Invoke-RestMethod $uri -Headers $headers
But it simply gives me back an empty response.
Does anyone know if something has changed in the Metrics API that would prevent custom metrics values to be retrieve from PowerShell or the REST API?
if you're getting an empty response (and not any kind of failure) then i'd suggest verifying that your query is doing what you expect and not filtering out all your data?
your filter looks really suspicious to me, this part timeGrain eq duration'PT5M' seems like an odd filter to me. normally you'd specify the range and the grain as other parts of the query, not inside the $filter part
i'd suggest verifying all of your REST stuff with the API docs at https://dev.applicationinsights.io, and try testing your query at
https://dev.applicationinsights.io/apiexplorer/metrics