Skip to content
Commits on Source (264)
# EditorConfig is awesome: http://EditorConfig.org
# top-most EditorConfig file
root = true
# Unix-style newlines with a newline ending every file
[*]
end_of_line = lf
insert_final_newline = true
charset = utf-8
[*.{js,html,css}]
indent_style = tab
indent_size = 2
[*.py]
indent_style = space
indent_size = 4
[Makefile]
indent_style = tab
[.gitlab-ci.yml}]
indent_style = space
indent_size = 2
......@@ -5,3 +5,5 @@ devel.sh
.coverage
dist
py2.7
_build
.tags
docker:
image: python:2.7
script:
- bash test/run_tests.sh
tags:
- docker
except:
- tags
Changelog
=========
Current
-------
- `Full changelog <https://git.ziirish.me/ziirish/burp-ui/compare/v0.0.7...master>`__
0.0.7
-----
- Add `Burp-2 backend <https://git.ziirish.me/ziirish/burp-ui/issues/52>`_
- Add `sortable tables <https://git.ziirish.me/ziirish/burp-ui/issues/51>`_
- Add `ACL support <https://git.ziirish.me/ziirish/burp-ui/issues/47>`_
- Add `support client-side encrypted backups while performing an online restoration <https://git.ziirish.me/ziirish/burp-ui/issues/44>`_
- Add `multiple archive format <https://git.ziirish.me/ziirish/burp-ui/issues/31>`_
- Add `better Active Directory support <https://git.ziirish.me/ziirish/burp-ui/issues/64>`__
- Improvement: `better config file parser <https://git.ziirish.me/ziirish/burp-ui/issues/50>`_
- Improvement: `better logging with Gunicorn <https://git.ziirish.me/ziirish/burp-ui/issues/65>`_
- Improvement: `full support of server configuration file + clientconfdir <https://git.ziirish.me/ziirish/burp-ui/issues/13>`_
- Fix issue `#35 <https://git.ziirish.me/ziirish/burp-ui/issues/35>`_
- Fix issue `#37 <https://git.ziirish.me/ziirish/burp-ui/issues/37>`_
- Fix issue `#41 <https://git.ziirish.me/ziirish/burp-ui/issues/41>`_
- Fix issue `#42 <https://git.ziirish.me/ziirish/burp-ui/issues/42>`_
- Fix issue `#46 <https://git.ziirish.me/ziirish/burp-ui/issues/46>`_
- Fix issue `#49 <https://git.ziirish.me/ziirish/burp-ui/issues/49>`_
- Fix issue `#53 <https://git.ziirish.me/ziirish/burp-ui/issues/53>`_
- Fix issue `#54 <https://git.ziirish.me/ziirish/burp-ui/issues/54>`_
- Fix issue `#59 <https://git.ziirish.me/ziirish/burp-ui/issues/59>`_
- Fix issue `#62 <https://git.ziirish.me/ziirish/burp-ui/issues/62>`_
- Fix issue `#68 <https://git.ziirish.me/ziirish/burp-ui/issues/68>`_
- Fix issue `#69 <https://git.ziirish.me/ziirish/burp-ui/issues/69>`_
- Fix issue `#70 <https://git.ziirish.me/ziirish/burp-ui/issues/70>`_
- Fix issue `#71 <https://git.ziirish.me/ziirish/burp-ui/issues/71>`_
- Fix issue `#72 <https://git.ziirish.me/ziirish/burp-ui/issues/72>`_
- doc on `readthedocs <http://burp-ui.readthedocs.org/en/latest/>`_
- Two merge requests from Wade Fitzpatrick (`!1 <https://git.ziirish.me/ziirish/burp-ui/merge_requests/1>`_ and `!2 <https://git.ziirish.me/ziirish/burp-ui/merge_requests/2>`_)
- API refactoring
- Security fixes
- Bufixes
- `Full changelog <https://git.ziirish.me/ziirish/burp-ui/compare/v0.0.6...v0.0.7>`__
0.0.6
-----
- Add `gunicorn support <https://git.ziirish.me/ziirish/burp-ui/commit/836f522f51ba0706ca94b379d93b20c75e71ecb1>`_
- Add `init script for CentOS <https://git.ziirish.me/ziirish/burp-ui/issues/27>`_
- Add `init script for Debian <https://git.ziirish.me/ziirish/burp-ui/issues/29>`_
- Add `autofocus login field on login page <https://git.ziirish.me/ziirish/burp-ui/commit/a559c3c2191991f1065ff15df4cd94757133e67d>`_
- Add `burp-server configuration panel <https://git.ziirish.me/ziirish/burp-ui/issues/13>`_
- Fix issue `#25 <https://git.ziirish.me/ziirish/burp-ui/issues/25>`_
- Fix issue `#26 <https://git.ziirish.me/ziirish/burp-ui/issues/26>`_
- Fix issue `#30 <https://git.ziirish.me/ziirish/burp-ui/issues/30>`_
- Fix issue `#32 <https://git.ziirish.me/ziirish/burp-ui/issues/32>`_
- Fix issue `#33 <https://git.ziirish.me/ziirish/burp-ui/issues/33>`_
- Fix issue `#34 <https://git.ziirish.me/ziirish/burp-ui/issues/34>`_
- Fix issue `#35 <https://git.ziirish.me/ziirish/burp-ui/issues/35>`_
- Fix issue `#39 <https://git.ziirish.me/ziirish/burp-ui/issues/39>`_
- Code cleanup
- Improve unit tests
- Bugfixes
- `Full changelog <https://git.ziirish.me/ziirish/burp-ui/compare/v0.0.5...v0.0.6>`__
0.0.5
-----
- Add multi-server support
- Fix bugs
- `Full changelog <https://git.ziirish.me/ziirish/burp-ui/compare/v0.0.4...v0.0.5>`__
0.0.4
-----
- Add the ability to download files directly from the web interface
- `Full changelog <https://git.ziirish.me/ziirish/burp-ui/compare/v0.0.3...v0.0.4>`__
0.0.3
-----
- Add authentication
- `Full changelog <https://git.ziirish.me/ziirish/burp-ui/compare/v0.0.2...v0.0.3>`__
0.0.2
-----
- Fix bugs
- `Full changelog <https://git.ziirish.me/ziirish/burp-ui/compare/v0.0.1...v0.0.2>`__
0.0.1
-----
- Initial release
......@@ -4,7 +4,7 @@ The following License only applies to the burp-ui sources
================================================================================
Copyright (c) 2014 by Benjamin SANS (Ziirish) <ziirish+burpui@ziirish.info>
Copyright (c) 2014-2015 by Benjamin SANS (Ziirish) <ziirish+burpui@ziirish.info>
http://ziirish.info/
Some rights reserved.
......
......@@ -3,8 +3,9 @@ include README.rst
include VERSION
include requirements.txt
include test-requirements.txt
include share/burpui/etc/burpui.cfg
include share/burpui/etc/buiagent.cfg
include share/burpui/etc/burpui.sample.cfg
include share/burpui/etc/buiagent.sample.cfg
include contrib/debian/init.sh
include contrib/centos/init.sh
include contrib/gunicorn.d/burp-ui
recursive-include burpui *
Build Status
------------
Badges
======
.. image:: https://ci.ziirish.me/projects/1/status.png?ref=0.0.7
:target: https://ci.ziirish.me/projects/1?ref=0.0.7
:alt: Build Status
.. image:: https://readthedocs.org/projects/burp-ui/badge/?version=stable
:target: https://readthedocs.org/projects/burp-ui/?badge=stable
:alt: Documentation Status
.. image:: https://ci.ziirish.me/projects/1/status.png?ref=master
:target: https://ci.ziirish.me/projects/1?ref=master
Introduction
============
Screenshots
-----------
......@@ -17,236 +25,58 @@ What's that?
Let me introduce you ``Burp-UI``. It is a web-based UI to manage your
burp-servers.
You can view different reports about burp-servers, burp-clients, backups, etc.
``Burp-UI`` allows you to perform *on-the-fly* restorations and should allow
you to edit/manage your burp-server's conf file very soon.
``Burp-UI`` allows you to perform *on-the-fly* restorations and to edit/manage
your burp-server's configuration files.
It is actually an improvement of the burp status monitor (``burp -c /etc/burp/burp-server.conf -a s``).
It currently supports only the burp-1.x branch but it is totally modular so
supporting burp-2.x won't be a big deal.
So in order to work properly, you must be running ``Burp-UI`` on the same host
that runs your burp-server (because the burp status port only listen on
*localhost*).
If you don't want to, I developed a ``bui-agent`` that allows you to *proxify*
In order to work properly, you must be running ``Burp-UI`` on the same host that
runs your burp-server (because the burp status port only listen on *localhost*).
If you don't want to, I developed a ``bui-agent`` that allows you to *proxify*
external commands to your burp status port.
Who are you?
------------
I'm `Ziirish <http://ziirish.info>`_, a French sysadmin that loves `Burp`_ and
would like to help its adoption by providing it a nice and powerful interface.
I'm `Ziirish <http://ziirish.info>`__, a French sysadmin who loves `Burp`_ and
who'd like to help its adoption by providing it a nice and powerful interface.
If you like my work, you can:
* Thank me by sending me an email or writing a nice comment
* Buy me a beer or some fries or both!
* Make a donation on my Paypal
Contributing
------------
Contributions are welcome. You can help in any way you want, for instance by
opening issues on the `bug tracker <https://git.ziirish.me/ziirish/burp-ui/issues>`__,
sending patches, etc.
There is also a dedicated website. Currently it only hosts a `Discourse <http://www.discourse.org/>`__
instance where you ca discuss with each other.
Feel free to use it and post your tips and remarks.
The address is: `http://burpui.ziirish.me/ <http://burpui.ziirish.me/>`__
Requirements
------------
Please note that currently, ``Burp-UI`` must be running on the same server that
runs the burp-server.
For LDAP authentication (optional), we need the ``simpleldap`` module that
requires the following packages on Debian:
::
aptitude install libsasl2-dev libldap2-dev python-dev
Then we install the module itself:
::
* Thank me by sending me an email or writing nice comments
* Buy me a beer or some fries (or both!)
* Make a donation on my `Paypal <http://ziirish.info>`__
pip install simpleldap
Documentation
=============
Installation
------------
``Burp-UI`` is written in Python with the `Flask`_ micro-framework.
The easiest way to install Flask is to use ``pip``.
On Debian, you can install ``pip`` with the following command:
::
aptitude install python-pip
Once ``pip`` is installed, you can install ``Burp-UI`` this way:
::
pip install burp-ui
You can setup various parameters in the `burpui.cfg`_ file.
This file can be specified with the ``-c`` flag or should be present in
``/etc/burp/burpui.cfg``.
By default ``Burp-UI`` ships with a default file located in
``$BURPUIDIR/../share/burpui/etc/burpui.cfg``.
Then you can run ``burp-ui``: ``burp-ui``
By default, ``burp-ui`` listens on all interfaces (including IPv6) on port 5000.
You can then point your browser to http://127.0.0.1:5000/
Development
-----------
If you wish to use the latest and yet unstable version (eg. `master <https://git.ziirish.me/ziirish/burp-ui/tree/master>`__),
you can install it using ``pip`` too, but I would recommend you to use a
``virtualenv``.
The documentation is hosted on `readthedocs <https://readthedocs.org>`_ at the
following address: `burp-ui.readthedocs.org <https://burp-ui.readthedocs.org/en/stable/>`_
To do so, run the following commands:
::
Community
=========
mkdir /opt/bui-venv
pip install virtualenv
virtualenv /opt/bui-venv
source /opt/bui-venv/bin/activate
pip install git+https://git.ziirish.me/ziirish/burp-ui.git
You can uninstall/disable this ``Burp-UI`` setup by typing ``deactivate`` and
removing the ``/opt/bui-venv`` directory.
Gunicorn
--------
Starting from v0.0.6, ``Burp-UI`` supports `Gunicorn <http://gunicorn.org>`_ in
order to handle multiple users simultaneously.
You need to install ``gunicorn`` and ``eventlet``:
::
pip install eventlet
pip install gunicorn
You will then be able to launch ``Burp-UI`` this way:
::
gunicorn -k eventlet -w 4 'burpui:init(conf="/path/to/burpui.cfg")'
Instructions
------------
In order to make the *on the fly* restoration/download functionality work, you
need to check a few things:
1. Provide the full path of the burp (client) binary file
2. Provide the full path of an empty directory where a temporary restoration
will be made. This involves you have enough space left on that location on
the server that runs ``Burp-UI``
3. Launch ``Burp-UI`` with a user that can proceed restorations and that can
write in the directory above
4. Make sure to configure a client on the server that runs ``Burp-UI`` that can
restore files of other clients (option *restore_client* in burp-server
configuration)
Troubleshooting
---------------
In case you encounter troubles with ``Burp-UI``, you should run it with the
``-d`` flag and paste the relevant output within your bug-report.
Please also give the version of ``burp`` AND ``Burp-UI``.
Since v0.0.6 you can use the ``-V`` or ``--version`` flag in order to get your
version number.
Please refer to the `Contributing <https://burp-ui.readthedocs.org/en/stable/contributing.html>`_ page.
Notes
-----
=====
Please feel free to report any issues on my `gitlab <https://git.ziirish.me/ziirish/burp-ui/issues>`_.
I have closed the *github tracker* to have a unique tracker system.
TODO
----
====
`Here <https://git.ziirish.me/ziirish/burp-ui/issues?label_name=todo>`_ is a
non-exhaustive list of things I'd like to add.
Also note that in the future, I'd like to write a burp-client GUI.
But I didn't think yet of what to do.
Changelog
---------
* version `current <https://git.ziirish.me/ziirish/burp-ui/>`_:
- Add `gunicorn support <https://git.ziirish.me/ziirish/burp-ui/commit/836f522f51ba0706ca94b379d93b20c75e71ecb1>`_
- Add `init script for CentOS <https://git.ziirish.me/ziirish/burp-ui/issues/27>`_
- Add `init script for Debian <https://git.ziirish.me/ziirish/burp-ui/issues/29>`_
- Add `autofocus login field on login page <https://git.ziirish.me/ziirish/burp-ui/commit/a559c3c2191991f1065ff15df4cd94757133e67d>`_
- Add `burp-server configuration panel <https://git.ziirish.me/ziirish/burp-ui/issues/13>`_
- Fix issue `#25 <https://git.ziirish.me/ziirish/burp-ui/issues/25>`_
- Fix issue `#26 <https://git.ziirish.me/ziirish/burp-ui/issues/26>`_
- Fix issue `#30 <https://git.ziirish.me/ziirish/burp-ui/issues/30>`_
- Fix issue `#32 <https://git.ziirish.me/ziirish/burp-ui/issues/32>`_
- Fix issue `#33 <https://git.ziirish.me/ziirish/burp-ui/issues/33>`_
- Fix issue `#34 <https://git.ziirish.me/ziirish/burp-ui/issues/34>`_
- Fix issue `#35 <https://git.ziirish.me/ziirish/burp-ui/issues/35>`_
- Fix issue `#39 <https://git.ziirish.me/ziirish/burp-ui/issues/39>`_
- Code cleanup
- Improve unit tests
- Bugfixes
- `Full changelog <https://git.ziirish.me/ziirish/burp-ui/compare/v0.0.5...master>`_
* version `0.0.5 <https://git.ziirish.me/ziirish/burp-ui/commits/v0.0.5>`_:
- Add multi-server support
- Fix bugs
- `Full changelog <https://git.ziirish.me/ziirish/burp-ui/compare/v0.0.4...v0.0.5>`_
* version `0.0.4 <https://git.ziirish.me/ziirish/burp-ui/commits/v0.0.4>`_:
- Add the ability to download files directly from the web interface
- `Full changelog <https://git.ziirish.me/ziirish/burp-ui/compare/v0.0.3...v0.0.4>`_
* version `0.0.3 <https://git.ziirish.me/ziirish/burp-ui/commits/v0.0.3>`_:
- Add authentication
- `Full changelog <https://git.ziirish.me/ziirish/burp-ui/compare/v0.0.2...v0.0.3>`_
* version `0.0.2 <https://git.ziirish.me/ziirish/burp-ui/commits/v0.0.2>`_:
- Fix bugs
- `Full changelog <https://git.ziirish.me/ziirish/burp-ui/compare/v0.0.1...v0.0.2>`_
* version `0.0.1 <https://git.ziirish.me/ziirish/burp-ui/commits/v0.0.1>`_:
- Initial release
Licenses
--------
========
``Burp-UI`` is released under the BSD 3-clause `License`_.
......@@ -265,18 +95,20 @@ But this project is built on top of other tools listed here:
- `angular-ui-select <https://github.com/angular-ui/ui-select>`_ (`MIT <https://git.ziirish.me/ziirish/burp-ui/blob/master/burpui/static/angular-ui-select/LICENSE>`__)
- `AngularStrap <http://mgcrea.github.io/angular-strap/>`_ (`MIT <https://git.ziirish.me/ziirish/burp-ui/blob/master/burpui/static/angular-strap/LICENSE.md>`__)
- `lodash <https://github.com/lodash/lodash>`_ (`MIT <https://git.ziirish.me/ziirish/burp-ui/blob/master/burpui/static/lodash/LICENSE.txt>`__)
- `DataTables <http://datatables.net/>`_ (`MIT <https://git.ziirish.me/ziirish/burp-ui/blob/master/burpui/static/DataTables/LICENSE.txt>`__)
- Home-made `favicon <https://git.ziirish.me/ziirish/burp-ui/blob/master/burpui/static/images/favicon.ico>`_ based on pictures from `simpsoncrazy <http://www.simpsoncrazy.com/pictures/homer>`_
Also note that this project is made with the Awesome `Flask`_ micro-framework.
Thanks
------
======
Special Thanks to Graham Keeling for its great software! This project would not
exist without `Burp`_.
.. _Flask: http://flask.pocoo.org/
.. _License: https://git.ziirish.me/ziirish/burp-ui/blob/master/LICENSE
.. _Burp: http://burp.grke.org/
.. _burpui.cfg: https://git.ziirish.me/ziirish/burp-ui/blob/master/burpui.cfg
.. _burpui.cfg: https://git.ziirish.me/ziirish/burp-ui/blob/master/share/burpui/etc/burpui.sample.cfg
......@@ -25,7 +25,18 @@ if __name__ == '__main__':
else:
raise IOError('File not found: \'{0}\''.format(options.config))
else:
conf_files = ['/etc/burp/buiagent.cfg', os.path.join(os.path.dirname(os.path.realpath(__file__)), '..', 'share', 'burpui', 'etc', 'buiagent.cfg')]
root = os.path.join(
os.path.dirname(os.path.realpath(__file__)),
'..',
'share',
'burpui',
'etc'
)
conf_files = [
'/etc/burp/buiagent.cfg',
os.path.join(root, 'buiagent.cfg'),
os.path.join(root, 'buiagent.sample.cfg')
]
for p in conf_files:
if os.path.isfile(p):
conf = p
......
......@@ -13,19 +13,19 @@ if __name__ == '__main__':
Main function
"""
parser = OptionParser()
parser.add_option('-v', '--verbose', dest='log', help='Verbose output.', action='store_true')
parser.add_option('-d', '--debug', dest='log', help='Verbose output (alias).', action='store_true') #alias for -v
parser.add_option('-V', '--version', dest='version', help='Print version and exit.', action='store_true')
parser.add_option('-c', '--config', dest='config', help='Configuration file.', metavar='CONFIG')
parser.add_option('-v', '--verbose', dest='log', help='verbose output', action='store_true')
parser.add_option('-d', '--debug', dest='log', help='verbose output (alias)', action='store_true') # alias for -v
parser.add_option('-V', '--version', dest='version', help='print version and exit', action='store_true')
parser.add_option('-c', '--config', dest='config', help='configuration file', metavar='CONFIG')
parser.add_option('-l', '--logfile', dest='logfile', help='output logs in defined file', metavar='FILE')
(options, args) = parser.parse_args()
d = options.log
if options.version:
print '{}: v{}'.format(__title__, __version__)
print ('{}: v{}'.format(__title__, __version__))
sys.exit(0)
init(options.config, d, False)
init(options.config, d, options.logfile, False)
bui.run(d)
share/burpui/etc/buiagent.cfg
\ No newline at end of file
share/burpui/etc/buiagent.sample.cfg
\ No newline at end of file
share/burpui/etc/burpui.cfg
\ No newline at end of file
share/burpui/etc/burpui.sample.cfg
\ No newline at end of file
......@@ -3,19 +3,28 @@
Burp-UI is a web-ui for burp backup written in python with Flask and
jQuery/Bootstrap
"""
__title__ = 'burp-ui'
__author__ = 'Benjamin SANS (Ziirish)'
__author_email__ = 'ziirish+burpui@ziirish.info'
__url__ = 'https://git.ziirish.me/ziirish/burp-ui'
__description__ = 'Burp-UI is a web-ui for burp backup written in python with Flask and jQuery/Bootstrap'
__license__ = 'BSD 3-clause'
__version__ = '0.0.6'
import os
import sys
import logging
from flask import Flask
from flask.ext.login import LoginManager
from burpui.server import BUIServer as BurpUI
from burpui.routes import view
from burpui.api import api
if sys.version_info < (3, 0):
reload(sys)
sys.setdefaultencoding('utf-8')
__title__ = 'burp-ui'
__author__ = 'Benjamin SANS (Ziirish)'
__author_email__ = 'ziirish+burpui@ziirish.info'
__url__ = 'https://git.ziirish.me/ziirish/burp-ui'
__description__ = 'Burp-UI is a web-ui for burp backup written in python with Flask and jQuery/Bootstrap'
__license__ = 'BSD 3-clause'
__version__ = '0.0.7.1'
# First, we setup the app
app = Flask(__name__)
......@@ -23,32 +32,79 @@ app = Flask(__name__)
app.config['CFG'] = None
app.secret_key = 'VpgOXNXAgcO81xFPyWj07ppN6kExNZeCDRShseNzFKV7ZCgmW2/eLn6xSlt7pYAVBj12zx2Vv9Kw3Q3jd1266A=='
app.jinja_env.globals.update(isinstance=isinstance,list=list)
app.jinja_env.globals.update(isinstance=isinstance, list=list)
app.jinja_env.globals.update(api=api)
# We initialize the core
bui = BurpUI(app)
# Then we load our routes
view.bui = bui
app.register_blueprint(view)
# We initialize the API
api.app = app
api.bui = bui
api.init_app(app)
# And the login_manager
login_manager = LoginManager()
login_manager.init_app(app)
login_manager.login_view = 'login'
login_manager.login_view = 'view.login'
login_manager.login_message_category = 'info'
# Then we load our routes
import burpui.routes
def init(conf=None, debug=False, gunicorn=True):
app.config['DEBUG'] = debug
if debug:
@login_manager.user_loader
def load_user(userid):
if bui.auth != 'none':
return bui.uhandler.user(userid)
return None
def init(conf=None, debug=False, logfile=None, gunicorn=True):
if debug and not gunicorn:
app.config['DEBUG'] = debug
app.config['TESTING'] = True
if logfile:
from logging import Formatter
from logging.handlers import RotatingFileHandler
file_handler = RotatingFileHandler(logfile, maxBytes=1024 * 1024 * 100, backupCount=20)
if debug:
LOG_FORMAT = (
'-' * 80 + '\n' +
'%(levelname)s in %(module)s [%(pathname)s:%(lineno)d]:\n' +
'%(message)s\n' +
'-' * 80
)
file_handler.setLevel(logging.DEBUG)
else:
LOG_FORMAT = '[%(asctime)s] %(levelname)s in %(module)s: %(message)s'
file_handler.setLevel(logging.INFO)
file_handler.setFormatter(Formatter(LOG_FORMAT))
app.logger.addHandler(file_handler)
if conf:
if os.path.isfile(conf):
app.config['CFG'] = conf
else:
raise IOError('File not found: \'{0}\''.format(conf))
else:
conf_files = ['/etc/burp/burpui.cfg', os.path.join(os.path.dirname(os.path.realpath(__file__)), '..', '..', '..', 'share', 'burpui', 'etc', 'burpui.cfg')]
root = os.path.join(
os.path.dirname(os.path.realpath(__file__)),
'..',
'..',
'..',
'..',
'share',
'burpui',
'etc'
)
conf_files = [
'/etc/burp/burpui.cfg',
os.path.join(root, 'burpui.cfg'),
os.path.join(root, 'burpui.sample.cfg')
]
for p in conf_files:
app.logger.debug('Trying file \'%s\'', p)
if os.path.isfile(p):
......
......@@ -2,39 +2,50 @@
import os
import struct
import select
import json
try:
import ujson as json
except ImportError:
import json
import time
import sys
import pickle
import traceback
import ConfigParser
import SocketServer
from threading import Thread
g_port = '10000'
g_bind = '::'
g_ssl = 'False'
g_ssl = 'False'
g_version = '1'
g_sslcert = ''
g_sslkey = ''
g_sslkey = ''
g_timeout = '5'
g_password = 'password'
class BUIAgent:
def __init__(self, conf=None, debug=False):
global g_port, g_bind, g_ssl, g_version, g_sslcert, g_sslkey, g_password
self.conf = conf
self.dbg = debug
print 'conf: '+self.conf
print 'debug: '+str(self.dbg)
print 'conf: ' + self.conf
print 'debug: ' + str(self.dbg)
if not conf:
raise IOError('No configuration file found')
config = ConfigParser.ConfigParser({'port': g_port,'bind': g_bind,
'ssl': g_ssl, 'sslcert': g_sslcert, 'sslkey': g_sslkey,
'version': g_version, 'password': g_password})
config = ConfigParser.ConfigParser({
'port': g_port, 'bind': g_bind,
'ssl': g_ssl, 'sslcert': g_sslcert, 'sslkey': g_sslkey,
'version': g_version, 'password': g_password
})
with open(conf) as fp:
config.readfp(fp)
try:
self.port = config.getint('Global', 'port')
self.bind = config.get('Global', 'bind')
self.vers = config.getint('Global', 'version')
self.timeout = config.getint('Global', 'timeout')
try:
self.ssl = config.getboolean('Global', 'ssl')
except ValueError:
......@@ -52,23 +63,29 @@ class BUIAgent:
Client = mod.Burp
self.backend = Client(conf=conf)
except Exception, e:
self.app.logger.error('Failed loading backend for Burp version %d: %s', self.vers, str(e))
traceback.print_exc()
self.debug('Failed loading backend for Burp version %d: %s', self.vers, str(e))
sys.exit(2)
self.methods = {
'status': self.backend.status,
'get_backup_logs': self.backend.get_backup_logs,
'get_counters': self.backend.get_counters,
'is_backup_running': self.backend.is_backup_running,
'is_one_backup_running': self.backend.is_one_backup_running,
'get_all_clients': self.backend.get_all_clients,
'get_client': self.backend.get_client,
'get_tree': self.backend.get_tree,
'restore_files': self.backend.restore_files,
'read_conf': self.backend.read_conf,
'store_conf': self.backend.store_conf,
'get_parser_attr': self.backend.get_parser_attr
}
'status': self.backend.status,
'get_backup_logs': self.backend.get_backup_logs,
'get_clients_report': self.backend.get_clients_report,
'get_counters': self.backend.get_counters,
'is_backup_running': self.backend.is_backup_running,
'is_one_backup_running': self.backend.is_one_backup_running,
'get_all_clients': self.backend.get_all_clients,
'get_client': self.backend.get_client,
'get_tree': self.backend.get_tree,
'restore_files': self.backend.restore_files,
'read_conf_cli': self.backend.read_conf_cli,
'store_conf_cli': self.backend.store_conf_cli,
'read_conf_srv': self.backend.read_conf_srv,
'store_conf_srv': self.backend.store_conf_srv,
'expand_path': self.backend.expand_path,
'delete_client': self.backend.delete_client,
'get_parser_attr': self.backend.get_parser_attr
}
self.server = AgentServer((self.bind, self.port), AgentTCPHandler, self)
......@@ -82,15 +99,18 @@ class BUIAgent:
if self.dbg:
print msg % (args)
class AgentTCPHandler(SocketServer.BaseRequestHandler):
"One instance per connection. Override handle(self) to customize action."
def handle(self):
# self.request is the client connection
self.server.agent.debug('===============>')
timeout = self.server.agent.timeout
try:
r, _, _ = select.select([self.request], [], [], 5)
err = None
r, _, _ = select.select([self.request], [], [], timeout)
if not r:
raise Exception ('Socket timed-out')
raise Exception('Socket timed-out 1')
lengthbuf = self.request.recv(8)
length, = struct.unpack('!Q', lengthbuf)
data = self.recvall(length)
......@@ -98,9 +118,9 @@ class AgentTCPHandler(SocketServer.BaseRequestHandler):
self.server.agent.debug('recv: %s', data)
self.server.agent.debug('####################')
j = json.loads(data)
_, w, _ = select.select([], [self.request], [], 5)
_, w, _ = select.select([], [self.request], [], timeout)
if not w:
raise Exception ('Socket timed-out')
raise Exception('Socket timed-out 2')
if j['password'] != self.server.agent.password:
self.server.agent.debug('-----> Wrong Password <-----')
self.request.sendall('KO')
......@@ -111,19 +131,29 @@ class AgentTCPHandler(SocketServer.BaseRequestHandler):
return
self.request.sendall('OK')
if j['func'] == 'restore_files':
res = self.server.agent.methods[j['func']](**j['args'])
res, err = self.server.agent.methods[j['func']](**j['args'])
else:
if j['args']:
if 'pickled' in j and j['pickled']:
# de-serialize arguments if needed
j['args'] = pickle.loads(j['args'])
res = json.dumps(self.server.agent.methods[j['func']](**j['args']))
else:
res = json.dumps(self.server.agent.methods[j['func']]())
self.server.agent.debug('####################')
self.server.agent.debug('result: %s', res)
self.server.agent.debug('####################')
_, w, _ = select.select([], [self.request], [], 5)
_, w, _ = select.select([], [self.request], [], timeout)
if not w:
raise Exception ('Socket timed-out')
raise Exception('Socket timed-out 3')
if j['func'] == 'restore_files':
if err:
self.request.sendall('KO')
size = len(err)
self.request.sendall(struct.pack('!Q', size))
self.request.sendall(err)
raise Exception('Restoration failed')
self.request.sendall('OK')
size = os.path.getsize(res)
self.request.sendall(struct.pack('!Q', size))
with open(res, 'rb') as f:
......@@ -132,14 +162,15 @@ class AgentTCPHandler(SocketServer.BaseRequestHandler):
self.server.agent.debug('sending %d Bytes', len(buf))
self.request.sendall(buf)
buf = f.read(1024)
_, w, _ = select.select([], [self.request], [], 5)
_, w, _ = select.select([], [self.request], [], timeout)
if not w:
raise Exception ('Socket timed-out')
raise Exception('Socket timed-out 4')
os.unlink(res)
else:
self.request.sendall(struct.pack('!Q', len(res)))
self.request.sendall(res)
self.request.close()
except Exception, e:
except Exception as e:
self.server.agent.debug('ERROR: %s', str(e))
finally:
self.server.agent.debug('<===============')
......@@ -159,6 +190,7 @@ class AgentTCPHandler(SocketServer.BaseRequestHandler):
received += len(newbuf)
return buf
class AgentServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
# Ctrl-C will cleanly kill all spawned threads
daemon_threads = True
......@@ -170,15 +202,16 @@ class AgentServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
SocketServer.TCPServer.__init__(self, server_address, RequestHandlerClass)
def get_request(self):
if self.agent.ssl:
if self.agent.ssl:
import ssl
(newsocket, fromaddr) = SocketServer.TCPServer.get_request(self)
connstream = ssl.wrap_socket(newsocket,
server_side=True,
certfile=self.agent.sslcert,
keyfile=self.agent.sslkey,
ssl_version=ssl.PROTOCOL_SSLv23)
connstream = ssl.wrap_socket(
newsocket,
server_side=True,
certfile=self.agent.sslcert,
keyfile=self.agent.sslkey,
ssl_version=ssl.PROTOCOL_SSLv23
)
return connstream, fromaddr
# if we don't use ssl, use the 'super' method
return SocketServer.TCPServer.get_request(self)
# -*- coding: utf8 -*-
"""
.. module:: api
:platform: Unix
:synopsis: Burp-UI api module.
.. moduleauthor:: Ziirish <ziirish@ziirish.info>
"""
import os
import re
from flask.ext.restful import Api
api = Api()
api.bui = None
# hack to automatically import api modules
for f in os.listdir(__path__[0]):
name, ext = os.path.splitext(f)
if (os.path.isfile(os.path.join(__path__[0], f)) and
ext == '.py' and
name not in ['__init__', '.', '..']):
mod = 'burpui.api.' + name
__import__(mod)
# -*- coding: utf8 -*-
"""
.. module:: client
:platform: Unix
:synopsis: Burp-UI client api module.
.. moduleauthor:: Ziirish <ziirish@ziirish.info>
"""
from burpui.api import api
from burpui.misc.backend.interface import BUIserverException
from flask.ext.restful import reqparse, Resource
from flask.ext.login import current_user, login_required
from flask import jsonify
@api.resource('/api/client-tree.json/<name>/<int:backup>',
'/api/<server>/client-tree.json/<name>/<int:backup>',
endpoint='api.client_tree')
class ClientTree(Resource):
"""
The :class:`burpui.api.client.ClientTree` resource allows you to
retrieve a list of files in a given backup.
This resource is part of the :mod:`burpui.api.client` module.
An optional ``GET`` parameter called ``server`` is supported when running
in multi-agent mode.
A mandatory ``GET`` parameter called ``root`` is used to know what path we
are working on.
"""
def __init__(self):
self.parser = reqparse.RequestParser()
self.parser.add_argument('server', type=str)
self.parser.add_argument('root', type=str)
@login_required
def get(self, server=None, name=None, backup=None):
"""
**GET** method provided by the webservice.
The *JSON* returned is:
::
{
"results": [
{
"date": "2015-05-21 14:54:49",
"gid": "0",
"inodes": "173",
"mode": "drwxr-xr-x",
"name": "/",
"parent": "",
"size": "12.0KiB",
"type": "d",
"uid": "0"
}
]
}
The output is filtered by the :mod:`burpui.misc.acl` module so that you
only see stats about the clients you are authorized to.
:param server: Which server to collect data from when in multi-agent mode
:type server: str
:param name: The client we are working on
:type name: str
:param backup: The backup we are working on
:type backup: int
:returns: The *JSON* described above.
"""
if not server:
server = self.parser.parse_args()['server']
j = []
if not name or not backup:
return jsonify(results=j)
root = self.parser.parse_args()['root']
try:
if (api.bui.acl and
(not api.bui.acl.is_admin(current_user.name) and not
api.bui.acl.is_client_allowed(current_user.name,
name,
server))):
raise BUIserverException('Sorry, you are not allowed to view this client')
j = api.bui.cli.get_tree(name, backup, root, agent=server)
except BUIserverException as e:
err = [[2, str(e)]]
return jsonify(notif=err)
return jsonify(results=j)
@api.resource('/api/client-stat.json/<name>',
'/api/<server>/client-stat.json/<name>',
'/api/client-stat.json/<name>/<int:backup>',
'/api/<server>/client-stat.json/<name>/<int:backup>',
endpoint='api.client_stats')
class ClientStats(Resource):
"""
The :class:`burpui.api.client.ClientStats` resource allows you to
retrieve a statistics on a given backup for a given client.
This resource is part of the :mod:`burpui.api.client` module.
An optional ``GET`` parameter called ``server`` is supported when running
in multi-agent mode.
"""
def __init__(self):
self.parser = reqparse.RequestParser()
self.parser.add_argument('server', type=str)
@login_required
def get(self, server=None, name=None, backup=None):
"""
**GET** method provided by the webservice.
The *JSON* returned is:
::
{
"results": {
"dir": {
"changed": 0,
"deleted": 0,
"new": 394,
"scanned": 394,
"total": 394,
"unchanged": 0
},
"duration": 5,
"efs": {
"changed": 0,
"deleted": 0,
"new": 0,
"scanned": 0,
"total": 0,
"unchanged": 0
},
"encrypted": true,
"end": 1422189124,
"files": {
"changed": 0,
"deleted": 0,
"new": 0,
"scanned": 0,
"total": 0,
"unchanged": 0
},
"files_enc": {
"changed": 0,
"deleted": 0,
"new": 1421,
"scanned": 1421,
"total": 1421,
"unchanged": 0
},
"hardlink": {
"changed": 0,
"deleted": 0,
"new": 0,
"scanned": 0,
"total": 0,
"unchanged": 0
},
"meta": {
"changed": 0,
"deleted": 0,
"new": 0,
"scanned": 0,
"total": 0,
"unchanged": 0
},
"meta_enc": {
"changed": 0,
"deleted": 0,
"new": 0,
"scanned": 0,
"total": 0,
"unchanged": 0
},
"number": 1,
"received": 1679304,
"softlink": {
"changed": 0,
"deleted": 0,
"new": 1302,
"scanned": 1302,
"total": 1302,
"unchanged": 0
},
"special": {
"changed": 0,
"deleted": 0,
"new": 0,
"scanned": 0,
"total": 0,
"unchanged": 0
},
"start": 1422189119,
"total": {
"changed": 0,
"deleted": 0,
"new": 3117,
"scanned": 3117,
"total": 3117,
"unchanged": 0
},
"totsize": 5345361,
"vssfooter": {
"changed": 0,
"deleted": 0,
"new": 0,
"scanned": 0,
"total": 0,
"unchanged": 0
},
"vssfooter_enc": {
"changed": 0,
"deleted": 0,
"new": 0,
"scanned": 0,
"total": 0,
"unchanged": 0
},
"vssheader": {
"changed": 0,
"deleted": 0,
"new": 0,
"scanned": 0,
"total": 0,
"unchanged": 0
},
"vssheader_enc": {
"changed": 0,
"deleted": 0,
"new": 0,
"scanned": 0,
"total": 0,
"unchanged": 0
},
"windows": "false"
}
}
The output is filtered by the :mod:`burpui.misc.acl` module so that you
only see stats about the clients you are authorized to.
:param server: Which server to collect data from when in multi-agent mode
:type server: str
:param name: The client we are working on
:type name: str
:param backup: The backup we are working on
:type backup: int
:returns: The *JSON* described above.
"""
if not server:
server = self.parser.parse_args()['server']
j = []
if not name:
err = [[1, 'No client defined']]
return jsonify(notif=err)
if (api.bui.acl and not
api.bui.acl.is_client_allowed(current_user.name,
name,
server)):
err = [[2, 'You don\'t have rights to view this client stats']]
return jsonify(notif=err)
if backup:
try:
j = api.bui.cli.get_backup_logs(backup, name, agent=server)
except BUIserverException as e:
err = [[2, str(e)]]
return jsonify(notif=err)
else:
try:
cl = api.bui.cli.get_client(name, agent=server)
except BUIserverException as e:
err = [[2, str(e)]]
return jsonify(notif=err)
err = []
for c in cl:
try:
j.append(api.bui.cli.get_backup_logs(c['number'], name, agent=server))
except BUIserverException as e:
temp = [2, str(e)]
if temp not in err:
err.append(temp)
if err:
return jsonify(notif=err)
return jsonify(results=j)
@api.resource('/api/client.json/<name>',
'/api/<server>/client.json/<name>',
endpoint='api.client_report')
class ClientReport(Resource):
"""
The :class:`burpui.api.client.ClientReport` resource allows you to
retrieve a list of backups for a given client.
This resource is part of the :mod:`burpui.api.client` module.
An optional ``GET`` parameter called ``server`` is supported when running
in multi-agent mode.
"""
def __init__(self):
self.parser = reqparse.RequestParser()
self.parser.add_argument('server', type=str)
@login_required
def get(self, server=None, name=None):
"""
**GET** method provided by the webservice.
The *JSON* returned is:
::
{
"results": [
{
"date": "2015-01-25 13:32:00",
"deletable": true,
"encrypted": true,
"number": "1"
}
]
}
The output is filtered by the :mod:`burpui.misc.acl` module so that you
only see stats about the clients you are authorized to.
:param server: Which server to collect data from when in multi-agent mode
:type server: str
:param name: The client we are working on
:type name: str
:returns: The *JSON* described above.
"""
if not server:
server = self.parser.parse_args()['server']
try:
if (api.bui.acl and (
not api.bui.acl.is_admin(current_user.name) and
not api.bui.acl.is_client_allowed(current_user.name,
name,
server))):
raise BUIserverException('Sorry, you cannot access this client')
j = api.bui.cli.get_client(name, agent=server)
except BUIserverException as e:
err = [[2, str(e)]]
return jsonify(notif=err)
return jsonify(results=j)
# -*- coding: utf8 -*-
"""
.. module:: clients
:platform: Unix
:synopsis: Burp-UI clients api module.
.. moduleauthor:: Ziirish <ziirish@ziirish.info>
"""
from burpui.api import api
from burpui.misc.backend.interface import BUIserverException
from flask.ext.restful import reqparse, Resource
from flask.ext.login import current_user, login_required
from flask import jsonify, make_response
@api.resource('/api/running-clients.json',
'/api/<server>/running-clients.json',
'/api/running-clients.json/<client>',
'/api/<server>/running-clients.json/<client>',
endpoint='api.running_clients')
class RunningClients(Resource):
"""
The :class:`burpui.api.clients.RunningClients` resource allows you to
retrieve a list of clients that are currently running a backup.
This resource is part of the :mod:`burpui.api.clients` module.
An optional ``GET`` parameter called ``server`` is supported when running
in multi-agent mode.
"""
def __init__(self):
self.parser = reqparse.RequestParser()
self.parser.add_argument('server', type=str)
@login_required
def get(self, client=None, server=None):
"""
**GET** method provided by the webservice.
The *JSON* returned is:
::
{
"results": [ ]
}
The output is filtered by the :mod:`burpui.misc.acl` module so that you
only see stats about the clients you are authorized to.
:param server: Which server to collect data from when in multi-agent mode
:type server: str
:param client: Ask a specific client in order to know if it is running a backup
:type client: str
:returns: The *JSON* described above.
"""
if not server:
server = self.parser.parse_args()['server']
if client:
if api.bui.acl:
if (not api.bui.acl.is_admin(current_user.name) and not
api.bui.acl.is_client_allowed(current_user.name,
client,
server)):
r = []
return jsonify(results=r)
if api.bui.cli.is_backup_running(client, server):
r = [client]
return jsonify(results=r)
else:
r = []
return jsonify(results=r)
r = api.bui.cli.is_one_backup_running(server)
# Manage ACL
if (api.bui.acl and not
api.bui.acl.is_admin(current_user.name)):
if isinstance(r, dict):
new = {}
for serv in api.bui.acl.servers(current_user.name):
allowed = api.bui.acl.clients(current_user.name, serv)
new[serv] = [x for x in r[serv] if x in allowed]
r = new
else:
allowed = api.bui.acl.clients(current_user.name, server)
r = [x for x in r if x in allowed]
return jsonify(results=r)
@api.resource('/api/running.json',
'/api/<server>/running.json',
endpoint='api.running_backup')
class RunningBackup(Resource):
"""
The :class:`burpui.api.clients.RunningBackup` resource allows you to access
the status of the server in order to know if there is a running backup
currently.
This resource is part of the :mod:`burpui.api.clients` module.
"""
@login_required
def get(self, server=None):
"""
**GET** method provided by the webservice.
The *JSON* returned is:
::
{
"results": false
}
The output is filtered by the :mod:`burpui.misc.acl` module so that you
only see stats about the clients you are authorized to.
:param server: Which server to collect data from when in multi-agent mode
:type server: str
:returns: The *JSON* described above.
"""
j = api.bui.cli.is_one_backup_running(server)
# Manage ACL
if (api.bui.acl and not
api.bui.acl.is_admin(current_user.name)):
if isinstance(j, dict):
new = {}
for serv in api.bui.acl.servers(current_user.name):
allowed = api.bui.acl.clients(current_user.name, serv)
new[serv] = [x for x in j[serv] if x in allowed]
j = new
else:
allowed = api.bui.acl.clients(current_user.name, server)
j = [x for x in j if x in allowed]
r = False
if isinstance(j, dict):
for k, v in j.iteritems():
if r:
break
r = r or (len(v) > 0)
else:
r = len(j) > 0
return jsonify(results=r)
@api.resource('/api/clients-report.json',
'/api/<server>/clients-report.json',
endpoint='api.clients_report')
class ClientsReport(Resource):
"""
The :class:`burpui.api.clients.ClientsReport` resource allows you to access
general reports about your clients.
This resource is part of the :mod:`burpui.api.clients` module.
An optional ``GET`` parameter called ``server`` is supported when running
in multi-agent mode.
"""
def __init__(self):
self.parser = reqparse.RequestParser()
self.parser.add_argument('server', type=str)
@login_required
def get(self, server=None):
"""
**GET** method provided by the webservice.
The *JSON* returned is:
::
{
"results": [
{
"backups": [
{
"name": "client1",
"number": 15
},
{
"name": "client2",
"number": 1
}
],
"clients": [
{
"name": "client1",
"stats": {
"total": 296377,
"totsize": 57055793698,
"windows": "false"
}
},
{
"name": "client2",
"stats": {
"total": 3117,
"totsize": 5345361,
"windows": "true"
}
}
]
}
]
}
The output is filtered by the :mod:`burpui.misc.acl` module so that you
only see stats about the clients you are authorized to.
:param server: Which server to collect data from when in multi-agent mode
:type server: str
:returns: The *JSON* described above
"""
if not server:
server = self.parser.parse_args()['server']
j = []
try:
# Manage ACL
if (not api.bui.standalone and api.bui.acl and
(not api.bui.acl.is_admin(current_user.name) and
server not in
api.bui.acl.servers(current_user.name))):
raise BUIserverException('Sorry, you don\'t have rights on this server')
clients = api.bui.cli.get_all_clients(agent=server)
except BUIserverException as e:
err = [[2, str(e)]]
return jsonify(notif=err)
cl = []
ba = []
# Filter only allowed clients
allowed = []
check = False
if (api.bui.acl and not
api.bui.acl.is_admin(current_user.name)):
check = True
allowed = api.bui.acl.clients(current_user.name, server)
aclients = []
for c in clients:
if check and c['name'] not in allowed:
continue
aclients.append(c)
j = api.bui.cli.get_clients_report(aclients, server)
return jsonify(results=j)
@api.resource('/api/clients.json',
'/api/<server>/clients.json',
endpoint='api.clients_stats')
class ClientsStats(Resource):
"""
The :class:`burpui.api.clients.ClientsStats` resource allows you to access
general statistics about your clients.
This resource is part of the :mod:`burpui.api.clients` module.
An optional ``GET`` parameter called ``server`` is supported when running
in multi-agent mode.
"""
def __init__(self):
self.parser = reqparse.RequestParser()
self.parser.add_argument('server', type=str)
@login_required
def get(self, server=None):
"""
**GET** method provided by the webservice.
The *JSON* returned is:
::
{
"results": [
{
"last": "2015-05-17 11:40:02",
"name": "client1",
"state": "idle"
},
{
"last": "never",
"name": "client2",
"state": "idle"
}
]
}
The output is filtered by the :mod:`burpui.misc.acl` module so that you
only see stats about the clients you are authorized to.
:param server: Which server to collect data from when in multi-agent mode
:type server: str
:returns: The *JSON* described above
"""
if not server:
server = self.parser.parse_args()['server']
try:
if (not api.bui.standalone and
api.bui.acl and
(not api.bui.acl.is_admin(current_user.name) and
server not in
api.bui.acl.servers(current_user.name))):
raise BUIserverException('Sorry, you don\'t have any rights on this server')
j = api.bui.cli.get_all_clients(agent=server)
if (api.bui.acl and not
api.bui.acl.is_admin(current_user.name)):
j = [x for x in j if x['name'] in api.bui.acl.clients(current_user.name, server)]
except BUIserverException as e:
err = [[2, str(e)]]
return jsonify(notif=err)
return jsonify(results=j)
# -*- coding: utf8 -*-
"""
.. module:: misc
:platform: Unix
:synopsis: Burp-UI misc api module.
.. moduleauthor:: Ziirish <ziirish@ziirish.info>
"""
from burpui.api import api
from burpui.misc.backend.interface import BUIserverException
from flask.ext.restful import reqparse, Resource
from flask.ext.login import current_user, login_required
from flask import jsonify, render_template, make_response, abort
@api.resource('/api/render-live-template',
'/api/<server>/render-live-template',
'/api/render-live-template/<name>',
'/api/<server>/render-live-template/<name>',
endpoint='api.render_live_tpl')
class RenderLiveTpl(Resource):
"""
The :class:`burpui.api.misc.RenderLiveTpl` resource allows you to
render the *live view* template of a given client.
This resource is part of the :mod:`burpui.api.api` module.
An optional ``GET`` parameter called ``server`` is supported when running
in multi-agent mode.
A mandatory ``GET`` parameter called ``name`` is used to know what client we
are working on.
"""
def __init__(self):
self.parser = reqparse.RequestParser()
self.parser.add_argument('server', type=str)
self.parser.add_argument('name', type=str)
@login_required
def get(self, server=None, name=None):
"""
API: render_live_tpl
:param name: the client name if any. You can also use the GET parameter
'name' to achieve the same thing
:returns: HTML that should be included directly into the page
"""
if not server:
server = self.parser.parse_args()['server']
if not name:
name = self.parser.parse_args()['name']
# Check params
if not name:
abort(500)
# Manage ACL
if (api.bui.acl and
(not api.bui.acl.is_client_allowed(current_user.name, name, server) or
not api.bui.acl.is_admin(current_user.name))):
abort(403)
if isinstance(api.bui.cli.running, dict):
if server and name not in api.bui.cli.running[server]:
abort(404)
else:
found = False
for k, a in api.bui.cli.running.iteritems():
found = found or (name in a)
if not found:
abort(404)
else:
if name not in api.bui.cli.running:
abort(404)
try:
counters = api.bui.cli.get_counters(name, agent=server)
except BUIserverException:
counters = []
response = make_response(render_template('live-monitor-template.html', cname=name, counters=counters, server=server))
response.headers['content-type'] = 'text/html'
return response