WhoIS Report
Really fascinating project came through Spiceworks the other day and I wanted to talk about it. In the DNS forum someone posted that they needed a tool to lookup certain WhoIs information. The interesting part was they had over 1000 domains so they needed something that could create a report on that kind of scale, so a simple WhoIs website or application wasn’t going to cut it. But as I looked at it, I began to wonder if this was something I could pull off with PowerShell? I knew there would be no problem once I had the data, but the trick would be getting the data. But surely there was a RESTful API out there for WhoIs data, right? If I could find that then a simple Invoke-RestMethod should retrieve the data necessary and we’re good to go. Right?
Update 7/13/14:
I want to let this post stand, but I have to update it. Unfortunately RestfulWhoIs.com made some kind of change to their API and the script no longer works (I’ve actually removed the source code from Spiceworks). I have worked on the problem some but haven’t been able to solve it. If anyone wants to take a crack at it I’d love to hear what you’ve done, and perhaps I will take another shot at it in the future but unfortunately it’s dead as of now. Which is too bad, I thought it was a useful addition to a IT Manager’s toolbox!
Nothing is Ever Easy
This project is very much like the Last Earthquake script I wrote a little while back, so I figured the hardest part would be finding an API that would get me the data. So I began my journey through Google and looking at all the different WhoIs data feeds out there. Turns out there are quite a few, but most wanted some kind of authentication or fee to get working. I don’t like making people buy third party things when running my scripts, so I really wanted to find a free data feed, if possible. Sure enough, I finally stumbled upon RestfulWhoIs.com, which is a very simple little data feed with just the information I needed. I reviewed how to use the API, and it turned out the syntax was incredibly simple, just the correct URL with the domain name at the end! The only thing interesting was their API allowed for different data objects to be returned (JSON, XML, etc) so I had to use an Accept header with “application/json” as the value. I had no idea what that meant so I reviewed the help file for Invoke-RestMethod and found the Header parameter, which accepted a hash table as input. So I built a simple hash table with a key of “Accept” and a value of “application/json” and gave the command a whirl:
Kind of a bizarre error message. Accept must be modified with the appropriate property or method? And why was it mentioning the name property? Ok, let’s replace the “Accept” key with “Name” and see if it’s happier.
It worked! Except that the data I got back was HTML, and not objects–Invoke-RestMethod will convert JSON objects into PowerShell objects for you. Since the API documentation specifically mentioned that if you don’t use the proper Accept header it will default to HTML. I was pretty sure that while the command executed properly it did not give the API what it needed. Time to break out the Google-fu and research this problem. Unfortunately it didn’t take long to find a bug report on Microsoft Connect about this very issue (read about it here). Turns out there is a known problem with PowerShell not being able to send a proper Accept header and the problem is fixed with PowerShell 4.0. I only just started using PowerShell 3.0, was I ready to upgrade to 4.0?! If I don’t do it, I won’t be able to do this project, and I wasn’t about to let that happen! Ten minutes later I had PowerShell 4.0 installed and tried the command again:
Success! After that it was a simple matter of wrapping some logic around it and producing a HTML type report. And here is the code I originally came up with:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#requires -Version 4.0 | |
$Path = "c:\test" | |
$Data = ForEach ($Domain in (Get-Content $Path\domains.txt)) | |
{ $Web = Invoke-RestMethod –Uri "http://www.restfulwhois.com/v1/$Domain" –Headers @{"accept"="application/json"} | |
$TimeSpan = New-TimeSpan –Start (Get-Date) –End ((Get-Date "1/1/1970").AddMilliseconds($Web.expiry)) | |
$DaysLeft = "$($TimeSpan.Days) Days, $($TimeSpan.Hours) Hours, $($TimeSpan.Minutes) Minutes" | |
[PSCustomObject]@{ | |
Domain = $Domain | |
Status = $Web.Status -join ", " | |
Created = (Get-Date "1/1/1970").AddMilliseconds($Web.registered) | |
Updated = (Get-Date "1/1/1970").AddMilliseconds($Web.updated) | |
Expires = (Get-Date "1/1/1970").AddMilliseconds($Web.expiry) | |
DaysLeft = $DaysLeft | |
Registrar = $Web.Registrar.Name | |
ns = $Web.ns.ipv4 -join ", " | |
} | |
} | |
$Header = @" | |
<style> | |
TABLE {border-width: 1px;border-style: solid;border-color: black;border-collapse: collapse;} | |
TH {border-width: 1px;padding: 3px;border-style: solid;border-color: black;background-color: #6495ED;} | |
TD {border-width: 1px;padding: 3px;border-style: solid;border-color: black;} | |
</style> | |
"@ | |
$Data | ConvertTo-Html –Head $Header –PreContent "<h2>Domain Information</h2>" –PostContent "<h6>Run on: $(Get-Date)</h6>" | Out-File $Path\DomainInfo.html |
But the more I thought about it, the more I began to realize that this is the kind of script that really should be an essential tool for every administrator. Run monthly it would be a great way to make sure your active domains never expires and that you always have budget set aside for the renewal of them as they come up. I decided to ramp the script up with error checking, verbose output, that kind of thing. I also decided to leverage my ConvertTo-AdvHTML function so as domains get closer to their expiration date the color of the row would change color.
Get-WhoIs.ps1
Problems with the Feed
I decided not to go into detail about how the script was built, frankly is not too different from many other scripts I’ve put out here but I’d be more than happy to discuss it over at Spiceworks if you want! But I did notice some problems with the data feed that I had to deal with. One weird thing was the data feed will report if there is an error in the _Status field, except when the error is the domain can’t be found!! It just returns a object with very little data in it, which is a real pain. I had to put in a couple of If statements in there to check if a couple of needed fields are missing. Why a couple? Well, it turns out the feed also had a problem with PowerShell.org in that it would only pull up the name server information and nothing much else. So had to deal with that.
Also, had fun creating a legend at the bottom of the report. My HTML-fu is not very strong, but I’ve been getting better and I ran through Codecademy’s excellent training material. Things I’ve been doing with CSS I now finally understand! Which, I suppose, is a good thing, yah?! So the Legend doesn’t look like much, but it was really interesting to make it without using a table. Also, I’ve found this website very useful for making websites, and not needing to install anything on my workstation: HTML Real-time Editor
[…] I haven’t been able to publish anything. I did finally come across another way to produced WhoIs data, so my WhoIs script is back in business! One nice thing about the report is I’m using a […]