Script de déploiement PowerShell pour des agents Zabbix avec PSK

zabbix logo

Le script ci-dessous permet de déployer un agent sur une station Windows. La Communication entre l’agent et le serveur Zabbix est sécurisé au moyen d’une PSK généré dynamiquement au sein du script. L’agent est automatiquement enregistré sur Zabbix et sa configuration est mise à jour vers PSK après son inscription en utilisant l’API native de Zabbix.

Le script va chercher sur un serveur distant l’ensemble des fichiers utile au déploiement d’un agent Zabbix sous Windows, puis les copie dans C:\zabbix.

Dans le dossier C:\zabbix on va retrouver également la lib openssl pour générer les PSK, il est requis d’ajouter les deux DDL lors de la copie.

En vert les éléments indispensables pour openssl, le reste sont les composants classiques de l’agent Zabbix.

En fin de Script on modifie les ACL NTFS afin de sécuriser l’accès au répertoire contenant la PSK ainsi que l’agent Zabbix.

#Suppression du service en cas de besoin
#$service = Get-WmiObject -Class Win32_Service -Filter "Name='Zabbix Agent'"
#$service.delete()
set-executionpolicy remotesigned
Import-Module NTFSSecurity


$Source = "\\srv-maindc\deploiement$\zabbix"
$Target = "C:"
$PersonnelPathRoot = "C:\zabbix"

#test afin de savoir si le service de l'agent zabbix est deja installé
If (get-service -Name "Zabbix Agent" -ErrorAction SilentlyContinue | Where-Object -Property Status -eq "Started")
{
    Exit
}
Elseif (get-service -Name "Zabbix Agent" -ErrorAction SilentlyContinue | Where-Object -Property Status -eq "Stopped")
{
    Start-Service "Zabbix Agent"
    Exit    
} else{
    echo "Agent Zabbix non présent début d'installation"
    Copy-Item -Recurse -Path $Source -Destination $Target -ErrorAction SilentlyContinue
    Start-Sleep -s 2
    if ( Test-Path "C:\zabbix" ) {
        #Installation Zabbix en service
        C:\zabbix\zabbix_agentd.exe --config C:\zabbix\zabbix_agentd.conf --install 2>&1 | out-null
        Start-Sleep -s 2
        #Je démarre le service pour que mon host s'enregistre du Zabbix(actif)
        C:\zabbix\zabbix_agentd.exe --config C:\zabbix\zabbix_agentd.conf --start 2>&1 | out-null
        #je coupe le service pour modifier la configuration
        Start-Sleep -s 2
        C:\zabbix\zabbix_agentd.exe --config C:\zabbix\zabbix_agentd.conf --stop 2>&1 | out-null

        #Génère la clef PSK de l'host avec son nom machine.psk
        $mypsk = C:\zabbix\openssl.exe rand -hex 32
        echo $mypsk > "C:\zabbix\$env:computername.txt"
         #suppression du utf BOM
        $orcFile = "C:\zabbix\$env:computername.txt"
        (Get-Content $orcFile) |
        Foreach-Object {$_ -replace "\xEF\xBB\xBF", ""} |
        Set-Content $orcFile
        #(Get-Content -path "C:\zabbix\$env:computername.txt") | Set-Content -Encoding UTF8 -Path "C:\zabbix\$env:computername.txt"
        #(Get-Content "C:\zabbix\$env:computername.txt") | Out-FileUtf8NoBom "C:\zabbix\$env:computername.txt"

    } else {
        Write-Host "Fail Copy check sources"
        Exit
    }
}
#A cette instant, le service Zabbix est installé avec une configuration sans chiffrement
#On doit à présent modifier le fichier de configuration afin que celui-ci soit chiffré en PSK, puis update le serveur.

#Liste des modifications :
#                 #TLSConnect=psk -> TLSConnect=psk
#                 #TLSAccept=psk -> TLSAccept=psk
#                 #TLSPSKIdentity=PSK 001 -> TLSPSKIdentity=PSK 001
#                 #TLSPSKFile=/etc/zabbix/zabbix_agentd.psk -> TLSPSKFile=/etc/zabbix/zabbix_agentd.psk

#Pour modifier avec le script le fichier de configuration, je dois generer un nombre aleatoire pour lid psk
$CurrentRandom = Get-Random -minimum 1 -maximum 99999
$FinalePSKId = "PSK $CurrentRandom"

(Get-Content C:\zabbix\zabbix_agentd.conf).replace('#TLSConnect=psk', 'TLSConnect=psk') | Set-Content C:\zabbix\zabbix_agentd.conf
(Get-Content C:\zabbix\zabbix_agentd.conf).replace('#TLSAccept=psk', 'TLSAccept=psk') | Set-Content C:\zabbix\zabbix_agentd.conf
(Get-Content C:\zabbix\zabbix_agentd.conf).replace('#TLSPSKIdentity=PSK 002', "TLSPSKIdentity=$FinalePSKId") | Set-Content C:\zabbix\zabbix_agentd.conf
(Get-Content C:\zabbix\zabbix_agentd.conf).replace('#TLSPSKFile=', "TLSPSKFile=C:\zabbix\$env:computername.txt") | Set-Content C:\zabbix\zabbix_agentd.conf

