Skip to content

Commit 0a0cb34

Browse files
author
Fückert, Oliver
committed
V1
0 parents  commit 0a0cb34

2 files changed

Lines changed: 152 additions & 0 deletions

File tree

.gitignore

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
*.json
2+
*.dot
3+
*.pdf
4+
*.svg
5+
*.png
6+
.aci2dot
7+
.vscode/*
8+
.vscode/settings.json

aci2dot.py

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
#!/usr/bin/env python
2+
3+
# aci2dot.py is free software: you can redistribute it and/or modify
4+
# it under the terms of the GNU General Public License as published by
5+
# the Free Software Foundation, either version 3 of the License, or
6+
# (at your option) any later version.
7+
8+
# This program is distributed in the hope that it will be useful,
9+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+
# GNU General Public License for more details.
12+
13+
# You should have received a copy of the GNU General Public License
14+
# along with this program. If not, see <https://www.gnu.org/licenses/>.
15+
16+
import argparse
17+
import sys
18+
import json
19+
import os
20+
21+
simple = False
22+
show_attributes = True
23+
24+
gformat = '''
25+
graph [
26+
size="8.27";
27+
ratio="1";
28+
nodesep="0.15";
29+
ranksep="0.5";
30+
#splines="false";
31+
rankdir=LR;
32+
bgcolor="transparent";
33+
];
34+
node [
35+
shape=box;
36+
style="rounded,filled";
37+
fillcolor=AZURE;
38+
fontname=Helvetica;
39+
]
40+
edge [
41+
#arrowsize=0.5;
42+
]
43+
'''
44+
45+
def format_attr(policy,attr):
46+
47+
if not show_attributes:
48+
return '<<B>{0}</B>>'.format(policy)
49+
50+
attr_table = '<<TABLE BORDER="0" CELLBORDER="0" CELLSPACING="1" CELLPADDING="1">'
51+
attr_table = attr_table + '<TR><TD ALIGN="LEFT" COLSPAN="2"><B>{0}</B></TD><TD></TD></TR>'.format(policy)
52+
attr_table = attr_table + '<TR><TD></TD><TD></TD></TR>'
53+
54+
for k, v in attr.items():
55+
if k not in ['status'] and v:
56+
attr_table = attr_table + '<TR><TD ALIGN="LEFT">{0}</TD><TD ALIGN="LEFT">: {1}</TD></TR>'.format(k,(v[:20] + '..') if len(v) > 20 else v)
57+
58+
attr_table = attr_table + '</TABLE>>'
59+
60+
return attr_table
61+
62+
def iterd(d, i):
63+
64+
#print('# Index: {0}, {1}'.format(i, d))
65+
for k, v in d.items():
66+
67+
if isinstance(v, dict):
68+
attr = v.get("attributes")
69+
70+
# Write Node Properties
71+
if attr:
72+
print('{0} [label={1};]'.format(k + str(i), format_attr(k, attr)))
73+
else:
74+
print('{0} [label="{0}";]'.format(k + str(i)))
75+
76+
children = v.get("children")
77+
78+
if children:
79+
i2=0
80+
for child in children:
81+
if not simple: i2 = i2 + 1
82+
for childk, childv in child.items():
83+
print('{0} -> {1}'.format(k + str(i), childk + str(i2)))
84+
iterd(child, i2)
85+
86+
def write_gformat():
87+
with open(".aci2dot", "wt") as text_file:
88+
text_file.write(gformat)
89+
90+
def main():
91+
92+
global simple
93+
global show_attributes
94+
global gformat
95+
parser = argparse.ArgumentParser(description='Export DOT formatted Graph from JSON formatted ACI policy export.\nConvert with: ./aci2dot.py policy.json | dot -o policy.svg -Tsvg')
96+
parser.add_argument('policy_file', type=argparse.FileType('r'), help='JSON ACI Policy Filename')
97+
parser.add_argument('--nr', action='store_true', help='Suppress redundant children')
98+
parser.add_argument('--na', action='store_true', help="Don't show attributes")
99+
parser.add_argument('--write', action='store_true', help="Write config template to .aci2dot and exit")
100+
group = parser.add_mutually_exclusive_group()
101+
group.add_argument('--stdout', action='store_true', help="Write to STDOUT instead of to file")
102+
choices = ["svg", "png", "pdf"]
103+
group.add_argument('--dot', choices=choices, help="Also write SVG/PNG/PDF. 'dot' needs to be installed.")
104+
105+
args = parser.parse_args()
106+
107+
#print(args.dot)
108+
#sys.exit()
109+
110+
if args.write:
111+
write_gformat()
112+
sys.exit('Config template written to .aci2dot')
113+
114+
simple = args.nr
115+
show_attributes = not args.na if not args.nr else False
116+
base_name = (os.path.splitext(args.policy_file.name)[0])
117+
118+
try:
119+
data = json.load(args.policy_file)
120+
except:
121+
sys.exit('JSON File can not be read.')
122+
123+
try:
124+
with open(".aci2dot", 'r') as config_file:
125+
gformat = config_file.read()
126+
print("Graph config read from .aci2dot", file=sys.stderr)
127+
except IOError:
128+
pass
129+
130+
if not args.stdout:
131+
sys.stdout = open('{0}.dot'.format(base_name), 'w')
132+
133+
print('strict digraph Policy {')
134+
print(gformat)
135+
iterd(data, 0)
136+
print('}', flush=True)
137+
138+
if args.dot:
139+
os.system("dot -T{0} -o{1}.{0} {1}.dot".format(args.dot, base_name))
140+
#print(("dot -T{0} -o{1}.svg {1}.dot".format(args.dot, base_name)))
141+
print("{0} exported to {1}.{0}".format(args.dot, base_name), file=sys.stderr)
142+
143+
if __name__ == '__main__':
144+
main()

0 commit comments

Comments
 (0)