bbz

パラメータシート

_
previous | next | edit
1: Sat Dec 7 11:23:43 2019
configからパラメータシートを作りたい。
3: Sat Dec 7 11:28:10 2019
たとえばfortigateのポリシーは以下のようなconfigだ。

config firewall policy
edit 1
set name "policy010"
set uuid ead546ac-1898-51ea-34fa-8a43c83cc7c2
set srcintf "internal1"
set dstintf "wan1"
set srcaddr "192.168.1.0/24"
set dstaddr "100.0.0.1/32"
set action accept
set schedule "always"
set service "ALL_ICMP" "HTTP" "HTTPS"
set nat enable
next
end
4: Sat Dec 7 11:32:47 2019
設定したポリシーの分だけ、edit 番号 が続く。

パラメータシートには、ポリシーは表形式にし、
最初の行に項目名を記載し、
その下にポリシーの内容を記載していく。

たとえば

id | name | src if | dst if | srcaddr | dstaddr | action | schedule | service | nat
1 | policy010 | internal1 | wan1 | 192.168.1.0/24 | 100.0.0.1/32 | accept | always | ALL_ICMP HTTP HTTPS | enable
2 | policy020 | internal1 | wan1 | 192.168.2.0/24 | 200.0.0.1/32 | accept | always | FTP | enable
3 | policy030 | internal1 | wan1 | any | 100.0.0.1/32 | deny | always | ALL |

みたいな感じ
5: Sat Dec 7 11:57:46 2019
私がconfigからパラメータシートを作るときは、だいたい以下のようにする。

configからpolicyの部分を抜き出す。
改行を削除する(1行になる)
edit を \nedit で置換する(1ポリシー1行になる)
エクセルに張り付けてスペースで区切る
項目をそろえる
項目名を見出しに移動する...
6: Sat Dec 7 12:01:46 2019
何度もやっているので、これは自動化できるだろうと感じている。

今考えているのは

ポリシークラスを作り、設定可能な項目をすべて属性として定義する。
configを読んで、edit IDが出てきたらそのidでオブジェクトを作り、
set xxxx yyyy が出てきたら、xxxxという属性にyyyyという値をセットする。

configを読み終えたら、すべてのポリシーオブジェクトの属性を印刷する。

最初に項目名を印刷する。

見出しとなる部分もid=0にするなどしてオブジェクトとして作るか

7: Tue Dec 10 08:06:50 2019
作ってみた。

最初に考えた、ポリシーオブジェクトをたくさん作る方法がどうやっていいかわからない。

たとえば、

class MyClass:
....

MyInstance = MyClass("Hello")


なんて例がよくあるけど、

この「MyInstance」を動的に生成したいのだが、その方法がわからない...


8: Tue Dec 10 08:08:24 2019
いろいろ調べているうちに、そもそもクラスやインスタンスってそういう風に使うもんじゃないのかな、
と思い始め、
ポリシーを読み込み、一時的にクラスを作成し、すぐに結果を出力してクラスは破棄する、
というのを繰り返すことにした。

おそらく、クラスをたくさん作る方法が実現できたとしてもメモリを大量に消費する
無駄な処理方法になってしまうのではないか?
9: Tue Dec 10 08:10:17 2019
私はずっと、たとえばサッカーゲームとか、格闘ゲームのキャラクタというものはクラスで定義されていて、
それをインスタンス化して動かしていると思っていた。

だから、あるクラスについて大量のインスタンスを、変数から動的に生成するというのは
よく使う手段だと思っていたのだが...
10: Sat Dec 14 07:29:12 2019

# -*- coding: utf-8 -*-
import glob
import re
import sys

class Policy():
def __init__(self,id):
self.name = ""
self.id = id
self.srcintf = ""
self.dstintf = ""
self.srcaddr = ""
self.dstaddr = ""


def print_title():
policy_title = Policy(0)
policy_title.name="名前"
policy_title.id="ポリシーID"
policy_title.srcintf="送信元IF"
policy_title.dstintf="宛先IF"
policy_title.srcaddr="送信元アドレス"
policy_title.dstaddr="宛先アドレス"

for key, value in policy_title.__dict__.items():
print(value, end=",")
del policy_title


vdom_flg=0
policy_flg=0

args = sys.argv
config_file = open(args[1], "r")

for line in config_file:
m_vdom = re.match(r'config vdom', line)
m_edit = re.match(r'edit (.*)\n', line)
m_policy = re.match(r'config firewall policy\n', line)
m_end = re.match(r'end\n', line)

