Update SVSTaskGate.ps1

This commit is contained in:
2025-01-31 16:39:05 -05:00
parent 194c4afcb9
commit c4a5d42462

View File

@@ -8,10 +8,6 @@
### need to fix path in the uninstall-DattoEDR - ### 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 ####### ❌ [Error] [GeneralTask] Uninstallation command 'C:\Program Files\Infocyte\Agent\agent.exe' not found. (Event ID: 3000) - bad path
### need to have the fetch button check if Install-DattoRMM function exist if not run the build in helpder function to fetch sites
### need to move the tweaks to the tweeks tab
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# 1) CREATE A GLOBAL LOG CACHE (NEW) # 1) CREATE A GLOBAL LOG CACHE (NEW)
@@ -222,12 +218,22 @@ function Install-DattoRMM-Helper {
#region SVS Module #region SVS Module
### SVS Module Overview:
# - This section includes the Install-SVSMSP function, which handles:
# 1. Cleanup of old modules and repositories.
# 2. Installation of new modules and repositories.
# 3. Setting execution policies and prerequisites.
# - TODO:
# 1. Validate all parameters for completeness and add error messages for missing inputs.
# 2. Refactor cleanup and installation steps for modularity and reusability.
function Install-SVSMSP { function Install-SVSMSP {
param ( param (
# Cleanup flag # Cleanup flag: Removes old modules and repositories if enabled.
[switch]$Cleanup, [switch]$Cleanup,
# Toolkit installation flag # Toolkit installation flag: Installs required modules and repositories.
[switch]$InstallToolkit, [switch]$InstallToolkit,
# Module settings # Module settings
@@ -265,21 +271,15 @@ function Install-SVSMSP {
), ),
# Log file path # Log file path for tracking installation steps
[Parameter(Mandatory = $false)] [Parameter(Mandatory = $false)]
[string]$LogFilePath = "$env:SVSMSP\svstoolkit.log", [string]$LogFilePath = "$env:SVSMSP\svstoolkit.log"
# DRMM API Settings
[Parameter(Mandatory = $false)]
[string]$ApiUrl,
[Parameter(Mandatory = $false)]
[string]$ApiKey,
[Parameter(Mandatory = $false)]
[string]$ApiSecretKey
) )
### Function: Perform-Cleanup
# - Removes all old modules and repositories.
# - Logs each step for debugging purposes.
function Perform-Cleanup { function Perform-Cleanup {
Write-LogHybrid -Message "Cleanup mode enabled. Starting cleanup process..." -Level "Info" -LogToEvent Write-LogHybrid -Message "Cleanup mode enabled. Starting cleanup process..." -Level "Info" -LogToEvent
@@ -326,11 +326,15 @@ function Install-SVSMSP {
Write-LogHybrid -Message "Cleanup process completed successfully." -Level "Success" -LogToEvent Write-LogHybrid -Message "Cleanup process completed successfully." -Level "Success" -LogToEvent
} }
### Function: Perform-ToolkitInstallation
# - Handles the installation of new repositories and modules.
# - Ensures execution policies are correctly set.
function Perform-ToolkitInstallation { function Perform-ToolkitInstallation {
# Perform cleanup
# Step 1: Cleanup old modules and repositories
Perform-Cleanup Perform-Cleanup
# Step 1: Set Execution Policy # Step 2: Set Execution Policy
$localMachineExecutionPolicy = Get-ExecutionPolicy -Scope LocalMachine $localMachineExecutionPolicy = Get-ExecutionPolicy -Scope LocalMachine
if ($localMachineExecutionPolicy -ne "RemoteSigned") { if ($localMachineExecutionPolicy -ne "RemoteSigned") {
Write-LogHybrid -Message "Setting execution policy to RemoteSigned..." -Level "Warning" -LogToEvent Write-LogHybrid -Message "Setting execution policy to RemoteSigned..." -Level "Warning" -LogToEvent
@@ -344,20 +348,10 @@ function Install-SVSMSP {
} }
} }
# Step 2: Ensure NuGet is Installed # Step 3: Ensure NuGet is Installed
#if (!(Get-PackageProvider -Name "NuGet" -ErrorAction SilentlyContinue)) { Install-PackageProvider -Name "NuGet" -Force -Scope AllUsers -Confirm:$false
# Write-LogHybrid -Message "NuGet package provider not found. Installing..." -Level "Warning" -LogToEvent
# try { # Step 4: Register the new repository
Install-PackageProvider -Name "NuGet" -Force -Scope AllUsers -Confirm:$false
# Write-LogHybrid -Message "NuGet package provider installed successfully." -Level "Success" -LogToEvent
# }
# catch {
# Write-LogHybrid -Message "Failed to install NuGet package provider. Error: $_" -Level "Error" -LogToEvent
# return
# }
#}
# Step 3: Register the new repository
Write-LogHybrid -Message "Registering the new repository '$NewRepositoryName'..." -Level "Info" -LogToEvent Write-LogHybrid -Message "Registering the new repository '$NewRepositoryName'..." -Level "Info" -LogToEvent
try { try {
if (!(Get-PSRepository -Name $NewRepositoryName -ErrorAction SilentlyContinue)) { if (!(Get-PSRepository -Name $NewRepositoryName -ErrorAction SilentlyContinue)) {
@@ -369,7 +363,7 @@ function Install-SVSMSP {
Write-LogHybrid -Message "Failed to register new repository '$NewRepositoryName'. Error: $($_.Exception.Message)" -Level "Error" -LogToEvent Write-LogHybrid -Message "Failed to register new repository '$NewRepositoryName'. Error: $($_.Exception.Message)" -Level "Error" -LogToEvent
} }
# Step 4: Install the new module # Step 5: Install the new module
Write-LogHybrid -Message "Installing the new module '$NewModuleName'..." -Level "Info" -LogToEvent Write-LogHybrid -Message "Installing the new module '$NewModuleName'..." -Level "Info" -LogToEvent
try { try {
Install-Module -Name $NewModuleName -Repository $NewRepositoryName -Scope AllUsers -Force Install-Module -Name $NewModuleName -Repository $NewRepositoryName -Scope AllUsers -Force
@@ -382,6 +376,8 @@ function Install-SVSMSP {
Write-LogHybrid -Message "Toolkit installation process completed successfully." -Level "Success" -LogToEvent Write-LogHybrid -Message "Toolkit installation process completed successfully." -Level "Success" -LogToEvent
} }
### Function Execution Logic
# - Determines whether to run cleanup, toolkit installation, or default to toolkit installation mode.
Write-LogHybrid -Message "Install-SVSMSP function started." -Level "Info" -LogToEvent Write-LogHybrid -Message "Install-SVSMSP function started." -Level "Info" -LogToEvent
if ($Cleanup) { if ($Cleanup) {
@@ -400,11 +396,39 @@ function Install-SVSMSP {
#endregion SVS Module #endregion SVS Module
# ---------------------------------------------------------------------------------- # ----------------------------------------------------------------------------------
# START THE LISTENER # START THE HTTP LISTENER
# ---------------------------------------------------------------------------------- # ----------------------------------------------------------------------------------
$listener = New-Object System.Net.HttpListener # This listener serves as the backend for handling requests from the GUI.
$listener.Prefixes.Add("http://localhost:8081/") # It supports multiple routes, such as:
$listener.Start() # - "/" (Root): Serves the HTML GUI.
# - "/getn8npw": Fetches n8n password and site information.
# - "/installSVSMSPModule": Triggers the installation of SVSMSP modules.
# - "/installrmm": Handles RMM installation with dynamic parameters.
# - Additional routes for tweaks and other tasks.
### Listener Initialization with Error Handling
try {
# Create a new HttpListener object
$listener = New-Object System.Net.HttpListener
# Check if the object was successfully created
if (-not $listener) {
throw "Failed to initialize HttpListener."
}
# Add prefix for the listener
$listener.Prefixes.Add("http://localhost:8081/")
Write-LogHybrid -Message "Listener initialized with prefix http://localhost:8081/" -Level "Info"
# Start the listener
$listener.Start()
Write-LogHybrid -Message "Listener started successfully." -Level "Info"
} catch {
# Log the error and rethrow it for visibility
Write-LogHybrid -Message "Critical error initializing listener: $($_.Exception.Message)" -Level "Error"
throw $_
}
function Get-N8nWebhookData { function Get-N8nWebhookData {
@@ -903,73 +927,64 @@ function GetHtmlContent {
<p>Logs will appear here...</p> <p>Logs will appear here...</p>
</div> </div>
</div> </div>
<script>
<script> // Central function to handle DattoRMM visibility
function toggleOnboardCheckboxes(selectedCheckbox) { function toggleDattoRMMVisibility() {
const checkboxes = document.querySelectorAll('#onboardTab input[type="checkbox"]'); const dattoRMMCheckbox = document.getElementById('installDattoRMMCheckbox');
const dattoRMMCheckbox = document.getElementById('installDattoRMMCheckbox'); const optionsContainer = document.getElementById('dattoRMMOptionsContainer');
const optionsContainer = document.getElementById('dattoRMMOptionsContainer'); const n8nPasswordContainer = document.getElementById('n8nPasswordContainer');
const n8nPasswordContainer = document.getElementById('n8nPasswordContainer'); const dattoRMMContainer = document.getElementById('DattoRMMContainer');
const dattoRMMContainer = document.getElementById('DattoRMMContainer');
if (dattoRMMCheckbox.checked) {
if (dattoRMMCheckbox.checked) { optionsContainer.style.display = 'block';
optionsContainer.style.display = 'block'; n8nPasswordContainer.style.display = 'block';
n8nPasswordContainer.style.display = 'block'; dattoRMMContainer.style.display = 'block';
dattoRMMContainer.style.display = 'block'; } else {
} else { optionsContainer.style.display = 'none';
optionsContainer.style.display = 'none'; n8nPasswordContainer.style.display = 'none';
n8nPasswordContainer.style.display = 'none'; dattoRMMContainer.style.display = 'none';
dattoRMMContainer.style.display = 'none';
}
} }
}
function toggleLeftColumnCheckboxes(selectAllCheckbox) { // Function to update "Select All" checkbox state
const leftCheckboxes = document.querySelectorAll('#leftColumn input[type="checkbox"]:not(#selectAllLeftCheckbox)'); function updateSelectAllCheckbox(selectAllId, checkboxGroupSelector) {
const dattoRMMCheckbox = document.getElementById('installDattoRMMCheckbox'); const selectAllCheckbox = document.getElementById(selectAllId);
const optionsContainer = document.getElementById('dattoRMMOptionsContainer'); const checkboxes = document.querySelectorAll(checkboxGroupSelector);
const n8nPasswordContainer = document.getElementById('n8nPasswordContainer');
const dattoRMMContainer = document.getElementById('DattoRMMContainer');
// Toggle all checkboxes // Uncheck "Select All" if any checkbox is unchecked
leftCheckboxes.forEach(checkbox => { selectAllCheckbox.checked = Array.from(checkboxes).every(checkbox => checkbox.checked);
checkbox.checked = selectAllCheckbox.checked; }
});
// Check if "Install DattoRMM" is selected // Function to handle "Select All" logic for the left column
if (dattoRMMCheckbox.checked) { function toggleLeftColumnCheckboxes(selectAllCheckbox) {
optionsContainer.style.display = 'block'; const leftCheckboxes = document.querySelectorAll('#leftColumn input[type="checkbox"]:not(#selectAllLeftCheckbox)');
n8nPasswordContainer.style.display = 'block';
dattoRMMContainer.style.display = 'block';
} else {
optionsContainer.style.display = 'none';
n8nPasswordContainer.style.display = 'none';
dattoRMMContainer.style.display = 'none';
}
}
// Toggle all checkboxes
function updateSelectAllonboard() { leftCheckboxes.forEach(checkbox => {
const selectAllCheckbox = document.getElementById('selectAllOnboardCheckbox'); checkbox.checked = selectAllCheckbox.checked;
const checkboxes = document
.getElementById('onboardTab')
.querySelectorAll('input[type="checkbox"]:not(#selectAllOnboardCheckbox)');
// If any checkbox is unchecked, uncheck "Select All"
selectAllCheckbox.checked = Array.from(checkboxes).every(checkbox => checkbox.checked);
}
function gatherSelectedTasks() {
const selectedLeftTasks = Array.from(document.querySelectorAll('.left-checkbox:checked')).map(checkbox => checkbox.name);
const selectedRightTasks = Array.from(document.querySelectorAll('.right-checkbox:checked')).map(checkbox => checkbox.name);
return [...selectedLeftTasks, ...selectedRightTasks];
}
// Attach the updateSelectAllonboard function to all individual checkboxes
document.querySelectorAll('#onboardTab input[type="checkbox"]:not(#selectAllOnboardCheckbox)').forEach(checkbox => {
checkbox.addEventListener('change', updateSelectAllonboard);
}); });
// Handle DattoRMM visibility
toggleDattoRMMVisibility();
}
// Function to handle checkbox changes in the Onboard tab
function toggleOnboardCheckboxes(selectedCheckbox) {
// Update DattoRMM visibility
toggleDattoRMMVisibility();
// Update "Select All" checkbox state
updateSelectAllCheckbox('selectAllLeftCheckbox', '#onboardTab input[type="checkbox"]:not(#selectAllLeftCheckbox)');
}
// Attach event listeners to dynamically update the "Select All" checkbox
document.querySelectorAll('#onboardTab input[type="checkbox"]:not(#selectAllLeftCheckbox)').forEach(checkbox => {
checkbox.addEventListener('change', () => {
updateSelectAllCheckbox('selectAllLeftCheckbox', '#onboardTab input[type="checkbox"]:not(#selectAllLeftCheckbox)');
});
});
function toggleOffboardCheckboxes(selectAllCheckbox) { function toggleOffboardCheckboxes(selectAllCheckbox) {
const checkboxes = document.querySelectorAll('#offboardTab input[type="checkbox"]:not(#selectAllOffboardCheckbox)'); const checkboxes = document.querySelectorAll('#offboardTab input[type="checkbox"]:not(#selectAllOffboardCheckbox)');
checkboxes.forEach(checkbox => { checkboxes.forEach(checkbox => {
@@ -1111,18 +1126,36 @@ function GetHtmlContent {
alert("Tweaks applied successfully!"); alert("Tweaks applied successfully!");
} }
function toggleDattoRMMOptions() { function toggleDattoRMMOptions() {
const checkbox = document.getElementById('installDattoRMMCheckbox'); const dattoRMMCheckbox = document.getElementById('installDattoRMMCheckbox');
const optionsContainer = document.getElementById('dattoRMMOptionsContainer'); const optionsContainer = document.getElementById('dattoRMMOptionsContainer');
const n8nPasswordContainer = document.getElementById('n8nPasswordContainer'); const n8nPasswordContainer = document.getElementById('n8nPasswordContainer');
const DattoRMMContainer = document.getElementById('DattoRMMContainer'); const dattoRMMContainer = document.getElementById('DattoRMMContainer');
const subCheckboxes = document.querySelectorAll('#dattoRMMOptionsContainer input[type="checkbox"]');
optionsContainer.style.display = checkbox.checked ? 'block' : 'none'; // Toggle visibility of sub-options
n8nPasswordContainer.style.display = checkbox.checked ? 'block' : 'none'; if (dattoRMMCheckbox.checked) {
DattoRMMContainer.style.display = checkbox.checked ? 'block' : 'none'; optionsContainer.style.display = 'block';
n8nPasswordContainer.style.display = 'block';
dattoRMMContainer.style.display = 'block';
// Automatically check sub-checkboxes
subCheckboxes.forEach(subCheckbox => {
subCheckbox.checked = true;
});
} else {
optionsContainer.style.display = 'none';
n8nPasswordContainer.style.display = 'none';
dattoRMMContainer.style.display = 'none';
// Automatically uncheck sub-checkboxes
subCheckboxes.forEach(subCheckbox => {
subCheckbox.checked = false;
});
}
} }
const tabButtons = document.querySelectorAll('.tab-button'); const tabButtons = document.querySelectorAll('.tab-button');
const tabContents = document.querySelectorAll('.tab-content'); const tabContents = document.querySelectorAll('.tab-content');
const logArea = document.getElementById('logArea'); const logArea = document.getElementById('logArea');
@@ -1399,12 +1432,23 @@ Start-Process "msedge.exe" -ArgumentList "--app=http://localhost:8081/"
try { try {
while ($listener.IsListening) { while ($listener.IsListening) {
### Process Incoming Requests
# - `$context`: Contains the request and response objects.
# - `$request`: Represents the HTTP request.
# - `$response`: Represents the HTTP response.
$context = $listener.GetContext() $context = $listener.GetContext()
$request = $context.Request $request = $context.Request
$response = $context.Response $response = $context.Response
### Route Handling
# - Routes are matched based on the `AbsolutePath` of the request URL.
# - Each route corresponds to a specific action or task.
switch ($request.Url.AbsolutePath) { switch ($request.Url.AbsolutePath) {
# ----------------------------------------------------------------
# ROOT ROUTE ("/")
# Serves the main HTML GUI to the client.
# ----------------------------------------------------------------
"/" { "/" {
$htmlContent = GetHtmlContent $htmlContent = GetHtmlContent
$buffer = [System.Text.Encoding]::UTF8.GetBytes($htmlContent) $buffer = [System.Text.Encoding]::UTF8.GetBytes($htmlContent)
@@ -1414,29 +1458,46 @@ try {
$response.OutputStream.Close() $response.OutputStream.Close()
} }
# ----------------------------------------------------------------
# ROUTE: /getn8npw
# Fetches the n8n password and retrieves DattoRMM site details.
# ----------------------------------------------------------------
"/getn8npw" { "/getn8npw" {
if ($request.HttpMethod -eq "POST") { if ($request.HttpMethod -eq "POST") {
$bodyStream = New-Object IO.StreamReader $request.InputStream try {
$body = $bodyStream.ReadToEnd() # Parse the JSON body to extract the password.
$data = ConvertFrom-Json $body $bodyStream = New-Object IO.StreamReader $request.InputStream
$password = $data.password $body = $bodyStream.ReadToEnd()
$data = ConvertFrom-Json $body
$password = $data.password
Get-N8nWebhookData -AuthHeaderValue $password # Call the webhook to fetch site details.
$sites = Install-DattoRMM-Helper -ApiUrl $ApiUrl -ApiKey $ApiKey -ApiSecretKey $ApiSecretKey -FetchSitesOnly Get-N8nWebhookData -AuthHeaderValue $password
if (-not $sites) { $sites = Install-DattoRMM-Helper -ApiUrl $ApiUrl -ApiKey $ApiKey -ApiSecretKey $ApiSecretKey -FetchSitesOnly
Write-Host "No sites returned. Please check the API." -ForegroundColor Red
$response.StatusCode = 500 if (-not $sites) {
$buffer = [System.Text.Encoding]::UTF8.GetBytes("No sites found") Write-Host "No sites returned. Please check the API." -ForegroundColor Red
$response.StatusCode = 500
$buffer = [System.Text.Encoding]::UTF8.GetBytes("No sites found")
$response.OutputStream.Write($buffer, 0, $buffer.Length)
$response.OutputStream.Close()
continue
}
# Return site details as JSON.
$responseData = $sites | ConvertTo-Json
$buffer = [System.Text.Encoding]::UTF8.GetBytes($responseData)
$response.ContentType = "application/json"
$response.ContentLength64 = $buffer.Length
$response.OutputStream.Write($buffer, 0, $buffer.Length)
$response.OutputStream.Close()
}catch {
Write-LogHybrid -Message "Error processing /getn8npw: $($_.Exception.Message)" -Level "Error"
$response.StatusCode = 500
$buffer = [System.Text.Encoding]::UTF8.GetBytes("Error: Failed to process the request.")
$response.OutputStream.Write($buffer, 0, $buffer.Length) $response.OutputStream.Write($buffer, 0, $buffer.Length)
$response.OutputStream.Close() $response.OutputStream.Close()
continue
} }
$responseData = $sites | ConvertTo-Json
$buffer = [System.Text.Encoding]::UTF8.GetBytes($responseData)
$response.ContentType = "application/json"
$response.ContentLength64 = $buffer.Length
$response.OutputStream.Write($buffer, 0, $buffer.Length)
$response.OutputStream.Close()
} }
} }
@@ -1914,6 +1975,17 @@ catch {
} }
finally { finally {
$listener.Stop() if ($listener -ne $null) {
$listener.Close() 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"
}
} }