opello.{com,net,org}

NameSilo API from PowerShell

Sunday, February 14, 2016 categories: code, dns, namesilo, powershell

A friend asked several people on irc about NameSilo's API and dynamic DNS entries. He found a PowerShell script to update a subdomain with the current IP address of the system running the script. The subdomain detail was the crux of the question: how to get it to update a "naked" domain. Several of us read through the API reference but the dnsUpdateRecord function didn't explain how to update the base domain's A record.

It turned out that simply leaving off the rrhost parameter was sufficient to get the job done.

After we were done iterating on it, we had a PowerShell function to update any record. Including enough intelligence to handle the base domain case. I don't believe non-A records were tested, but it met the need of updating the base domain and a sub-domain or two from a scheduled task.

# NameSilo API Dynamic DNS
# Variables
$APIkey = ""
$domain = ""

function NameSilo-dnsUpdateRecord {
    param ([string]$APIKey, [string]$Domain, [string]$Record, [string]$Type)

    # Retrieve the DNS entries in the domain.
    $listdomains = Invoke-RestMethod -Uri "https://www.namesilo.com/api/dnsListRecords?version=1&type=xml&key=$APIkey&domain=$domain"
    $Records = $listdomains.namesilo.reply.resource_record | where { $_.type -eq $Type }

    $UpdateRecord = $null
    $IsNaked = $False
    foreach ($r in $Records ) {
        if ([string]::IsNullOrEmpty($Record) -and $r.host -eq $Domain) {
            $UpdateRecord = $r
            $IsNaked = $True
            break
        } elseif ($r.host -eq "$($Record).$($Domain)") {
            $UpdateRecord = $r
            break
        }
    }
    if ($UpdateRecord -eq $null) {
        echo "Error: Could not find requested record: $($Record).$($Domain)"
        Exit
    }

    $CurrentIP = $listdomains.namesilo.request.ip
    $RecordIP = $UpdateRecord.value
    $RecordID = $UpdateRecord.record_id

    # Only update the record if necessary.
    if ($CurrentIP -ne $RecordIP){
        $url = "https://www.namesilo.com/api/dnsUpdateRecord?version=1&type=xml&key=$APIkey&domain=$Domain&rrid=$RecordID"
        if ($IsNaked -eq $False) {
            $url += "&rrhost=$record"
        }
        $url += "&rrvalue=$CurrentIP&rrttl=3600"
        $update = Invoke-RestMethod -Uri $url
    } else {
        echo "IP Address has not changed."
    }
}

# Invocations:
NameSilo-dnsUpdateRecord -APIKey $APIkey -Domain $domain -Record "" -Type "A"
NameSilo-dnsUpdateRecord -APIKey $APIkey -Domain $domain -Record "*" -Type "A"
NameSilo-dnsUpdateRecord -APIKey $APIkey -Domain $domain -Record "test" -Type "A"

Since I don't do hardly anything in PowerShell, aside from trying to use it more than cmd.exe on Windows because it is a resizable window, I did a little more reading after this was written and concluded that it is not likely representative of PowerShell best practices.

But it is posted here just in case it might be useful to someone.