This commit is contained in:
2025-05-17 14:32:11 -04:00
parent e16324d214
commit 407a165830

656
testTaskGate.ps1 Normal file
View File

@@ -0,0 +1,656 @@
### To Modify as of January 27 2025
### let's start thinking about the write-log -TaskCategory "On-boarding" or "Off-boarding"
### need RGB color codes form 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)
# ---------------------------------------------------------------------------
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)) {
function Write-LogHelper {
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
)
$EventID = switch ($Level) {
"Info" { 1000 }
"Warning" { 2000 }
"Error" { 3000 }
"Success" { 4000 }
"General" { 1000 }
}
$Icon = switch ($Level) {
"Info" { [System.Char]::ConvertFromUtf32(0x1F4CB) }
"Warning" { ([char]0x26A0) }
"Error" { ([char]0x274C) }
"Success" { ([char]0x2705) }
"General" { ([char]0x1F4E6) }
}
$Color = switch ($Level) {
"Info" { "Cyan" }
"Warning" { "Yellow" }
"Error" { "Red" }
"Success" { "Green" }
"General" { "White" }
}
$logEntry = [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)
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 "([char]0x26A0) [Warning] [EventLog] Failed to write to Event Log: $($_.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
}
}
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
#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 -TypeName 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
}
$getHeaders = @{"Authorization" = "Bearer $requestToken"}
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 $getHeaders -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 from the API. Details: $($_.Exception.Message)" -ForegroundColor Red
return
}
}
}
#endregion
#region LastPass Extensions
function ForceInstall-LastPassChrome {
# Chrome (Web Store) extension ID and update URL for LastPass
$ExtensionID_LastPass_Chrome = "hdokiejnpimakedhajhdlcegeplioahd"
$ChromeUpdateURL = "https://clients2.google.com/service/update2/crx"
$ChromePolicyRegPath = "HKLM:\SOFTWARE\Policies\Google\Chrome\ExtensionInstallForcelist"
try {
New-Item -Path "HKLM:\SOFTWARE\Policies\Google" -Force -ErrorAction SilentlyContinue | Out-Null
New-Item -Path "HKLM:\SOFTWARE\Policies\Google\Chrome" -Force -ErrorAction SilentlyContinue | Out-Null
New-Item -Path $ChromePolicyRegPath -Force -ErrorAction SilentlyContinue | Out-Null
$chromeValue = "$ExtensionID_LastPass_Chrome;$ChromeUpdateURL"
Set-ItemProperty -Path $ChromePolicyRegPath -Name "1" -Value $chromeValue -ErrorAction Stop
Write-Host "Successfully configured LastPass in Chrome ExtensionInstallForcelist."
}
catch {
Write-Host "Failed to configure Chrome: $($_.Exception.Message)" -ForegroundColor Red
}
}
function ForceInstall-LastPassEdge {
# Edge (Add-ons Store) extension ID and update URL for LastPass
$ExtensionID_LastPass_Edge = "bbcinlkgjjkejfdpemiealijmmooekmp"
$EdgeUpdateURL = "https://edge.microsoft.com/extensionwebstorebase/v1/crx"
$EdgePolicyRegPath = "HKLM:\SOFTWARE\Policies\Microsoft\Edge\ExtensionInstallForcelist"
try {
New-Item -Path "HKLM:\SOFTWARE\Policies\Microsoft" -Force -ErrorAction SilentlyContinue | Out-Null
New-Item -Path "HKLM:\SOFTWARE\Policies\Microsoft\Edge" -Force -ErrorAction SilentlyContinue | Out-Null
New-Item -Path $EdgePolicyRegPath -Force -ErrorAction SilentlyContinue | Out-Null
$edgeValue = "$ExtensionID_LastPass_Edge;$EdgeUpdateURL"
Set-ItemProperty -Path $EdgePolicyRegPath -Name "1" -Value $edgeValue -ErrorAction Stop
Write-Host "Successfully configured LastPass in Edge ExtensionInstallForcelist."
}
catch {
Write-Host "Failed to configure Edge: $($_.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,
[Parameter(Mandatory = $false)]
[array]$AllModules = @(
@{ ModuleName = "SVS_Toolkit" },
@{ ModuleName = "SVSMSP" }
),
[Parameter(Mandatory = $false)]
[string]$NewModuleName = "SVSMSP",
[Parameter(Mandatory = $false)]
[array]$AllRepositories = @(
@{ RepoName = "SVS_Repo" },
@{ RepoName = "SVS_Toolkit" }
),
[Parameter(Mandatory = $false)]
[string]$NewRepositoryName = "SVS_Repo",
[Parameter(Mandatory = $false)]
[string]$NewRepositoryURL = "http://proget.svstools.ca:8083/nuget/SVS_Repo/",
[Parameter(Mandatory = $false)]
[array]$CommandsToCheck = @(
"Install-DattoRMM",
"Install-CyberQP",
"Install-RocketCyber",
"Install-Splashtop",
"Install-ThreatLocker",
"Install-SVSHelpdesk"
),
[Parameter(Mandatory = $false)]
[string]$LogFilePath = "$env:SVSMSP\svstoolkit.log"
)
function Perform-Cleanup {
Write-LogHybrid -Message "Cleanup mode enabled. Starting cleanup process..." -Level "Info" -LogToEvent
Write-LogHybrid -Message "Starting cleanup of old modules..." -Level "Info" -LogToEvent
foreach ($module in $AllModules) {
$ModuleName = $module.ModuleName
if (Get-Module -Name $ModuleName -ListAvailable) {
Write-LogHybrid -Message "Removing module '$ModuleName'..." -Level "Warning" -LogToEvent
try {
Get-Module -Name $ModuleName -ListAvailable | ForEach-Object {
Uninstall-Module -Name $_.Name -AllVersions -Force
}
Write-LogHybrid -Message "Module '$ModuleName' removed successfully." -Level "Success" -LogToEvent
}
catch {
Write-LogHybrid -Message "Failed to remove module '$ModuleName'. Error: $($_.Exception.Message)" -Level "Error" -LogToEvent
}
}
else {
Write-LogHybrid -Message "Module '$ModuleName' not found. Skipping..." -Level "Info" -LogToEvent
}
}
Write-LogHybrid -Message "Starting cleanup of old repositories..." -Level "Info" -LogToEvent
foreach ($repo in $AllRepositories) {
$RepoName = $repo.RepoName
Write-LogHybrid -Message "Removing repository '$RepoName'..." -Level "Warning" -LogToEvent
if (Get-PSRepository -Name $RepoName -ErrorAction SilentlyContinue) {
try {
Unregister-PSRepository -Name $RepoName -ErrorAction Stop
Write-LogHybrid -Message "Repository '$RepoName' removed successfully." -Level "Success" -LogToEvent
}
catch {
Write-LogHybrid -Message "Failed to remove repository '$RepoName'. Error: $($_.Exception.Message)" -Level "Error" -LogToEvent
}
}
else {
Write-LogHybrid -Message "Repository '$RepoName' does not exist. Skipping removal." -Level "Info" -LogToEvent
}
}
Write-LogHybrid -Message "Cleanup process completed successfully." -Level "Success" -LogToEvent
}
function Perform-ToolkitInstallation {
Perform-Cleanup
$localMachineExecutionPolicy = Get-ExecutionPolicy -Scope LocalMachine
if ($localMachineExecutionPolicy -ne "RemoteSigned") {
Write-LogHybrid -Message "Setting execution policy to RemoteSigned..." -Level "Warning" -LogToEvent
try {
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope LocalMachine -Force
Write-LogHybrid -Message "Execution policy set to RemoteSigned successfully." -Level "Success" -LogToEvent
}
catch {
Write-LogHybrid -Message "Failed to set execution policy. Error: $_" -Level "Error" -LogToEvent
return
}
}
Install-PackageProvider -Name "NuGet" -Force -Scope AllUsers -Confirm:$false
Write-LogHybrid -Message "Registering the new repository '$NewRepositoryName'..." -Level "Info" -LogToEvent
try {
if (!(Get-PSRepository -Name $NewRepositoryName -ErrorAction SilentlyContinue)) {
Register-PSRepository -Name $NewRepositoryName -SourceLocation $NewRepositoryURL -InstallationPolicy Trusted
Write-LogHybrid -Message "Repository '$NewRepositoryName' registered successfully." -Level "Success" -LogToEvent
}
}
catch {
Write-LogHybrid -Message "Failed to register new repository '$NewRepositoryName'. Error: $($_.Exception.Message)" -Level "Error" -LogToEvent
}
Write-LogHybrid -Message "Installing the new module '$NewModuleName'..." -Level "Info" -LogToEvent
try {
Install-Module -Name $NewModuleName -Repository $NewRepositoryName -Scope AllUsers -Force
Write-LogHybrid -Message "Module '$NewModuleName' installed successfully." -Level "Success" -LogToEvent
}
catch {
Write-LogHybrid -Message "Failed to install new module '$NewModuleName'. Error: $($_.Exception.Message)" -Level "Error" -LogToEvent
}
Write-LogHybrid -Message "Toolkit installation process completed successfully." -Level "Success" -LogToEvent
}
Write-LogHybrid -Message "Install-SVSMSP function started." -Level "Info" -LogToEvent
if ($Cleanup) {
Perform-Cleanup
return
}
if ($InstallToolkit) {
Perform-ToolkitInstallation
return
}
Write-LogHybrid -Message "No specific mode specified. Defaulting to toolkit installation mode..." -Level "Info" -LogToEvent
Perform-ToolkitInstallation
}
#endregion SVS Module
#region HTTP Listener Setup
try {
$listener = New-Object System.Net.HttpListener
if (-not $listener) {
throw "Failed to initialize HttpListener."
}
$listener.Prefixes.Add("http://localhost:8081/")
Write-LogHybrid -Message "Listener initialized with prefix http://localhost:8081/" -Level "Info"
$listener.Start()
Write-LogHybrid -Message "Listener started successfully." -Level "Info"
} catch {
Write-LogHybrid -Message "Critical error initializing listener: $($_.Exception.Message)" -Level "Error"
throw $_
}
#endregion
function Get-N8nWebhookData {
param (
[Parameter(Mandatory = $true)]
[string]$AuthHeaderValue
)
$url = "https://automate.svstools.ca/webhook/svsmspkit"
$headers = @{
"SVSMSPKit" = $AuthHeaderValue
}
try {
$response = Invoke-RestMethod -Uri $url -Headers $headers -Method Get
Write-Host "Response received successfully:" -ForegroundColor Green
$data = $response
$global:Comment_SVSmodule = $data._Comment_SVSmodule
$global:ModuleName = $data.ModuleName
$global:RepositoryURL = $data.RepositoryURL
$global:OldRepo = $data.OldRepo
$global:NewRepo = $data.NewRepo
$global:CommandsToCheck = $data.CommandsToCheck
$global:LogFilePath = $data.LogFilePath
$global:Comment_DRMM = $data._Comment_DRMM
$global:ApiUrl = $data.ApiUrl
$global:ApiKey = $data.ApiKey
$global:ApiSecretKey = $data.ApiSecretKey
}
catch {
Write-Host "Error making the GET request:" -ForegroundColor Red
Write-Host $_.Exception.Message
return $null
}
}
#region HTML Content
function GetHtmlContent {
@"
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SVS TaskGate</title>
<link rel="icon" href="https://git.svstools.com/syelle/Logo/raw/branch/main/SVS_Favicon.ico" type="image/x-icon">
<style>
:root {
/* Cool Palette */
--background-color: rgba(18, 18, 18, 1);
--border-color: rgba(255, 127, 0, 0.25);
/* Neutral Colors */
--white-color: rgba(255, 255, 255);
--gray-color: rgba(102, 102, 102);
--dark-gray-color: rgba(51, 51, 51);
--light-gray-color: rgba(187, 187, 187);
/* Sidebar Button Colors */
--btn-sidebar-light-gray: rgba(68, 68, 68);
--btn-sidebar-blue: rgba(30, 144, 255, 1);
--btn-hover: rgba(0, 86, 179, 1);
--btn-hover-scale: 1.05;
/* Fixed go button colors */
--btn-success: rgba(40, 167, 69, 1);
--btn-success-disabled: rgba(108, 117, 125, 1);
--btn-danger: rgba(220, 53, 69, 1);
}
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
background-color: var(--background-color);
color: var(--white-color);
height: 100%;
overflow: hidden;
}
.logo-container {
text-align: left;
padding: 20px;
background-color: var(--background-color);
}
.logo-container img {
max-width: 300px;
height: auto;
}
.subtitle {
font-size: 1.2rem;
color: var(--gray-color);
margin-top: 0.5em;
}
.container {
display: flex;
height: 100vh;
overflow: hidden;
}
.sidebar {
width: 200px;
height: 100%;
background-color: var(--background-color);
padding: 10px;
}
.sidebar button {
display: block;
width: 100%;
margin-bottom: 10px;
padding: 10px;
color: var(--white-color);
background-color: var(--btn-sidebar-light-gray);
border: none;
border-radius: 5px;
cursor: pointer;
text-align: left;
transition: background-color 0.3s ease, transform 0.2s ease;
}
.sidebar button.active {
background-color: var(--btn-sidebar-blue);
}
.sidebar button:hover {
background-color: var(--btn-hover);
transform: scale(var(--btn-hover-scale));
}
.content {
flex: 1;
padding: 20px;
overflow-y: auto;
max-height: calc(100vh - 50px);
}
.tab-content {
display: none;
}
.tab-content.active {
display: block;
}
.checkbox-group label {
margin: 0;
padding: 0;
line-height: 1.5;
display: flex;
align-items: center;
}
.password-input,
.dropdown {
width: 30%;
padding: 10px;
margin-bottom: 20px;
border-radius: 5px;
border: 1px solid var(--border-color);
background-color: var(--background-color);
color: var(--white-color);
}
#n8nPasswordContainer {
display: none;
margin-top: 20px;
}
.button-group {
margin-top: 20px;
text-align: right;
}
/* Hide the entire log pane */
.log {
display: none !important;
}
/* Uniform styling for all .button-group buttons */
.button-group button {
display: inline-block;
padding: 0.75rem 1.5rem;
margin-left: 0.5rem;
font-size: 1rem;
line-height: 1.4;
text-align: center;
border: none;
border-radius: 0.375rem;
cursor: pointer;
transition: opacity 0.1s ease;
}
/* Remove left margin on first button */
.button-group > button:first-child {
margin-left: 0;
}
/* Green go buttons */
.install-button {
background-color: var(--btn-success);
color: #fff;
}
.install-button:disabled {
background-color: var(--btn-success-disabled);
cursor: not-allowed;
}
/* Red danger buttons */
.exit-button {
background-color: var(--btn-danger);
color: #fff;
}
/* Hover effect */
.button-group button:hover:not(:disabled) {
opacity: 0.9;
}
@media (max-width: 768px) {
.container {
flex-direction: column;
}
.sidebar {
width: 100%;
}
}
</style>
</head>
<body>
<div class="logo-container">
<img src="https://git.svstools.com/syelle/Logo/raw/branch/main/SVS_logo.svg" alt="SVS Logo">
</div>
<div class="container">
<div class="sidebar">
<button class="tab-button active" data-tab="onboardTab" aria-expanded="true">On-Boarding</button>
<button class="tab-button" data-tab="offboardTab" aria-expanded="false">Off-Boarding</button>
<button class="tab-button" data-tab="tweaksTab" aria-expanded="false">Tweaks</button>
<button class="tab-button" data-tab="SVSAppsTab" aria-expanded="false">SVS APPs</button>
</div>
<div class="content">
<!-- On-Boarding Tab -->
<div id="onboardTab" class="tab-content active">
<h2>On-Boarding</h2>
<h3 class="subtitle">This new deployment method ensures everything is successfully deployed with greater ease!</h3>
<div class="columns-container">
<!-- leftColumn, rightColumn, etc... (unchanged) -->
</div>
<div id="n8nPasswordContainer" style="display: none;">
<label for="n8nPassword">Enter Password:</label><br>
<input type="password" id="n8nPassword" class="password-input" placeholder="Enter Password">
</div>
<br>
<div id="DattoRMMContainer" style="display: none;">
<label for="dattoRmmDropdown">Select a Datto RMM site:</label><br>
<select id="dattoRmmDropdown" class="dropdown">
<option value="">Fetching sites...</option>
$siteOptions
</select>
</div>
<div class="button-group">
<button class="install-button" id="fetchSitesButton" onclick="fetchSites()" disabled>Fetch Sites</button>
<button class="install-button" onclick="triggerInstall()">Install</button>
</div>
</div>
<!-- Off-Boarding, Tweaks, SVS Apps tabs all unchanged -->
<!-- ... -->
<!-- Shared Exit Button -->
<div class="button-group">
<button class="exit-button" onclick="endSession()">Exit</button>
</div>
<!-- Log Area (now hidden via CSS) -->
<div class="log" id="logArea">
<p>Logs will appear here...</p>
</div>
</div>
</div>
<script>
// (All your existing JS unchanged: tab nav, toggle functions, triggerInstall, fetchLogs, etc.)
</script>
</body>
</html>
"@
}
# Save and launch the HTML
Start-Process "msedge.exe" -ArgumentList "--app=http://localhost:8081/"
#region HTTP Listener Route Handling
try {
while ($listener.IsListening) {
# (All your listener routing code as before)
}
}
catch {
Write-Host "Error: $($_.Exception.Message)"
}
finally {
if ($listener -ne $null) {
try {
Write-LogHybrid -Message "Stopping the listener." -Level "Info"
$listener.Stop()
$listener.Close()
Write-LogHybrid -Message "Listener stopped successfully." -Level "Info"
} catch {
Write-LogHybrid -Message "Error stopping the listener: $($_.Exception.Message)" -Level "Error"
}
} else {
Write-LogHybrid -Message "Listener object is null; nothing to stop." -Level "Warning"
}
}