A Hundred Domains and SHA-1 Depreciation

September 17, 2014 at 4:30 pm

Apparently I’ve been living under a rock for a while, because I didn’t know that SHA-1 was being phased out in the immediate future. Thank you, GoDaddy, for notifying me with a month and change to spare. As it turns out, Google will no longer be trusting certain SHA-1 signed SSL certificates with the release of Chrome 39, which is set for November. For details, see the following links.

Due to the fact that our clients often purchase their own SSL certificates, we have no internal records to check what algorithm was used to sign the certificates in use. So now we get to audit slightly over 100 domains to check and see what signature algorithm is in use. We could browse to each domain manually and take a look at their certificate but that would just take way too long. There were some web based tools around that could do it, but they also only worked on one site at a time.

So, instead, I looked to PowerShell to see what could be done… Unfortunately, there was no native cmdlet to do anything like this! I did find a module that had a lot of great PKI-related functionality, the Public Key Infrastructure PowerShell module, but it, too, didn’t have the much-needed signature algorithm. However, it did provide a very robust base on which to build. Below is the solution I came up with.

function get-SSLSigningAlgorithm {
[CmdletBinding()]
    param(
        [Parameter(Mandatory = $true, ValueFromPipeline = $true, Position = 0)]
        [string]$URL,
        [Parameter(Position = 1)]
        [ValidateRange(1,65535)]
        [int]$Port = 443,
        [Parameter(Position = 2)]
        [Net.WebProxy]$Proxy,
        [Parameter(Position = 3)]
        [int]$Timeout = 15000,
        [switch]$UseUserContext
    )
    $ConnectString = "https://$url`:$port"
    $WebRequest = [Net.WebRequest]::Create($ConnectString)
    $WebRequest.Proxy = $Proxy
    $WebRequest.Credentials = $null
    $WebRequest.Timeout = $Timeout
    $WebRequest.AllowAutoRedirect = $true
    [Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}
    try {$Response = $WebRequest.GetResponse()}
    catch {}
    if ($WebRequest.ServicePoint.Certificate -ne $null) {
        $Cert = [Security.Cryptography.X509Certificates.X509Certificate2]$WebRequest.ServicePoint.Certificate.Handle
	write-host $Cert.SignatureAlgorithm.FriendlyName;
    } else {
        Write-Error $Error[0]
    }
}

I’ll create a CSV of the domains that I need to check, and iterate over them in a for-each loop. That function will be used within the loop to check the sites, and the output will go into another CSV. We’ll use that to plan our re-keying.

Hide Disabled AD Accounts from the GAL using Powershell

September 8, 2014 at 10:48 am

Our account decommission process involves disabling a user and moving them to a “Disabled Domain Accounts” OU. Well, it turns out that our previous admin never actually hid these mailboxes from the Global Address List (GAL), so many of our offshore partners have still been sending emails to them. I decided to start cleaning this up a bit today with the following:

Search-ADAccount -SearchBase "ou=Disabled Domain Accounts,dc=example,dc=local" -AccountDisabled -UsersOnly |Set-ADUser  -Replace @{msExchHideFromAddressLists=$true}

Another simple bit of PowerShell. The first command searches within the disabled account OU, and looks for disabled user accounts only. That output is piped into the second command which replaces the Exchange attribute that hides that account from the GAL.

How to clear all Workstation DNS caches from PowerShell

September 4, 2014 at 2:32 pm

I recently found myself in need of the ability to clear the DNS cache of all the laptops in my company. I found a very powerful and simple way to do so and thought I would share.

$c = Get-ADComputer -Filter {operatingsystem -notlike "*server*" }
Invoke-Command -cn $c.name -SCRIPT { ipconfig /flushdns }

The first line queries Active Directory for all computers that are not servers. The second line simply invokes the normal windows command “ipconfig /flushdns” on all computers.

This technique could be used to run any command across all workstations. Very powerful, and dangerous. Use at your own risk!

Finding Expired User Accounts in AD and Resetting Their Passwords with PowerShell

June 2, 2014 at 4:01 pm

The Setup

I came into the office today and was bombarded with users not being able to access our TFS server. Now, before I get too far into this story, you have to understand: Technically I’m only responsible for client-facing infrastructure. However, over the years I’ve started wearing more of a devops hat because, apparently, I’m quite good at it. That means TFS is now largely my problem. Funny how that works, eh? Anyway, back to TFS.

There were a few odd things about this issue: the oddest being that some of our off-shore developers were having no problems and others just couldn’t get in. The users with issues also couldn’t access the web portal. We (at least me) hadn’t made any changes to TFS in about a month, so I started to investigate.

After a brief panic about SharePoint not being installed properly (Hey, I didn’t set up this system, I’m just its current keeper) I managed to trace the issue to network logons. Thank you Security log! Wait, what’s this? Turns out many, many users recently had their accounts marked as expired… Turns out we just implemented mandatory password rotation and guess what? Today – 90 days was the day that a large batch of offshore development accounts were created! So now I had to reset credentials on 35+ accounts, and I’ll be damned if I’m going to do that manually!

Enter PowerShell!

List all accounts in an OU that have expired passwords

Get-ADUser -searchbase "ou=contractors,dc=example,dc=com" -filter {Enabled -eq $True} -Prop PasswordExpired | Where {$_.PasswordExpired } |select-object -property SAMAccountName,Name,PasswordExpired |format-table

Get-ADUser

SearchBase tells the Get-ADUser command to limit the search to a specific OU. This is very handy since I only have admin access to the one OU anyway. I filtered only for enabled accounts since trying to filter on PasswordExpired here didn’t work for some reason. I also explicitly called out the PasswordExpired property.  This output was piped to the where-object commandlet.

Where-Object

This was where I filtered on the current object group. Since passwordExpired is a bool, no fanciness needed here. Then I piped the output to Select-Object.

Select-Object

I only cared about some specific data for the output. I used this to select the properties I needed. Finally, I piped to Format-Table to make everything display nicely.

Reset passwords for accounts in an OU with expired passwords

Get-ADUser -searchbase "ou=contractors,dc=example,dc=com" -filter {Enabled -eq $True} -Prop PasswordExpired | Where {$_.PasswordExpired } | ForEach-Object {Set-ADAccountPassword -Identity $_.SAMAccountName -NewPassword (ConvertTo-SecureString -AsPlainText "Changeme1" -Force) }

Get-ADUser & Where-Object

These are the same as in the section above. We are filtering for enabled accounts in the contractors OU. This was piped to one of my favorite commands on earth: ForEach-Object.

ForEach-Object

This is, hands down, one of the handiest commands in PowerShell. Or any language for that matter. In this particular instance, we are running the Set-ADAccountPassword option for each object that we pass in. We pass the object’s SAMAccountName as the identity. We then create a new secure string password and pass that to -NewPassword. Then you hit enter and the magic runs!