Powershell icingaweb2 login not work

Hello. i am trying to connect to icingaweb2 via powershell script but i can’t get csrfToken. What am I doing wrong please?

I created the script based on network traffic tracing in firefox.

We currently do not have an operational API and I don’t know if we ever will. Likewise, our ICT department does not want to allow login via certificate.

So I wanted to initiate a classic connection via https PUSH and GET queries in powershell and then parse the returned HTML code. But I can’t do that. I’m done when logging in.

How to proceed correctly (in powershell) connecting to the website? What am i doing wrong in the script?

The mentioned script only works if I create an active session in firefox and thus the corresponding token. After I log out in firefox, the powershell script also stops working.

I have to add a new token to it, possibly other information, so that everything starts working again. But again only until the session expires.

$dnsName   = "icinga2.mySite.com"
$baseUri   = "https://" + $dnsName
$logonUri  = $baseURI + "/icingaweb2/authentication/login"
$dataUri   = $baseURI + "/icingaweb2/monitoring/list/services?sort=service_state&dir=desc&service_state%3E0&limit=500&showCompact=1"
$uName     = "myUserName"
$uPwd      = "myPassword"
#$csrfToken = "myToken"


$session = New-Object Microsoft.PowerShell.Commands.WebRequestSession
$session.Cookies.Add((New-Object System.Net.Cookie("_chc", "1", "/", "$($dnsName)")))
$session.Cookies.Add((New-Object System.Net.Cookie("icingaweb2-session", "1721822041", "/", "$($dnsName)")))
$session.Cookies.Add((New-Object System.Net.Cookie("Icingaweb2", "mmlmngu2ncr4u94ncbboe3hka9", "/", "$($dnsName)")))
$session.Cookies.Add((New-Object System.Net.Cookie("icingaweb2-tzo", "7200-1", "/", "$($dnsName)")))
Invoke-WebRequest -UseBasicParsing -Uri "$($logonUri)" `
-Method POST `
-WebSession $session `
-UserAgent "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:128.0) Gecko/20100101 Firefox/128.0" `
-Headers @{
"Accept" = "*/*"
  "Accept-Language" = "cs,sk;q=0.8,en-US;q=0.5,en;q=0.3"
  "Accept-Encoding" = "gzip, deflate, br, zstd"
  "X-Icinga-Accept" = "text/html"
  "X-Icinga-Container" = "layout"
  "X-Icinga-WindowId" = "qboktawylfrj"
  "X-Requested-With" = "XMLHttpRequest"
  "Origin" = "$($baseUri)"
  "Referer" = "$($logonUri)"
  "Sec-Fetch-Dest" = "empty"
  "Sec-Fetch-Mode" = "cors"
  "Sec-Fetch-Site" = "same-origin"
  "Priority" = "u=0"
} `
-ContentType "application/x-www-form-urlencoded; charset=UTF-8" `
-Body "username=$($uName)&password=$($uPwd)&rememberme=0&redirect=&formUID=form_login&CSRFToken=655133125%7C52db29ddf2b7ec477253aa787e791b6da2163c4d8382e852988d1bcd40a482be&btn_submit=Login"




$session = New-Object Microsoft.PowerShell.Commands.WebRequestSession
$session.Cookies.Add((New-Object System.Net.Cookie("icingaweb2-session", "1721823545", "/", "$($dnsName)")))
$session.Cookies.Add((New-Object System.Net.Cookie("Icingaweb2", "5s2f849efld37coa0fgbpcimms", "/", "$($dnsName)")))
$session.Cookies.Add((New-Object System.Net.Cookie("icingaweb2-tzo", "7200-1", "/", "$($dnsName)")))
$result = Invoke-WebRequest -UseBasicParsing -Uri "$($dataUri)" `
-WebSession $session `
-UserAgent "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:128.0) Gecko/20100101 Firefox/128.0" `
-Headers @{
"Accept" = "*/*"
  "Accept-Language" = "cs,sk;q=0.8,en-US;q=0.5,en;q=0.3"
  "Accept-Encoding" = "gzip, deflate, br, zstd"
  "X-Icinga-Accept" = "text/html"
  "X-Icinga-Container" = "ciu_1"
  "X-Icinga-WindowId" = "qboktawylfrj"
  "X-Requested-With" = "XMLHttpRequest"
  "Referer" = "$($baseUri)/icingaweb2/dashboard"
  "Sec-Fetch-Dest" = "empty"
  "Sec-Fetch-Mode" = "cors"
  "Sec-Fetch-Site" = "same-origin"
} `
-ContentType "application/x-www-form-urlencoded; charset=UTF-8"


$result.rawcontent
$result.rawcontent | out-file K:\ZakInst\_InstPws\_upgradePws\icinga18.data.html


Hi @devMydlar,
Sorry if I am sidetracking here, but what are you intending to do in the end?
If it is something like triggering a check or scheduling a downtime it would be far easier to use the Icinga 2 HTTP API directly.

If you really need/want to programm against Icingaweb2, you can probably get further by setting the Accept: Application/json Header to address the API instead of the “real” webinterface.

1 Like

Hi.
I need to make something like a very simple nagstamon. Load all warning events and then work with them further in powershell. For example, to remind (by email) a worker who solves events in icinga that he already has two hours / two days of unsolved warning etc…

The Rest API is great, but in the examples there is login via certificate. Is it possible without a certificate, only with user and password? Is there an example somewhere?
I don’t have the API enabled yet. I won’t get into it at this time.

You can define an ApiUser like this which allows either client certificate or username/password, which which you could then query Icinga 2 objects like Services, including the current state.

2 Likes

Super… it works

