ひょんなことから、次世代ファイアウォール(たとえtcp/udpポート番号が同じでもアプリケーションの識別が可能なFW) の先駆けとして有名なPaloAltoのconfigファイル(XML形式)から、ACLルールだけをCSVファイルにする必要があったので、作ってみました。
方針としては、configのXMLファイルを読み込み、ACLルール(セキュリティポリシールール)を抽出し、書き込みファイルを準備し、 あとは1行1行読み込んだのをCSV形式で書き込んでいきます。
ちょっと工夫が必要なのが、1行のACLルール内で、1つの属性に複数の属性値がある場合。例えば、以下のルールの場合。
送信元:10.0.0.1と10.0.1.2 宛先:192.168.1.1 tcp:80 appli:web-browsing action:allow
"送信元"という属性に属性値が2つあり、(今回の目標はCSVファイルをMS Office Excelで読み込めるようにすることなので)、 これをExcelの1つのセル内に2行で表示させたいと思います。
Excelの仕様では、通常の改行の改行コードはCR+LFなのですが、セル内の改行の改行コードはLFのみのようです。 それに加えて""(ダブルクォーテーション)で囲む必要もあるようです。
PaloAltoのconfigでは1つの属性に複数の属性値がある場合は半角スペースが書かれているようなので、 属性値が複数ありうる場合は、ダブルクォーテーションで囲った上で、半角スペースをLFに変換すればよいわけですね。
というわけで、以下のように実装。
-----------------
"xml2csv.vbs"
-----------------
Option Explicit '各種変数宣言 Dim xmlDoc 'XMLのDomDocumentオブジェクト、元ネタXMLファイル全体を読み込む。 Dim xmlNodeList 'XMLのNodeListオブジェクト、xmlDocからACLルール全体を抽出する。 Dim xmlNode 'XMLのNodeオブジェクト、xmlNodeListからACLルールを1行単位で抽出する。 Dim objFileSys '書き込み用ファイル作成用オブジェクト。 Dim strScriptPath '書き込み用ファイルのPath。今回は""なのでvbs設置箇所に書き込む。 Dim strWriteFile '書き込み用ファイル。 Dim objWriteStream '書き込み用ファイルストリーム。 Dim strText '1行単位で書き込むためのForループ内の仮利用の変数。 '以下はPaloAltoの属性値を読み込む変数。 Dim Pname 'ポリシーネーム Dim Tag 'タグ Dim From '送信元ゾーン Dim ToTo '宛先ゾーン Dim Source '送信元アドレス Dim Dest '宛先アドレス Dim SrcUsr '送信元ユーザ Dim Appli 'アプリケーション Dim Srvc 'サービス(tcp/udpポート) Dim Prfl 'セキュリティプロファイル(AntiVirus等) Dim Action 'アクション(Allow or Deny) 'XMLDOMDocument作成と読み込み Set xmlDoc = WScript.CreateObject("MSXML2.DOMDocument") With xmlDoc .Async = False .Load("running-config.xml") '引数をファイル名として読み込み 'ACLルール全体を取得 Set xmlNodeList = .selectNodes("/config/devices/entry/vsys/entry/rulebase/security/rules/entry") '書き込み用ファイルの準備 Set objFileSys = CreateObject("Scripting.FileSystemObject") strWriteFile = objFileSys.BuildPath(strScriptPath,"WriteData.csv") Set objWriteStream = objFileSys.OpenTextFile(strWriteFile, 2, True) 'ACLルールを1行ずつ抽出し、属性値を対応する変数へ代入 For Each xmlNode In xmlNodeList Pname = xmlNode.selectSingleNode("@name").text Tag = """" & Replace(xmlNode.selectSingleNode("tag").text," ",vbLf) & """" From = """" & Replace(xmlNode.selectSingleNode("from").text," ",vbLf) & """" ToTo = """" & Replace(xmlNode.selectSingleNode("to").text," ",vbLf) & """" Source = """" & Replace(xmlNode.selectSingleNode("source").text," ",vbLf) & """" Dest = """" & Replace(xmlNode.selectSingleNode("destination").text," ",vbLf) & """" SrcUsr = """" & Replace(xmlNode.selectSingleNode("source-user").text," ",vbLf) & """" Appli = """" & Replace(xmlNode.selectSingleNode("application").text," ",vbLf) & """" Srvc = """" & Replace(xmlNode.selectSingleNode("service").text," ",vbLf) & """" 'セキュリティプロファイルは属性値が無い場合もあるため、条件分岐 Set Prfl = xmlNode.selectSingleNode("profile-setting") if not Prfl is Nothing then Prfl = """" & + Replace(xmlNode.selectSingleNode("profile-setting").text," ",vbLf) & """" else Prfl = "" end if Action = xmlNode.selectSingleNode("action").text strText = Pname +","+ Tag +","+ From +","+ ToTo +","+ Source +","+ SrcUsr +","+ Dest +","+ Appli +","+ Srvc +","+ Prfl +","+ Action objWriteStream.WriteLine strText Next End With 'ファイルストリームを閉じる objWriteStream.Close '変数の片づけ Set xmlDoc = Nothing Set xmlNodeList = Nothing Set xmlNode = Nothing Set objFileSys = Nothing Set strScriptPath = Nothing Set strWriteFile = Nothing Set objWriteStream = Nothing Set strText = Nothing Set Pname = Nothing Set Tag = Nothing Set From = Nothing Set ToTo = Nothing Set Source = Nothing Set Dest = Nothing Set SrcUsr = Nothing Set Appli = Nothing Set Srvc = Nothing Set Prfl = Nothing Set Action = Nothing
ちなみに、PaloAltoのXML形式configファイルはこんな感じ。
---running-config.xml---
<config urldb="brightcloud" version="???"> <devices> <entry name="localhost.localdomain"> <vsys> <entry name="vsys1"> <rulebase> <security> <rules> <entry name="ポリシーネーム1"> <tag> <member>タグ1</menber> <member>タグ2</menber> </tag> <from> <member>送信元ゾーン1</member> <member>送信元ゾーン2</member> </from> <to> <member>送信元ゾーン1</member> <member>送信元ゾーン2</member> </to> <source> <member>送信元アドレス1</member> <member>送信元アドレス2</member> </source> <destination> <member>宛先アドレス1</member> <member>宛先アドレス2</member> </destination> <source-user> <member>送信元ゾーン1</member> <member>送信元ゾーン2</member> </source-user> <application> <member>送信元ゾーン1</member> <member>送信元ゾーン2</member> </application> <service> <member>送信元アドレス1</member> <member>送信元アドレス2</member> </service> <action>アクション</action> <profile-setting> <group> <member>セキュリティプロファイルグループ</member> </group> </profile-setting> </entry> <entry name="ポリシーネーム2"> <tag> ~~~~ </entry> </rules> </security> </rulebase> </entry> </vsys> </entry> </devices> </confing>
-----------------
コメント