if policy_flg == 0:
if vdom_flg==2:
if m_vdom != None:
print("\n\nvdom: "+m_vdom.group(1)+"\n")
vdom_flg=1
elif m_policy != None:
policy_flg=1
# print("--- policy start ---\n")
print_title()
elif m_vdom != None:
vdom_flg+=1
elif m_end != None:
policy_flg=0
# print("\n--- policy end ---\n")
else:
m_edit = re.match(r'.*edit (.*)\n',line)
m_next = re.match(r'.*next\n',line)

m_srcintf = re.match(r'.*set srcintf (.*)\n', line)
m_dstintf = re.match(r'.*set dstintf (.*)\n', line)

m_srcaddr = re.match(r'.*set srcaddr (.*)\n', line)
m_dstaddr = re.match(r'.*set dstaddr (.*)\n', line)

if m_edit != None:
tmp_policy = Policy(m_edit.group(1))
elif m_next != None:
print("")
for key, value in tmp_policy.__dict__.items():
print(value, end=",")
del tmp_policy
elif m_srcintf != None:
tmp_policy.srcintf = m_srcintf.group(1)
elif m_dstintf != None:
tmp_policy.dstintf = m_dstintf.group(1)
elif m_srcaddr != None:
tmp_policy.srcaddr = m_srcaddr.group(1)
elif m_dstaddr != None:
tmp_policy.dstaddr = m_dstaddr.group(1)
else:
pass


config_file.close()
11: Sat Dec 14 07:32:23 2019
いちおう動くものができた。
fortigateのconfigから、policyの部分を表形式にするものだ。
この結果をcsvファイルとして出力してexcelで開けばよい。

vdomが設定されていれば、vdomごとに表示する。

入力ファイルは args[1]、つまり一個目の引数である。
値のチェックは何もしていない。

12: Sat Dec 14 07:37:29 2019
ファイルを読んで、狙ったキーワードが出てきたらフラグを立て、
フラグの状態に応じてまた狙ったキーワードが出てきたらそれを項目にセットする。

policy設定が見つかったらpolicyクラスからインスタンスを生成し、
設定されている項目をセットしていく。

デフォルト設定は表示されないので、コンストラクタでデフォルト値をセットし、
結果を出力するときはデフォルト値も含めている。

上記のソースでは6個の項目しかないが、
実際には55個の項目がある。
ただし55個全部出力するのは現実的ではなく、ほとんど使うことのない項目もあるので、
必要そうな項目を適当に選び、不要なものはコメントにして非表示にしている。
13: Sat Dec 14 07:39:20 2019
頭にあったのは、表示する・しないも設定できるようにすることだった。

itemA
display enable
value "abcd"

みたいな項目を作りたかった。
14: Sat Dec 14 07:42:43 2019
キーワードは正規表現で探す。
これはこれでいいと思うのだが、

マッチした後それを項目にセットする方法は、もっとよい方法がないだろうか?

今は、

キーワードAを正規表現でマッチさせる

結果Aが !=Noneでなければ

項目Aに結果Aをセット

キーワードBを正規表現でマッチさせる

結果Bが !=Noneでなければ

項目Bに結果Bをセット

・・・

と、ずらずら書いている。

厳密にするならば55項目すべてについて書かねばならないが、
今は必要そうなもののみを選んでいる。

15: Sat Dec 14 07:44:18 2019
こういう時こそクラスや関数が役立つのだと思うのだが......

結果Aと項目Aの紐づけを動的にできないものか......
16: Sat Dec 14 07:50:11 2019
思いつく方法は2つ

1つめは配列を作って、どの項目が何番目になるかを決め、
マッチした項目を配列に格納し、配列をクラスの各項目にセットする


2つ目は、クラスに「マッチすべき文字列」と「項目名」をペアで作り、
マッチした内容を項目にセットするメソッドを作る
17: Sat Dec 14 07:55:48 2019
ここで前提となるのが、
マッチすべき文字列をそのまま項目名にできないことである。

できたとしても、文字列を変数名として呼び出せるだろうか?

つまり、

「name」という文字列変数があったとして、

入力文字列が

set name John
set address 1-2-3
set phonenumber 080-xxx-xxxx

みたいになっていたとき、

正規表現で

m = re.match(r'.*set (.*?) (.*)\n', line)

で検索すると m.group(1) は 「name」、m.group(2)は「John」となる。

このとき、「John」という値を変数「name」にセットしたいのだ。


18: Sat Dec 14 08:12:23 2019
そして、m.group(1)が addressなら変数addressにm.group(2)を、
そして、m.group(1)が phonenumberなら変数phonenumberにm.group(2)を、セットしたい。

