Update SVSTaskGate-sy.ps1
This commit is contained in:
994
SVSTaskGate.ps1
994
SVSTaskGate.ps1
@@ -1,994 +0,0 @@
|
||||
### at this point we need to get the checkbox working again
|
||||
|
||||
### add tweek to set default provider, add to toolkit?
|
||||
### need to see if there's anything else we could take from Theo script?
|
||||
### make when using select all the datto rmm pus var runs before install-splashtop
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# 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
|
||||
}
|
||||
|
||||
|
||||
# Check if the Write-Log function exists
|
||||
if (-not (Get-Command -Name Write-Log -CommandType Function -ErrorAction SilentlyContinue)) {
|
||||
# If the Write-Log function doesn't exist, create the Write-LogHelper function
|
||||
function Write-LogHelper {
|
||||
param (
|
||||
[string]$Message,
|
||||
[ValidateSet("Info", "Warning", "Error", "Success", "General")]
|
||||
[string]$Level = "Info",
|
||||
[string]$TaskCategory = "GeneralTask", # Task Category for the log entry
|
||||
[switch]$LogToEvent = $false, # Log to Windows Event Log
|
||||
[string]$EventSource = "SVSMSP_Module", # Event Source
|
||||
[string]$EventLog = "Application", # Event Log (default: Application)
|
||||
[int]$CustomEventID # Optional custom Event ID
|
||||
)
|
||||
|
||||
# Simplified Event ID mapping
|
||||
$EventID = switch ($Level) {
|
||||
"Info" { 1000 }
|
||||
"Warning" { 2000 }
|
||||
"Error" { 3000 }
|
||||
"Success" { 4000 }
|
||||
"General" { 1000 }
|
||||
}
|
||||
|
||||
# Icons for each level
|
||||
$Icon = switch ($Level) {
|
||||
"Info" { [System.Char]::ConvertFromUtf32(0x1F4CB) } # Information icon
|
||||
"Warning" { ([char]0x26A0) } # Warning icon
|
||||
"Error" { ([char]0x274C) } # Error icon
|
||||
"Success" { ([char]0x2705) } # Success icon
|
||||
"General" { ([char]0x1F4E6) } # Package icon
|
||||
}
|
||||
|
||||
# Map levels to colors
|
||||
$Color = switch ($Level) {
|
||||
"Info" { "Cyan" }
|
||||
"Warning" { "Yellow" }
|
||||
"Error" { "Red" }
|
||||
"Success" { "Green" }
|
||||
"General" { "White" }
|
||||
}
|
||||
|
||||
# Write to the PowerShell console
|
||||
Write-Host "$Icon [$Level] [$TaskCategory] $Message (Event ID: $EventID)" -ForegroundColor $Color
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
# 2) ALSO STORE THE LOG IN OUR GLOBAL LOG CACHE (NEW)
|
||||
# -------------------------------------------------------------------
|
||||
$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)
|
||||
# -------------------------------------------------------------------
|
||||
|
||||
# Optionally log to the Windows Event Log
|
||||
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 {
|
||||
# If Write-Log exists, define Write-LogHybrid to use Write-Log
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
# Example usage of Write-LogHybrid
|
||||
Write-LogHybrid -Message "This is a test log message. Write-logHybrid" -Level "Info" -TaskCategory "TestCategory" -LogToEvent:$true
|
||||
Write-Log -Message "This is a test log message. Write-log" -Level "Info" -TaskCategory "TestCategory" -LogToEvent:$true
|
||||
|
||||
|
||||
function Install-SVSMSP {
|
||||
param (
|
||||
# Cleanup flag
|
||||
[switch]$Cleanup,
|
||||
|
||||
# Toolkit installation flag
|
||||
[switch]$InstallToolkit,
|
||||
|
||||
# Module settings
|
||||
[Parameter(Mandatory = $false)]
|
||||
[array]$AllModules = @(
|
||||
@{ ModuleName = "SVS_Toolkit" },
|
||||
@{ ModuleName = "SVSMSP" }
|
||||
),
|
||||
|
||||
[Parameter(Mandatory = $false)]
|
||||
[string]$NewModuleName = "SVSMSP",
|
||||
|
||||
# Repository settings
|
||||
[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/",
|
||||
|
||||
# Commands to check
|
||||
[Parameter(Mandatory = $false)]
|
||||
[array]$CommandsToCheck = @(
|
||||
"Install-DattoRMM",
|
||||
"Install-CyberQP",
|
||||
"Install-RocketCyber",
|
||||
"Install-Splashtop",
|
||||
"Install-Threatlocker"
|
||||
),
|
||||
|
||||
# Log file path
|
||||
[Parameter(Mandatory = $false)]
|
||||
[string]$LogFilePath = "$env:temp\svstoolkit.log",
|
||||
|
||||
# DRMM API Settings
|
||||
[Parameter(Mandatory = $false)]
|
||||
[string]$ApiUrl = "https://example-api-url.com",
|
||||
|
||||
[Parameter(Mandatory = $false)]
|
||||
[string]$ApiKey = "YOUR_API_KEY_HERE",
|
||||
|
||||
[Parameter(Mandatory = $false)]
|
||||
[string]$ApiSecretKey = "YOUR_API_SECRET_HERE"
|
||||
)
|
||||
|
||||
function Perform-Cleanup {
|
||||
Write-LogHybrid -Message "Cleanup mode enabled. Starting cleanup process..." -Level "Info" -LogToEvent -EventID 1502
|
||||
|
||||
# Step 1: Remove all old modules
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
# Step 2: Remove all old repositories
|
||||
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 -EventID 1510
|
||||
}
|
||||
|
||||
function Perform-ToolkitInstallation {
|
||||
# Perform cleanup
|
||||
Perform-Cleanup
|
||||
|
||||
# Step 1: Set Execution Policy
|
||||
$localMachineExecutionPolicy = Get-ExecutionPolicy -Scope LocalMachine
|
||||
if ($localMachineExecutionPolicy -ne "RemoteSigned") {
|
||||
Write-LogHybrid -Message "Setting execution policy to RemoteSigned..." -Level "Warning" -LogToEvent -EventID 1522
|
||||
try {
|
||||
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope LocalMachine -Force
|
||||
Write-LogHybrid -Message "Execution policy set to RemoteSigned successfully." -Level "Success" -LogToEvent -EventID 1513
|
||||
}
|
||||
catch {
|
||||
Write-LogHybrid -Message "Failed to set execution policy. Error: $_" -Level "Error" -LogToEvent -EventID 1534
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
# Step 2: Ensure NuGet is Installed
|
||||
if (!(Get-PackageProvider -Name "NuGet" -ErrorAction SilentlyContinue)) {
|
||||
Write-LogHybrid -Message "NuGet package provider not found. Installing..." -Level "Warning" -LogToEvent -EventID 1520
|
||||
try {
|
||||
Install-PackageProvider -Name "NuGet" -Force -Scope AllUsers -Confirm:$false
|
||||
Write-LogHybrid -Message "NuGet package provider installed successfully." -Level "Success" -LogToEvent -EventID 1514
|
||||
}
|
||||
catch {
|
||||
Write-LogHybrid -Message "Failed to install NuGet package provider. Error: $_" -Level "Error" -LogToEvent -EventID 1535
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
# Step 3: Register the new repository
|
||||
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
|
||||
}
|
||||
|
||||
# Step 4: Install the new module
|
||||
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 -EventID 1510
|
||||
}
|
||||
|
||||
Write-LogHybrid -Message "Install-SVSMSP function started." -Level "Info" -LogToEvent -EventID 1500
|
||||
|
||||
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 -EventID 1504
|
||||
Perform-ToolkitInstallation
|
||||
}
|
||||
|
||||
Install-SVSMSP -InstallToolkit
|
||||
|
||||
|
||||
# ----------------------------------------------------------------------------------
|
||||
# START THE LISTENER
|
||||
# ----------------------------------------------------------------------------------
|
||||
$listener = New-Object System.Net.HttpListener
|
||||
$listener.Prefixes.Add("http://localhost:8081/")
|
||||
$listener.Start()
|
||||
|
||||
|
||||
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
|
||||
|
||||
# Map fields
|
||||
$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
|
||||
|
||||
|
||||
|
||||
return $data
|
||||
}
|
||||
catch {
|
||||
Write-Host "Error making the GET request:" -ForegroundColor Red
|
||||
Write-Host $_.Exception.Message
|
||||
return $null
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Define the HTML Content with an Off-Boarding Tab
|
||||
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>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background-color: #1e1e1e;
|
||||
color: #ffffff;
|
||||
}
|
||||
.logo-container {
|
||||
text-align: center;
|
||||
padding: 20px;
|
||||
background-color: #1e1e1e; /* Matches the background color */
|
||||
}
|
||||
.logo-container img {
|
||||
max-width: 300px; /* Adjust size as needed */
|
||||
height: auto;
|
||||
}
|
||||
.container {
|
||||
display: flex;
|
||||
height: 100vh;
|
||||
}
|
||||
.sidebar {
|
||||
width: 200px;
|
||||
background-color: #1e1e1e;
|
||||
padding: 10px;
|
||||
}
|
||||
.sidebar button {
|
||||
display: block;
|
||||
width: 100%;
|
||||
margin-bottom: 10px;
|
||||
padding: 10px;
|
||||
color: white;
|
||||
background-color: #444;
|
||||
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: #007bff;
|
||||
}
|
||||
.sidebar button:hover {
|
||||
background-color: #0056b3;
|
||||
transform: scale(1.05);
|
||||
}
|
||||
.content {
|
||||
flex: 1;
|
||||
padding: 20px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.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 #555;
|
||||
background-color: #2e2e2e;
|
||||
color: white;
|
||||
}
|
||||
.button-group {
|
||||
margin-top: 20px;
|
||||
text-align: right;
|
||||
}
|
||||
.button-group button {
|
||||
padding: 10px 20px;
|
||||
margin-left: 10px;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.install-button {
|
||||
background-color: #28a745;
|
||||
color: white;
|
||||
}
|
||||
.install-button:disabled {
|
||||
background-color: #6c757d;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
.exit-button {
|
||||
background-color: #dc3545;
|
||||
color: white;
|
||||
}
|
||||
.log {
|
||||
width: 80%;
|
||||
margin-top: 20px;
|
||||
padding: 10px;
|
||||
background-color: #333;
|
||||
color: #bbb;
|
||||
border-radius: 5px;
|
||||
max-height: 500px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
@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.png" 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="TweeksTab" aria-expanded="false">Tweeks</button>
|
||||
</div>
|
||||
<div class="content">
|
||||
<!-- On-Boarding Tab -->
|
||||
<div id="onboardTab" class="tab-content active">
|
||||
<h2>On-Boarding</h2>
|
||||
<div class="checkbox-group">
|
||||
<label>
|
||||
<input type="checkbox" id="selectAllOnboardCheckbox" onclick="toggleOnboardCheckboxes(this)">
|
||||
Select All
|
||||
</label>
|
||||
<label>
|
||||
<input type="checkbox" name="setSVSPowerplan" id="installSVSPowerplanCheckbox">
|
||||
Set SVS Powerplan
|
||||
</label>
|
||||
<label>
|
||||
<input type="checkbox" name="installCyberQP" id="installCyberQPCheckbox">
|
||||
Install CyberQP
|
||||
</label>
|
||||
<label>
|
||||
<input type="checkbox" name="installSplashtop" id="installSplashtopCheckbox">
|
||||
Install Splashtop
|
||||
</label>
|
||||
<label>
|
||||
<input type="checkbox" name="installSVSHelpDesk" id="installSVSHelpDeskCheckbox">
|
||||
Install SVSHelpDesk
|
||||
</label>
|
||||
<label>
|
||||
<input type="checkbox" name="installSVSWatchtower" id="installSVSWatchtowerCheckbox">
|
||||
Install SVSWatchtower
|
||||
</label>
|
||||
<label>
|
||||
<input type="checkbox" name="installThreatLocker" id="installThreatLockerCheckbox">
|
||||
Install ThreatLocker
|
||||
</label>
|
||||
<label>
|
||||
<input type="checkbox" name="installRocketCyber" id="installRocketCyberCheckbox">
|
||||
Install RocketCyber
|
||||
</label>
|
||||
<label>
|
||||
<input type="checkbox" name="installDattoRMM" id="installDattoRMMCheckbox"
|
||||
onclick="toggleDattoRMMOptions()">
|
||||
Install DattoRMM
|
||||
</label>
|
||||
<div id="dattoRMMOptionsContainer" style="display:none; padding-left: 20px;">
|
||||
<label>
|
||||
<input type="checkbox" name="dattoRMMOption" value="inputVar">
|
||||
Copy Site Variables
|
||||
</label>
|
||||
<label>
|
||||
<input type="checkbox" name="dattoRMMOption" value="rmm">
|
||||
Install DRMM Agent
|
||||
</label>
|
||||
<label>
|
||||
<input type="checkbox" name="dattoRMMOption" value="exe">
|
||||
Download.exe
|
||||
</label>
|
||||
<br><br>
|
||||
</div>
|
||||
</div>
|
||||
<div id="n8nPasswordContainer" style="display: none;">
|
||||
<label for="n8nPassword">Enter n8n Password:</label><br>
|
||||
<input type="password" id="n8nPassword" class="password-input" placeholder="Enter N8N 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>
|
||||
<button class="exit-button" onclick="endSession()">Exit</button>
|
||||
</div>
|
||||
<div class="log" id="logArea">
|
||||
<p>Logs will appear here...</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function toggleOnboardCheckboxes(selectedCheckbox) {
|
||||
const checkboxes = document.querySelectorAll('#onboardTab input[type="checkbox"]');
|
||||
const dattoRMMCheckbox = document.getElementById('installDattoRMMCheckbox');
|
||||
const optionsContainer = document.getElementById('dattoRMMOptionsContainer');
|
||||
const n8nPasswordContainer = document.getElementById('n8nPasswordContainer');
|
||||
const dattoRMMContainer = document.getElementById('DattoRMMContainer');
|
||||
|
||||
checkboxes.forEach(checkbox => {
|
||||
if (checkbox !== selectedCheckbox) {
|
||||
checkbox.checked = selectedCheckbox.checked;
|
||||
}
|
||||
});
|
||||
|
||||
if (dattoRMMCheckbox.checked) {
|
||||
optionsContainer.style.display = 'block';
|
||||
n8nPasswordContainer.style.display = 'block';
|
||||
dattoRMMContainer.style.display = 'block';
|
||||
} else {
|
||||
optionsContainer.style.display = 'none';
|
||||
n8nPasswordContainer.style.display = 'none';
|
||||
dattoRMMContainer.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
function toggleDattoRMMOptions() {
|
||||
const checkbox = document.getElementById('installDattoRMMCheckbox');
|
||||
const optionsContainer = document.getElementById('dattoRMMOptionsContainer');
|
||||
const n8nPasswordContainer = document.getElementById('n8nPasswordContainer');
|
||||
const DattoRMMContainer = document.getElementById('DattoRMMContainer');
|
||||
|
||||
optionsContainer.style.display = checkbox.checked ? 'block' : 'none';
|
||||
n8nPasswordContainer.style.display = checkbox.checked ? 'block' : 'none';
|
||||
DattoRMMContainer.style.display = checkbox.checked ? 'block' : 'none';
|
||||
}
|
||||
|
||||
const tabButtons = document.querySelectorAll('.tab-button');
|
||||
const tabContents = document.querySelectorAll('.tab-content');
|
||||
const logArea = document.getElementById('logArea');
|
||||
const fetchSitesButton = document.getElementById('fetchSitesButton');
|
||||
const n8nPasswordInput = document.getElementById('n8nPassword');
|
||||
|
||||
tabButtons.forEach(button => {
|
||||
button.addEventListener('click', () => {
|
||||
tabButtons.forEach(btn => {
|
||||
btn.classList.remove('active');
|
||||
btn.setAttribute('aria-expanded', 'false');
|
||||
});
|
||||
tabContents.forEach(tab => tab.classList.remove('active'));
|
||||
button.classList.add('active');
|
||||
button.setAttribute('aria-expanded', 'true');
|
||||
document.getElementById(button.dataset.tab).classList.add('active');
|
||||
});
|
||||
});
|
||||
|
||||
n8nPasswordInput.addEventListener('input', () => {
|
||||
fetchSitesButton.disabled = n8nPasswordInput.value.length < 4;
|
||||
});
|
||||
|
||||
async function fetchSites() {
|
||||
const password = document.getElementById('n8nPassword').value;
|
||||
const dropdown = document.getElementById('dattoRmmDropdown');
|
||||
|
||||
if (!password) {
|
||||
appendLog("Please enter the n8n password.", "red");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
appendLog("Fetching sites...", "yellow");
|
||||
|
||||
const response = await fetch('/getn8npw', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ password })
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to fetch sites. Please try again.');
|
||||
}
|
||||
|
||||
const sites = await response.json();
|
||||
dropdown.innerHTML = '';
|
||||
|
||||
sites.forEach(site => {
|
||||
const option = document.createElement('option');
|
||||
// Adjust property names based on your actual data
|
||||
option.value = site.UID;
|
||||
option.textContent = site.Name;
|
||||
dropdown.appendChild(option);
|
||||
});
|
||||
|
||||
appendLog("Sites fetched successfully, please select a site!", "green");
|
||||
}
|
||||
catch (error) {
|
||||
dropdown.innerHTML = '<option value="">Fetching sites failed</option>';
|
||||
appendLog('Error:' + error.message, "red");
|
||||
}
|
||||
}
|
||||
|
||||
function triggerInstall() {
|
||||
const dropdown = document.getElementById('dattoRmmDropdown');
|
||||
const UID = dropdown.options[dropdown.selectedIndex].value;
|
||||
const Name = dropdown.options[dropdown.selectedIndex].text;
|
||||
|
||||
const installDattoRMM = document.querySelector('input[name="installDattoRMM"]');
|
||||
const installCyberQP = document.querySelector('input[name="installCyberQP"]');
|
||||
const installSplashtop = document.querySelector('input[name="installSplashtop"]');
|
||||
const installSVSHelpDesk = document.querySelector('input[name="installSVSHelpDesk"]');
|
||||
const installSVSWatchtower = document.querySelector('input[name="installSVSWatchtower"]');
|
||||
const installThreatLocker = document.querySelector('input[name="installThreatlocker"]');
|
||||
const installRocketCyber = document.querySelector('input[name="installRocketCyber"]');
|
||||
|
||||
if (installDattoRMM.checked) {
|
||||
const DattoRMMCheckbox = document.querySelectorAll('input[name="dattoRMMOption"]:checked');
|
||||
appendLog("Installing selected site RMM...", "cyan");
|
||||
|
||||
const checkedValues = Array.from(DattoRMMCheckbox).map(c => c.value);
|
||||
let installRMMCommand = 'Install-DattoRMM -ApiUrl $ApiUrl -ApiKey $ApiKey -ApiSecretKey $ApiSecretKey';
|
||||
|
||||
if (checkedValues.includes('inputVar')) {
|
||||
installRMMCommand += ' -PushSiteVars';
|
||||
}
|
||||
if (checkedValues.includes('rmm')) {
|
||||
installRMMCommand += ' -InstallRMM';
|
||||
}
|
||||
if (checkedValues.includes('exe')) {
|
||||
installRMMCommand += ' -SaveCopy';
|
||||
}
|
||||
|
||||
fetch('/installrmm', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ installRMMCommand, UID, Name })
|
||||
});
|
||||
}
|
||||
|
||||
if (document.querySelector('input[name="setSVSPowerplan"]').checked) {
|
||||
fetch('/installSVSPowerplan', { method: 'GET' });
|
||||
appendLog("Setting SVS Powerplan", "cyan");
|
||||
}
|
||||
|
||||
if (installCyberQP.checked) {
|
||||
fetch('/installCyberQP', { method: 'GET' });
|
||||
appendLog("Installing CyberQP", "cyan");
|
||||
}
|
||||
if (installSplashtop.checked) {
|
||||
fetch('/installSplashtop', { method: 'GET' });
|
||||
appendLog("Installing Splashtop", "cyan");
|
||||
}
|
||||
if (installSVSHelpDesk.checked) {
|
||||
fetch('/installSVSHelpDesk', { method: 'GET' });
|
||||
appendLog("Installing SVSHelpdesk", "cyan");
|
||||
}
|
||||
if (installSVSWatchtower.checked) {
|
||||
fetch('/installSVSWatchtower', { method: 'GET' });
|
||||
appendLog("Installing SVSWatchtower", "cyan");
|
||||
}
|
||||
if (installThreatLocker.checked) {
|
||||
fetch('/installThreatLocker', { method: 'GET' });
|
||||
appendLog("Installing ThreatLocker", "cyan");
|
||||
}
|
||||
if (installRocketCyber.checked) {
|
||||
fetch('/installRocketCyber', { method: 'GET' });
|
||||
appendLog("Installing RocketCyber", "cyan");
|
||||
}
|
||||
}
|
||||
|
||||
function endSession() {
|
||||
appendLog("Session ended. Closing application...", "yellow");
|
||||
fetch('/quit', { method: 'GET' })
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to end session');
|
||||
}
|
||||
window.close();
|
||||
})
|
||||
.catch(error => {
|
||||
appendLog("Error ending session: " + error.message, "red");
|
||||
});
|
||||
}
|
||||
|
||||
function appendLog(message, color = "white") {
|
||||
const log = document.createElement('p');
|
||||
log.style.color = color;
|
||||
log.textContent = message;
|
||||
document.getElementById('logArea').appendChild(log);
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// 3) POLL THE SERVER LOGS (NEW)
|
||||
// -------------------------------------------------------------------
|
||||
let lastLogCount = 0;
|
||||
async function fetchLogs() {
|
||||
try {
|
||||
const resp = await fetch('/getLogs');
|
||||
if (!resp.ok) return;
|
||||
const logs = await resp.json(); // array of {Timestamp, Level, Message}
|
||||
|
||||
// Append only new messages
|
||||
for (let i = lastLogCount; i < logs.length; i++) {
|
||||
// We'll display each new line in "white" or a color of your choice
|
||||
appendLog(logs[i].Message, "white");
|
||||
}
|
||||
lastLogCount = logs.length;
|
||||
} catch (err) {
|
||||
console.error("Error fetching logs:", err);
|
||||
}
|
||||
}
|
||||
// Poll logs every 3 seconds (feel free to adjust)
|
||||
setInterval(fetchLogs, 3000);
|
||||
// -------------------------------------------------------------------
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
"@
|
||||
}
|
||||
|
||||
|
||||
|
||||
# Save and launch the HTML
|
||||
Start-Process "msedge.exe" -ArgumentList "--app=http://localhost:8081/"
|
||||
|
||||
|
||||
try {
|
||||
while ($listener.IsListening) {
|
||||
$context = $listener.GetContext()
|
||||
$request = $context.Request
|
||||
$response = $context.Response
|
||||
|
||||
switch ($request.Url.AbsolutePath) {
|
||||
|
||||
"/" {
|
||||
$htmlContent = GetHtmlContent
|
||||
$buffer = [System.Text.Encoding]::UTF8.GetBytes($htmlContent)
|
||||
$response.ContentType = "text/html"
|
||||
$response.ContentLength64 = $buffer.Length
|
||||
$response.OutputStream.Write($buffer, 0, $buffer.Length)
|
||||
$response.OutputStream.Close()
|
||||
}
|
||||
|
||||
"/getn8npw" {
|
||||
if ($request.HttpMethod -eq "POST") {
|
||||
$bodyStream = New-Object IO.StreamReader $request.InputStream
|
||||
$body = $bodyStream.ReadToEnd()
|
||||
$data = ConvertFrom-Json $body
|
||||
$password = $data.password
|
||||
|
||||
Get-N8nWebhookData -AuthHeaderValue $password
|
||||
$sites = Install-DattoRMM -ApiUrl $ApiUrl -ApiKey $ApiKey -ApiSecretKey $ApiSecretKey -FetchSitesOnly
|
||||
if (-not $sites) {
|
||||
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
|
||||
}
|
||||
$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()
|
||||
}
|
||||
}
|
||||
|
||||
"/installrmm" {
|
||||
if ($request.HttpMethod -eq "POST") {
|
||||
$bodyStream = New-Object IO.StreamReader $request.InputStream
|
||||
$body = $bodyStream.ReadToEnd()
|
||||
$selectedSite = ConvertFrom-Json $body
|
||||
Invoke-Expression $selectedSite.installRMMCommand
|
||||
|
||||
$responseString = "RMM install triggered."
|
||||
$buffer = [System.Text.Encoding]::UTF8.GetBytes($responseString)
|
||||
$response.ContentType = "text/plain"
|
||||
$response.ContentLength64 = $buffer.Length
|
||||
$response.OutputStream.Write($buffer, 0, $buffer.Length)
|
||||
$response.OutputStream.Close()
|
||||
}
|
||||
}
|
||||
|
||||
"/setSVSPowerplan" {
|
||||
if ($request.HttpMethod -eq "GET") {
|
||||
Set-SVSPowerPlan
|
||||
}
|
||||
$responseString = "Install SVS Powerplan triggered."
|
||||
$buffer = [System.Text.Encoding]::UTF8.GetBytes($responseString)
|
||||
$response.ContentType = "text/plain"
|
||||
$response.ContentLength64 = $buffer.Length
|
||||
$response.OutputStream.Write($buffer, 0, $buffer.Length)
|
||||
$response.OutputStream.Close()
|
||||
}
|
||||
|
||||
|
||||
"/installCyberQP" {
|
||||
if ($request.HttpMethod -eq "GET") {
|
||||
Install-CyberQP
|
||||
}
|
||||
$responseString = "Install CyberQP triggered."
|
||||
$buffer = [System.Text.Encoding]::UTF8.GetBytes($responseString)
|
||||
$response.ContentType = "text/plain"
|
||||
$response.ContentLength64 = $buffer.Length
|
||||
$response.OutputStream.Write($buffer, 0, $buffer.Length)
|
||||
$response.OutputStream.Close()
|
||||
}
|
||||
|
||||
"/installSplashtop" {
|
||||
if ($request.HttpMethod -eq "GET") {
|
||||
Install-Splashtop
|
||||
}
|
||||
$responseString = "Install Splashtop triggered."
|
||||
$buffer = [System.Text.Encoding]::UTF8.GetBytes($responseString)
|
||||
$response.ContentType = "text/plain"
|
||||
$response.ContentLength64 = $buffer.Length
|
||||
$response.OutputStream.Write($buffer, 0, $buffer.Length)
|
||||
$response.OutputStream.Close()
|
||||
}
|
||||
|
||||
"/installRocketCyber" {
|
||||
if ($request.HttpMethod -eq "GET") {
|
||||
Install-RocketCyber
|
||||
}
|
||||
$responseString = "Install RocketCyber triggered."
|
||||
$buffer = [System.Text.Encoding]::UTF8.GetBytes($responseString)
|
||||
$response.ContentType = "text/plain"
|
||||
$response.ContentLength64 = $buffer.Length
|
||||
$response.OutputStream.Write($buffer, 0, $buffer.Length)
|
||||
$response.OutputStream.Close()
|
||||
}
|
||||
|
||||
"/installThreatlocker" {
|
||||
if ($request.HttpMethod -eq "GET") {
|
||||
Install-Threatlocker
|
||||
}
|
||||
$responseString = "Install Threatlocker triggered."
|
||||
$buffer = [System.Text.Encoding]::UTF8.GetBytes($responseString)
|
||||
$response.ContentType = "text/plain"
|
||||
$response.ContentLength64 = $buffer.Length
|
||||
$response.OutputStream.Write($buffer, 0, $buffer.Length)
|
||||
$response.OutputStream.Close()
|
||||
}
|
||||
|
||||
"/installSVSHelpDesk" {
|
||||
if ($request.HttpMethod -eq "GET") {
|
||||
Install-SVSHelpDesk
|
||||
}
|
||||
$responseString = "Install SVSHelpDesk triggered."
|
||||
$buffer = [System.Text.Encoding]::UTF8.GetBytes($responseString)
|
||||
$response.ContentType = "text/plain"
|
||||
$response.ContentLength64 = $buffer.Length
|
||||
$response.OutputStream.Write($buffer, 0, $buffer.Length)
|
||||
$response.OutputStream.Close()
|
||||
}
|
||||
|
||||
"/installSVSWatchtower" {
|
||||
if ($request.HttpMethod -eq "GET") {
|
||||
Install-SVSWatchtower
|
||||
}
|
||||
$responseString = "Install SVSWatchtower triggered."
|
||||
$buffer = [System.Text.Encoding]::UTF8.GetBytes($responseString)
|
||||
$response.ContentType = "text/plain"
|
||||
$response.ContentLength64 = $buffer.Length
|
||||
$response.OutputStream.Write($buffer, 0, $buffer.Length)
|
||||
$response.OutputStream.Close()
|
||||
}
|
||||
|
||||
# ----------------------------------------------------------------
|
||||
# 4) NEW ROUTE: /getLogs
|
||||
# Returns $Global:LogCache as JSON for the polling function
|
||||
# ----------------------------------------------------------------
|
||||
"/getLogs" {
|
||||
if ($request.HttpMethod -eq "GET") {
|
||||
$jsonLogs = $Global:LogCache | ConvertTo-Json
|
||||
$logBuffer = [System.Text.Encoding]::UTF8.GetBytes($jsonLogs)
|
||||
$response.ContentType = "application/json"
|
||||
$response.ContentLength64 = $logBuffer.Length
|
||||
$response.OutputStream.Write($logBuffer, 0, $logBuffer.Length)
|
||||
$response.OutputStream.Close()
|
||||
}
|
||||
}
|
||||
|
||||
"/quit" {
|
||||
if ($request.HttpMethod -eq "GET") {
|
||||
$responseString = "Server shutting down."
|
||||
$buffer = [System.Text.Encoding]::UTF8.GetBytes($responseString)
|
||||
$response.ContentType = "text/plain"
|
||||
$response.ContentLength64 = $buffer.Length
|
||||
$response.OutputStream.Write($buffer, 0, $buffer.Length)
|
||||
$response.OutputStream.Close()
|
||||
Write-Host $responseString
|
||||
$listener.stop()
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
default {
|
||||
$response.StatusCode = 404
|
||||
$response.StatusDescription = "Not Found"
|
||||
$buffer = [System.Text.Encoding]::UTF8.GetBytes("404 - Not Found")
|
||||
$response.OutputStream.Write($buffer, 0, $buffer.Length)
|
||||
$response.OutputStream.Close()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Write-Host "Error: $($_.Exception.Message)"
|
||||
|
||||
}
|
||||
finally {
|
||||
$listener.Stop()
|
||||
$listener.Close()
|
||||
}
|
||||
Reference in New Issue
Block a user