New-NpsRadiusClientWithTemplate.ps1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 |
#requires -Version 2.0 <#PSScriptInfo .VERSION 0.1 .GUID 59c4a6c3-5bd5-43cd-913b-f4e533f6ef73 .AUTHOR Chris Masters .COMPANYNAME Chris Masters .COPYRIGHT (c) 2019 Chris Masters. All rights reserved. .TAGS NPS RADIUS SecretKey SharedSecret .LICENSEURI .PROJECTURI https://www.powershellgallery.com/profiles/masters274/ .ICONURI .EXTERNALMODULEDEPENDENCIES .REQUIREDSCRIPTS .EXTERNALSCRIPTDEPENDENCIES .RELEASENOTES Initial release, with very little testing. I know it works for adding. And when you check the GUI, it shows the device as using the template. However, I have not gone so far as to setup a dev env so I could change the keys we use for our various SharedSecretTemplates. Some notes on the process (observed only, not research)... The IAS (Network Policy Server) service stores its files in $env:SystemRoot\System32\IAS\ When you edit data, it gets entered into ias_converted.xml and ias.xml. I'm not sure of the process or reason for the two different files, as they're identical (SHA256 hashed). Maybe the changes are entered into the converted files, checked for proper formatting, then copied to ias.xml...? Either way, I don't think it would be a good idea to edit these files directly, because stuff happens. PROCESS: - First the script creates a session with your NPS server. - Creates a new NPS radius client - Exports the configuration (messy, I know. Yet will be worth it when you need to change the key later) - Changes the GUID for the template used on that client - Then imports the changed config - And optionaly restarts the service. I've noticed that it doesn't take affect until a service restart when editing via the command line. Also of note.... it wasn't 3am when I wrote this, so not my best work... but it was pretty late, so maybe it's not so bad. .PRIVATEDATA #> <# .Synopsis Adds a new NPS RADIUS client, and applies an authentication template to the client .DESCRIPTION Why Microsoft doesn't give you the ability to apply a template when creating a new client puzzles me. This script aims to solve this problem, as many organizations have a lot of devices, and a password policy that requires changing RADIUS secrets. You don't want to have to update all the clients, just the template. That why we use them...! This may not be the best way to solve this problem, however it does work. .EXAMPLE Example of how to use this cmdlet .EXAMPLE Another example of how to use this cmdlet .NOTES I would suggest that you add default parameter values into your profile. You don't want to put in values that don't change often, every time. $PSDefaultParameterValues = @{ ComputerName = 'myNpsServer.domain.name' AuthenticationTemplate = 'Cisco_Template' Vendor = 'Cisco' } #> [CmdLetBinding()] Param ( [Parameter(Mandatory=$true, position=0, HelpMessage='Client name', ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)] [String] $ClientName, [Parameter(Mandatory=$true, position=1, HelpMessage='Client IP', ValueFromPipelineByPropertyName=$true)] [IPAddress] $IPAddress, [Parameter(Mandatory=$true, HelpMessage='Name of computer to manage', ValueFromPipelineByPropertyName=$true)] [String] $AuthenticationTemplate, [Parameter(Mandatory=$false, HelpMessage='Radius client vendor name. i.e cisco', ValueFromPipelineByPropertyName=$true)] [String] $Vendor = 'RADIUS Standard', [Parameter(Mandatory=$true, HelpMessage='Name of NPS server(s)')] [String[]] $ComputerName, [Switch] $Restart, # The service needs to be restarted before the settings take effect [Parameter(Mandatory=$false, HelpMessage='Credentials for administering NPS')] [System.Management.Automation.Credential()] [PSCredential] $Credential, [ValidateSet('Default','Basic','CredSSP','Digest','Kerberos','Negotiate','NegotiateWithImplicitCredential')] [String] $Authentication = 'Kerberos' ) Begin { # If you don't want ur stuff to work, don't restart If (!$Restart) { Write-Warning -Message 'You need to restart before settings take affect' } # Constants $Params = @{ ComputerName = $ComputerName Authentication = $Authentication } If ($Credential) { $Params += @{ Credential = $Credential } } # We only need to make our connection once $s = New-PSSession @Params } Process { # Variables [ScriptBlock] $sbCommand = { Param ( $ClientName, $IPAddress, $AuthenticationTemplate, $Vendor, $Restart ) Try { # IAS templates are stored in a file on the NPS server. [String] $strIASFile = $env:SystemRoot + '\System32\ias\iastemplates.xml' [xml] $objIAS = Get-Content -Path $strIASFile [String] $strTemplateGuid = $objIAS.GetElementsByTagName($AuthenticationTemplate).Properties.Template_Guid.InnerText [String] $strSharedSecret = $objIAS.GetElementsByTagName($AuthenticationTemplate).Properties.RADIUS_Shared_Secret.InnerText # We need to make the object firt, then we'll apply the auth template New-NpsRadiusClient -Name $ClientName -Address ($IPAddress.ToString()) -AuthAttributeRequired $False -VendorName $Vendor -SharedSecret $strSharedSecret # we now need to export the config, update the affected object, then re-import $strTempExportFile = [System.IO.Path]::GetTempPath() + [Guid]::NewGuid().guid + '.xml' $strTempImportFile = [System.IO.Path]::GetTempPath() + [Guid]::NewGuid().guid + '.xml' Export-NpsConfiguration -Path $strTempExportFile [xml] $objNPSExport = Get-Content $strTempExportFile } Catch { "Error was $_" $line = $_.InvocationInfo.ScriptLineNumber "Error was in Line $line" } Try { $cleanedClientName = $ClientName -replace '\s|\-','_' $objNPSExport.GetElementsByTagName($cleanedClientName).properties.Client_Secret_Template_Guid.'#text' = $strTemplateGuid } Catch { # No need to keep it, if we can't find it later. Remove-NpsRadiusClient -Name $ClientName -ErrorAction SilentlyContinue # clean up the temp file Remove-Item -Path $strTempExportFile Write-Error -Message 'Unable to find your object. Please only use uderscores "_", instead of spaces or dashes "-"' # exiting return } $objNPSExport.Save($strTempImportFile) Import-NpsConfiguration -Path $strTempImportFile # Clean up remove-item -Path $strTempExportFile -ErrorAction SilentlyContinue Remove-Item -Path $strTempImportFile -ErrorAction SilentlyContinue # when making changes to clients, the service has to be restarted. If ($Restart) { Restart-Service -Name IAS } } Invoke-Command -Session $s -ScriptBlock $sbCommand -ArgumentList $ClientName, $IPAddress, $AuthenticationTemplate, $Vendor, $Restart } End { Remove-PSSession -Session $s } |