From 1517027e70d555a46592abfd6450b213923d269f Mon Sep 17 00:00:00 2001 From: Stephan Yelle Date: Tue, 9 Dec 2025 23:01:22 -0500 Subject: [PATCH] Add test/Samy.Datto.ps1 --- test/Samy.Datto.ps1 | 213 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 213 insertions(+) create mode 100644 test/Samy.Datto.ps1 diff --git a/test/Samy.Datto.ps1 b/test/Samy.Datto.ps1 new file mode 100644 index 0000000..a50dad2 --- /dev/null +++ b/test/Samy.Datto.ps1 @@ -0,0 +1,213 @@ +# Samy.Datto.ps1 +# Datto RMM helper and HTTP handlers + +function Invoke-FetchSites { + param($Context) + + try { + $raw = (New-Object IO.StreamReader $Context.Request.InputStream).ReadToEnd() + $pw = (ConvertFrom-Json $raw).password + + $Global:WebhookPassword = $pw + + $sites = Install-DattoRMM ` + -UseWebhook ` + -WebhookPassword $pw ` + -FetchSites + + Send-JSON $Context $sites + } + catch { + Write-LogHybrid "Invoke-FetchSites error: $($_.Exception.Message)" Error DattoRMM -LogToEvent + $Context.Response.StatusCode = 500 + Send-Text $Context "Internal server error fetching sites." + } +} + +function Invoke-InstallDattoRMM { + param($Context) + + try { + if ($Context.Request.HttpMethod -ne 'POST') { + $Context.Response.StatusCode = 405 + Send-Text $Context 'Use POST' + return + } + + $body = (New-Object IO.StreamReader $Context.Request.InputStream).ReadToEnd() + $data = ConvertFrom-Json $body + + Install-DattoRMM ` + -UseWebhook ` + -WebhookPassword $Global:WebhookPassword ` + -SiteUID $data.UID ` + -SiteName $data.Name ` + -PushSiteVars:($data.checkedValues -contains 'inputVar') ` + -InstallRMM: ($data.checkedValues -contains 'rmm') ` + -SaveCopy: ($data.checkedValues -contains 'exe') + + Send-Text $Context "Triggered DattoRMM for $($data.Name)" + } + catch { + Write-LogHybrid "Invoke-InstallDattoRMM error: $($_.Exception.Message)" Error DattoRMM -LogToEvent + $Context.Response.StatusCode = 500 + Send-Text $Context "Internal server error during DattoRMM install." + } +} + +function Install-DattoRMM { + [CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact='Medium')] + param ( + [switch]$UseWebhook, + [string]$WebhookPassword, + [string]$WebhookUrl = $Global:DattoWebhookUrl, + [string]$ApiUrl, + [string]$ApiKey, + [string]$ApiSecretKey, + [switch]$FetchSites, + [switch]$SaveSitesList, + [string]$OutputFile = 'datto_sites.csv', + [switch]$PushSiteVars, + [switch]$InstallRMM, + [switch]$SaveCopy, + [string]$SiteUID, + [string]$SiteName + ) + + if ($SaveSitesList -and -not $FetchSites) { + Write-LogHybrid "-SaveSitesList requires -FetchSites." Error DattoRMM -LogToEvent + return + } + + if ($UseWebhook) { + if (-not $WebhookPassword) { + Write-LogHybrid "Webhook password missing." Error DattoRMM -LogToEvent + return + } + try { + $resp = Invoke-RestMethod -Uri $WebhookUrl ` + -Headers @{ SVSMSPKit = $WebhookPassword } ` + -Method GET + $ApiUrl = $resp.ApiUrl + $ApiKey = $resp.ApiKey + $ApiSecretKey = $resp.ApiSecretKey + Write-LogHybrid "Webhook credentials fetched." Success DattoRMM -LogToEvent + } + catch { + Write-LogHybrid "Failed to fetch webhook credentials: $($_.Exception.Message)" Error DattoRMM -LogToEvent + return + } + } + + if (-not $ApiUrl -or -not $ApiKey -or -not $ApiSecretKey) { + Write-LogHybrid "Missing required API parameters." Error DattoRMM -LogToEvent + return + } + + [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 + try { + $publicCred = New-Object System.Management.Automation.PSCredential( + 'public-client', (ConvertTo-SecureString 'public' -AsPlainText -Force) + ) + $tokenResp = Invoke-RestMethod -Uri "$ApiUrl/auth/oauth/token" ` + -Credential $publicCred ` + -Method Post ` + -ContentType 'application/x-www-form-urlencoded' ` + -Body "grant_type=password&username=$ApiKey&password=$ApiSecretKey" + $token = $tokenResp.access_token + Write-LogHybrid "OAuth token acquired." Success DattoRMM -LogToEvent + } + catch { + Write-LogHybrid "OAuth token fetch failed: $($_.Exception.Message)" Error DattoRMM -LogToEvent + return + } + $headers = @{ Authorization = "Bearer $token" } + + if ($FetchSites) { + try { + $sitesResp = Invoke-RestMethod -Uri "$ApiUrl/api/v2/account/sites" -Method Get -Headers $headers + $siteList = $sitesResp.sites | Sort-Object name | ForEach-Object { + [PSCustomObject]@{ Name = $_.name; UID = $_.uid } + } + Write-LogHybrid "Fetched $($siteList.Count) sites." Success DattoRMM -LogToEvent + + if ($SaveSitesList) { + $desktop = [Environment]::GetFolderPath('Desktop') + $path = Join-Path $desktop $OutputFile + $ext = [IO.Path]::GetExtension($OutputFile).ToLower() + if ($ext -eq '.json') { + $siteList | ConvertTo-Json -Depth 3 | Out-File -FilePath $path -Encoding UTF8 + } + else { + $siteList | Export-Csv -Path $path -NoTypeInformation -Encoding UTF8 + } + Write-LogHybrid "Wrote $($siteList.Count) sites to $path" Success DattoRMM -LogToEvent + } + + return $siteList + } + catch { + Write-LogHybrid "Failed to fetch sites: $($_.Exception.Message)" Error DattoRMM -LogToEvent + return @() + } + } + + if ($PushSiteVars) { + try { + $varsResp = Invoke-RestMethod -Uri "$ApiUrl/api/v2/site/$SiteUID/variables" -Method Get -Headers $headers + Write-LogHybrid "Fetched variables for '$SiteName'." Success DattoRMM -LogToEvent + } + catch { + Write-LogHybrid "Variable fetch failed: $($_.Exception.Message)" Error DattoRMM -LogToEvent + } + + $regPath = "HKLM:\Software\SVS\Deployment" + foreach ($v in $varsResp.variables) { + try { + if (-not (Test-Path $regPath)) { + New-Item -Path $regPath -Force | Out-Null + } + New-ItemProperty -Path $regPath -Name $v.name -Value $v.value -PropertyType String -Force | Out-Null + Write-LogHybrid "Wrote '$($v.name)' to registry." Success DattoRMM -LogToEvent + } + catch { + Write-LogHybrid "Failed to write '$($v.name)': $($_.Exception.Message)" Error DattoRMM -LogToEvent + } + } + } + + if ($InstallRMM) { + if ($PSCmdlet.ShouldProcess("Site '$SiteName'", "Install RMM agent")) { + try { + $dlUrl = "https://zinfandel.centrastage.net/csm/profile/downloadAgent/$SiteUID" + $tmp = "$env:TEMP\AgentInstall.exe" + Invoke-WebRequest -Uri $dlUrl -OutFile $tmp -UseBasicParsing + Write-LogHybrid "Downloaded agent to $tmp." Info DattoRMM -LogToEvent + Start-Process -FilePath $tmp -NoNewWindow + Write-LogHybrid "RMM agent installer launched." Success DattoRMM -LogToEvent + } + catch { + Write-LogHybrid "Agent install failed: $($_.Exception.Message)" Error DattoRMM -LogToEvent + } + } + } + + if ($SaveCopy) { + try { + $dlUrl = "https://zinfandel.centrastage.net/csm/profile/downloadAgent/$SiteUID" + $path = "C:\Temp\AgentInstall.exe" + if (-not (Test-Path 'C:\Temp')) { + New-Item -Path 'C:\Temp' -ItemType Directory | Out-Null + } + Invoke-WebRequest -Uri $dlUrl -OutFile $path -UseBasicParsing + Write-LogHybrid "Saved installer copy to $path." Info DattoRMM -LogToEvent + } + catch { + Write-LogHybrid "Save-copy failed: $($_.Exception.Message)" Error DattoRMM -LogToEvent + } + } + + if (-not ($PushSiteVars -or $InstallRMM -or $SaveCopy)) { + Write-LogHybrid "No action specified. Use -FetchSites, -SaveSitesList, -PushSiteVars, -InstallRMM, or -SaveCopy." Warning DattoRMM -LogToEvent + } +}