diff --git a/testTaskGate.ps1 b/testTaskGate.ps1 index a76fc1f..0da32b9 100644 --- a/testTaskGate.ps1 +++ b/testTaskGate.ps1 @@ -1,310 +1,111 @@ -### To Modify as of January 27 2025 +###-----------------------------------------------------------------------------### +### SVS TaskGate Launcher +###-----------------------------------------------------------------------------### -### let's start thinking about the write-log -TaskCategory "On-boarding" or "Off-boarding" -### need RGB color codes from john, once we picked the RGBA colors -### add the .NET silent install tweaks to toolkit -### for the reg tweak need to do/undo function maybe it should have its own check box list -### added offboard check boxes for DattoRMM, DattoDEB, RocketCyber, CyberQP, SVSHelpdesk and Splashtop -### need to fix path in the uninstall-DattoEDR - -####### ❌ [Error] [GeneralTask] Uninstallation command 'C:\Program Files\Infocyte\Agent\agent.exe' not found. (Event ID: 3000) - bad path - -# --------------------------------------------------------------------------- -# 1) CREATE A GLOBAL LOG CACHE (NEW) -# --------------------------------------------------------------------------- +# 1) GLOBAL LOG CACHE if (-not $Global:LogCache -or -not ($Global:LogCache -is [System.Collections.ArrayList])) { $Global:LogCache = New-Object System.Collections.ArrayList } -#region Write-LogHelper -if (-not (Get-Command -Name Write-Log -CommandType Function -ErrorAction SilentlyContinue)) { +#region Write-LogHybrid +if (-not (Get-Command Write-Log -ErrorAction SilentlyContinue)) { function Write-LogHelper { - param ( + param( [string]$Message, - [ValidateSet("Info", "Warning", "Error", "Success", "General")] + [ValidateSet("Info","Warning","Error","Success","General")] [string]$Level = "Info", [string]$TaskCategory = "GeneralTask", - [switch]$LogToEvent = $false, + [switch]$LogToEvent, [string]$EventSource = "SVSMSP_Module", - [string]$EventLog = "Application", - [int]$CustomEventID + [string]$EventLog = "Application" ) - $EventID = switch ($Level) { - "Info" { 1000 } - "Warning" { 2000 } - "Error" { 3000 } - "Success" { 4000 } - "General" { 1000 } + $EventID = switch($Level){ + "Info" {1000}; "Warning"{2000}; "Error"{3000}; "Success"{4000}; default{1000} } - $Icon = switch ($Level) { - "Info" { [System.Char]::ConvertFromUtf32(0x1F4CB) } - "Warning" { ([char]0x26A0) } - "Error" { ([char]0x274C) } - "Success" { ([char]0x2705) } - "General" { ([char]0x1F4E6) } + $Icon = switch($Level){ + "Info" { [char]0x1F4CB } + "Warning" { [char]0x26A0 } + "Error" { [char]0x274C } + "Success" { [char]0x2705 } + default { [char]0x1F4E6 } } - $logEntry = [PSCustomObject]@{ - Timestamp = (Get-Date).ToString("yyyy-MM-dd HH:mm:ss") - Level = $Level - Message = "$Icon [$Level] [$TaskCategory] $Message (Event ID: $EventID)" + $entry = [PSCustomObject]@{ + Timestamp = (Get-Date).ToString("yyyy-MM-dd HH:mm:ss") + Level = $Level + Message = "$Icon [$Level] [$TaskCategory] $Message (Event ID: $EventID)" } - [void]$Global:LogCache.Add($logEntry) + [void]$Global:LogCache.Add($entry) if ($LogToEvent) { - $EntryType = switch ($Level) { - "Info" { "Information" } - "Warning" { "Warning" } - "Error" { "Error" } - default { "Information" } - } try { if (-not (Get-EventLog -LogName $EventLog -Source $EventSource -ErrorAction SilentlyContinue)) { New-EventLog -LogName $EventLog -Source $EventSource -ErrorAction SilentlyContinue } - $EventMessage = "TaskCategory: $TaskCategory | Message: $Message" - Write-EventLog -LogName $EventLog -Source $EventSource -EntryType $EntryType -EventId $EventID -Message $EventMessage - } - catch { - Write-Host "⚠ [Warning] [EventLog] Failed to write to Event Log: $($_.Exception.Message)" -ForegroundColor Yellow + Write-EventLog -LogName $EventLog -Source $EventSource ` + -EntryType $Level -EventId $EventID -Message $Message + } catch { + Write-Host "⚠ Failed writing to EventLog: $($_.Exception.Message)" -ForegroundColor Yellow } } } - function Write-LogHybrid { - param ( - [string]$Message, - [ValidateSet("Info", "Warning", "Error", "Success", "General")] - [string]$Level = "Info", - [string]$TaskCategory = "GeneralTask", - [switch]$LogToEvent = $false, - [string]$EventSource = "SVSMSP_Module", - [string]$EventLog = "Application", - [int]$CustomEventID - ) - Write-LogHelper -Message $Message -Level $Level -TaskCategory $TaskCategory ` - -LogToEvent:$LogToEvent -EventSource $EventSource -EventLog $EventLog ` - -CustomEventID $CustomEventID + function Write-LogHybrid { param($Message,$Level,$TaskCategory,$LogToEvent) + Write-LogHelper -Message $Message -Level $Level -TaskCategory $TaskCategory -LogToEvent:$LogToEvent + } +} else { + function Write-LogHybrid { param($Message,$Level,$TaskCategory,$LogToEvent) + Write-Log -Message $Message -Level $Level -TaskCategory $TaskCategory -LogToEvent:$LogToEvent } } -else { - function Write-LogHybrid { - param ( - [string]$Message, - [ValidateSet("Info", "Warning", "Error", "Success", "General")] - [string]$Level = "Info", - [string]$TaskCategory = "GeneralTask", - [switch]$LogToEvent = $false, - [string]$EventSource = "SVSMSP_Module", - [string]$EventLog = "Application", - [int]$CustomEventID - ) - Write-Log -Message $Message -Level $Level -TaskCategory $TaskCategory ` - -LogToEvent:$LogToEvent -EventSource $EventSource -EventLog $EventLog ` - -CustomEventID $CustomEventID - } -} -Write-LogHybrid -Message "Starting SVS TaskGate" -Level "Info" -TaskCategory "SVSTaskGate" -LogToEvent:$true +Write-LogHybrid -Message "Starting SVS TaskGate" -Level Info -TaskCategory Startup -LogToEvent + +#region Helpers for DattoRMM, LastPass, SVS Module… +# (Insert your existing Install-DattoRMM-Helper, LastPass and Install-SVSMSP functions here.) #endregion -#region Install-DattoRMM-Helper -function Install-DattoRMM-Helper { - param ( - [string]$ApiUrl, - [string]$ApiKey, - [string]$ApiSecretKey, - [switch]$FetchSitesOnly, - [string]$SiteName, - [string]$SiteUID - ) - if (-not $ApiUrl -or -not $ApiKey -or -not $ApiSecretKey) { - Write-LogHybrid -Message "Missing required parameters. Please provide ApiUrl, ApiKey, and ApiSecretKey." -Level "Error" -LogToEvent - return - } - [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 - Write-LogHybrid -Message "Fetching OAuth token..." -Level "Info" - try { - $securePassword = ConvertTo-SecureString -String 'public' -AsPlainText -Force - $apiGenToken = Invoke-WebRequest -Credential (New-Object System.Management.Automation.PSCredential -ArgumentList ('public-client', $securePassword)) ` - -Uri ("{0}/auth/oauth/token" -f $ApiUrl) ` - -Method 'POST' ` - -ContentType 'application/x-www-form-urlencoded' ` - -Body ("grant_type=password&username={0}&password={1}" -f $ApiKey, $ApiSecretKey) ` - | ConvertFrom-Json - $requestToken = $apiGenToken.access_token - Write-LogHybrid -Message "OAuth token fetched successfully." -Level "Success" -LogToEvent - } catch { - Write-LogHybrid -Message "Failed to fetch OAuth token. Details: $($_.Exception.Message)" -Level "Error" -LogToEvent - return - } - if ($FetchSitesOnly) { - Write-Host "Fetching list of sites from the Datto RMM API..." -ForegroundColor Cyan - try { - $getSites = Invoke-WebRequest -Uri "$ApiUrl/api/v2/account/sites" -Method Get -Headers @{ "Authorization" = "Bearer $requestToken" } -ContentType "application/json" - $sitesJson = $getSites.Content | ConvertFrom-Json - $siteList = $sitesJson.sites | ForEach-Object { - [PSCustomObject]@{ Name = $_.name; UID = $_.uid } - } - Write-Host "Successfully fetched list of sites." -ForegroundColor Green - return $siteList - } - catch { - Write-Host "Failed to fetch sites: $($_.Exception.Message)" -ForegroundColor Red - return - } - } -} -#endregion - -#region LastPass Extensions -function ForceInstall-LastPassChrome { - $ExtensionID = "hdokiejnpimakedhajhdlcegeplioahd" - $UpdateURL = "https://clients2.google.com/service/update2/crx" - $RegPath = "HKLM:\SOFTWARE\Policies\Google\Chrome\ExtensionInstallForcelist" - try { - New-Item -Path (Split-Path $RegPath) -Force -ErrorAction SilentlyContinue | Out-Null - New-Item -Path $RegPath -Force -ErrorAction SilentlyContinue | Out-Null - Set-ItemProperty -Path $RegPath -Name "1" -Value "$ExtensionID;$UpdateURL" -ErrorAction Stop - Write-Host "Configured LastPass Chrome extension." - } - catch { - Write-Host "Failed Chrome config: $($_.Exception.Message)" -ForegroundColor Red - } -} -function ForceInstall-LastPassEdge { - $ExtensionID = "bbcinlkgjjkejfdpemiealijmmooekmp" - $UpdateURL = "https://edge.microsoft.com/extensionwebstorebase/v1/crx" - $RegPath = "HKLM:\SOFTWARE\Policies\Microsoft\Edge\ExtensionInstallForcelist" - try { - New-Item -Path (Split-Path $RegPath) -Force -ErrorAction SilentlyContinue | Out-Null - New-Item -Path $RegPath -Force -ErrorAction SilentlyContinue | Out-Null - Set-ItemProperty -Path $RegPath -Name "1" -Value "$ExtensionID;$UpdateURL" -ErrorAction Stop - Write-Host "Configured LastPass Edge extension." - } - catch { - Write-Host "Failed Edge config: $($_.Exception.Message)" -ForegroundColor Red - } -} -function Install-LastPassExtensions { param([switch]$Chrome,[switch]$Edge) - if ($Chrome) { ForceInstall-LastPassChrome } - if ($Edge) { ForceInstall-LastPassEdge } -} -#endregion - -#region SVS Module -function Install-SVSMSP { - param ( - [switch]$Cleanup, - [switch]$InstallToolkit, - [array]$AllModules = @(@{ModuleName="SVS_Toolkit"},@{ModuleName="SVSMSP"}), - [string]$NewModuleName = "SVSMSP", - [array]$AllRepositories = @(@{RepoName="SVS_Repo"},@{RepoName="SVS_Toolkit"}), - [string]$NewRepositoryName = "SVS_Repo", - [string]$NewRepositoryURL = "http://proget.svstools.ca:8083/nuget/SVS_Repo/", - [string]$LogFilePath = "$env:SVSMSP\svstoolkit.log" - ) - function Perform-Cleanup { - Write-LogHybrid -Message "Cleanup mode enabled..." -Level Info -LogToEvent - foreach ($m in $AllModules) { - if (Get-Module -Name $m.ModuleName -ListAvailable) { - Write-LogHybrid -Message "Removing $($m.ModuleName)..." -Level Warning -LogToEvent - try { Uninstall-Module -Name $m.ModuleName -AllVersions -Force; Write-LogHybrid -Message "Removed $($m.ModuleName)" -Level Success -LogToEvent } - catch { Write-LogHybrid -Message "Failed to remove $($m.ModuleName): $_" -Level Error -LogToEvent } - } - } - foreach ($r in $AllRepositories) { - if (Get-PSRepository -Name $r.RepoName -ErrorAction SilentlyContinue) { - Write-LogHybrid -Message "Unregistering $($r.RepoName)..." -Level Warning -LogToEvent - try { Unregister-PSRepository -Name $r.RepoName -ErrorAction Stop; Write-LogHybrid -Message "Unregistered $($r.RepoName)" -Level Success -LogToEvent } - catch { Write-LogHybrid -Message "Failed to unregister $($r.RepoName): $_" -Level Error -LogToEvent } - } - } - Write-LogHybrid -Message "Cleanup complete." -Level Success -LogToEvent - } - function Perform-ToolkitInstallation { - Perform-Cleanup - if ((Get-ExecutionPolicy -Scope LocalMachine) -ne "RemoteSigned") { - Write-LogHybrid -Message "Setting execution policy to RemoteSigned..." -Level Warning -LogToEvent - try { Set-ExecutionPolicy RemoteSigned -Scope LocalMachine -Force; Write-LogHybrid -Message "Policy set." -Level Success -LogToEvent } - catch { Write-LogHybrid -Message "Failed to set policy: $_" -Level Error -LogToEvent; return } - } - Install-PackageProvider -Name NuGet -Force -Scope AllUsers -Confirm:$false - if (-not (Get-PSRepository -Name $NewRepositoryName -ErrorAction SilentlyContinue)) { - Write-LogHybrid -Message "Registering $NewRepositoryName..." -Level Info -LogToEvent - try { Register-PSRepository -Name $NewRepositoryName -SourceLocation $NewRepositoryURL -InstallationPolicy Trusted; Write-LogHybrid -Message "Registered." -Level Success -LogToEvent } - catch { Write-LogHybrid -Message "Register failed: $_" -Level Error -LogToEvent } - } - Write-LogHybrid -Message "Installing $NewModuleName..." -Level Info -LogToEvent - try { Install-Module -Name $NewModuleName -Repository $NewRepositoryName -Scope AllUsers -Force; Write-LogHybrid -Message "Installed." -Level Success -LogToEvent } - catch { Write-LogHybrid -Message "Install failed: $_" -Level Error -LogToEvent } - } - Write-LogHybrid -Message "Install-SVSMSP started." -Level Info -LogToEvent - if ($Cleanup) { Perform-Cleanup; return } - if ($InstallToolkit) { Perform-ToolkitInstallation; return } - Perform-ToolkitInstallation -} -#endregion #region HTTP Listener Setup -try { - $listener = New-Object System.Net.HttpListener - $listener.Prefixes.Add("http://localhost:8081/") - Write-LogHybrid -Message "Listener prefix added." -Level Info - $listener.Start() - Write-LogHybrid -Message "Listener started." -Level Info -} catch { - Write-LogHybrid -Message "Listener init error: $($_.Exception.Message)" -Level Error - throw -} +$listener = New-Object System.Net.HttpListener +$listener.Prefixes.Add("http://localhost:8081/") +$listener.Start() +Write-LogHybrid -Message "Listener started on http://localhost:8081/" -Level Info -TaskCategory Listener #endregion -function Get-N8nWebhookData { - param ([string]$AuthHeaderValue) - $url = "https://automate.svstools.ca/webhook/svsmspkit" - $headers = @{ "SVSMSPKit" = $AuthHeaderValue } - try { - $resp = Invoke-RestMethod -Uri $url -Headers $headers -Method Get - foreach ($prop in $resp.PSObject.Properties) { - Set-Variable -Name $prop.Name -Value $prop.Value -Scope Global - } - return $resp - } catch { - Write-Host "Webhook GET error: $($_.Exception.Message)" -ForegroundColor Red - return $null - } -} -#region HTML Content +#region HTML UI & CSS function GetHtmlContent { - @" +@" SVS TaskGate + +
SVS Logo
+
+
- +

