Add ability to download system logs
This commit is contained in:
parent
5c7a9d0daf
commit
4ca877c1d4
9 changed files with 78 additions and 19 deletions
|
@ -23,12 +23,14 @@ import features
|
|||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
LOGS_PATH = "/var/log/%s/current"
|
||||
SERVICES_PATH = "conf/init/"
|
||||
|
||||
def get_immediate_subdirectories(directory):
|
||||
return [name for name in os.listdir(directory) if os.path.isdir(os.path.join(directory, name))]
|
||||
|
||||
def get_services():
|
||||
services = set(get_immediate_subdirectories(app.config['SYSTEM_SERVICES_PATH']))
|
||||
services = services - set(app.config['SYSTEM_SERVICE_BLACKLIST'])
|
||||
return services
|
||||
|
||||
|
||||
@resource('/v1/superuser/systemlogs/<service>')
|
||||
@internal_only
|
||||
|
@ -39,12 +41,11 @@ class SuperUserGetLogsForService(ApiResource):
|
|||
def get(self, service):
|
||||
""" Returns the logs for the specific service. """
|
||||
if SuperUserPermission().can():
|
||||
services = get_immediate_subdirectories(SERVICES_PATH)
|
||||
if not service in services:
|
||||
if not service in get_services():
|
||||
abort(404)
|
||||
|
||||
try:
|
||||
with open(LOGS_PATH % service, 'r') as f:
|
||||
with open(app.config['SYSTEM_SERVICE_LOGS_PATH'] % service, 'r') as f:
|
||||
logs = f.read()
|
||||
except Exception as ex:
|
||||
logger.exception('Cannot read logs')
|
||||
|
@ -67,7 +68,7 @@ class SuperUserSystemLogServices(ApiResource):
|
|||
""" List the system logs for the current system. """
|
||||
if SuperUserPermission().can():
|
||||
return {
|
||||
'services': get_immediate_subdirectories(SERVICES_PATH)
|
||||
'services': list(get_services())
|
||||
}
|
||||
|
||||
abort(403)
|
||||
|
|
|
@ -19,19 +19,21 @@ def generate_csrf_token():
|
|||
|
||||
return session['_csrf_token']
|
||||
|
||||
def verify_csrf():
|
||||
token = session.get('_csrf_token', None)
|
||||
found_token = request.values.get('_csrf_token', None)
|
||||
|
||||
if not token or token != found_token:
|
||||
msg = 'CSRF Failure. Session token was %s and request token was %s'
|
||||
logger.error(msg, token, found_token)
|
||||
abort(403, message='CSRF token was invalid or missing.')
|
||||
|
||||
def csrf_protect(func):
|
||||
@wraps(func)
|
||||
def wrapper(*args, **kwargs):
|
||||
oauth_token = get_validated_oauth_token()
|
||||
if oauth_token is None and request.method != "GET" and request.method != "HEAD":
|
||||
token = session.get('_csrf_token', None)
|
||||
found_token = request.values.get('_csrf_token', None)
|
||||
|
||||
if not token or token != found_token:
|
||||
msg = 'CSRF Failure. Session token was %s and request token was %s'
|
||||
logger.error(msg, token, found_token)
|
||||
abort(403, message='CSRF token was invalid or missing.')
|
||||
verify_csrf()
|
||||
|
||||
return func(*args, **kwargs)
|
||||
return wrapper
|
||||
|
|
|
@ -12,15 +12,18 @@ from data import model
|
|||
from data.model.oauth import DatabaseAuthorizationProvider
|
||||
from app import app, billing as stripe, build_logs, avatar
|
||||
from auth.auth import require_session_login, process_oauth
|
||||
from auth.permissions import AdministerOrganizationPermission, ReadRepositoryPermission
|
||||
from auth.permissions import (AdministerOrganizationPermission, ReadRepositoryPermission,
|
||||
SuperUserPermission)
|
||||
|
||||
from util.invoice import renderInvoiceToPdf
|
||||
from util.seo import render_snapshot
|
||||
from util.cache import no_cache
|
||||
from endpoints.common import common_login, render_page_template, route_show_if, param_required
|
||||
from endpoints.csrf import csrf_protect, generate_csrf_token
|
||||
from endpoints.csrf import csrf_protect, generate_csrf_token, verify_csrf
|
||||
from endpoints.registry import set_cache_headers
|
||||
from util.names import parse_repository_name
|
||||
from util.useremails import send_email_changed
|
||||
from util.systemlogs import build_logs_archive
|
||||
from auth import scopes
|
||||
|
||||
import features
|
||||
|
@ -466,3 +469,21 @@ def exchange_code_for_token():
|
|||
|
||||
provider = FlaskAuthorizationProvider()
|
||||
return provider.get_token(grant_type, client_id, client_secret, redirect_uri, code, scope=scope)
|
||||
|
||||
|
||||
@web.route('/systemlogsarchive', methods=['GET'])
|
||||
@process_oauth
|
||||
@route_show_if(features.SUPER_USERS)
|
||||
@no_cache
|
||||
def download_logs_archive():
|
||||
# Note: We cannot use the decorator here because this is a GET method. That being said, this
|
||||
# information is sensitive enough that we want the extra protection.
|
||||
verify_csrf()
|
||||
|
||||
if SuperUserPermission().can():
|
||||
archive_data = build_logs_archive(app)
|
||||
return Response(archive_data,
|
||||
mimetype="application/octet-stream",
|
||||
headers={"Content-Disposition": "attachment;filename=erlogs.tar.gz"})
|
||||
|
||||
abort(403)
|
||||
|
|
Reference in a new issue