Some obvious stuff here. I need to call various APIs to do various things. Previously I used to use curl
but now I want to use Invoke-RestMethod
(of PowerShell) too just to spice things up. This blog post is going to be a “running” blog post that I keep updating as I pick up new things on this topic.
NS1
One of the sites I am accessing is NS1 for DNS. Their API documentation is here and is quite straightforward. They don’t need me to login with a username/password, but an API key that I send via the headers.
Here’s an example of the curl
command I could use with them to list all their zones:
1 |
curl -X GET -H 'X-NSONE-Key: $API_KEY' https://api.nsone.net/v1/zones |
The $API_KEY
is a token I generate from their website. The URL keeps changing depending on what I want to do, and sometimes I’d have to POST
rather than GET
when I want to send data.
For example, to create a new zone:
1 |
curl -X PUT -H 'X-NSONE-Key: $API_KEY' -d '{"zone":"{ZONE_NAME}", "nx_ttl":60}' https://api.nsone.net/v1/zones/{ZONE_NAME} |
Usually what I’d do is something like this:
1 2 3 4 5 6 7 8 9 |
zone="<Replace with Zone Name>" api_key="<Create from Website>" # note the space matters header="'X-NSONE-Key: ${api_key}'" body="'{\"zone\":\"$zone\", \"nx_ttl\":60}'" eval curl -X PUT -H "$header" -d "$body" https://api.nsone.net/v1/zones/$zone |
I have to do an eval curl
because without it the API call wasn’t working and then I read on some StackOverflow post that running it under eval
ensures all the parameters are passed correctly. I think since the body
and header
variables have spaces or curly braces that is messing things up unless I do an eval
.
A better approach that I discovered later is the following:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
zone="<Replace with Zone Name>" api_key="<Create from Website>" header="'X-NSONE-Key: ${api_key}'" body=$(cat <<EOF '{ "zone": "$zone", "nx_ttl":60 }' EOF ) curl -X PUT -H "$header" -d "$body" https://api.nsone.net/v1/zones/$zone |
No need to eval
here and since I am using a heredoc I can keep the body
more readable.
Another option is to put the body in a JSON file and invoke it via the --data @filename.json
switch in curl
(replace filename.json
with the real filename).
Doing the same via Invoke-RestMethod
is similar:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
$zone="<Replace with Zone Name>" $api_key = "<Create from Website>" $contentType = "application/json" $headers = @{ "X-NSONE-Key" = "$api_key" } $body = @{ "zone" = $zone "nx_ttl" = 60 } $bodyJSON = ConvertTo-Json $body Invoke-RestMethod -ContentType "$contentType" -Headers $headers -UseBasicParsing -Method "PUT" -Body $bodyJSON https://api.nsone.net/v1/zones/$zone |
Bit more organized with PowerShell as I can use hash tables and convert them to JSON for the body.
OAuth2 in General
I will tackle OAuth2 in another post but the above method is quite common for most OAuth2 implementations. You get an access/ bearer token and authenticate using it. These are the variations (of the header) I have come across:
1 |
Authorization: OAuth <ACCESS_TOKEN> |
1 |
Authorization: Bearer <ACCESS_TOKEN> |
Other authentication
Just for my info here’s the switches to do other forms of authentication using curl
.
1 2 3 4 5 6 7 8 9 10 11 |
# basic auth curl --user user:password https://url # digest auth curl --digest --user user:password https://url # ntlm auth curl --ntlm --user user:password https://url # negotiate auth curl --negotiate --user user:password https://url |
There’s also an --anyauth --user
that lets curl
try without authentication first.
I will fill in the equivalent or Invoke-RestMethod
later.
Mark Monitor
Another one I had to login to was Mark Monitor. They have a very limited API and I ended up not using it, but in their case the authentication was not via headers. I had to send the username and password via the body.
1 2 3 4 5 6 7 8 9 |
body=$(cat <<EOF '{ "username": "user", "password": "pass" }' EOF ) curl -X POST "https://domains.markmonitor.com/domains/restapi/v2/login" -H "accept: application/json" -H "Content-Type: application/json" -d $body |
This is similar to the NS1 case above except that I don’t authorize via the headers. Similar technique via Invoke-RestMethod
too:
1 2 3 4 5 6 7 8 9 10 |
$body = @{ "username" = "user" "password" = "pass" } $bodyJSON = ConvertTo-Json $body $contentType = "application/json" Invoke-RestMethod -ContentType "$contentType" -Body $bodyJSON -UseBasicParsing -Method "Post" -Uri https://domains.markmonitor.com/domains/restapi/v2/login |