Sei già un cliente NinjaOne? Effettua il login per visualizzare le altre guide e gli ultimi aggiornamenti.

Script personalizzato: Importatore vulnerabilità

Argomento

Questo script importa un file CSV contenente le vulnerabilità esportate da vari strumenti e piattaforme di scansione delle vulnerabilità.

Ambiente

NinjaOne Automation

Descrizione

Per utilizzare questo script, salvalo come file batch e caricalo nella tua Libreria script. Potrai quindi eseguirlo secondo necessità dal pulsante di riproduzione nella pagina Dettagli dispositivo o dalla vista Ricerca dispositivi. Per istruzioni e risorse, consulta Automazione del processo di importazione delle vulnerabilità.

<#
.SYNOPSIS
Questo script viene utilizzato per importare un file CSV delle vulnerabilità esportato da vari strumenti/piattaforme di scansione delle vulnerabilità.
.DESCRIPTION
Questo script viene utilizzato per importare un file CSV delle vulnerabilità esportato da vari strumenti/piattaforme di scansione delle vulnerabilità.
Una volta importato correttamente il file, il file CSV verrà eliminato. Se l'importazione del file CSV non va a buon fine a causa di un problema
con il CSV, verrà aggiunto "FAILED_" al nome del CSV. Se la chiamata di importazione iniziale va a buon fine ma i controlli di stato successivi
falliscono, verrà aggiunto "UNKNOWN_" al nome del CSV. A quel punto sarà necessario controllare lo stato nell'interfaccia utente di NinjaOne.
# ---------------------------------------------------------------
# Autore: Mark Giordano
# Data: 03/05/2025
# Descrizione: Vulnerabilità NinjaOne Importazione e registro
# ---------------------------------------------------------------
.NOTES
Gli URL API standard sono:
app.ninjarmm.com
eu.ninjarmm.com
oc.ninjarmm.com
ca.ninjarmm.com
us2.ninjarmm.com
Se desideri impostare questa operazione come attività ricorrente in NinjaOne, ti consigliamo di farlo su un dispositivo sicuro che non viene utilizzato per scopi quotidiani.
Le credenziali devono essere memorizzate in campi personalizzati sicuri e recuperate da lì.
Vedere la configurazione consigliata da Luke Whitelock (Guida introduttiva) qui: https://docs.mspp.io/ninjaone/getting-started
#>
<# Rimuovere il commento da questa sezione se si intende recuperare le credenziali API dai campi personalizzati sicuri di NinjaOne
$ClientID = Ninja-Property-Get NinjaOneAPIClientID
$ClientSecret = Ninja-Property-Get NinjaOneAPISecret
#>
# Modificare BaseURL in base all'istanza applicabile #
$BaseURL = 'ca.ninjarmm.com'
# Specifica l'ID del gruppo di scansione #
$ScanGroupID = 'INSERISCI NUMERO ID GRUPPO DI SCANSIONE'
# Directory dei file CSV da importare #
$PathtoCSV = "$env:SystemDrivetemp"
# Modello iniziale dei nomi dei file CSV da abbinare #
$CSVName = 'VulnExport_'
## Impostazione della funzione ##
function Get-NinjaToken {
$Headers = @{
"Content-Type" = "application/x-www-form-urlencoded"
}
$Scope = "monitoring management offline_access"
if ([string]::IsNullOrWhiteSpace($ClientID) -or [string]::IsNullOrWhiteSpace($ClientSecret)) {
if ($($PSVersionTable.PSVersion -lt [version]'7.0')) {
$ClientID = Read-Host -Prompt "ClientID"
$ClientSecret = Read-Host -Prompt "ClientSecret"
}
else {
$ClientID = Read-Host -MaskInput "ClientID"
$ClientSecret = Read-Host -MaskInput "ClientSecret"
}
}
$GrantType = 'client_credentials'
$params = @{
Uri = "https://$($BaseURL)/ws/oauth/token"
Method = 'POST'
Body = "grant_type=$GrantType&client_id=$ClientID&client_secret=$ClientSecret&scope=$Scope"
}
$Response = Invoke-RestMethod @Params -Headers $Headers
return $Response.access_token
}
function Get-BaseSettings {
[CmdletBinding()]
param (
[Parameter()]
[String]$Method = 'Get',
[Parameter()]
[String]$Body,
[switch]$Paginate,
[string]$After,
[string]$ContentType
)
if ($Paginate) {
$URL = "https://$($BaseURL)/api/v2/$($Request)?pageSize=$($PageSize)&after=$($After)"
}
else {
$URL = "https://$($BaseURL)/api/v2/$($Request)"
}
$Params = @{
Uri = "$URL"
Method = "$Method"
Headers = @{
'Authorization' = 'Bearer {0}' -f "$Token"
"Content-Type" = 'application/json'
}
}
if ($Body) {
$Params['Body'] = $Body
}
return $Params
}
function Get-VulScanGroups {
[CmdletBinding()]
param (
[Parameter()]
[int]$SGID
)
if ($SGID) {
$Request = "/vulnerability/scan-groups/$SGID"
}
else {
$Request = '/vulnerability/scan-groups'
}
$Params = Get-BaseSettings
try {
$ScanGroupRaw = Invoke-WebRequest @Params
return $ScanGroupRaw.Content | ConvertFrom-Json
}
catch {
return $false
}
}
function New-VulScanImport {
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[int]$SGID,
[Parameter(Mandatory = $true)]
[string]$CSV
)
if ($($PSVersionTable.PSVersion -ge [version]'7.0')) {
$Request = "vulnerability/scan-groups/$SGID/upload"
$Params = Get-BaseSettings -Method 'Post'
$Form = @{
"csv" = Get-Item $CSV
}
try {
$Response = Invoke-WebRequest @Params -Form $Form
Write-LogEntry -Message ($Response.Content | Out-String)
}
catch {
Write-LogEntry -Message 'Impossibile importare CSV.'
Write-LogEntry -Message "$($_.Exception.Message)"
exit 1
}
}
else {
$APIURL = "https://$BaseUrl/api/v2/vulnerability/scan-groups/$SGID/upload"
Add-Type -AssemblyName System.Net.Http
$HTTPClient = New-Object System.Net.Http.HttpClient
$HTTPClient.DefaultRequestHeaders.Authorization = New-Object System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", $Token)
# Creare il contenuto multipart form-data
$MPFormData = New-Object System.Net.Http.MultipartFormDataContent
# Aprire il file CSV come flusso e preparare StreamContent
$FileStream = [System.IO.File]::OpenRead($CSV)
$FileName = [System.IO.Path]::GetFileName($CSV)
$StreamContent = New-Object System.Net.Http.StreamContent($FileStream)
$StreamContent.Headers.ContentType = [System.Net.Http.Headers.MediaTypeHeaderValue]::Parse("text/csv")
# Aggiungi il contenuto del file CSV con il nome del campo del modulo "csv"
$MPFormData.Add($StreamContent, "csv", $FileName)
# Pubblica il contenuto multipart e attendi il risultato
$APICall = $HTTPClient.PostAsync($APIURL, $MPFormData)
$APICall.Wait()
$Response = $APICall.Result
# Leggi il contenuto della risposta
$APIResponse = $Response.Content.ReadAsStringAsync()
$APIResponse.Wait()
if (!($Response.IsSuccessStatusCode)) {
Write-LogEntry -Message 'Impossibile importare CSV.'
Write-LogEntry -Message ($APIResponse.Result | Out-String)
$FileStream.Close()
$HTTPClient.Dispose()
exit 1
}
Write-LogEntry -Message ($APIResponse.Result | Out-String)
$FileStream.Close()
$HTTPClient.Dispose()
}
}
function Write-LogEntry {
param (
[Parameter(Mandatory = $true)]
[string]$Message
)
$LogPath = "$PathtoCSVNinjaOneVulnerabiltyImport.log"
$TimeStamp = Get-Date -Format 'yyyy-MM-dd HH:mm:ss'
Add-Content -Path $LogPath -Value "$TimeStamp $Message"
Write-Host "$TimeStamp $Message"
}
## End Function Setup ##
$Token = Get-NinjaToken
if (!(Test-Path $PathtoCSV)) {
Write-LogEntry -Message 'Il percorso inserito per i file CSV non esiste. Uscita.'
exit 1
}
$CSVFiles = Get-ChildItem $PathtoCSV | Where-Object { $_.Extension -eq '.csv' -and $_.Name -match "^$CSVName" }
if (!($CSVFiles)) {
Write-LogEntry -Message 'Nessun file CSV presente da importare. Uscita.'
exit 0
}
foreach ($CSV in $CSVFiles) {
Write-LogEntry -Message "CSV trovato: $($CSV.Name)"
Write-LogEntry -Message "Importazione in ScanGroup $ScanGroupID"
try {
New-VulScanImport -SGID $ScanGroupID -CSV $($CSV.FullName)
}
catch {
Write-LogEntry -Message 'Impossibile importare il file csv.'
Write-LogEntry -Message ($_.Exception.Message)
exit 1
}
$ImportStatus = (Get-VulScanGroups -SGID $ScanGroupID).Status
if (!($ImportStatus)) {
Write-LogEntry -Message 'Impossibile recuperare lo stato dell'importazione, ma l'importazione potrebbe comunque avere esito positivo.'
Write-LogEntry -Message 'Controllare l'interfaccia utente di NinjaOne per lo stato dell'importazione delle vulnerabilità.'
Write-LogEntry -Message 'Aggiunta di UNKNOWN_ al nome del file CSV'
try {
Rename-Item -Path $($CSV.FullName) "UNKNOWN_$($CSV.Name)" -ErrorAction Stop
Write-LogEntry -Message "Rinominato correttamente in UNKNOWN_$($CSV.Name)."
exit 1
}
catch {
Write-LogEntry -Message "Impossibile rinominare CSV."
exit 1
}
}
while ($ImportStatus -ne 'Complete') {
Write-LogEntry -Message "Stato importazione: $ImportStatus"
Start-Sleep 10
$ImportStatus = (Get-VulScanGroups -SGID $ScanGroupID).Status
}
if ($ImportStatus -eq 'Complete' ) {
Write-LogEntry -Message "Stato importazione: $ImportStatus"
Write-LogEntry -Message "Importazione riuscita"
Write-LogEntry -Message "Eliminazione di $($CSV.Name)..."
try {
Remove-Item -Path $($CSV.FullName) -Force -ErrorAction Stop
Write-LogEntry -Message "Eliminazione riuscita."
exit 0
}
catch {
Write-LogEntry -Message "Impossibile eliminare CSV."
exit 1
}
}
else {
Write-LogEntry -Message "Stato importazione: $ImportStatus"
Write-LogEntry -Message "Importazione non riuscita!"
Write-LogEntry -Message "Rinominazione di $($CSV.Name)..."
try {
Rename-Item -Path $($CSV.FullName) "FAILED_$($CSV.Name)" -ErrorAction Stop
Write-LogEntry -Message "Rinominato correttamente in FAILED_$($CSV.Name)."
exit 1
}
catch {
Write-LogEntry -Message "Impossibile rinominare CSV."
exit 1
}
}
}

Risorse aggiuntive

Automatizzazione del processo di importazione delle vulnerabilità

Domande frequenti

Passi successivi