言葉で書くなら、「正規表現でマッチして格納される結果の1番目が変数名で2番目がその内容となる」
ということである。

できるよね?

絶対できるはず。

19: Sat Dec 14 08:44:01 2019

class Friend():
def __init__(self,name):
self.name=name
self.phone=""


NameToSet = "John"

AFriendOfMine = Friend(NameToSet)

print(AFriendOfMine.name+"\n")
print(AFriendOfMine.phone+"\n")


ItemToSet = "name"
ValueToSet = "Paul"

AFriendOfMine.__dict__[ItemToSet] = ValueToSet


print(AFriendOfMine.name+"\n")


ItemToSet = "phone"
ValueToSet = "xxx-yyyy-zzzz"

AFriendOfMine.__dict__[ItemToSet] = ValueToSet


print(AFriendOfMine.phone+"\n")

20: Sat Dec 14 08:47:54 2019
「変数名を動的に指定する」はできた。

クラス Friendの定義。
クラスの属性はnameとphone(電話番号)

クラス Friendのインスタンス AFriendOfMineを、nameに "John"を設定して生成する。

AFriendOfMine の nameは John
phoneは未設定


ItemToSetという変数に "name"を、ValueToSetという変数に"Paul"を格納。

次の1行が「指定した変数に設定された項目名に指定した変数の内容を設定する」である。

AFriendOfMine.__dict__[ItemToSet] = ValueToSet
21: Sat Dec 14 08:48:22 2019
実行結果は以下のようになる。

>python poltest.py
John



Paul

xxx-yyyy-zzzz
22: Sat Dec 14 12:05:37 2019
改良版


# -*- coding: utf-8 -*-
import glob
import re
import sys

class Policy():
def __init__(self,id):
self.id = id
self.name = ""
self.uuid = ""
self.srcintf = ""
self.dstintf = ""
self.srcaddr = ""
self.dstaddr = ""
self.action = ""
self.schedule = ""
self.service = ""
self.logtraffic = "utm"
self.session_ttl = ""
self.nat = "enable"
self.ippool = ""
self.poolname = ""


def print_title():
policy_title = Policy(0)
policy_title.id="ポリシーID"
policy_title.name="名前"
policy_title.uuid="uuid"
policy_title.srcintf="送信元IF"
policy_title.dstintf="宛先IF"
policy_title.srcaddr="送信元アドレス"
policy_title.dstaddr="宛先アドレス"
policy_title.action="action"
policy_title.schedule="スケジュール"
policy_title.service="サービス"
policy_title.logtraffic="トラフィックログ"
policy_title.session_ttl="セッションTTL"
policy_title.nat="NAT"
policy_title.ippool="IPプール"
policy_title.poolname="NAT"

for key, value in policy_title.__dict__.items():
print(value, end=",")
del policy_title


vdom_flg=0
policy_flg=0

args = sys.argv
config_file = open(args[1], "r")

for line in config_file:
m_vdom = re.match(r'config vdom', line)
m_edit = re.match(r'edit (.*)\n', line)
m_policy = re.match(r'config firewall policy\n', line)
m_end = re.match(r'end\n', line)

if policy_flg == 0:
if vdom_flg==2:
if m_vdom != None:
print("\n\nvdom: "+m_vdom.group(1)+"\n")
vdom_flg=1
elif m_policy != None:
policy_flg=1
print_title()
elif m_vdom != None:
vdom_flg+=1
elif m_end != None:
policy_flg=0
else:
m_edit = re.match(r'.*edit (.*)\n', line)
m_next = re.match(r'.*next\n', line)
m_set = re.match(r'.*set .*\n', line)

if m_edit != None:
tmp_policy = Policy(m_edit.group(1))
elif m_next != None:
print("")
for key, value in tmp_policy.__dict__.items():
print(value, end=",")
del tmp_policy
elif m_set !=None:
pattern = '.*set (.*?) (.*)\n'
repattern = re.compile(pattern)
m = repattern.match(line)
if m !=None:
item = m.group(1).replace('-','_')
tmp_policy.__dict__[item]=m.group(2)
else:
pass

config_file.close()

23: Sat Dec 14 12:07:13 2019
変数名にハイフンが使えないので、
マッチした項目名はハイフンをアンダーバーに置換した。
24: Mon Dec 16 16:22:30 2019
その1

# -*- coding: utf-8 -*-
import glob
import re
import sys

config_flg=0
config2_flg=0
edit_flg=0
edit_count=0

args = sys.argv

