-
Notifications
You must be signed in to change notification settings - Fork 2
/
AAD-Password-Protection-Install-Proxy-Service.ps1
662 lines (589 loc) · 32.6 KB
/
AAD-Password-Protection-Install-Proxy-Service.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
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
### Abstract: This PoSH Script Helps Install The Azure AD Password Protection Proxy Service
### Written by: Jorge de Almeida Pinto [MVP-EMS]
### BLOG: http://jorgequestforknowledge.wordpress.com/
###
### 2019-10-08: Initial version of the script (v0.1)
### 2019-10-22: Improved output on screen to be more clear and added check for required .NET Framework version (v0.2)
### 2019-10-30: Updated the portConnectionCheck to also check name resolution (v0.3)
###
<#
.SYNOPSIS
With this PoSH script, one can install The Azure AD Password Protection Proxy Service on targeted Windows Servers
.DESCRIPTION
With this PoSH script, one can install The Azure AD Password Protection Proxy Service on targeted Windows Servers
.PARAMETER servers
The FQDN of the server(s), in a comma separated list, to target
.PARAMETER installSourceFullPath
The full path to the MSI/EXE install source
.EXAMPLE
Install The Azure AD Password Protection Proxy Service on the LOCAL Server
.\AAD-Password-Protection-Install-Proxy-Service.ps1 -servers LOCAL -installSourceFullPath "<Full Path To The MSI/EXE Install Source>"
.EXAMPLE
Install The Azure AD Password Protection Proxy Service on the LOCAL Server and a remote Server
.\AAD-Password-Protection-Install-Proxy-Service.ps1 -servers LOCAL,SERVER1.COMPANY.COM -installSourceFullPath "<Full Path To The MSI/EXE Install Source>"
.NOTES
This script requires local administrator equivalent permissions on Windows Server to install the software.
The path for installation source files must be the same on each targeted Windows Server
It creates a log for the machine in the same location as the MSI/EXE Install Source
#>
Param(
[Parameter(Mandatory=$FALSE, ValueFromPipeline=$TRUE, ValueFromPipelineByPropertyName=$TRUE,
HelpMessage='Please specify the list of servers by specifying FQDNs in a comma-separated manner')]
[string[]]$servers,
[Parameter(Mandatory=$TRUE, ValueFromPipeline=$TRUE, ValueFromPipelineByPropertyName=$TRUE,
HelpMessage='Please specify the full path to the MSI/EXE to install the Azure AD Password Protection Proxy Service')]
[ValidateNotNullOrEmpty()]
[string]$installSourceFullPath
)
### FUNCTION: Load Required PowerShell Modules
Function loadPoSHModules($PoSHModule) {
If(@(Get-Module | Where-Object {$_.Name -eq $PoSHModule}).count -eq 0) {
If(@(Get-Module -ListAvailable | Where-Object {$_.Name -eq $PoSHModule} ).count -ne 0) {
Import-Module $PoSHModule
Write-Host ""
Write-Host "PoSH Module '$PoSHModule' Has Been Loaded..." -ForeGroundColor Green
Write-Host "Continuing Script..." -ForeGroundColor Green
Write-Host ""
} Else {
Write-Host ""
Write-Host "PoSH Module '$PoSHModule' Is Not Available To Load..." -ForeGroundColor Red
Write-Host "Aborting Script..." -ForeGroundColor Red
Write-Host ""
EXIT
}
} Else {
Write-Host ""
Write-Host "PoSH Module '$PoSHModule' Already Loaded..." -ForeGroundColor Yellow
Write-Host "Continuing Script..." -ForeGroundColor Yellow
Write-Host ""
}
}
### FUNCTION: Test Credentials For Specific Admin Role
Function testAdminRole($adminRole) {
# Determine Current User
$currentUser = [Security.Principal.WindowsIdentity]::GetCurrent()
# Check The Current User Is In The Specified Admin Role
(New-Object Security.Principal.WindowsPrincipal $currentUser).IsInRole($adminRole)
}
### FUNCTION: Test Credentials For Remote Admin Privileges
Function testRemoteAdmin ($server) {
$adminShare = "\\" + $server + "\admin$"
If (Test-Path $adminShare) {
Return $True
} Else {
Return $False
}
}
### FUNCTION: Test The Port Connection
Function portConnectionCheck($fqdnServer, $port, $timeOut) {
# Test To See If The HostName Is Resolvable At All
Try {
[System.Net.Dns]::gethostentry($fqdnServer) | Out-Null
} Catch {
Return "ERROR"
}
$tcpPortSocket = $null
$portConnect = $null
$tcpPortWait = $null
$tcpPortSocket = New-Object System.Net.Sockets.TcpClient
$portConnect = $tcpPortSocket.BeginConnect($fqdnServer, $port, $null, $null)
$tcpPortWait = $portConnect.AsyncWaitHandle.WaitOne($timeOut, $false)
If(!$tcpPortWait) {
$tcpPortSocket.Close()
Return "ERROR"
} Else {
#$error.Clear()
$ErrorActionPreference = "SilentlyContinue"
$tcpPortSocket.EndConnect($portConnect) | Out-Null
If (!$?) {
Return "ERROR"
} Else {
Return "SUCCESS"
}
$tcpPortSocket.Close()
$ErrorActionPreference = "Continue"
}
}
### FUNCTION: Retrieve The Product Version From Within The MSI
Function retrieveMsiProductVersion($installSourceFullPath) {
Try {
$windowsInstaller = New-Object -com WindowsInstaller.Installer
$msiDatabase = $windowsInstaller.GetType().InvokeMember("OpenDatabase", "InvokeMethod", $null, $windowsInstaller, @($installSourceFullPath, 0))
$msiQuery = "SELECT Value FROM Property WHERE Property = 'ProductVersion'"
$msiView = $msiDatabase.GetType().InvokeMember("OpenView", "InvokeMethod", $null, $msiDatabase, ($msiQuery))
$msiView.GetType().InvokeMember("Execute", "InvokeMethod", $null, $msiView, $null)
$record = $msiView.GetType().InvokeMember("Fetch", "InvokeMethod", $null, $msiView, $null)
$msiProductVersion = $record.GetType().InvokeMember("StringData", "GetProperty", $null, $record, 1)
$msiView.GetType().InvokeMember("Close", "InvokeMethod", $null, $msiView, $null)
Return $msiProductVersion
} catch {
#Throw "Unable To Determine Product Version. The Error Was: {0}." -f $_
Return "0.0.0.0"
}
}
$retrieveMsiProductVersionDef = "function retrieveMsiProductVersion{${function:retrieveMsiProductVersion}}"
### FUNCTION: Check .NET Version
Function checkDotNETVersion() {
# Get Installed Version Of .NET
$dotNETVersionNrInstalled = $null
$dotNETVersionNrInstalled = (Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full\" -Name Release).Release
# Determine .NET Framework Version Text
If ($dotNETVersionNrInstalled) {
$dotNETVErsionText = $null
Switch ($dotNETVersionNr) {
# SOURCE: https://docs.microsoft.com/en-us/dotnet/framework/migration-guide/how-to-determine-which-versions-are-installed
{$dotNETVersionNrInstalled -lt 378389} {$dotNETVErsionText = ".NET Framework 4 Or Lower"}
{$dotNETVersionNrInstalled -eq 378389} {$dotNETVErsionText = ".NET Framework 4.5"} # All Windows operating systems
{$dotNETVersionNrInstalled -eq 378389} {$dotNETVErsionText = ".NET Framework 4.5"} # All Windows operating systems
{$dotNETVersionNrInstalled -eq 378675} {$dotNETVErsionText = ".NET Framework 4.5.1"} # On Windows 8.1 and Windows Server 2012 R2
{$dotNETVersionNrInstalled -eq 378758} {$dotNETVErsionText = ".NET Framework 4.5.1"} # On all other Windows operating systems
{$dotNETVersionNrInstalled -eq 379893} {$dotNETVErsionText = ".NET Framework 4.5.2"}
{$dotNETVersionNrInstalled -eq 393295} {$dotNETVErsionText = ".NET Framework 4.6"} # On Windows 10
{$dotNETVersionNrInstalled -eq 393297} {$dotNETVErsionText = ".NET Framework 4.6"} # On all other Windows operating systems
{$dotNETVersionNrInstalled -eq 394254} {$dotNETVErsionText = ".NET Framework 4.6.1"} # On Windows 10 November Update systems
{$dotNETVersionNrInstalled -eq 394271} {$dotNETVErsionText = ".NET Framework 4.6.1"} # On all other Windows operating systems (including Windows 10)
{$dotNETVersionNrInstalled -eq 394802} {$dotNETVErsionText = ".NET Framework 4.6.2"} # On Windows 10 Anniversary Update and Windows Server 2016
{$dotNETVersionNrInstalled -eq 394806} {$dotNETVErsionText = ".NET Framework 4.6.2"} # On all other Windows operating systems (including other Windows 10 operating systems)
{$dotNETVersionNrInstalled -eq 460798} {$dotNETVErsionText = ".NET Framework 4.7"} # On Windows 10 Creators Update
{$dotNETVersionNrInstalled -eq 460805} {$dotNETVErsionText = ".NET Framework 4.7"} # On all other Windows operating systems (including other Windows 10 operating systems)
{$dotNETVersionNrInstalled -eq 461308} {$dotNETVErsionText = ".NET Framework 4.7.1"} # On Windows 10 Fall Creators Update and Windows Server, version 1709
{$dotNETVersionNrInstalled -eq 461310} {$dotNETVErsionText = ".NET Framework 4.7.1"} # On all other Windows operating systems (including other Windows 10 operating systems)
{$dotNETVersionNrInstalled -eq 461808} {$dotNETVErsionText = ".NET Framework 4.7.2"} # On Windows 10 April 2018 Update and Windows Server, version 1803
{$dotNETVersionNrInstalled -eq 461814} {$dotNETVErsionText = ".NET Framework 4.7.2"} # On all Windows operating systems other than Windows 10 April 2018 Update and Windows Server, version 1803
{$dotNETVersionNrInstalled -eq 528040} {$dotNETVErsionText = ".NET Framework 4.8"} # On Windows 10 May 2019 Update
{$dotNETVersionNrInstalled -eq 528049} {$dotNETVErsionText = ".NET Framework 4.8"} # On all others Windows operating systems (including other Windows 10 operating systems)
{$dotNETVersionNrInstalled -gt 528049} {$dotNETVErsionText = "Higher Than .NET Framework 4.8"}
Default {$dotNETVErsionText = "Unable To Determine .NET Framework Version"}
}
} Else {
$dotNETVErsionText = ".NET Framework Not Installed"
}
If ($dotNETVersionNrInstalled -ge 460798) {
Return "SUCCESS","Minimum Required .NET Framework Version (4.7) IS Installed",$dotNETVErsionText
} Else {
Return "FAILURE","Minimum Required .NET Framework Version (4.7) IS NOT Installed",$dotNETVErsionText
}
}
$checkDotNETVersionDef = "function checkDotNETVersion{${function:checkDotNETVersion}}"
### FUNCTION: Install The Azure AD Password Protection Proxy Service
Function installAADPwdProtectPrx($installSourceFullPath, $installSourceVersion, $execArgs) {
If ($installSourceFullPath.EndsWith(".msi")) {
$installCommand = Start-Process C:\WINDOWS\SYSTEM32\MSIEXEC.EXE -ArgumentList $execArgs -wait -PassThru
}
If ($installSourceFullPath.EndsWith(".exe")) {
$installCommand = Start-Process $installSourceFullPath -ArgumentList $execArgs -wait -PassThru
}
Start-Sleep 3
# Old School --> WMIC PRODUCT GET NAME | FIND /I "Azure AD Password Protection Proxy"
$productAADPwdProtectPrx = $null
$productAADPwdProtectPrx = Get-WmiObject -Class win32_product -Filter "Name like 'Azure AD Password Protection Proxy'"
If ($productAADPwdProtectPrx -And $([System.Version]$($productAADPwdProtectPrx.Version) -eq $installSourceVersion)) {
Return "SUCCESS","Azure AD Password Protection Proxy Service INSTALLED SUCCESSFULLY On '$server'",$(If ($productAADPwdProtectPrx) {$($productAADPwdProtectPrx.Version)} Else {"NO-VERSION-INSTALLED"}),$installSourceVersion
} Else {
Return "FAILURE","Azure AD Password Protection Proxy Service FAILED TO INSTALL On '$server'",$(If ($productAADPwdProtectPrx) {$($productAADPwdProtectPrx.Version)} Else {"NO-VERSION-INSTALLED"}),$installSourceVersion
}
}
$installAADPwdProtectPrxDef = "function installAADPwdProtectPrx{${function:installAADPwdProtectPrx}}"
### Clear The Screen
Clear-Host
### Configure The Appropriate Screen And Buffer Size To Make Sure Everything Fits Nicely
$uiConfig = (Get-Host).UI.RawUI
$uiConfig.WindowTitle = "+++ INSTALL THE AZURE AD PASSWORD PROTECTION PROXY SERVICE +++"
$uiConfig.ForegroundColor = "Yellow"
$uiConfigBufferSize = $uiConfig.BufferSize
$uiConfigBufferSize.Width = 160
$uiConfigBufferSize.Height = 9999
$uiConfigScreenSizeMax = $uiConfig.MaxPhysicalWindowSize
$uiConfigScreenSizeMaxWidth = $uiConfigScreenSizeMax.Width
$uiConfigScreenSizeMaxHeight = $uiConfigScreenSizeMax.Height
$uiConfigScreenSize = $uiConfig.WindowSize
If ($uiConfigScreenSizeMaxWidth -lt 160) {
$uiConfigScreenSize.Width = $uiConfigScreenSizeMaxWidth
} Else {
$uiConfigScreenSize.Width = 160
}
If ($uiConfigScreenSizeMaxHeight -lt 75) {
$uiConfigScreenSize.Height = $uiConfigScreenSizeMaxHeight - 5
} Else {
$uiConfigScreenSize.Height = 75
}
$uiConfig.BufferSize = $uiConfigBufferSize
$uiConfig.WindowSize = $uiConfigScreenSize
Write-Host ""
Write-Host " **************************************************************************" -ForeGroundColor Cyan
Write-Host " * *" -ForeGroundColor Cyan
Write-Host " * --> Install The Azure AD Password Protection Proxy Service <-- *" -ForeGroundColor Cyan
Write-Host " * *" -ForeGroundColor Cyan
Write-Host " * Written By: Jorge de Almeida Pinto [MVP-EMS] *" -ForeGroundColor Cyan
Write-Host " * *" -ForeGroundColor Cyan
Write-Host " * BLOG: http://jorgequestforknowledge.wordpress.com/ *" -ForeGroundColor Cyan
Write-Host " * *" -ForeGroundColor Cyan
Write-Host " **************************************************************************" -ForeGroundColor Cyan
Write-Host ""
### Check The Arguments/Parameters
If ($psboundparameters.count -eq 0 -Or $args.count -gt 0) {
Write-Host ""
Write-Host "No Arguments/Parameters Were Specified..." -ForeGroundColor Red
Write-Host "Showing Full Help..." -ForeGroundColor Red
Write-Host ""
Get-help $MyInvocation.MyCommand.Definition -full
EXIT
}
### Definition Of Some Constants
$dateTime = Get-Date -Format "yyyy-MM-dd_HH.mm.ss"
$localComputerName = $(Get-WmiObject -Class Win32_ComputerSystem).Name
$fqdnDomainName = $(Get-WmiObject -Class Win32_ComputerSystem).Domain
$fqdnLocalComputer = $localComputerName + "." + $fqdnDomainName
$currentScriptPath = $MyInvocation.MyCommand.Definition
$currentScriptFolderPath = Split-Path $MyInvocation.MyCommand.Definition
$outputCSVFilePath = $currentScriptFolderPath + "\" + $dateTime + "_AAD-Pwd-Protection-Proxy-Service-Install.CSV"
### Test For Availability Of PowerShell CMDlets And Load Required PowerShell Module
loadPoSHModules ActiveDirectory
### Determine A Global Catalog To Query
$gcFQDN = (Get-ADDomainController -Discover -Service GlobalCatalog).Hostname[0]
### Create A New List Of Servers To Process, Replace LOCAL With The Actual FQDN Of The Local Server, And Count The Number Of Specified Servers
$listOfServers = @()
$servers | %{
$server = $null
$server = $_
# If LOCAL Was Specified, Translate It To The FQDN
If ($server.ToUpper() -eq "LOCAL") {
$serverToAdd = $fqdnLocalComputer
} Else {
$serverToAdd = $server
}
# If The Server To Add Is The Local Computer Check Permissions
If ($serverToAdd -eq $fqdnLocalComputer) {
$localAdminObjectSID = "S-1-5-32-544"
$localAdminRole = (New-Object System.Security.Principal.SecurityIdentifier($localAdminObjectSID)).Translate([System.Security.Principal.NTAccount]).Value
$userIsLocalAdmin = $null
$userIsLocalAdmin = testAdminRole $localAdminRole
If (!$userIsLocalAdmin) {
# The User Account Running This Script Has Been Validated Not Being A Member Of The Local Admins Group Of The Local Server
Write-Host ""
Write-Host "No Admin Permissions For The Server '$serverToAdd'..." -ForegroundColor Red
Write-Host "Skipping Server '$serverToAdd'..." -ForegroundColor Red
} Else {
If ($listOfServers -notcontains $serverToAdd) {
$listOfServers += $serverToAdd
}
}
} Else {
# Check If The Object Exists In AD. If It Exists Check If The Required Permissions Are In Place And If Yes Add To The List, Otherwise Skip
$adObject = Get-ADComputer -LDAPFilter "(dNSHostName=$serverToAdd)" -Server $gcFQDN`:3268
If ($adObject) {
$userIsRemoteAdmin = $null
$userIsRemoteAdmin = testRemoteAdmin $serverToAdd
If (!$userIsRemoteAdmin) {
# The User Account Running This Script Has Been Validated Not Being A Member Of The Local Admins Group Of The Remote Server
Write-Host ""
Write-Host "Server Not Accessible Or No Admin Permissions For The Server '$serverToAdd'..." -ForegroundColor Red
Write-Host "Skipping Server '$serverToAdd'..." -ForegroundColor Red
} Else {
If ($listOfServers -notcontains $serverToAdd) {
$listOfServers += $serverToAdd
}
}
} Else {
Write-Host ""
Write-Host "The Server '$serverToAdd' DOES NOT Exist..." -ForegroundColor Red
Write-Host "Skipping Server '$serverToAdd'..." -ForegroundColor Red
}
}
}
### Check For The Number Of Server. Azure AD Password Protection Only Supports 2 Servers Per AD Forest With The Azure AD Password Protection Proxy Service
If ($listOfServers.Count -gt 2) {
Write-Host ""
Write-Host "It Is NOT Supported To Have More Than 2 Servers With The Azure AD Password Protection Proxy Service Role..." -ForeGroundColor Red
Write-Host "Aborting Script..." -ForeGroundColor Red
Write-Host ""
EXIT
}
### Building Empty List Of Installation Results
$installResults = @()
### If A List Of Servers Exists Process It
If ($listOfServers) {
$listOfServers | %{
# Get The FQDN Of The Server
$server = $null
$server = $_
Write-Host ""
Write-Host "--> Server.............................: $server" -ForegroundColor Cyan
# Applicable For The Local Computer, Otherwise Applicable For The Remote Computer
If ($server -eq $fqdnLocalComputer) {
# If The Correct .NET Version Is Installed Then Continue, Otherwise Abort
$checkDotNETVersionResult = $null
$checkDotNETVersionResult = checkDotNETVersion
$result = $null
$result = $checkDotNETVersionResult[0]
$message = $null
$message = $checkDotNETVersionResult[1]
$dotNETVersion = $null
$dotNETVersion = $checkDotNETVersionResult[2]
If ($result.ToUpper() -eq "SUCCESS") {
Write-Host "$message on '$server'" -ForegroundColor Green
Write-Host "Installed .NET Version.................: $dotNETVersion" -ForegroundColor Green
Write-Host "Continuing..." -ForegroundColor Green
# If The Full Path To The MSI/EXE Exists Then Continue, Otherwise Abort
If (Test-Path $installSourceFullPath) {
$installSourceVersion = $null
# Determine The Version If It Is An MSI
If ($installSourceFullPath.EndsWith(".msi")) {
[string]$installSourceVersion = retrieveMsiProductVersion $installSourceFullPath
$installSourceVersion = $installSourceVersion.Trim()
}
# Determine The Version If It Is An EXE
If ($installSourceFullPath.EndsWith(".exe")) {
$installSourceVersion = [System.Diagnostics.FileVersionInfo]::GetVersionInfo($installSourceFullPath).FileVersion
}
# Specify The Full Path For The Log File
$logFolder = $null
$logFolder = Split-Path $installSourceFullPath
$logFile = $null
$logFile = Join-Path $logFolder $("AzureADPasswordProtectionProxyService_Install_v" + $installSourceVersion + "_" + $server + "_" + $dateTime + ".log")
# Specify The Arguments For When Using An MSI
$execArgs = $null
If ($installSourceFullPath.EndsWith(".msi")) {
$execArgs = @(
"/I"
"$installSourceFullPath"
"/LV"
"$logFile"
"/NoRestart"
)
}
# Specify The Arguments For When Using An EXE
If ($installSourceFullPath.EndsWith(".exe")) {
$execArgs = @(
"/install"
"/quiet"
"/log"
"$logFile"
"/NoRestart"
)
}
# Retrieve The 'Azure AD Password Protection Proxy' Product Installation
$productAADPwdProtectPrx = $null
$productAADPwdProtectPrx = Get-WmiObject -Class win32_product -Filter "Name like 'Azure AD Password Protection Proxy'"
# If It Does Not Yet Exist, Then Install It
# If It Does Exist, Then Either Upgrade (Newer Version) Or Reinstall (Same Version) It After Confirmation
If (!$productAADPwdProtectPrx) {
Write-Host "Azure AD Password Protection Proxy Service Not Yet Installed On '$server'" -ForegroundColor Yellow
Write-Host "Installing Azure AD Password Protection Proxy Service On '$server'" -ForegroundColor Yellow
$productAADPwdProtectPrxResult = installAADPwdProtectPrx $installSourceFullPath $installSourceVersion $execArgs
Write-Host "Installation Completed!..." -ForegroundColor Yellow
Write-Host "New Version............................: $installSourceVersion" -ForegroundColor Yellow
Write-Host "Log File...............................: $logFile" -ForegroundColor Yellow
$installResultOnServer = $productAADPwdProtectPrxResult
$installResultOnServer += $dotNETVersion
} Else {
Write-Host "Azure AD Password Protection Proxy Service ALREADY INSTALLED On '$server'" -ForegroundColor Yellow
Write-Host "Installed Version......................: $($productAADPwdProtectPrx.Version)" -ForegroundColor Yellow
Write-Host "New Version............................: $installSourceVersion" -ForegroundColor Yellow
Write-Host ""
# If The Current Product Version Is Lower Than The New Product Version, Upgrade It
# If The Current Product Version Is Equal To The New Product Version, Reinstall It
# If The Current Product Version Is Higher Than The New Product Version, Do Not Do Anything
$response = $null
If ([System.Version]$($productAADPwdProtectPrx.Version) -lt [System.Version]$installSourceVersion) {
$response = Read-Host "Do You Want To UPGRADE The Current Version? (Y|N)"
} ElseIf ([System.Version]$($productAADPwdProtectPrx.Version) -eq [System.Version]$installSourceVersion) {
$response = Read-Host "Do You Want To Reinstall The Current Version? (Y|N)"
} Else {
$response = "N"
}
# When Confirmed To Upgrade/Reinstall, Then Actually Do It
Write-Host ""
If ($response.ToUpper() -eq "Y" -Or $response.ToUpper() -eq "YES") {
Write-Host "Installing Azure AD Password Protection DC Agent Service On '$server'" -ForegroundColor Yellow
$productAADPwdProtectPrxResult = installAADPwdProtectPrx $installSourceFullPath $installSourceVersion $execArgs
Write-Host "Installation Completed!..." -ForegroundColor Yellow
Write-Host "Log File...............................: $logFile" -ForegroundColor Yellow
$installResultOnServer = $productAADPwdProtectPrxResult
$installResultOnServer += $dotNETVersion
} Else {
Write-Host "Nothing Was Installed On '$server' As It Was Not Confirmed..." -ForegroundColor Yellow
$installResultOnServer = "NO-INSTALL","Azure AD Password Protection Proxy Service Was NOT Upgraded/Reinstalled On '$server'",$($productAADPwdProtectPrx.Version),$installSourceVersion,$dotNETVersion
}
}
} Else {
Write-Host "Nothing Was Installed On '$server' As The Installation Source '$installSourceFullPath' Was Not Found..." -ForegroundColor Red
$installResultOnServer = "NO-SOURCE","Azure AD Password Protection Proxy Service MSI IS NOT AVAILABLE/ACCESSIBLE On '$server'",$(If ($productAADPwdProtectPrx) {$($productAADPwdProtectPrx.Version)} Else {"NO-VERSION-INSTALLED"}),"VERSION-NOT-AVAILABLE",$dotNETVersion
}
} Else {
Write-Host "$message on '$server'" -ForegroundColor Red
Write-Host "Installed Version: $dotNETVersion" -ForegroundColor Red
Write-Host "Skipping '$server'..." -ForegroundColor Red
$installResultOnServer = "NO-DOTNET","$message on '$server'","NO-VERSION-INSTALLED","VERSION-NOT-AVAILABLE",$dotNETVersion
}
} Else {
# Check The Connection To The Server If Remote
$ports = 5985 # WinRM For Remote PowerShell
$connectionCheckOK = $true
$ports | %{
$port = $null
$port = $_
$connectionResult = $null
$connectionResult = portConnectionCheck $server $port 500
If ($connectionResult -eq "ERROR") {
$connectionCheckOK = $false
}
}
$installResultOnServer = $null
# If The Connection To The Server Is OK...
If ($connectionCheckOK) {
Write-Host "ALL Required Ports ($($ports -join ",")) To The Server '$server' Are Available!..." -ForegroundColor Green
# Setup A Session To The RWDC
$targetedServerSession = $null
$targetedServerSession = New-PSSession -ComputerName $server
# Connect To The Server And Execute The Scriptblock
$installResultOnServer = Invoke-Command -Session $targetedServerSession -ArgumentList $dateTime,$server,$installSourceFullPath,$retrieveMsiProductVersionDef,$checkDotNETVersionDef,$installAADPwdProtectPrxDef -ScriptBlock {
Param(
$dateTime,
$server,
$installSourceFullPath,
$retrieveMsiProductVersionDef,
$checkDotNETVersionDef,
$installAADPwdProtectPrxDef
)
. ([ScriptBlock]::Create($retrieveMsiProductVersionDef))
. ([ScriptBlock]::Create($checkDotNETVersionDef))
. ([ScriptBlock]::Create($installAADPwdProtectPrxDef))
# If The Correct .NET Version Is Installed Then Continue, Otherwise Abort
$checkDotNETVersionResult = $null
$checkDotNETVersionResult = checkDotNETVersion
$result = $null
$result = $checkDotNETVersionResult[0]
$message = $null
$message = $checkDotNETVersionResult[1]
$dotNETVersion = $null
$dotNETVersion = $checkDotNETVersionResult[2]
If ($result.ToUpper() -eq "SUCCESS") {
Write-Host "$message on '$server'" -ForegroundColor Green
Write-Host "Installed Version: $dotNETVersion" -ForegroundColor Green
Write-Host "Continuing..." -ForegroundColor Green
# If The Full Path To The MSI/EXE Exists Then Continue, Otherwise Abort
If (Test-Path $installSourceFullPath) {
$installSourceVersion = $null
# Determine The Version If It Is An MSI
If ($installSourceFullPath.EndsWith(".msi")) {
[string]$installSourceVersion = retrieveMsiProductVersion $installSourceFullPath
$installSourceVersion = $installSourceVersion.Trim()
}
# Determine The Version If It Is An EXE
If ($installSourceFullPath.EndsWith(".exe")) {
$installSourceVersion = [System.Diagnostics.FileVersionInfo]::GetVersionInfo($installSourceFullPath).FileVersion
}
# Specify The Full Path For The Log File
$logFolder = $null
$logFolder = Split-Path $installSourceFullPath
$logFile = $null
$logFile = Join-Path $logFolder $("AzureADPasswordProtectionProxyService_Install_v" + $installSourceVersion + "_" + $server + "_" + $dateTime + ".log")
# Specify The Arguments For When Using An MSI
$execArgs = $null
If ($installSourceFullPath.EndsWith(".msi")) {
$execArgs = @(
"/I"
"$installSourceFullPath"
"/LV"
"$logFile"
"/NoRestart"
)
}
# Specify The Arguments For When Using An EXE
If ($installSourceFullPath.EndsWith(".exe")) {
$execArgs = @(
"/install"
"/quiet"
"/log"
"$logFile"
"/NoRestart"
)
}
# Retrieve The 'Azure AD Password Protection Proxy' Product Installation
$productAADPwdProtectPrx = $null
$productAADPwdProtectPrx = Get-WmiObject -Class win32_product -Filter "Name like 'Azure AD Password Protection Proxy'"
# If It Does Not Yet Exist, Then Install It
# If It Does Exist, Then Either Upgrade (Newer Version) Or Reinstall (Same Version) It After Confirmation
If (!$productAADPwdProtectPrx) {
$productAADPwdProtectPrxResult = installAADPwdProtectPrx $installSourceFullPath $installSourceVersion $execArgs
Write-Host "Done!..." -ForegroundColor Yellow
Write-Host "Log File...............................: $logFile" -ForegroundColor Yellow
Return $productAADPwdProtectPrxResult,$dotNETVersion
} Else {
Write-Host "Azure AD Password Protection Proxy Service ALREADY INSTALLED On '$server'" -ForegroundColor Yellow
Write-Host "Installed Version......................: $($productAADPwdProtectPrx.Version)" -ForegroundColor Yellow
Write-Host "New Version............................: $installSourceVersion" -ForegroundColor Yellow
Write-Host ""
# If The Current Product Version Is Lower Than The New Product Version, Upgrade It
# If The Current Product Version Is Equal To The New Product Version, Reinstall It
# If The Current Product Version Is Higher Than The New Product Version, Do Not Do Anything
$response = $null
If ([System.Version]$($productAADPwdProtectPrx.Version) -lt [System.Version]$installSourceVersion) {
$response = Read-Host "Do You Want To UPGRADE The Current Version? (Y|N)"
} ElseIf ([System.Version]$($productAADPwdProtectPrx.Version) -eq [System.Version]$installSourceVersion) {
$response = Read-Host "Do You Want To Reinstall The Current Version? (Y|N)"
} Else {
$response = "N"
}
# When Confirmed To Upgrade/Reinstall, Then Actually Do It
Write-Host ""
If ($response.ToUpper() -eq "Y" -Or $response.ToUpper() -eq "YES") {
Write-Host "Installing Azure AD Password Protection DC Agent Service On '$server'" -ForegroundColor Yellow
$productAADPwdProtectPrxResult = installAADPwdProtectPrx $installSourceFullPath $installSourceVersion $execArgs
Write-Host "Installation Completed!..." -ForegroundColor Yellow
Write-Host "Log File...............................: $logFile" -ForegroundColor Yellow
Return $productAADPwdProtectPrxResult + $dotNETVersion
} Else {
Write-Host "Nothing Was Installed On '$server' As It Was Not Confirmed..." -ForegroundColor Yellow
Return "NO-INSTALL","Azure AD Password Protection Proxy Service Was NOT Upgraded/Reinstalled On '$server'",$($productAADPwdProtectPrx.Version),$installSourceVersion,$dotNETVersion
}
}
} Else {
Write-Host "Nothing Was Installed On '$server' As The Installation Source '$installSourceFullPath' Was Not Found..." -ForegroundColor Red
Return "NO-SOURCE","Azure AD Password Protection Proxy Service MSI IS NOT AVAILABLE/ACCESSIBLE On '$server'",$(If ($productAADPwdProtectPrx) {$($productAADPwdProtectPrx.Version)} Else {"NO-VERSION-INSTALLED"}),"VERSION-NOT-AVAILABLE",$dotNETVersion
}
} Else {
Write-Host "$message on '$server'" -ForegroundColor Red
Write-Host "Installed Version: $dotNETVersion" -ForegroundColor Red
Write-Host "Skipping '$server'..." -ForegroundColor Red
Return "NO-DOTNET","$message on '$server'","NO-VERSION-INSTALLED","VERSION-NOT-AVAILABLE",$dotNETVersion
}
}
Remove-PSSession $targetedServerSession
} Else {
Write-Host "ALL Required Ports ($($ports -join ",")) To The Server '$server' ARE NOT Available!..." -ForegroundColor Red
Write-Host "Skipping Server '$server'..." -ForegroundColor Red
$installResultOnServer = @("NO-CONNECTION","NOT ALL Required Ports ($($ports -join ",")) To The Server '$server' Are Available!...","VERSION-NOT-AVAILABLE","VERSION-NOT-AVAILABLE","UNABLE-TO-DETERMINE")
}
}
# Add The Result For This RWDC To The Install Results List
$resultStatus = $null
$resultStatus = $installResultOnServer[0]
$messageStatus = $null
$messageStatus = $installResultOnServer[1]
$previousPrxServiceVersion = $null
$previousPrxServiceVersion = $installResultOnServer[2]
$newPrxServiceVersion = $null
$newPrxServiceVersion = $installResultOnServer[3]
$dotNETVersion = $null
$dotNETVersion = $installResultOnServer[4]
$installStatus = New-Object -TypeName System.Object
$installStatus | Add-Member -MemberType NoteProperty -Name "Server FQDN" -Value $server
$installStatus | Add-Member -MemberType NoteProperty -Name "Result" -Value $resultStatus
$installStatus | Add-Member -MemberType NoteProperty -Name "Message" -Value $messageStatus
$installStatus | Add-Member -MemberType NoteProperty -Name "\.NET Version" -Value $dotNETVersion
$installStatus | Add-Member -MemberType NoteProperty -Name "Prev. Version" -Value $previousPrxServiceVersion
$installStatus | Add-Member -MemberType NoteProperty -Name "New Version" -Value $newPrxServiceVersion
$installResults += $installStatus
}
}
Write-Host ""
### Display The Results In A GridView And Export To A Csv
# $installResults | FT -Autosize -Wrap
$installResults | Export-Csv -Path $outputCSVFilePath -Force -NoTypeInformation
Write-Host "CSV Report File........................: $outputCSVFilePath" -ForegroundColor DarkCyan
$installResults | Out-GridView
Write-Host ""
Write-Host "DONE!"
Write-Host ""