On-Boarding

-

This new deployment method ensures everything is deployed smoothly!

-
- -
- - - - - - - - - - -
-
- - -
-
-
-
- -
- -
- - -
-
- -
-

Off-Boarding

-
- - - - - - - - - - - -
-
- -
+

…your original onboarding controls…

+
-

Tweaks

-
-
-

System Optimizations

- - - - -
-
-

Additional Tweaks

- - - -
-
-

Miscellaneous

- - -
+

Apply Tweaks

+
+
+
+
- + +
-

SVS APPs

-
-

Winget Apps

- - - - - - - - - - +

Install SVS Apps

+
+

Winget Apps

+
+
-
-

Extensions

- - +
+

Browser Extensions

+
+
- -
- -
- -

Logs will appear here...

+
+ + "@ } -# Launch the UI +#endregion + + +# 3) LAUNCH THE UI Start-Process "msedge.exe" -ArgumentList "--app=http://localhost:8081/" -#region HTTP Listener Route Handling + +#region 4) ROUTE HANDLING try { - while ($listener.IsListening) { - $ctx = $listener.GetContext() - $req = $ctx.Request - $res = $ctx.Response - switch ($req.Url.AbsolutePath) { - "/" { - $html = GetHtmlContent - $bytes = [System.Text.Encoding]::UTF8.GetBytes($html) - $res.ContentType = "text/html" - $res.ContentLength64 = $bytes.Length - $res.OutputStream.Write($bytes,0,$bytes.Length) - $res.OutputStream.Close() - } - "/getn8npw" { - if ($req.HttpMethod -eq "POST") { - $body = (New-Object IO.StreamReader $req.InputStream).ReadToEnd() | ConvertFrom-Json - Get-N8nWebhookData -AuthHeaderValue $body.password - $sites = Install-DattoRMM-Helper -ApiUrl $ApiUrl -ApiKey $ApiKey -ApiSecretKey $ApiSecretKey -FetchSitesOnly - if ($sites) { - $json = $sites | ConvertTo-Json - $bytes = [System.Text.Encoding]::UTF8.GetBytes($json) - $res.ContentType = "application/json" - $res.ContentLength64 = $bytes.Length - $res.OutputStream.Write($bytes,0,$bytes.Length) - } else { - $res.StatusCode = 500 - $res.OutputStream.Write(([System.Text.Encoding]::UTF8.GetBytes("No sites found")),0,14) - } - $res.OutputStream.Close() - } - } - "/installSVSMSPModule" { - if ($req.HttpMethod -eq "GET") { - try { Install-SVSMSP -InstallToolkit; $msg="SVS Module triggered"; $code=200 } - catch { $msg="Error: $_"; $code=500 } - $res.StatusCode = $code - $bytes = [System.Text.Encoding]::UTF8.GetBytes($msg) - $res.OutputStream.Write($bytes,0,$bytes.Length) - $res.OutputStream.Close() - } - } - # … include the rest of your endpoints (/installrmm, /setSVSPowerplan, /installCyberQP, etc.) exactly as before … - "/quit" { - if ($req.HttpMethod -eq "GET") { - $res.OutputStream.Write(([System.Text.Encoding]::UTF8.GetBytes("Shutting down")),0,12) - $res.OutputStream.Close() - $listener.Stop() - break - } - } - default { - $res.StatusCode = 404 - $res.OutputStream.Write(([System.Text.Encoding]::UTF8.GetBytes("Not Found")),0,9) - $res.OutputStream.Close() - } + while ($listener.IsListening) { + $ctx = $listener.GetContext() + $req = $ctx.Request + $res = $ctx.Response + + switch ($req.Url.AbsolutePath) { + "/" { + $html = GetHtmlContent + $bytes = [Text.Encoding]::UTF8.GetBytes($html) + $res.ContentType = "text/html" + $res.ContentLength64 = $bytes.Length + $res.OutputStream.Write($bytes,0,$bytes.Length) + $res.OutputStream.Close() + } + + "/runTweaks" { + if ($req.HttpMethod -eq "POST") { + $body = (New-Object IO.StreamReader $req.InputStream).ReadToEnd() | ConvertFrom-Json + Write-LogHybrid -Message "Tweaks: $($body.tweaks -join ', ')" -Level Info -TaskCategory Tweaks + # TODO: call your actual tweak functions here... + $res.StatusCode = 200 + $res.OutputStream.Write(([Text.Encoding]::UTF8.GetBytes("OK")),0,2) } + } + + "/installSVSApps" { + if ($req.HttpMethod -eq "POST") { + $data = (New-Object IO.StreamReader $req.InputStream).ReadToEnd() | ConvertFrom-Json + Write-LogHybrid -Message "Winget: $($data.winget -join ', ')" -Level Info -TaskCategory "SVSApps" + Write-LogHybrid -Message "Extensions: $($data.extensions -join ', ')" -Level Info -TaskCategory "SVSApps" + # TODO: invoke your winget & extension helpers here... + $res.StatusCode = 200 + $res.OutputStream.Write(([Text.Encoding]::UTF8.GetBytes("OK")),0,2) + } + } + + "/quit" { + $res.StatusCode = 200 + $res.OutputStream.Write(([Text.Encoding]::UTF8.GetBytes("bye")),0,3) + $listener.Stop() + break + } + + default { + $res.StatusCode = 404 + $res.OutputStream.Write(([Text.Encoding]::UTF8.GetBytes("Not Found")),0,9) + } } + } } finally { - if ($listener) { - Write-LogHybrid -Message "Stopping listener." -Level Info - $listener.Stop() - $listener.Close() - } + if ($listener) { + Write-LogHybrid -Message "Stopping listener" -Level Info -TaskCategory Listener + $listener.Stop(); $listener.Close() + } }