$icingaApiHost     = "yourwebsite"
$IcingaApiPort     = 5665
$icingaApiUser     = "yourusername"
$requestUrl = "https://{0}:{1}/v1/objects/services" -f $icingaApiHost,$IcingaApiPort

$attrs =  @( "name", "state", "last_check_result", "last_state_change", "downtime_depth", "acknowledgement")
$joins = @( "host.name", "host.state", "host.last_check_result")
#$filter = 'service.state==2 || host.name=="dbmycash"'
$filter = 'service.state==1 || service.state==2 || host.state==1 || host.state==2'


$SecPass = read-host "Insert password" -AsSecureString

# Put the certificate from your master (/etc/icinga2/pki/*.crt) here.
# You will get it with "openssl s_client -connect <master>:5665" too.

$cert64 = @"
-----BEGIN CERTIFICATE-----
yourcert
-----END CERTIFICATE-----
"@


# register callback for comparing the certificate
function set-SSLCertificate {
    param(
        $Cert
    )

    if (-not("validateCert" -as [type])) {
        add-type -TypeDefinition @"
            using System.Net.Security;
            using System.Security.Cryptography.X509Certificates;

            public static class ValidateCert {
                static X509Certificate2 MyCert;

                public static bool Validate(object sender,
                    X509Certificate cert,
                    X509Chain chain,
                    SslPolicyErrors sslPolicyErrors) {
                        if (MyCert.Equals(cert)) {
                            return true;
                        } else {
                            return false;
                        }
                }

                public static RemoteCertificateValidationCallback GetDelegate(X509Certificate2 Cert) {
                    MyCert = Cert;
                    return new RemoteCertificateValidationCallback(ValidateCert.Validate);
                }
            }
"@
    }
    [System.Net.ServicePointManager]::ServerCertificateValidationCallback = [validateCert]::GetDelegate($Cert)
}

# convert base64 based certificate to X509 certificate
function get-x509 {
    param(
        [string]
            $Cert64
    )

    $CertBin=[System.Convert]::FromBase64String(($Cert64.Trim(" ") -replace "-.*-",""))

    [System.Security.Cryptography.X509Certificates.X509Certificate2]$CertBin
}


# Allow TLS 1.2. Old powershell (.net) uses TLS 1.0 only. Icinga2 >2.10 needs TLS 1.2
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]'Ssl3,Tls,Tls11,Tls12'


$Cred = New-Object System.Management.Automation.PSCredential($icingaApiUser, $SecPass)

$Cert = get-x509 $Cert64
set-SSLCertificate $Cert

$httpHeaders = @{
    "X-HTTP-Method-Override" = "GET"
    "accept"                 = "application/json"
}


$data = @{
    "attrs" = $attrs
    "joins" = $joins
    "filter" = $filter
}

$result = Invoke-RestMethod -Uri $requestUrl -Method "POST" -Body (ConvertTo-Json -InputObject $data)  -Credential $Cred -ContentType "application/json" -Headers $httpHeaders

$icItemList = @()

foreach ($s in $result.results) 
{
<#
    Write-Host "****************************************"
    Write-Host "Host:         " $s.joins.host.name
    Write-Host "Host state:   " $s.joins.host.state
    Write-Host "Service:      " $s.attrs.name
    Write-HOst "Service State:" $s.attrs.state
    Write-Host "Output:       " $s.attrs.last_check_result.output
    Write-Host ""
    # Debug
    Write-Host "Debug: Attributes " $s.attrs | ConvertTo-Json
    Write-Host "Debug: Joins Host" $s.joins.host | ConvertTo-Json
    Write-Host "`n"
#>


    Function get-eventDuration ($UnixDate)
    {
        [datetime]$startDate = [dateTime]$myDateTime = [timezone]::CurrentTimeZone.ToLocalTime(([datetime]'1/1/1970').AddSeconds($UnixDate))
        $endDate = (get-date)
        new-timespan –Start $startDate –End $endDate
    }

    [dateTime]$startDate = [dateTime]$myDateTime = [timezone]::CurrentTimeZone.ToLocalTime(([datetime]'1/1/1970').AddSeconds($s.attrs.last_state_change))
    $endDate = (get-date)
    $tmpDuration = new-timeSpan –Start $startDate –End $endDate
    
    $originalDuration = new-timeSpan -days $tmpDuration.days -hours $tmpDuration.hours -minutes $tmpDuration.minutes -seconds $tmpDuration.seconds

    if($originalDuration.days -gt 0)
    {
        $duration     = $("{0}d{1}h" -f $tmpDuration.days, $tmpDuration.hours)
    }
    elseif($originalDuration.hours -gt 0)
    {
        $duration     = $("{0}h{1}m" -f $tmpDuration.hours, $tmpDuration.minutes)
    }
    elseif($originalDuration.minutes -gt 0)
    {
        $duration     = $("{0}m" -f $tmpDuration.minutes)
    }
    else
    {
        $duration     = $("{0,2}s" -f $tmpDuration.seconds)
    }
 
    

    $icItem = [PSCustomObject]@{
        host             = $s.joins.host.name
        hostState        = $s.joins.host.state
        service          = $s.attrs.name
        serviceState     = $s.attrs.state
        serviceInfo      = $s.attrs.last_check_result.output
        originalDuration = $originalDuration
        duration         = $duration
        downtimes        = $s.joins.downtimes
        comments         = $s.joins.downtimes.comment
        down             = $s.attrs.downtime_depth
        ack              = $s.attrs.acknowledgement
    }
    $icItemList += $icItem
    $icItem = $null
}



$icItemList | Sort-Object -property @{Expression="serviceState"; Descending=$true}, @{Expression="host"; Descending=$false} | Format-Table -property down, ack, originalDuration, duration, host, hostState, service, serviceState, serviceInfo, downtimes, comments -autosize

1 Like