# Library of functions for installing DP Security controls # # VERSION: 1.0.0 # # Author: ...... David J. Copenhaver # Company: ..... Datapipe # Department: .. Security # # Every function is written to explicitly return a bool (either true, or false) nothing else. This design is for easy consumption by other automation. # Other code (your code) just needs to include this library and call the required functions for your scenario, and you will recieve a simple true/false answer for success/fail per function. # To keep it simple, just dot source this ps1 file into your code. (e.g. ". \pathToThisFile"). Use the dot '.' operator. This will include this code in yours, making all the functions available. # # Expanded upon from my first version which was written specifically for MCD, due to time constraints. # # - Only tested on Windows Server 2012 R2, Powershell V4 # - Currently only supports x64 systems (for directory/registry paths) - does anyone even deploy 32bit Windows OS's anymore? # - HARDENING: package is hardcoded to harden as workgroup servers (member servers would be fine also, just not domain controllers) # # *** Logs to DPSecLog.txt in whatever it determines is the 'temp' directory (depends on the user context within which it is executed) *** # # Important NOTES: # - AWS 'initial boot', when admin password is auto generated, this script (userdata) runs under administrator context, otherwise, it runs under the ec2configService context, which is set to localsystem # - somewhat counter intuitively, hardening needs to be done last for aws 'initial boot' scenario as MSI installs were failing when attempting to do after (maybe because there was no reboot between hardening and starting the other installs, not positive, didn't test the theory) # - I've found that script output is only shown in the ec2ConfigService log file when run as system, so not on initial boot scenario's when run under administrator context # Script Logging function SecLog([string] $sMessage) { try { $LogFile = (([environment]::GetEnvironmentVariable("temp")) + '\DPSecLog.txt') if ((Test-Path $LogFile) -ne $true) { New-Item (([environment]::GetEnvironmentVariable("temp")) + '\DPSecLog.txt') -ItemType File -ea Stop | Out-Null } Add-Content -Path $LogFile -Value (([datetime]::Now).ToString() + ' ' + $sMessage) -Encoding Ascii -ea Stop | Out-Null } catch { $_.Exception.Message } } # Install BES Agent function Install-BESAgent { $CurrentErrorCount = $error.Count # check for prerequisite directory, create if not there try { if ((Test-Path 'c:\DPAutomation') -ne $true) { New-Item 'c:\DPAutomation' -ItemType Directory -ea Stop | Out-Null } } catch { SecLog 'Install-BESAgent: Returning FALSE - Error creating DPAutomation directory.' SecLog $_.Exception.Message return $false } # download file Invoke-WebRequest https://toolkit.datapipe.net/bestasks/postinstalls/mcd/TEMInstallerMCDs.exe -OutFile c:\DPAutomation\TEMInstallerMCDs.exe # run it $TEMInstaller_Process = Start-Process c:\DPAutomation\TEMInstallerMCDs.exe -WindowStyle Hidden -Wait -PassThru if ($error.Count -gt $CurrentErrorCount -or $TEMInstaller_Process.ExitCode -gt 0) { SecLog 'Install-BESAgent: Returning FALSE.' return $false } else { SecLog 'Install-BESAgent: Returning TRUE.' return $true } } # Generalize BES Agent function Generalize-BESAgent { # Service exist? if ((Get-Service BESClient -ea SilentlyContinue) -eq $null) { SecLog "Generalize-BESAgent: BESClient service was not found! Returning FALSE." return false } # service found, stop and change startup mode to manual, mod the reg keys and remove directory per Ant's instructions Try { Stop-Service BESClient -ea Stop | Out-Null Set-Service BESClient -StartupType Manual -ea Stop | Out-Null rp HKLM:\SOFTWARE\Wow6432Node\BigFix\EnterpriseClient\GlobalOptions -Name RegCount -Force -ea Stop | Out-Null rp HKLM:\SOFTWARE\Wow6432Node\BigFix\EnterpriseClient\GlobalOptions -Name ReportSequenceNumber -Force -ea Stop | Out-Null rp HKLM:\SOFTWARE\Wow6432Node\BigFix\EnterpriseClient\GlobalOptions -Name ComputerID -Force -ea Stop | Out-Null ri "C:\Program Files (x86)\BigFix Enterprise\BES Client\__BESData" -Recurse -Force -ea Stop | Out-Null } Catch { SecLog "Generalize-BESAgent: Error occurred, returning FALSE:" SecLog $_.Exception.Message return $false } # made it this far... SecLog 'Generalize-BESAgent: Returning TRUE.' return $true } # Install Alert Logic Threat Manager Agent function Install-ALTMAgent { param ( [switch] $ForImaging = $false, [switch] $ForAutoScaling = $false, [string] $Key = [string]::Empty ) if ($key.Trim() -eq [string]::Empty) { SecLog 'Install-ALTMAgent: Username and/or password parameters were not supplied. Returning FALSE.' return false } $CurrentErrorCount = $error.Count # check for prerequisite directory, create if not there try { if ((Test-Path 'c:\DPAutomation') -ne $true) { New-Item 'c:\DPAutomation' -ItemType Directory -ea Stop | Out-Null } } catch { SecLog 'Install-ALTMAgent: Returning FALSE - Error creating DPAutomation directory.' SecLog $_.Exception.Message return $false } # download file Invoke-WebRequest https://toolkit.datapipe.net/bestasks/postinstalls/mcd/TMAgent-LATEST.msi -OutFile c:\DPAutomation\TMAgent-LATEST.msi $ArgList = [string]::Empty #run it if ($ForImaging -eq $true -and $ForAutoScaling -eq $true) { # INSTALL_ONLY=1 <- For imaging (leaves service stopped, manual start mode) # PROV_ONLY=role <- For auto scaling $ArgList = "/i c:\DPAutomation\TMAgent-LATEST.msi /log tmagent_install.log /quiet INSTALL_ONLY=1 PROV_ONLY=role PROV_KEY=$Key REBOOT=ReallySuppress" # above installs service, doesn't start it, leaves in a 'manual' startup mode, when it does start, it will provision/register in ROLE Mode. } elseif ($ForImaging -eq $true -and $ForAutoScaling -eq $false) { # INSTALL_ONLY=1 <- For imaging (leaves service stopped, manual start mode) # PROV_ONLY=host <- NOT auto scaling $ArgList = "/i c:\DPAutomation\TMAgent-LATEST.msi /log tmagent_install.log /quiet INSTALL_ONLY=1 PROV_ONLY=host PROV_KEY=$Key REBOOT=ReallySuppress" # above installs service, doesn't start it, leaves in a 'manual' startup mode, when it does start, it will provision/register in HOST mode. } elseif ($ForImaging -eq $false -and $ForAutoScaling -eq $true) { # just install, provision and register, ROLE mode $ArgList = "/i c:\DPAutomation\TMAgent-LATEST.msi /log tmagent_install.log /quiet PROV_ONLY=role PROV_KEY=$Key REBOOT=ReallySuppress" } else { # just install, provision and register, HOST mode $ArgList = "/i c:\DPAutomation\TMAgent-LATEST.msi /log tmagent_install.log /quiet PROV_KEY=$Key REBOOT=ReallySuppress" } # run it $ALTMInstaller_Process = Start-Process Msiexec.exe -ArgumentList $ArgList -Wait -PassThru if ($error.Count -gt $CurrentErrorCount -or ($ALTMInstaller_Process.ExitCode -gt 0 -and $ALTMInstaller_Process.ExitCode -ne 3010 )) # 3010 indicates success but needs reboot { SecLog 'Install-ALTMAgent: Returning FALSE.' return $false } else { SecLog 'Install-ALTMAgent: Returning TRUE.' return $true } } # Harden OS function Install-OSHardening { # This currently uses a package that hardcodes to harden workgroup / domain member - NOT DOMAIN CONTROLLERS $CurrentErrorCount = $error.Count # check for prerequisite directory, create if not there try { if ((Test-Path 'c:\DPAutomation') -ne $true) { New-Item 'c:\DPAutomation' -ItemType Directory -ea Stop | Out-Null } } catch { SecLog 'Install-OSHardening: Returning FALSE - Error creating DPAutomation directory.' SecLog $_.Exception.Message return $false } # download file Invoke-WebRequest https://toolkit.datapipe.net/bestasks/postinstalls/mcd/Datapipe_Windows_OS_Hardening_mcd.exe -OutFile c:\DPAutomation\Datapipe_Windows_OS_Hardening_mcd.exe # run it $OSHardening_Process = Start-Process c:\DPAutomation\Datapipe_Windows_OS_Hardening_mcd.exe -WindowStyle Hidden -Wait -PassThru if ($error.Count -gt $CurrentErrorCount -or $OSHardening_Process.ExitCode -gt 0) { SecLog 'Install-OSHardening: Returning FALSE.' return $false } else { SecLog 'Install-OSHardening: Returning TRUE.' return $true } } # Create user account for their Log Management system function Create-LocalUser { param ( [switch] $Admin = $false, [switch] $PasswordNeverExpires = $false, [string] $Username = '', [string] $Password = '' ) if ($Username.Trim() -eq '' -or $Password.Trim() -eq '') { SecLog "Create-LocalUser: Either username or password parameter was not supplied! Returning FALSE." return $false } try { $ADS_UF_NORMAL_ACCOUNT = 512 # 0x200 $ADS_UF_DONT_EXPIRE_PASSWD = 65536 # 0x10000 $ADSI = [ADSI]"WinNT://$Env:COMPUTERNAME, Computer" $TheNewUser = $ADSI.Create("User", $Username) $TheNewUser.SetPassword($Password) | Out-Null $TheNewUser.SetInfo() | Out-Null if ($Admin -eq $true) { $AdministratorsGroup = [ADSI]"WinNT://$Env:COMPUTERNAME/Administrators, Group" $AdministratorsGroup.Add($TheNewUser.PSBase.Path) | Out-Null } if ($PasswordNeverExpires -eq $true) { $TheNewUser.UserFlags[0] = $TheNewUser.UserFlags[0] -bor $ADS_UF_DONT_EXPIRE_PASSWD $TheNewUser.SetInfo() | Out-Null } # made it here without error so.. SecLog "Create-LocalUser: Returning TRUE." return $true } catch { SecLog "Create-LocalUser: An error occured! Returning FALSE." SecLog $_.Exception.Message return $false } } # Install MCD McAffee AV function Install-MCD-McAffee { $CurrentErrorCount = $error.Count # check for prerequisite directory, create if not there try { if ((Test-Path 'c:\DPAutomation') -ne $true) { New-Item 'c:\DPAutomation' -ItemType Directory -ea Stop | Out-Null } } catch { SecLog 'Install-MCD-McAffee: Returning FALSE - Error creating DPAutomation directory.' SecLog $_.Exception.Message return $false } # download file Invoke-WebRequest https://toolkit.datapipe.net/bestasks/postinstalls/mcd/McAfee.exe -OutFile c:\DPAutomation\McAfee.exe # run it, extracts to c:\DPAutomation in root folder McAfee $AVExtract_Process = Start-Process c:\DPAutomation\McAfee.exe -WindowStyle Hidden -Wait -PassThru if ($AVExtract_Process.ExitCode -eq 0) { # run installers $FramePkg_Process = Start-Process c:\DPAutomation\McAfee\FramePkg.exe -ArgumentList "/INSTALL=AGENT /SILENT" -Wait -PassThru $ArgList = '/lIew "' + [environment]::GetEnvironmentVariable("temp") + '\McAfeeInstallLog.txt" ' + 'RUNAUTOUPDATE="" RUNONDEMANDSCAN="" REBOOT=R /q' $SetupVSE_Process = Start-Process c:\DPAutomation\McAfee\VSE880LMLRP4\SetupVSE.Exe -ArgumentList $ArgList -Wait -PassThru } else { SecLog 'Install-MCD-McAffee: Extract process failed. Returning FALSE.' return $false } if ($error.Count -gt $CurrentErrorCount -or $FramePkg_Process.ExitCode -gt 0 -or $SetupVSE_Process.ExitCode -gt 0) { SecLog 'Install-MCD-McAffee: FramePkg.exe and/or SetupVSE.exe failed. Returning FALSE.' return $false } else { SecLog 'Install-MCD-McAffee: Returning TRUE' return $true } } # Generalize their McAffee AV function Generalize-McAffee { # stop services and delete reg values prior to imaging Try { Stop-Service McAfeeFramework -ea Stop | Out-Null #Stop-Service McShield -ea Stop | Out-Null #Stop-Service McTaskManager -ea Stop | Out-Null #Stop-Service mfevtp -ea Stop | Out-Null Set-Service McAfeeFramework -StartupType Manual -ea Stop | Out-Null #Set-Service McShield -StartupType Manual -ea Stop | Out-Null #Set-Service McTaskManager -StartupType Manual -ea Stop | Out-Null #Set-Service mfevtp -StartupType Manual -ea Stop | Out-Null rp "HKLM:\SOFTWARE\Wow6432Node\Network Associates\ePolicy Orchestrator\Agent" -Name AgentGUID -Force -ea Stop | Out-Null rp "HKLM:\SOFTWARE\Wow6432Node\Network Associates\ePolicy Orchestrator\Agent" -Name MacAddress -Force -ea Stop | Out-Null } Catch { SecLog "Generalize-McAffee: An error occurred! Returning FALSE." SecLog $_.Exception.Message return $false } # made it this far so... SecLog "Generalize-McAffee: Returning TRUE." return $true }