config_file = open(args[1], "r")

class EditObject():
def __init__(self):
self.indent=""



for line in config_file:
m_config = re.match(r'config system global\n', line)
m_end = re.match(r'end\n', line)

if config_flg == 0:
if m_config != None:
config_flg=1
else:
if config2_flg ==0:
m_set = re.match(r'.*set (.*?) (.*)\n',line)
m_config2 = re.match(r'.*config (.*)\n',line)
m_end = re.match(r'end\n',line)

if m_set != None:
print(m_set.group(1)+","+m_set.group(2))
elif m_config2 != None:
config2_flg = 1
print(m_config2.group(1))
elif m_end != None:
break
else:
m_edit = re.match(r'.*edit (.*)\n',line)
m_set = re.match(r'.*set (.*?) (.*)\n',line)
m_next = re.match(r'.*next\n',line)
m_end = re.match(r'.*end\n',line)

if m_edit != None:
tmp_object = EditObject()
edit_flg = 1
edit_count += 1;
elif m_set != None:
pattern = '.*set (.*?) (.*)\n'
repattern = re.compile(pattern)
m = repattern.match(line)
if m !=None:
item = m.group(1).replace('-','_')
tmp_object.__dict__[item]=m.group(2)
elif m_next != None:
if edit_count < 2:
for key in tmp_object.__dict__.keys():
if key == "indent":
print(" ",end=",")
else:
print(key,end=",")
print("")
for key, value in tmp_object.__dict__.items():
print(value, end=",")
del tmp_object
elif m_end != None:
config2_flg = 0
edit_count = 0
print("")


config_file.close()

25: Mon Dec 16 16:23:27 2019
その2

### config system firewall
### config system interface

# -*- coding: utf-8 -*-
import glob
import re
import sys

vdom_flg=0
config_flg=0
edit_count=0

args = sys.argv
config_file = open(args[1], "r")

class EditObject():
def __init__(self):
pass

tmp_object = EditObject()

#仮読み
for line in config_file:
m_vdom = re.match(r'config vdom', line)
m_edit = re.match(r'edit (.*)\n', line)
# m_config = re.match(r'config system interface\n', line)
m_config = re.match(r'config firewall policy\n', line)
m_end = re.match(r'end\n', line)

if config_flg == 0:
if vdom_flg==2:
if m_edit != None:
vdom_flg=1
elif m_config != None:
config_flg=1

elif m_vdom != None:
vdom_flg+=1
config_flg=0
edit_count=0
elif m_end != None:
config_flg=0
else:
m_edit = re.match(r'.*edit (.*)\n', line)
m_next = re.match(r'.*next\n', line)
m_set = re.match(r'.*set .*\n', line)

if m_set !=None:
pattern = '.*set (.*?) (.*)\n'
repattern = re.compile(pattern)
m = repattern.match(line)
if m !=None:
item = m.group(1).replace('-','_')
tmp_object.__dict__[item]=m.group(2)
else:
pass

config_file.close()



config_file = open(args[1], "r")



for line in config_file:
m_vdom = re.match(r'config vdom', line)
m_edit = re.match(r'edit (.*)\n', line)
# m_config = re.match(r'config system interface\n', line)
m_config = re.match(r'config firewall policy\n', line)
m_end = re.match(r'end\n', line)

if config_flg == 0:
if vdom_flg==2:
if m_edit != None:
print("\n\nvdom: "+m_edit.group(1)+"\n")
vdom_flg=1
elif m_config != None:
config_flg=1

elif m_vdom != None:
vdom_flg+=1
config_flg=0
edit_count=0
elif m_end != None:
config_flg=0
else:
m_edit = re.match(r'.*edit (.*)\n', line)
m_next = re.match(r'.*next\n', line)
m_set = re.match(r'.*set .*\n', line)

if m_edit != None:
for x, key in tmp_object.__dict__.items():
tmp_object.__dict__[x]=""
# tmp_object.name=m_edit.group(1)
tmp_object.id=m_edit.group(1)
edit_count += 1;
elif m_next != None:
if edit_count < 2:
for key in tmp_object.__dict__.keys():
print(key,end=",")
print("")
for key, value in tmp_object.__dict__.items():
print(value,end=",")
value=""
elif m_set !=None:
pattern = '.*set (.*?) (.*)\n'
repattern = re.compile(pattern)
m = repattern.match(line)
if m !=None:
item = m.group(1).replace('-','_')
tmp_object.__dict__[item]=m.group(2)
else:
pass

del tmp_object
config_file.close()

^
previous | next | edit



log