188 lines
5.1 KiB
PowerShell
188 lines
5.1 KiB
PowerShell
# POLISH LANGUAGE
|
|
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
|
chcp 65001 | Out-Null
|
|
|
|
# LOG
|
|
$logDir = Join-Path $env:ProgramData "PSITAgent"
|
|
$logPath = Join-Path $logDir "assets.log"
|
|
|
|
function Write-Log {
|
|
param([string]$Message, [string]$Level = "INFO")
|
|
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
|
|
Write-Host $Message
|
|
try {
|
|
if (-not (Test-Path $logDir)) { New-Item -ItemType Directory -Path $logDir -Force | Out-Null }
|
|
if ((Test-Path $logPath) -and (Get-Item $logPath).Length -gt 1MB) {
|
|
Move-Item -Path $logPath -Destination (Join-Path $logDir "assets.log.bak") -Force
|
|
}
|
|
Add-Content -Path $logPath -Value "[$timestamp] [$Level] $Message" -Encoding UTF8
|
|
} catch { }
|
|
}
|
|
|
|
# LOAD CONFIG
|
|
$configPath = Join-Path $PSScriptRoot "config.json"
|
|
$config = Get-Content $configPath -Raw | ConvertFrom-Json
|
|
|
|
$apiUrl = $config."snipe-it".url.TrimEnd('/')
|
|
$apiKey = $config."snipe-it".apikey
|
|
$verifySSL = $config."snipe-it"."verify-ssl"
|
|
|
|
# SSL (opcjonalne - self-signed cert wewnetrznego Snipe-IT)
|
|
if (-not $verifySSL) {
|
|
add-type @"
|
|
using System.Net;
|
|
using System.Security.Cryptography.X509Certificates;
|
|
public class TrustAllCertsPolicy : ICertificatePolicy {
|
|
public bool CheckValidationResult(
|
|
ServicePoint srvPoint, X509Certificate certificate,
|
|
WebRequest request, int certificateProblem) {
|
|
return true;
|
|
}
|
|
}
|
|
"@
|
|
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy
|
|
}
|
|
|
|
# HEADERS
|
|
$headers = @{
|
|
"Authorization" = "Bearer $apiKey"
|
|
"Accept" = "application/json"
|
|
"Content-Type" = "application/json"
|
|
}
|
|
|
|
# GET SEARCH VALUE
|
|
try {
|
|
$searchValue = Invoke-Expression $config."search-term".value
|
|
} catch {
|
|
Write-Log "Blad pobierania wartosci wyszukiwania (search-term)" "ERROR"
|
|
exit 1
|
|
}
|
|
|
|
if (-not $searchValue) {
|
|
Write-Log "Nie udalo sie uzyskac wartosci wyszukiwania" "ERROR"
|
|
exit 1
|
|
}
|
|
|
|
Write-Log "======== Wyszukiwanie assetu ========"
|
|
Write-Log "Szukana wartosc: $searchValue"
|
|
|
|
# FIND ASSET
|
|
$searchUrl = "$apiUrl/hardware?search=$searchValue"
|
|
|
|
try {
|
|
$response = Invoke-RestMethod -Uri $searchUrl -Headers $headers -Method GET
|
|
} catch {
|
|
Write-Log "Blad komunikacji z API Snipe-IT (wyszukiwanie)" "ERROR"
|
|
exit 1
|
|
}
|
|
|
|
if ($response.total -eq 0) {
|
|
Write-Log "Nie znaleziono assetu w Snipe-IT" "ERROR"
|
|
exit 0
|
|
}
|
|
|
|
# WERYFIKACJA DOPASOWANIA
|
|
$searchType = $config."search-term".type
|
|
$matched = $response.rows | Where-Object { "$($_.($searchType))".Trim() -eq "$searchValue".Trim() }
|
|
$matchCount = ($matched | Measure-Object).Count
|
|
|
|
if ($matchCount -eq 0) {
|
|
Write-Log "Brak dokladnego dopasowania assetu ($searchType = $searchValue)" "ERROR"
|
|
exit 1
|
|
}
|
|
if ($matchCount -gt 1) {
|
|
Write-Log "Znaleziono wiecej niz jeden pasujacy asset ($searchType = $searchValue) - przerwano aktualizacje" "ERROR"
|
|
exit 1
|
|
}
|
|
|
|
$assetId = $matched[0].id
|
|
Write-Log "ID assetu: $assetId"
|
|
|
|
# COLLECT DATA
|
|
$customFields = @{}
|
|
|
|
foreach ($field in $config.fields.custom_fields.PSObject.Properties) {
|
|
|
|
$key = $field.Name
|
|
$fieldConfig = $field.Value
|
|
|
|
if (-not $fieldConfig.enabled) {
|
|
continue
|
|
}
|
|
|
|
try {
|
|
$value = Invoke-Expression $fieldConfig.ps_command
|
|
if ($value -is [int] -or $value -is [double]) {
|
|
$finalValue = $value
|
|
} else {
|
|
$finalValue = "$value"
|
|
}
|
|
$customFields[$key] = $finalValue
|
|
|
|
} catch {
|
|
Write-Log "Blad odczytu pola: $key" "ERROR"
|
|
}
|
|
}
|
|
|
|
# MINIMALIZACJA RUCHU API - POROWNANIE Z OSTATNIO WYSLANYMI WARTOSCIAMI
|
|
$cachePath = Join-Path $logDir "last_sent.json"
|
|
$previous = @{}
|
|
|
|
if (Test-Path $cachePath) {
|
|
try {
|
|
$obj = Get-Content $cachePath -Raw | ConvertFrom-Json
|
|
foreach ($p in $obj.PSObject.Properties) { $previous[$p.Name] = $p.Value }
|
|
} catch {
|
|
$previous = @{}
|
|
}
|
|
}
|
|
|
|
$changedFields = @{}
|
|
foreach ($key in $customFields.Keys) {
|
|
if (-not $previous.ContainsKey($key) -or "$($previous[$key])" -ne "$($customFields[$key])") {
|
|
$changedFields[$key] = $customFields[$key]
|
|
}
|
|
}
|
|
|
|
if ($changedFields.Count -eq 0) {
|
|
Write-Log "Brak zmian danych - pominieto aktualizacje API"
|
|
exit 0
|
|
}
|
|
|
|
# PREVIEW
|
|
Write-Log "=== Podglad zmienionych danych ==="
|
|
|
|
foreach ($field in $config.fields.custom_fields.PSObject.Properties) {
|
|
|
|
$key = $field.Name
|
|
$fieldConfig = $field.Value
|
|
|
|
if ($changedFields.ContainsKey($key)) {
|
|
$name = if ($fieldConfig.name) { $fieldConfig.name } else { $key }
|
|
$value = $changedFields[$key]
|
|
$namePadded = $name.PadRight(20)
|
|
Write-Log "- $namePadded : $value"
|
|
}
|
|
}
|
|
|
|
# BUILD BODY
|
|
$body = $changedFields | ConvertTo-Json -Depth 5
|
|
|
|
# UPDATE ASSET
|
|
$updateUrl = "$apiUrl/hardware/$assetId"
|
|
|
|
Write-Log "======== Aktualizacja assetu ========"
|
|
|
|
try {
|
|
Invoke-RestMethod -Uri $updateUrl -Headers $headers -Method PATCH -Body $body | Out-Null
|
|
Write-Log "Aktualizacja Snipe-IT zakonczona powodzeniem"
|
|
} catch {
|
|
Write-Log "Blad aktualizacji assetu ID: $assetId - $($_.Exception.Message)" "ERROR"
|
|
exit 1
|
|
}
|
|
|
|
foreach ($key in $changedFields.Keys) {
|
|
$previous[$key] = $changedFields[$key]
|
|
}
|
|
$previous | ConvertTo-Json -Depth 5 | Set-Content -Path $cachePath -Encoding UTF8
|