1
2
3 __docformat__ = 'restructuredtext'
4 __version__ = '$Id$'
5
6 from routerdefense.common import *
7 from routerdefense.metrics import *
8
9 -def pdfReport(outputFile, genericCfg, ManagementPlaneMetrics, ControlPlaneMetrics, DataPlaneMetrics):
10 from reportlab.pdfgen import canvas
11 from reportlab.lib.enums import TA_JUSTIFY
12 from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Image
13 from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
14 from reportlab.lib.units import inch
15 import time
16 import inspect
17 import __builtin__
18
19 doc = SimpleDocTemplate(outputFile)
20 report = []
21 logo = "logo-router-defense.png"
22 im = Image(logo)
23 formatted_time = time.ctime()
24 intro = """
25 <font size=12>Some of those recommandations could not fit with your environment for any reason from layer 1 to layer 8 (financial) and layer 9 (political).
26 </font>
27 """
28
29 outro = """RouterDefense is created and maintained by Francois Ropert.<br />
30 <a href='http://code.google.com/p/routerdefense'>http://code.google.com/p/routerdefense</a>
31 """
32 report.append(im)
33 report.append(Spacer(1, 24))
34 styles=getSampleStyleSheet()
35 styles.add(ParagraphStyle(name='Justify', alignment=TA_JUSTIFY))
36 ptext = '<font size=12>Report generation date: <b> %s </b></font>' % formatted_time
37 report.append(Paragraph(ptext, styles["Justify"]))
38 ptext = '<font size=12>%s</font>' % intro
39 report.append(Paragraph(ptext, styles["Justify"]))
40 report.append(Spacer(1, 24))
41
42 ptext = '<font size=14><b><u>Hostname:</u></b> %s </font><br />' % genericCfg.hostName
43 ptext += '<font size=14><b><u>IOS:</u></b> %s </font><br />' % genericCfg.iosVersion
44 ptext += '<font size=14><b><u>Switching:</u></b> %s </font><br />' % genericCfg.switchingMethod
45 ptext += '<font size=14><b><u>Multicast:</u></b> %s </font><br />' % genericCfg.multicast
46 ptext += '<font size=14><b><u>QoS:</u></b> %s </font><br />' % genericCfg.qos
47 ptext += '<font size=14><b><u>IPv6:</u></b> %s </font><br />' % genericCfg.ipv6
48 ptext += '<font size=14><b><u>IPSEC VPN:</u></b> %s </font><br />' % genericCfg.ipsec
49 report.append(Paragraph(ptext, styles["Justify"]))
50
51 report.append(Spacer(1, 24))
52 ptext = '<font size=20>Management Plane</font>'
53 report.append(Paragraph(ptext, styles["Justify"]))
54 report.append(Spacer(1, 24))
55
56 for name in ManagementPlaneMetrics:
57 if name != 'interface':
58 for k,v in inspect.getmembers(name):
59 if isinstance(v, dict):
60 if v['must_report'] == True:
61 definition = v['definition'].strip()
62 threatInfo = v['threatInfo'].strip()
63 howtofix = v['howtofix'].strip()
64 fixImpact = v['fixImpact'].strip()
65 cvss = v['cvss'].strip()
66
67 ptext = '<font size=12><u>%s</u> <b>%s</b></font><br />' % (name.long_name, definition)
68 report.append(Paragraph(ptext, styles["Justify"]))
69 report.append(Spacer(1, 6))
70 ptext = '<font size=12><u>Threat:</u> %s (Score: %s)</font><br />' % (threatInfo, cvss)
71 report.append(Paragraph(ptext, styles["Justify"]))
72 report.append(Spacer(1, 6))
73 ptext = '<font size=12><u>Fix impact:</u> %s</font><br />' % fixImpact
74 report.append(Paragraph(ptext, styles["Justify"]))
75 report.append(Spacer(1, 6))
76 ptext = '<font size=14><b><u>How to fix:</u></b> %s </font><br />' % howtofix
77 report.append(Paragraph(ptext, styles["Justify"]))
78 report.append(Spacer(1, 12))
79
80 report.append(Spacer(1, 24))
81 ptext = '<font size=20>Control Plane</font>'
82 report.append(Paragraph(ptext, styles["Justify"]))
83 report.append(Spacer(1, 24))
84 for name in ControlPlaneMetrics:
85 if name != 'interface':
86 for k,v in inspect.getmembers(name):
87 if isinstance(v, dict):
88 if v['must_report'] == True:
89 definition = v['definition'].strip()
90 threatInfo = v['threatInfo'].strip()
91 fixImpact = v['fixImpact'].strip()
92 cvss = v['cvss'].strip()
93 if definition == 'OSPF route filtering in':
94 v['howtofix'] = v['howtofix'].strip().replace('[%ospfPID]', ", ".join(name.rfilter_in['pid']), 1)
95 v['howtofix'] = v['howtofix'].strip().replace('[%ospfArea]', ", ".join(name.rfilter_in['area']), 1)
96 elif definition == 'OSPF MD5 authentication':
97 v['howtofix'] = v['howtofix'].strip().replace('[%ospfinterface]', ", ".join(name.auth_md5['interfaces']), 1)
98 v['howtofix'] = v['howtofix'].strip().replace('[%ospfArea]', ", ".join(name.auth_md5['area']), 1)
99 v['howtofix'] = v['howtofix'].strip().replace('[%ospfPID]', ", ".join(name.auth_md5['pid']), 1)
100 elif definition == 'OSPF route filtering out':
101 v['howtofix'] = v['howtofix'].strip().replace('[%ospfPID]', ", ".join(name.rfilter_out['pid']), 1)
102 v['howtofix'] = v['howtofix'].strip().replace('[%ospfArea]', ", ".join(name.rfilter_out['area']), 1)
103 elif definition == 'OSPF passive interface default':
104 v['howtofix'] = v['howtofix'].strip().replace('[%ospfInstance]', ", ".join(name.passive['pid']), 1)
105 elif definition == 'OSPF maximum LSA':
106 v['howtofix'] = v['howtofix'].strip().replace('[%ospfInstance]', ", ".join(name.maxLSA['pid']), 1)
107 elif definition == 'EIGRP MD5 authentication':
108 v['howtofix'] = v['howtofix'].strip().replace('[%eigrpinterface]', ", ".join(name.auth_md5['interfaces']), 1)
109 v['howtofix'] = v['howtofix'].strip().replace('[%eigrpAs]', ", ".join(name.auth_md5['asn']), 1)
110 elif definition == 'EIGRP passive interface default':
111 v['howtofix'] = v['howtofix'].strip().replace('[%eigrpAs]', ", ".join(name.passive['asn']), 1)
112 elif definition == 'EIGRP route filtering inbound':
113 v['howtofix'] = v['howtofix'].strip().replace('[%eigrpAs]', ", ".join(name.rfilter_in['asn']), 1)
114 elif definition == 'EIGRP route filtering outbound':
115 v['howtofix'] = v['howtofix'].strip().replace('[%eigrpAs]', ", ".join(name.rfilter_out['asn']), 1)
116 elif definition == 'RIP MD5 authentication':
117 v['howtofix'] = v['howtofix'].strip().replace('[%ripinterface]', ", ".join(name.auth_md5['interfaces']), 1)
118 howtofix = v['howtofix']
119
120 ptext = '<font size=12><u>%s</u> <b>%s</b></font><br />' % (name.long_name, definition)
121 report.append(Paragraph(ptext, styles["Justify"]))
122 report.append(Spacer(1, 6))
123 ptext = '<font size=12><u>Threat:</u> %s (Score: %s)</font><br />' % (threatInfo, cvss)
124 report.append(Paragraph(ptext, styles["Justify"]))
125 report.append(Spacer(1, 6))
126 ptext = '<font size=12><u>Fix impact:</u> %s</font><br />' % fixImpact
127 report.append(Paragraph(ptext, styles["Justify"]))
128 report.append(Spacer(1, 6))
129 ptext = '<font size=14><b><u>How to fix:</u></b> %s </font><br />' % howtofix
130 report.append(Paragraph(ptext, styles["Justify"]))
131 report.append(Spacer(1, 12))
132
133 report.append(Spacer(1, 24))
134 ptext = '<font size=20>Data Plane</font>'
135 report.append(Paragraph(ptext, styles["Justify"]))
136 report.append(Spacer(1, 24))
137 for name in DataPlaneMetrics:
138 if name != 'interface':
139 for k,v in inspect.getmembers(name):
140 if isinstance(v, dict):
141 if v['must_report'] == True:
142 definition = v['definition'].strip()
143 threatInfo = v['threatInfo'].strip()
144 fixImpact = v['fixImpact'].strip()
145 cvss = v['cvss'].strip()
146 if definition == 'Port security violation':
147 v['howtofix'] = v['howtofix'].strip().replace('[%interface]', ", ".join(name.violation['candidates']), 1)
148 if definition == 'Port security MAC address sticky':
149 v['howtofix'] = v['howtofix'].strip().replace('[%interface]', ", ".join(name.sticky['candidates']), 1)
150 if definition == 'Port security total maximum MAC addresses':
151 v['howtofix'] = v['howtofix'].strip().replace('[%interface]', ", ".join(name.maximum_total['candidates']), 1)
152 if definition == 'Port security access vlan maximum MAC addresses':
153 v['howtofix'] = v['howtofix'].strip().replace('[%interface]', ", ".join(name.maximum_access['candidates']), 1)
154 if definition == 'Port security voice vlan maximum MAC addresses':
155 v['howtofix'] = v['howtofix'].strip().replace('[%interface]', ", ".join(name.maximum_voice['candidates']), 1)
156 if definition == 'DTP negotiation':
157 v['howtofix'] = v['howtofix'].strip().replace('[%interface]', ", ".join(name.nonegotiate['candidates']), 1)
158 if definition == 'Flow Control 802.3x':
159 v['howtofix'] = v['howtofix'].strip().replace('[%interface]', ", ".join(name.flowcontrol['candidates']), 1)
160 if definition == 'VLAN 1':
161 v['howtofix'] = v['howtofix'].strip().replace('[%interface]', ", ".join(name.vlan_1['candidates']), 1)
162 if definition == 'Unused ports':
163 v['howtofix'] = v['howtofix'].strip().replace('[%interface]', ", ".join(name.unused_ports['candidates']), 1)
164
165 howtofix = v['howtofix']
166
167 ptext = '<font size=12><u>%s</u> <b>%s</b></font><br />' % (name.long_name, definition)
168 report.append(Paragraph(ptext, styles["Justify"]))
169 report.append(Spacer(1, 6))
170 ptext = '<font size=12><u>Threat:</u> %s (Score: %s)</font><br />' % (threatInfo, cvss)
171 report.append(Paragraph(ptext, styles["Justify"]))
172 report.append(Spacer(1, 6))
173 ptext = '<font size=12><u>Fix impact:</u> %s</font><br />' % fixImpact
174 report.append(Paragraph(ptext, styles["Justify"]))
175 report.append(Spacer(1, 6))
176 ptext = '<font size=14><b><u>How to fix:</u></b> %s </font><br />' % howtofix
177 report.append(Paragraph(ptext, styles["Justify"]))
178 report.append(Spacer(1, 12))
179
180
181 ptext = outro
182 report.append(Paragraph(ptext, styles["Justify"]))
183
184 doc.build(report)
185
186 print "Audit has been saved under the filename: %s " % outputFile
187 return "PDF"
188