Interface IP per REST API ermitteln

Die REST-API der Fortigate bietet viele Möglichkeiten, um Systemeigenschaften abzufragen und auch zu konfigurieren. Leider ist die Dokumentation sehr lückenhaft, bzw. man muss im Fortinet Developer Network registriert sein – ohne 2 Sponsoren von Fortinet kann man sich aber leider nicht registrieren.

Um Azure DNS Records dynamisch zu aktualisieren habe ich bereits einen Beitrag erstellt, allerdings wollte ich die Ermittlung der WAN IP direkt an der Fortigate machen und habe mich deshalb auf die Suche nach Möglichkeiten der REST-API gemacht. Herausgekommen ist das unten folgende Script.

In diesem Beispiel möchte ich die IP des WAN1 Interfaces ausgeben und in eine Variable umleiten.

$fgtAddress = "<Fortigate Hostname/IP>:<Port>"
$postParams = @{username='<Admin-User>';secretkey='<Admin-User Password>'}
$fgtInterface = "wan1"
$request = Invoke-WebRequest -Headers $headers -Uri "https://$fgtAddress/logincheck" -SessionVariable fgtSession -Method POST -Body $postParams
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add('Accept','application/json')
$headers.Add('Content-Type','application/json')
$request = Invoke-WebRequest -Headers $headers -Uri "https://$fgtAddress/api/v2/monitor/system/interface/?interface_name=$fgtInterface" -WebSession $fgtSession -Method GET
$interface = $request.Content | ConvertFrom-Json
$ip = $interface.results.$fgtInterface.ip

Hinweis:
Obwohl es auf der Fortigate die Möglichkeit gibt, einen REST Admin anzulegen – was ja suggeriert, dass dieser für REST API Zugriffe genutzt werden kann – funktioniert dieser NICHT mit dem obigen Script. Es muss hierfür ein regulärer Firewall Admin Account verwendet werden.

Update 27.06.2023

Nachdem ich die o.g. Funktion mal wieder habe aufleben lassen, konnte ich feststellen, dass das Ganze inzwischen bei meiner Fortigate mit FortiOS 7.2 glücklicherweise auch mit einem API User funktioniert (ob’s auch schon mit älteren Versionen geht, möchte ich nicht mehr ausprobieren). Im Gegensatz zu einem normalen User wird hierbei nicht die /api/v2/monitor Bereich verwendet, sondern der /api/v2/cmdb Bereich. Zudem ist der Code etwas kürzer.

$fgtAddress = "<Fortigate Hostname/IP>:<Port>"
$fgtApiToken = "<API-Token>"
$fgtWanInterface = "<WAN-Interface-Name>
$interface = Invoke-RestMethod "https://$fgtAddress/api/v2/cmdb/system/interface/$fgtWanInterface/?access_token="$fgtApiToken" | Select-Object -ExpandProperty results
$ipMask = $interface.ip
$ip = $ipMask.Split()[0]
Besonderheiten / Fehler

Während meiner Tests bin ich auf folgende Fehler gestoßen, die je nach Konfiguration der Fortigate auftreten können.

Fehlermeldung 1

Invoke-WebRequest : The request was aborted: Could not create SSL/TLS secure channel.

Die Ursache hierfür ist in der Regel, dass die PowerShell Session noch ältere Protokolle verwendet, die auf der Fortigate schon abgeschaltet sind (z.B. TLS 1.0). Daher muss im Fehlerfall das Script mit folgenden beiden Befehlen begonnen werden (in diesem Beispiel wird nur TLS 1.1 und TLS 1.2 eingestellt):

$AllProtocols = [System.Net.SecurityProtocolType]'Tls11,Tls12'
[System.Net.ServicePointManager]::SecurityProtocol = $AllProtocols

Fehlermeldung 2

Invoke-WebRequest : The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel.

Der Fehler tritt auf, wenn die HTTPS Verbindung über ein Self-Signed Zertifikat verschlüsselt ist. Lösen lässt sich das, indem die Zertifikatsprüfung in der PowerShell-Session deaktiviert wird. Auch dies muss an den Anfang des Scripts nach den Zeilen zur Lösung von Fehlermeldung 1.

if (-not ([System.Management.Automation.PSTypeName]'ServerCertificateValidationCallback').Type)
{
$certCallback = @"
  using System;
  using System.Net;
  using System.Net.Security;
  using System.Security.Cryptography.X509Certificates;
  public class ServerCertificateValidationCallback
  {
    public static void Ignore()
    {
      if(ServicePointManager.ServerCertificateValidationCallback ==null)
      {
        ServicePointManager.ServerCertificateValidationCallback += 
          delegate
          (
            Object obj, 
            X509Certificate certificate, 
            X509Chain chain, 
            SslPolicyErrors errors
          )
          {
            return true;
          };
      }
    }
  }
"@
  Add-Type $certCallback
}
[ServerCertificateValidationCallback]::Ignore()

Alternativ lassen sich Self-signed Zertifikate auch über folgende Funktion ignorieren:

function Unblock-SelfSignedCerts
{
  try
  {
    Write-Host "Adding TrustAllCertsPolicy type." -ForegroundColor White
    Add-Type -TypeDefinition @"
    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;
      }
    }
"@
    Write-Host "TrustAllCertsPolicy type added." -ForegroundColor White
  }
  catch
  {
    Write-Host $_ -ForegroundColor "Yellow"
  }
  [System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy
}
Unblock-SelfSignedCerts

Das komplette Script inkl. Protokollanpassung, deaktivierter Zertifikatsvalidierung und variabler Daten findet ihr hier.

Weiterführende Links:
https://github.com/fortinet-solutions-cse/fortiosapi

Quellen:
https://docs.datacore.com/RESTSupport-WebHelp/using_windows_powershell_as_a_rest_client.htm

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.