Managing NPS using PowerShell and netsh

The following post will detail how you can use a combination of PowerShell and netsh to manage one or more Microsoft NPS servers (Server 2008 R2). In the example I’ll detail how you can update the shared secret on all the RADIUS clients across all your NPS servers.

The first thing you need to do in such a PS script is to have a way of identifying your NPS servers. If you’re running a small environment where all the NPS servers are going to need to be setup the same way, then this is easy and I’ll explain what I’ve done below. If you’re running a larger more complex environment where you have groups of NPS servers setup differently, then you’re likely going to want to create some config files for your script to pull server names from.

Assuming you have a small environment… make sure you have your NPS servers registered. To register an NPS server, launch the ‘Network Policy Server’ console, right click the top node ‘NPS (local)’ and click ‘Register server in Active Directory’. This will cause the servers computer account in Active Directory to be added to the security group ‘RAS and IAS Servers’. You can then have your PS script pull a list of NPS servers from this group using a line like

$NPSServers = Get-ADGroupMember “RAS and IAS Servers”

The next step is to build an array of all the Radius clients you have on your NPS servers. Ideally you would already have the same Radius clients on each NPS server, however if you happened to have a Raidus client setup on one NPS server and not on another it’s not a super big deal in regards to having the script update the shared secret.

To build the array of the Radius clients, the first thing you’ll want to do is create the array object.

$ClientArray = @()

You then will want to do a ForEach on your list of NPS servers and collect an export of the Radius clients using netsh. The below can be used to do this.

$NPSServers | ForEach-Object {
$Server = $_.Name
$Result = Invoke-Command -ComputerName $Server -ScriptBlock {
netsh nps show client
}

This will populate the variable Result with an export of all the clients. You’ll then have to parse through the result variable and pull out the client information. The below shows a way (maybe not the best way) to pull out the name of each client on the NPS server, along with the other information on the client.

$Result|ForEach-Object {

$currenttext=$_

If ($currenttext-like“*Client configuration*”) {

$nameline= ($currentline+ 2)

$name=$result[$nameline]

$IPline= ($currentline+ 3)

$IP=$result[$IPline]

$stateline= ($currentline+ 4)

$State=$result[$stateline]

$secretline= ($currentline+ 5)

$Secret=$result[$secretline]

$name=$name.split(“=”)

$name=$name[1]

$IP=$IP.Split(“=”)

$IP=$IP[1]

$State=$State.split(“=”)

$State=$State[1]

$Secret=$Secret.Split(“=”)

$Secret=$Secret[1]

$String=“$Name”

If ($Global:ClientArray-contains$String) {

#skip

}

Else {

$Global:ClientArray+=$String

}

}

$currentline++

}

Just for the record, I’m well aware that the above code could be improved upon. I just copy and pasted that from the first version of a utility I wrote and have never gone back to review and clean it up. It works, so… yeah.

After the above has been ran against each NPS server, you’ll have an array that contains a list of Radius clients without any duplicate names. You can then run the following to go through each client in the array on each server and update the shared secret.

$ServerLoop= 1

$ServerArray|ForEach-Object {

$CurrentServer=$_

Log (“Currently processing NPS server $CurrentServer.”)

$ClientLoop= 1

$Global:ClientArray|ForEach-Object {

Status (“Client $ClientLoop of $ClientCount. Server $ServerLoop of $ServerCount.”)

$Name=$_

Log (“Updating secret on RADIUS client $Name on $CurrentServer.”)

$Result=Invoke-CommandComputerName $CurrentServerScriptBlock {

$Name=$args[0]

$Secret=$args[1]

netsh nps set client name =$Name sharedsecret =$Secret

} ArgumentList $Name, $NewSecret

If ($Result-like“*Ok.*”) {

Log (“The client $Name successfully received the new secret on $CurrentServer.”)

}

Else {

Log (“ERROR: A problem occured while updateing the secret for $Name on $CurrentServer.”)

$Issues=$true

}

$ClientLoop++

}

$ServerLoop++

}

 

As you can see, the main thing to note is the use of netsh to specify the name of a Radius client, and then specify the new shared secret. Below are some other netsh commands you can use to manage your Radius clients using PS scripting like what you saw above.

Add a client

netsh nps add client name = $ClientName address = $ClientIP state = enable sharedsecret = $secret

Edit a client name

netsh nps rename client name = $Name newname = $NewName

Edit other details of a client

netsh nps set client name = $name address = $IP state = $status sharedsecret = $secret

Delete a client

netsh nps delete client name = $Name

 

Alternatively to having a bunch of PowerShell scripts that do this stuff for you, you can create a PS Forms based app that provides you central management of your NPS servers. Below are some screenshots of what I’ve created for the network team at my current employer to use to do day to day tasks with the NPS servers we have.

The screenshot below is of the main page of the app. From here you can add/edit/delete clients, as well as view the radius logs combined from all the NPS servers, update the shared secret across the board, and view information on a specific NPS server.

Main

The screenshot below is of the interface to create a new radius client. When the create button is pressed, PS goes out and creates the new client on all the NPS servers.

Add

The screenshot below is of the interface to edit a radius client. Like when creating a new client, clicking the update button causes PS to go out across all NPS servers and update information for the client on each server.

Edit

The screenshot below is of the interface for syncing an NPS server with another. This could be useful if a single NPS server seems to be out of sync from the others, or if you stand up a new NPS server. (I’m well aware of the ability to export your NPS config and then import it on new NPS servers.)

Sync

The screenshot below is the first of several interfaces for viewing the NPS logs. The screenshot below just shows a list of all the dates there are logs for on all the NPS servers. Upon clicking a date, the screen would update with a list of all the systems that have connected to the NPS servers. Clicking a system would result in a cleaned up view of the NPS logs for that system. Useful when troubleshooting connectivity issues.

Logs1