[Python] FortiAnalyzer XML API




FortiAnalyzer XML API에 대하여 테스트한 내용의 코드를 정리 합니다.

일부 API에 대해서 샘플로 테스트한 내용입니다.


FortiAnalyzer XML API

import requests
import xml.etree.ElementTree as ET
import re
import time

from dateutil.parser import parse
from bs4 import BeautifulSoup
from pprint import pprint
import math
from requests.packages.urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
 
class FortiAnalyzer_API:
    def __init__(self):
        # event
        self.ip = "[Forti Analyzer IP]"
 
        self.userid = "[ID]"
        self.password = "[Password]"
 
        self.log_type = "event"
        self.dlp_archive_type = "web"
         
    def response_data_json_parse(self, split_lists):
        temp_list = []
        temp_word =''
 
        for parse_word in split_lists:
            if parse_word.find("=") == -1:
                temp_list[len(temp_list)-2] = temp_list[len(temp_list)-2] + " " + split_lists[split_lists.index(parse_word)]
 
            else:
                temp_list.append(parse_word)
 
        return temp_list
             
    def searchFazLog(self, log_type, dlp_archive_type, dt_s, dt_e):
        """
        Use this request to provide raw logs in FortiAnalyzer per conditions set in the request. You need to input the log
        format, device name, log type, search criteria, start index, and maximum return value in the request message
        body.
 
        - request :
        <servicePass> XML structure consists of username and password variables.
            <userID> The administrator user name.
            <password> Administrator password options: Enter the administrator password or leave field blank for no password.
        <adom> The ADOMs for which you want to search logs.
        <content> The log contents you want to search. Log content options: logs, contentLogs, and localLogs.
        <format> The log formats to display, either rawFormat, or CSV.
        <deviceName> The device name you want to search logs from.
        <vdom> The VDOM you want to search.
        <logType> Type of logs you want to search. Log type options: event, traffic, attack, antiVirus, webLogs, IM, email, content, history, generic, voIP, DLP, appCtrl, or netScan.
        <searchCriteria> The search criteria used to search logs. For example, vd-root.
        <maxNumMatches> The maximum number of matches to display from the search results.
        <startIndex> The start index of the matched logs.
        <checkArchive> This variable is not used. Always set the value to 0.
        <DLPArchiveType> The DLP archive type. DLP archive type options: web, email, ftp, IM, MMS, quarantine, or IPS.
        <compression> The compression type of the report that will be returned by this command.
 
        - response :
        <errorMsg> Indicates if the request was successful or if it failed. The error message consists of the error code and detail.
        <errorCode> Error code and message details:
            l -101: Invalid username, password, or ADOM. Cannot get device name. Cannot get search criteria. Incorrect DLP archive type.
            l -102: Cannot find device name on system.
            l -104: Cannot find logs with criteria.
            l -106: Not enough memory.
        <errorMsg>
        <totalResultsFound> The total number of logs found.
        <matchesReturned> The total number of logs which matched the search criteria.
        <startIndex> The start index in the request.
        <logs> Log data will be displayed under this element.
        <logEntry> Displays log data.
        """
        
        dt_s = str(math.trunc(time.mktime(parse(dt_s).timetuple())))
        dt_e = str(math.trunc(time.mktime(parse(dt_e).timetuple())))

        print(dt_s, dt_e)
        
        url = "https://" + self.ip + ":8080/FortiAnalyzerWSxml"
 
        headers = {'content-type': 'text/xml'}
 
        data = """
            <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:r20="http://r200806.ws.fmg.fortinet.com/">
               <soapenv:Header/>
               <soapenv:Body>
                  <r20:searchFazLog>
                     <!--Optional:-->
                     <servicePass>
                        <!--Optional:-->
                        <userID>""" + self.userid + """</userID>
                        <!--Optional:-->
                        <password>""" + self.password + """</password>
                     </servicePass>
                     <!--Optional:-->
                     <adom>root</adom>
                     <!--Optional:-->
                     <content>logs</content>
                     <!--Optional:-->
                     <format>rawFormat</format>
                     <!--Optional:-->
                     <deviceName></deviceName>
                     <!--Optional:-->
                     <vdom></vdom>
                     <logType>""" + log_type + """</logType>
                     <!--Optional:-->
                     <searchCriteria><![CDATA[itime>""" + dt_s + """ and itime<""" + dt_e + """ and subtype=vpn and action=tunnel-up and tunnelip=* and tunneltype=ssl-tunnel]]></searchCriteria>
                     <maxNumMatches>1000</maxNumMatches>
                     <startIndex>1</startIndex>
                     <checkArchive>0</checkArchive>
                     <!--Optional:-->
                     <DLPArchiveType>""" + dlp_archive_type + """</DLPArchiveType>
                     <!--Optional:-->
                     <compression>tar</compression>
                  </r20:searchFazLog>
               </soapenv:Body>
            </soapenv:Envelope>
            """
         
        response = requests.post(url, data=data.encode('utf-8'), headers=headers, verify=False)
 
        root = ET.fromstring(response.text)
        soup = BeautifulSoup(response.text)
 
        results = []
         
        for parent in soup.find_all('logentry'):
            split_lists = parent.string.split()
 
            results.append(self.response_data_json_parse(split_lists))
            #return " ".join(self.response_data_json_parse(split_lists))
 
        return results


    def getDeviceList(self):
        """
        
        """
 
        url = "https://" + self.ip + ":8080/FortiAnalyzerWSxml"
 
        headers = {'content-type': 'text/xml'}
 
        data = """
            <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:r20="http://r200806.ws.fmg.fortinet.com/">
               <soapenv:Header/>
               <soapenv:Body>
                  <r20:getDeviceList>
                     <!--Optional:-->
                     <servicePass>
                        <!--Optional:-->
                        <userID>""" + self.userid + """</userID>
                        <!--Optional:-->
                        <password>""" + self.password + """</password>
                     </servicePass>
                     <!--Optional:-->
                     <adom>root</adom>
                     <!--Optional:-->
                     <detail>true</detail>
                  </r20:getDeviceList>
               </soapenv:Body>
            </soapenv:Envelope>
            """
         
        response = requests.post(url, data=data.encode('utf-8'), headers=headers, verify=False)
 
        root = ET.fromstring(response.text)
        soup = BeautifulSoup(response.text)
 
        results = []
        
        for parent in soup.find_all('devicedetail'):
            #print(parent.find('devid').get_text())
            print(parent.get_text("|"))
            #print(parent)
            
            #plit_lists = parent.string.split()
 
            #esults.append(parent)
            #return " ".join(self.response_data_json_parse(split_lists))

        
    def getListFazGeneratedReports(self, keyword=''):
        """

        """
        url = "https://" + self.ip + ":8080/FortiAnalyzerWSxml"

        headers = {'content-type': 'text/xml'}

        data = """
            <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:r20="http://r200806.ws.fmg.fortinet.com/">
               <soapenv:Header/>
               <soapenv:Body>
                  <r20:listFazGeneratedReports>
                     <!--Optional:-->
                     <servicePass>
                        <!--Optional:-->
                        <userID>""" + self.userid + """</userID>
                        <!--Optional:-->
                        <password>""" + self.password + """</password>
                     </servicePass>
                     <!--Optional:-->
                     <adom>root</adom>
                     <!--Optional:-->
                     <startDate></startDate>
                     <!--Optional:-->
                     <endDate></endDate>
                  </r20:listFazGeneratedReports>
               </soapenv:Body>
            </soapenv:Envelope>
            """

        response = requests.post(url, data=data.encode('utf-8'), headers=headers, verify=False)

        root = ET.fromstring(response.text)
        soup = BeautifulSoup(response.text)

        results = []

        # print(soup)

        for parent in soup.find_all('reportlist'):
            # print(parent.find('reportname').get_text())
            
            if(re.search(keyword, parent.find('reportname').get_text())):
                results.append(parent.find('reportname').get_text())
        
        return results

    
    def getFazGeneratedReport(self):
        """

        """
        url = "https://" + self.ip + ":8080/FortiAnalyzerWSxml"

        headers = {'content-type': 'text/xml'}

        data = """
            <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:r20="http://r200806.ws.fmg.fortinet.com/">
               <soapenv:Header/>
               <soapenv:Body>
                  <r20:getFazGeneratedReport>
                     <!--Optional:-->
                     <servicePass>
                        <!--Optional:-->
                        <userID>""" + self.userid + """</userID>
                        <!--Optional:-->
                        <password>""" + self.password + """</password>
                     </servicePass>
                     <!--Optional:-->
                     <adom>root</adom>
                     <!--Optional:-->
                     <reportDate></reportDate>
                     <!--Optional:-->
                     <reportName></reportName>
                     <!--Optional:-->
                     <compression>tar</compression>
                  </r20:getFazGeneratedReport>
               </soapenv:Body>
            </soapenv:Envelope>    
            """

        response = requests.post(url, data=data.encode('utf-8'), headers=headers, verify=False)

        root = ET.fromstring(response.text)
        soup = BeautifulSoup(response.text)

        results = []
        
        # print(soup)
        
        for parent in soup.find_all('fazreportdata'):
            # print(parent.find('reportcontent').get_text())
            
            results.append(parent.find('reportcontent').get_text())
        
        return results

사용

api_con = FortiAnalyzer_API()
data = api_con.searchFazLog_sslvpn_logon('event', 'web', '2022-08-16 00:00:00', '2022-08-16 23:59:59')



Leave a Comment