#A ce stade, lhost a la configuration requise, je dois à present update la configuration de lhost dans le CMS
#Je vais donc récupérer l'ID de l'host nouvellement enregistré
#Pour cela je dois recupérer la liste des hosts sur Zabbix, puis je compare dans la boucle l'host courant

if(!$credential){
    $credential = Get-Credential
}
$baseurl = 'http://mondomaine.laintimes.com'
$params = @{
    body =  @{
        "jsonrpc"= "2.0"
        "method"= "user.login"
        "params"= @{
            "user"= $credential.UserName
            "password"= $credential.GetNetworkCredential().Password
        }
        "id"= 1
        "auth"= $null
    } | ConvertTo-Json
    uri = "$baseurl/api_jsonrpc.php"
    headers = @{"Content-Type" = "application/json"}
    method = "Post"
}

$result = Invoke-WebRequest @params



$params.body = @{
    "jsonrpc"= "2.0"
    "method"= "host.get"
    "params"= @{
        output = "extend"
        selectFunctions = "extend"
        selectLastEvent = "extend"
        selectGroups = "extend"
        selectHosts = "extend"
    }
    auth = ($result.Content | ConvertFrom-Json).result
    id = 2
} | ConvertTo-Json


$result = Invoke-WebRequest @params
$result = $result.Content | ConvertFrom-Json

ForEach ($cluster in $result.result) {
    $CurrentName = $cluster.name
    $CurrentHostId = $cluster.hostid
    #$env:computername
    IF ($CurrentName.Equals($env:computername)){
        Write-Host "$env:computername match Id : "$CurrentHostId
        $FinaleHostId = $CurrentHostId
        $FinaleHostname = $env:computername  
    }
}
$CurrentPsk = Get-Content "C:\zabbix\$env:computername.txt" -First 1
#A ce stade $FinaleHostId et $FinaleHostname sont renseigné, je peux faire un update
Write-Host "On va Update lhost : $FinaleHostname avec comme id : $FinaleHostId"
Write-Host "PSK : $CurrentPsk"

$params = @{
    body =  @{
        "jsonrpc"= "2.0"
        "method"= "user.login"
        "params"= @{
            "user"= $credential.UserName
            "password"= $credential.GetNetworkCredential().Password
        }
        "id"= 1
        "auth"= $null
    } | ConvertTo-Json
    uri = "$baseurl/api_jsonrpc.php"
    headers = @{"Content-Type" = "application/json"}
    method = "Post"
}

$result = Invoke-WebRequest @params

$params.body = @{
    "jsonrpc"= "2.0"
    "method"= "host.update"
    "params"= @{
        hostid = "$FinaleHostId"
        tls_connect = "2"
        tls_accept = "2"
        tls_psk_identity = "$FinalePSKId"
        tls_psk = "$CurrentPsk"
    }
    auth = ($result.Content | ConvertFrom-Json).result
    id = 2
} | ConvertTo-Json

$result = Invoke-WebRequest @params
$result = $result.Content | ConvertFrom-Json

#La configuration est achevé, je modifie les droits sur le dossier des sources afin d'en verouiller lacc
    # Desactiver l'heritage tout en copiant les autorisations NTFS héritées
    Get-Item "$PersonnelPathRoot" | Disable-NTFSAccessInheritance
    # Ajout des autorisations NTFS pour admins de domaine et compte système
    Add-NTFSAccess –Path "$PersonnelPathRoot"  –Account "Admins du domaine" –AccessRights FullControl
    Add-NTFSAccess –Path "$PersonnelPathRoot"  –Account "Système" –AccessRights FullControl
    # Passe Admins du domaine en proprietaire
    Set-NTFSOwner -Path "$PersonnelPathRoot" -Account "Admins du domaine"
    # Supprimer des autorisations NTFS
    Remove-NTFSAccess –Path "$PersonnelPathRoot"  –Account "Utilisateurs" -AccessRights FullControl
    #Remove-NTFSAccess –Path "$PersonnelPathRoot"  –Account "Administrateurs" -AccessRights FullControl
    Remove-NTFSAccess –Path "$PersonnelPathRoot"  –Account "Utilisateurs authentifiés" -AccessRights FullControl

C:\zabbix\zabbix_agentd.exe --config C:\zabbix\zabbix_agentd.conf --stop 2>&1 | out-null
Start-Sleep -s 2
C:\zabbix\zabbix_agentd.exe --config C:\zabbix\zabbix_agentd.conf --start 2>&1 | out-null

Laisser un commentaire