Mercurial > farol > farol
comparison farol/main.py @ 0:4a9f23230eba
Initial Release
author | Benoît Allard <benoit.allard@greenbone.net> |
---|---|
date | Wed, 24 Sep 2014 10:07:49 +0200 |
parents | |
children | 63b00c10ada8 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:4a9f23230eba |
---|---|
1 # -*- encoding: utf-8 -*- | |
2 # Description: | |
3 # Farol Web Application | |
4 # | |
5 # Authors: | |
6 # BenoƮt Allard <benoit.allard@greenbone.net> | |
7 # | |
8 # Copyright: | |
9 # Copyright (C) 2014 Greenbone Networks GmbH | |
10 # | |
11 # This program is free software; you can redistribute it and/or | |
12 # modify it under the terms of the GNU General Public License | |
13 # as published by the Free Software Foundation; either version 2 | |
14 # of the License, or (at your option) any later version. | |
15 # | |
16 # This program is distributed in the hope that it will be useful, | |
17 # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
18 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
19 # GNU General Public License for more details. | |
20 # | |
21 # You should have received a copy of the GNU General Public License | |
22 # along with this program; if not, write to the Free Software | |
23 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
24 | |
25 import os | |
26 | |
27 from farolluz.cvrf import (CVRF, CVRFPublisher, CVRFTracking, CVRFTrackingID, | |
28 CVRFGenerator, CVRFRevision, CVRFReference, CVRFAcknowledgment, CVRFNote, | |
29 ValidationError, CVRFAggregateSeverity) | |
30 from farolluz.parsers.cvrf import parse, parseVersion, parseDate | |
31 from farolluz.py2 import urlopen | |
32 from farolluz.renderer import render as render_cvrf | |
33 from farolluz.utils import utcnow | |
34 | |
35 from flask import Flask, request, render_template, redirect, url_for, flash, abort | |
36 from werkzeug import secure_filename | |
37 | |
38 from .session import get_current, set_current, has_current, del_current, document_required | |
39 from .vulnerability import vulnerability | |
40 from .producttree import producttree | |
41 | |
42 app = Flask(__name__) | |
43 | |
44 app.register_blueprint(vulnerability, url_prefix='/vulnerability') | |
45 app.register_blueprint(producttree, url_prefix='/producttree') | |
46 | |
47 @app.context_processor | |
48 def cache_content(): | |
49 """ List the documents in cache """ | |
50 if 'CACHE_DIRECTORY' not in app.config: | |
51 return dict(cache=[]) | |
52 dirname = app.config['CACHE_DIRECTORY'] | |
53 if not os.path.exists(dirname): | |
54 os.mkdir(dirname) | |
55 l = [] | |
56 for path in os.listdir(dirname): | |
57 name, ext = os.path.splitext(path) | |
58 if ext == '.xml': | |
59 l.append(name) | |
60 return dict(cache=l) | |
61 | |
62 @app.context_processor | |
63 def doc_properties(): | |
64 if not has_current(): | |
65 return {'has_current': False} | |
66 cvrf = get_current() | |
67 vulns = [(v.getTitle(), v._ordinal) for v in cvrf._vulnerabilities] | |
68 prods = [] | |
69 if cvrf._producttree: | |
70 prods = [(p._name, p._productid) for p in cvrf._producttree._products] | |
71 try: | |
72 cvrf.validate() | |
73 error = None | |
74 except ValidationError as ve: | |
75 error = ve | |
76 return dict(has_current=True, vulnerabilities=vulns, products=prods, error=error) | |
77 | |
78 @app.template_filter('secure_filename') | |
79 def makeId(string): | |
80 return secure_filename(string) | |
81 | |
82 @app.route('/new', methods=['GET', 'POST']) | |
83 def new(): | |
84 if request.method != 'POST': | |
85 return render_template('new.j2', has_document=has_current(), now=utcnow()) | |
86 | |
87 if 'url' in request.form: | |
88 set_current(parse(urlopen(request.form['url']).read())) | |
89 elif 'local' in request.files: | |
90 upload = request.files['local'] | |
91 if not upload.filename.endswith('.xml'): | |
92 flash('Uploaded files should end in .xml', 'danger') | |
93 return redirect(url_for('new')) | |
94 fpath = os.path.join('/tmp', secure_filename(upload.filename)) | |
95 upload.save(fpath) | |
96 with open(fpath, 'rt') as f: | |
97 set_current(parse(f)) | |
98 os.remove(fpath) | |
99 elif 'text' in request.form: | |
100 set_current(parse(request.form['text'].encode('utf-8'))) | |
101 else: | |
102 set_current(CVRF(request.form['title'], request.form['type'])) | |
103 return redirect(url_for('document')) | |
104 | |
105 @app.route('/') | |
106 @document_required | |
107 def document(): | |
108 cvrf = get_current() | |
109 return render_template('doc.j2', cvrf=cvrf) | |
110 | |
111 @app.route('/title/edit', methods=['GET', 'POST']) | |
112 @document_required | |
113 def edit_title(): | |
114 if request.method != 'POST': | |
115 return render_template('edit_title.j2', title = get_current()._title, _type = get_current()._type) | |
116 | |
117 | |
118 get_current()._title = request.form['title'] | |
119 get_current()._type = request.form['type'] | |
120 return redirect(url_for('document')) | |
121 | |
122 @app.route('/publisher/edit', methods=['GET', 'POST']) | |
123 @document_required | |
124 def edit_publisher(): | |
125 if request.method != 'POST': | |
126 return render_template('edit_publisher.j2', publisher = get_current()._publisher or CVRFPublisher(''), types=CVRFPublisher.TYPES) | |
127 | |
128 publisher = CVRFPublisher(request.form['type'], request.form['vendorid'] or None) | |
129 publisher.setContact(request.form['contact'] or None) | |
130 publisher.setAuthority(request.form['authority'] or None) | |
131 get_current().setPublisher(publisher) | |
132 return redirect(url_for('document')) | |
133 | |
134 @app.route('/tracking/edit', methods=['GET', 'POST']) | |
135 @document_required | |
136 def edit_tracking(): | |
137 wasNone = False | |
138 tracking = get_current()._tracking | |
139 if tracking is None: | |
140 wasNone = True | |
141 tracking = CVRFTracking(CVRFTrackingID(''), 'Draft', (0,), utcnow(), utcnow()) | |
142 generator = tracking._generator | |
143 if not tracking._generator: | |
144 generator = CVRFGenerator() | |
145 if request.method != 'POST': | |
146 return render_template('edit_tracking.j2', tracking=tracking, version='.'.join('%s'%v for v in tracking._version), generator=generator, now=utcnow(), statuses=tracking.STATUSES) | |
147 | |
148 tracking._identification._id = request.form['id'] | |
149 aliases = [] | |
150 if request.form['id_aliases']: | |
151 aliases = [a.strip() for a in request.form['id_aliases'].split(',')] | |
152 tracking._identification._aliases = aliases | |
153 tracking._status = request.form['status'] | |
154 tracking._version = parseVersion(request.form['version']) | |
155 tracking._initialDate = parseDate(request.form['initial']) | |
156 tracking._currentDate = parseDate(request.form['current']) | |
157 if wasNone: | |
158 get_current().setTracking(tracking) | |
159 if (not request.form['gen_engine']) and (not request.form['gen_date']): | |
160 generator = None | |
161 else: | |
162 generator._engine = request.form['gen_engine'] or None | |
163 if request.form['gen_date']: | |
164 generator._date = parseDate(request.form['gen_date']) | |
165 else: | |
166 generator._date = None | |
167 tracking.setGenerator(generator) | |
168 return redirect(url_for('document')) | |
169 | |
170 @app.route('/revision/<int:index>/edit', methods=['GET', 'POST']) | |
171 @document_required | |
172 def edit_revision(index): | |
173 cvrf = get_current() | |
174 if cvrf._tracking is None: | |
175 abort(404) | |
176 try: | |
177 revision = cvrf._tracking._history[index] | |
178 except IndexError: | |
179 abort(404) | |
180 if request.method != 'POST': | |
181 return render_template('edit_revision.j2', number='.'.join('%s'%v for v in revision._number), date=revision._date, description=revision._description, action='Update') | |
182 | |
183 revision._number = parseVersion(request.form['number']) | |
184 revision._date = parseDate(request.form['date']) | |
185 revision._description = request.form['description'] | |
186 return redirect(url_for('document')) | |
187 | |
188 @app.route('/revision/add', methods=['GET', 'POST']) | |
189 @document_required | |
190 def add_revision(): | |
191 tracking = get_current()._tracking | |
192 if request.method != 'POST': | |
193 version = tracking._version | |
194 version = version[:-1] + (version[-1] + 1,) | |
195 return render_template('edit_revision.j2', number='.'.join("%d"%v for v in version), date=utcnow(), action='Add') | |
196 | |
197 version = parseVersion(request.form['number']) | |
198 date = parseDate(request.form['date']) | |
199 revision = CVRFRevision(version, date, request.form['description']) | |
200 tracking.addRevision(revision) | |
201 if 'update_tracking' in request.form: | |
202 tracking._version = version | |
203 tracking._currentDate = date | |
204 return redirect(url_for('document')) | |
205 | |
206 @app.route('/distribution/edit', methods=['GET', 'POST']) | |
207 @document_required | |
208 def edit_distribution(): | |
209 if request.method != 'POST': | |
210 return render_template('edit_distribution.j2', distribution=get_current()._distribution) | |
211 | |
212 get_current().setDistribution(request.form['distribution']) | |
213 return redirect(url_for('document')) | |
214 | |
215 @app.route('/severity/edit', methods=['GET', 'POST']) | |
216 @document_required | |
217 def edit_severity(): | |
218 severity = get_current()._aggregateseverity | |
219 if severity is None: | |
220 severity = CVRFAggregateSeverity('') | |
221 if request.method != 'POST': | |
222 return render_template('edit_severity.j2', severity=severity) | |
223 if not request.form['severity']: | |
224 severity = None | |
225 else: | |
226 severity._severity = request.form['severity'] | |
227 severity.setNamespace(request.form['namespace'] or None) | |
228 get_current().setAggregateSeverity(severity) | |
229 return redirect(url_for('document')) | |
230 | |
231 @app.route('/note/<int:ordinal>') | |
232 @document_required | |
233 def view_note(ordinal): | |
234 note = get_current().getNote(ordinal) | |
235 if note is None: | |
236 abort(404) | |
237 return render_template('view_note.j2', note=note) | |
238 | |
239 @app.route('/note/<int:ordinal>/edit', methods=['GET', 'POST']) | |
240 @document_required | |
241 def edit_note(ordinal): | |
242 note = get_current().getNote(ordinal) | |
243 if note is None: | |
244 abort(404) | |
245 if request.method != 'POST': | |
246 return render_template('edit_note.j2', note=note, types = note.TYPES) | |
247 | |
248 note._type = request.form['type'] | |
249 note._ordinal = int(request.form['ordinal']) | |
250 note._note = request.form['note'] | |
251 note._title = request.form['title'] or None | |
252 note._audience = request.form['audience'] or None | |
253 return redirect(url_for('view_note', ordinal=note._ordinal )) | |
254 | |
255 | |
256 @app.route('/note/add', methods=['GET', 'POST']) | |
257 @document_required | |
258 def add_note(): | |
259 if request.method != 'POST': | |
260 next_ordinal = 1 | |
261 notes = get_current()._notes | |
262 if notes: | |
263 next_ordinal = notes[-1]._ordinal + 1 | |
264 return render_template('edit_note.j2', ordinal=next_ordinal, types=CVRFNote.TYPES, action='Add') | |
265 | |
266 title = None | |
267 audience = None | |
268 title = request.form['title'] or None | |
269 audience = request.form['audience'] or None | |
270 | |
271 note = CVRFNote(request.form['type'], int(request.form['ordinal']), request.form['note'], title, audience) | |
272 get_current().addNote(note) | |
273 return redirect(url_for('document')) | |
274 | |
275 @app.route('/reference/<int:index>/edit', methods=['GET', 'POST']) | |
276 @document_required | |
277 def edit_reference(index): | |
278 try: | |
279 ref = get_current()._references[index] | |
280 except IndexError: | |
281 abort(404) | |
282 if request.method != 'POST': | |
283 return render_template('edit_reference.j2', _type=ref._type, url=ref._url, description=ref._description, types=('',) + ref.TYPES) | |
284 | |
285 ref._type = request.form['type'] or None | |
286 ref._url = request.form['url'] | |
287 ref._description = request.form['description'] | |
288 return redirect(url_for('document')) | |
289 | |
290 | |
291 @app.route('/reference/add', methods=['GET', 'POST']) | |
292 @document_required | |
293 def add_reference(): | |
294 if request.method != 'POST': | |
295 return render_template('edit_reference.j2', action='Add', types=('',) + CVRFReference.TYPES) | |
296 | |
297 ref = CVRFReference(request.form['url'], request.form['description'], request.form['type'] or None) | |
298 get_current().addReference(ref) | |
299 return redirect(url_for('document')) | |
300 | |
301 @app.route('/acknowledgment/<int:index>') | |
302 @document_required | |
303 def view_acknowledgment(index): | |
304 try: | |
305 ack = get_current()._acknowledgments[index] | |
306 except IndexError: | |
307 abort(404) | |
308 return render_template('view_acknowledgment.j2', acknowledgment=ack, index=index, action='Update') | |
309 | |
310 @app.route('/acknowledgment/<int:index>/edit', methods=['GET', 'POST']) | |
311 @document_required | |
312 def edit_acknowledgment(index): | |
313 try: | |
314 ack = get_current()._acknowledgments[index] | |
315 except IndexError: | |
316 abort(404) | |
317 if request.method != 'POST': | |
318 return render_template('edit_acknowledgment.j2', name=ack._name, organization=ack._organization, description=ack._description, url=ack._url, action='Update') | |
319 | |
320 ack._name = request.form['name'] or None | |
321 ack._organization = request.form['organization'] or None | |
322 ack._description = request.form['description'] or None | |
323 ack._url = request.form['url'] or None | |
324 return redirect(url_for('document')) | |
325 | |
326 @app.route('/acknowledgment/add', methods=['GET', 'POST']) | |
327 @document_required | |
328 def add_acknowledgment(): | |
329 if request.method != 'POST': | |
330 return render_template('edit_acknowledgment.j2', action='Add') | |
331 | |
332 ack = CVRFAcknowledgment() | |
333 ack._name = request.form['name'] or None | |
334 ack._organization = request.form['organization'] or None | |
335 ack._description = request.form['description'] or None | |
336 ack._url = request.form['url'] or None | |
337 get_current().addAcknowledgment(ack) | |
338 return redirect(url_for('document')) | |
339 | |
340 | |
341 @app.route('/render/<format_>') | |
342 @document_required | |
343 def render(format_): | |
344 cvrf = get_current() | |
345 doc = render_cvrf(cvrf, format_ + '.j2') | |
346 return render_template('render.j2', format_=format_, title=cvrf._title, type_=cvrf._type, doc=doc ) | |
347 | |
348 @app.route('/save', methods=['GET', 'POST']) | |
349 @document_required | |
350 def save(): | |
351 if request.method != 'POST': | |
352 return render_template('save.j2', id_=get_current()._tracking._identification._id) | |
353 # Get some kind of filename, and save the cvrf on cache (disk) | |
354 path = secure_filename(request.form['fname']) | |
355 path, _ = os.path.splitext(path) | |
356 with open(os.path.join(app.config['CACHE_DIRECTORY'], path + '.xml'), 'wt') as f: | |
357 f.write(render_cvrf(get_current(), 'cvrf.j2').encode('utf-8')) | |
358 flash('File saved as %s' % path) | |
359 del_current() | |
360 return redirect(url_for('new')) | |
361 | |
362 @app.route('/load/<element>', methods=['GET', 'POST']) | |
363 def load(element): | |
364 if request.method != 'POST': | |
365 if has_current(): | |
366 # Suggest to save first | |
367 return render_template('load.j2', element=element) | |
368 | |
369 fpath = os.path.join(app.config['CACHE_DIRECTORY'], element+'.xml') | |
370 with open(fpath, 'rt') as f: | |
371 set_current(parse(f)) | |
372 os.remove(fpath) | |
373 flash('"%s" has been removed from cache' % element) | |
374 # Get some kind of id, and load the file. | |
375 return redirect(url_for('document')) | |
376 | |
377 @app.route('/about') | |
378 def about(): | |
379 return render_template('about.j2') | |
380 |