Mercurial > farol > farol
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/farol/main.py Wed Sep 24 10:07:49 2014 +0200 @@ -0,0 +1,380 @@ +# -*- encoding: utf-8 -*- +# Description: +# Farol Web Application +# +# Authors: +# BenoƮt Allard <benoit.allard@greenbone.net> +# +# Copyright: +# Copyright (C) 2014 Greenbone Networks GmbH +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + +import os + +from farolluz.cvrf import (CVRF, CVRFPublisher, CVRFTracking, CVRFTrackingID, + CVRFGenerator, CVRFRevision, CVRFReference, CVRFAcknowledgment, CVRFNote, + ValidationError, CVRFAggregateSeverity) +from farolluz.parsers.cvrf import parse, parseVersion, parseDate +from farolluz.py2 import urlopen +from farolluz.renderer import render as render_cvrf +from farolluz.utils import utcnow + +from flask import Flask, request, render_template, redirect, url_for, flash, abort +from werkzeug import secure_filename + +from .session import get_current, set_current, has_current, del_current, document_required +from .vulnerability import vulnerability +from .producttree import producttree + +app = Flask(__name__) + +app.register_blueprint(vulnerability, url_prefix='/vulnerability') +app.register_blueprint(producttree, url_prefix='/producttree') + +@app.context_processor +def cache_content(): + """ List the documents in cache """ + if 'CACHE_DIRECTORY' not in app.config: + return dict(cache=[]) + dirname = app.config['CACHE_DIRECTORY'] + if not os.path.exists(dirname): + os.mkdir(dirname) + l = [] + for path in os.listdir(dirname): + name, ext = os.path.splitext(path) + if ext == '.xml': + l.append(name) + return dict(cache=l) + +@app.context_processor +def doc_properties(): + if not has_current(): + return {'has_current': False} + cvrf = get_current() + vulns = [(v.getTitle(), v._ordinal) for v in cvrf._vulnerabilities] + prods = [] + if cvrf._producttree: + prods = [(p._name, p._productid) for p in cvrf._producttree._products] + try: + cvrf.validate() + error = None + except ValidationError as ve: + error = ve + return dict(has_current=True, vulnerabilities=vulns, products=prods, error=error) + +@app.template_filter('secure_filename') +def makeId(string): + return secure_filename(string) + +@app.route('/new', methods=['GET', 'POST']) +def new(): + if request.method != 'POST': + return render_template('new.j2', has_document=has_current(), now=utcnow()) + + if 'url' in request.form: + set_current(parse(urlopen(request.form['url']).read())) + elif 'local' in request.files: + upload = request.files['local'] + if not upload.filename.endswith('.xml'): + flash('Uploaded files should end in .xml', 'danger') + return redirect(url_for('new')) + fpath = os.path.join('/tmp', secure_filename(upload.filename)) + upload.save(fpath) + with open(fpath, 'rt') as f: + set_current(parse(f)) + os.remove(fpath) + elif 'text' in request.form: + set_current(parse(request.form['text'].encode('utf-8'))) + else: + set_current(CVRF(request.form['title'], request.form['type'])) + return redirect(url_for('document')) + +@app.route('/') +@document_required +def document(): + cvrf = get_current() + return render_template('doc.j2', cvrf=cvrf) + +@app.route('/title/edit', methods=['GET', 'POST']) +@document_required +def edit_title(): + if request.method != 'POST': + return render_template('edit_title.j2', title = get_current()._title, _type = get_current()._type) + + + get_current()._title = request.form['title'] + get_current()._type = request.form['type'] + return redirect(url_for('document')) + +@app.route('/publisher/edit', methods=['GET', 'POST']) +@document_required +def edit_publisher(): + if request.method != 'POST': + return render_template('edit_publisher.j2', publisher = get_current()._publisher or CVRFPublisher(''), types=CVRFPublisher.TYPES) + + publisher = CVRFPublisher(request.form['type'], request.form['vendorid'] or None) + publisher.setContact(request.form['contact'] or None) + publisher.setAuthority(request.form['authority'] or None) + get_current().setPublisher(publisher) + return redirect(url_for('document')) + +@app.route('/tracking/edit', methods=['GET', 'POST']) +@document_required +def edit_tracking(): + wasNone = False + tracking = get_current()._tracking + if tracking is None: + wasNone = True + tracking = CVRFTracking(CVRFTrackingID(''), 'Draft', (0,), utcnow(), utcnow()) + generator = tracking._generator + if not tracking._generator: + generator = CVRFGenerator() + if request.method != 'POST': + return render_template('edit_tracking.j2', tracking=tracking, version='.'.join('%s'%v for v in tracking._version), generator=generator, now=utcnow(), statuses=tracking.STATUSES) + + tracking._identification._id = request.form['id'] + aliases = [] + if request.form['id_aliases']: + aliases = [a.strip() for a in request.form['id_aliases'].split(',')] + tracking._identification._aliases = aliases + tracking._status = request.form['status'] + tracking._version = parseVersion(request.form['version']) + tracking._initialDate = parseDate(request.form['initial']) + tracking._currentDate = parseDate(request.form['current']) + if wasNone: + get_current().setTracking(tracking) + if (not request.form['gen_engine']) and (not request.form['gen_date']): + generator = None + else: + generator._engine = request.form['gen_engine'] or None + if request.form['gen_date']: + generator._date = parseDate(request.form['gen_date']) + else: + generator._date = None + tracking.setGenerator(generator) + return redirect(url_for('document')) + +@app.route('/revision/<int:index>/edit', methods=['GET', 'POST']) +@document_required +def edit_revision(index): + cvrf = get_current() + if cvrf._tracking is None: + abort(404) + try: + revision = cvrf._tracking._history[index] + except IndexError: + abort(404) + if request.method != 'POST': + return render_template('edit_revision.j2', number='.'.join('%s'%v for v in revision._number), date=revision._date, description=revision._description, action='Update') + + revision._number = parseVersion(request.form['number']) + revision._date = parseDate(request.form['date']) + revision._description = request.form['description'] + return redirect(url_for('document')) + +@app.route('/revision/add', methods=['GET', 'POST']) +@document_required +def add_revision(): + tracking = get_current()._tracking + if request.method != 'POST': + version = tracking._version + version = version[:-1] + (version[-1] + 1,) + return render_template('edit_revision.j2', number='.'.join("%d"%v for v in version), date=utcnow(), action='Add') + + version = parseVersion(request.form['number']) + date = parseDate(request.form['date']) + revision = CVRFRevision(version, date, request.form['description']) + tracking.addRevision(revision) + if 'update_tracking' in request.form: + tracking._version = version + tracking._currentDate = date + return redirect(url_for('document')) + +@app.route('/distribution/edit', methods=['GET', 'POST']) +@document_required +def edit_distribution(): + if request.method != 'POST': + return render_template('edit_distribution.j2', distribution=get_current()._distribution) + + get_current().setDistribution(request.form['distribution']) + return redirect(url_for('document')) + +@app.route('/severity/edit', methods=['GET', 'POST']) +@document_required +def edit_severity(): + severity = get_current()._aggregateseverity + if severity is None: + severity = CVRFAggregateSeverity('') + if request.method != 'POST': + return render_template('edit_severity.j2', severity=severity) + if not request.form['severity']: + severity = None + else: + severity._severity = request.form['severity'] + severity.setNamespace(request.form['namespace'] or None) + get_current().setAggregateSeverity(severity) + return redirect(url_for('document')) + +@app.route('/note/<int:ordinal>') +@document_required +def view_note(ordinal): + note = get_current().getNote(ordinal) + if note is None: + abort(404) + return render_template('view_note.j2', note=note) + +@app.route('/note/<int:ordinal>/edit', methods=['GET', 'POST']) +@document_required +def edit_note(ordinal): + note = get_current().getNote(ordinal) + if note is None: + abort(404) + if request.method != 'POST': + return render_template('edit_note.j2', note=note, types = note.TYPES) + + note._type = request.form['type'] + note._ordinal = int(request.form['ordinal']) + note._note = request.form['note'] + note._title = request.form['title'] or None + note._audience = request.form['audience'] or None + return redirect(url_for('view_note', ordinal=note._ordinal )) + + +@app.route('/note/add', methods=['GET', 'POST']) +@document_required +def add_note(): + if request.method != 'POST': + next_ordinal = 1 + notes = get_current()._notes + if notes: + next_ordinal = notes[-1]._ordinal + 1 + return render_template('edit_note.j2', ordinal=next_ordinal, types=CVRFNote.TYPES, action='Add') + + title = None + audience = None + title = request.form['title'] or None + audience = request.form['audience'] or None + + note = CVRFNote(request.form['type'], int(request.form['ordinal']), request.form['note'], title, audience) + get_current().addNote(note) + return redirect(url_for('document')) + +@app.route('/reference/<int:index>/edit', methods=['GET', 'POST']) +@document_required +def edit_reference(index): + try: + ref = get_current()._references[index] + except IndexError: + abort(404) + if request.method != 'POST': + return render_template('edit_reference.j2', _type=ref._type, url=ref._url, description=ref._description, types=('',) + ref.TYPES) + + ref._type = request.form['type'] or None + ref._url = request.form['url'] + ref._description = request.form['description'] + return redirect(url_for('document')) + + +@app.route('/reference/add', methods=['GET', 'POST']) +@document_required +def add_reference(): + if request.method != 'POST': + return render_template('edit_reference.j2', action='Add', types=('',) + CVRFReference.TYPES) + + ref = CVRFReference(request.form['url'], request.form['description'], request.form['type'] or None) + get_current().addReference(ref) + return redirect(url_for('document')) + +@app.route('/acknowledgment/<int:index>') +@document_required +def view_acknowledgment(index): + try: + ack = get_current()._acknowledgments[index] + except IndexError: + abort(404) + return render_template('view_acknowledgment.j2', acknowledgment=ack, index=index, action='Update') + +@app.route('/acknowledgment/<int:index>/edit', methods=['GET', 'POST']) +@document_required +def edit_acknowledgment(index): + try: + ack = get_current()._acknowledgments[index] + except IndexError: + abort(404) + if request.method != 'POST': + return render_template('edit_acknowledgment.j2', name=ack._name, organization=ack._organization, description=ack._description, url=ack._url, action='Update') + + ack._name = request.form['name'] or None + ack._organization = request.form['organization'] or None + ack._description = request.form['description'] or None + ack._url = request.form['url'] or None + return redirect(url_for('document')) + +@app.route('/acknowledgment/add', methods=['GET', 'POST']) +@document_required +def add_acknowledgment(): + if request.method != 'POST': + return render_template('edit_acknowledgment.j2', action='Add') + + ack = CVRFAcknowledgment() + ack._name = request.form['name'] or None + ack._organization = request.form['organization'] or None + ack._description = request.form['description'] or None + ack._url = request.form['url'] or None + get_current().addAcknowledgment(ack) + return redirect(url_for('document')) + + +@app.route('/render/<format_>') +@document_required +def render(format_): + cvrf = get_current() + doc = render_cvrf(cvrf, format_ + '.j2') + return render_template('render.j2', format_=format_, title=cvrf._title, type_=cvrf._type, doc=doc ) + +@app.route('/save', methods=['GET', 'POST']) +@document_required +def save(): + if request.method != 'POST': + return render_template('save.j2', id_=get_current()._tracking._identification._id) + # Get some kind of filename, and save the cvrf on cache (disk) + path = secure_filename(request.form['fname']) + path, _ = os.path.splitext(path) + with open(os.path.join(app.config['CACHE_DIRECTORY'], path + '.xml'), 'wt') as f: + f.write(render_cvrf(get_current(), 'cvrf.j2').encode('utf-8')) + flash('File saved as %s' % path) + del_current() + return redirect(url_for('new')) + +@app.route('/load/<element>', methods=['GET', 'POST']) +def load(element): + if request.method != 'POST': + if has_current(): + # Suggest to save first + return render_template('load.j2', element=element) + + fpath = os.path.join(app.config['CACHE_DIRECTORY'], element+'.xml') + with open(fpath, 'rt') as f: + set_current(parse(f)) + os.remove(fpath) + flash('"%s" has been removed from cache' % element) + # Get some kind of id, and load the file. + return redirect(url_for('document')) + +@app.route('/about') +def about(): + return render_template('about.j2') +