diff options
Diffstat (limited to 'elivepatch_server')
-rw-r--r-- | elivepatch_server/__init__.py | 0 | ||||
-rw-r--r-- | elivepatch_server/elivepatch | 41 | ||||
-rw-r--r-- | elivepatch_server/requirements.txt | 2 | ||||
-rw-r--r-- | elivepatch_server/resources/AgentInfo.py | 54 | ||||
-rw-r--r-- | elivepatch_server/resources/__init__.py | 9 | ||||
-rw-r--r-- | elivepatch_server/resources/dispatcher.py | 171 | ||||
-rw-r--r-- | elivepatch_server/resources/livepatch.py | 134 | ||||
-rw-r--r-- | elivepatch_server/setup.py | 12 |
8 files changed, 0 insertions, 423 deletions
diff --git a/elivepatch_server/__init__.py b/elivepatch_server/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/elivepatch_server/__init__.py +++ /dev/null diff --git a/elivepatch_server/elivepatch b/elivepatch_server/elivepatch deleted file mode 100644 index cd14f75..0000000 --- a/elivepatch_server/elivepatch +++ /dev/null @@ -1,41 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -# (c) 2017, Alice Ferrazzi <alice.ferrazzi@gmail.com> -# Distributed under the terms of the GNU General Public License v2 or later - - -from flask import Flask -from flask_restful import Api -from elivepatch_server.resources import AgentInfo, dispatcher - - -def create_app(): - """ - Create server application - RESTful api version 1.0 - """ - - app = Flask(__name__, static_url_path="") - api = Api(app) - - api.add_resource(AgentInfo.AgentAPI, '/elivepatch/api/', - endpoint='root') - - # get agento information - api.add_resource(AgentInfo.AgentAPI, '/elivepatch/api/v1.0/agent', - endpoint='agent') - - # where to retrieve the live patch when ready - api.add_resource(dispatcher.SendLivePatch, - '/elivepatch/api/v1.0/send_livepatch', - endpoint='send_livepatch') - - # where to receive the config file - api.add_resource(dispatcher.GetFiles, '/elivepatch/api/v1.0/get_files', - endpoint='config') - return app - -if __name__ == '__main__': - app = create_app() - app.run(debug=True, host='0.0.0.0', threaded=True) diff --git a/elivepatch_server/requirements.txt b/elivepatch_server/requirements.txt deleted file mode 100644 index 1aff942..0000000 --- a/elivepatch_server/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -flask -flask_restful
\ No newline at end of file diff --git a/elivepatch_server/resources/AgentInfo.py b/elivepatch_server/resources/AgentInfo.py deleted file mode 100644 index 495512a..0000000 --- a/elivepatch_server/resources/AgentInfo.py +++ /dev/null @@ -1,54 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -# (c) 2017, Alice Ferrazzi <alice.ferrazzi@gmail.com> -# Distributed under the terms of the GNU General Public License v2 or later - -from flask_restful import Resource, reqparse, fields, marshal - -agent_fields = { - 'module': fields.String, - 'version': fields.String, -} - - -def agentinfo(module=None): - """ - :rtype: object - """ - agents = [] - agent = { - 'id': 1, - 'module': 'elivepatch', - 'version' : '0.01', - } - agents.append(agent) - return agents - -agents = agentinfo() - - -class AgentAPI(Resource): - - def __init__(self): - self.reqparse = reqparse.RequestParser() - self.reqparse.add_argument('module', type=str, required=True, - help='No task title provided', - location='json') - self.reqparse.add_argument('version', type=str, required=True, - help='No task title provided', - location='json') - super(AgentAPI, self).__init__() - - def get(self): - return {'agent': [marshal(host, agent_fields) for host in agents]} - - def post(self): - args = self.reqparse.parse_args() - host = { - 'id': agents[-1]['id'] + 1, - 'module': args['module'], - 'version': args['version'], - } - agents.append(host) - return {'agent': marshal(host, agent_fields)}, 201 diff --git a/elivepatch_server/resources/__init__.py b/elivepatch_server/resources/__init__.py deleted file mode 100644 index 7797189..0000000 --- a/elivepatch_server/resources/__init__.py +++ /dev/null @@ -1,9 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -# (c) 2017, Alice Ferrazzi <alice.ferrazzi@gmail.com> -# Distributed under the terms of the GNU General Public License v2 or later - -__version__ = '0.0.1' -__author__ = 'Alice Ferrazzi' -__license__ = 'GNU GPLv2+'
\ No newline at end of file diff --git a/elivepatch_server/resources/dispatcher.py b/elivepatch_server/resources/dispatcher.py deleted file mode 100644 index 92fbe4e..0000000 --- a/elivepatch_server/resources/dispatcher.py +++ /dev/null @@ -1,171 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -# (c) 2017, Alice Ferrazzi <alice.ferrazzi@gmail.com> -# Distributed under the terms of the GNU General Public License v2 or later - - -import re - -import os -import werkzeug -from flask import jsonify, make_response -from flask_restful import Resource, reqparse, fields, marshal - -from elivepatch_server.resources.livepatch import PaTch - -pack_fields = { - 'KernelVersion': fields.String, - 'UUID': fields.String - -} - -packs = { - 'id': 1, - 'KernelVersion': None, - 'UUID': None -} - - -def check_uuid(uuid): - """ - Check uuid is in the correct format - :param uuid: - :return: - """ - if not uuid: - print('uuid is missing') - else: - # check uuid format - prog = re.compile('^\w{8}-\w{4}-\w{4}-\w{4}-\w{12}$') - result = prog.match(uuid) - if result: - print('UUID: ' + str(uuid)) - return uuid - print('uuid format is not correct') - - -def get_uuid_dir(uuid): - return os.path.join('/tmp/', 'elivepatch-' + uuid) - - -class SendLivePatch(Resource): - - def __init__(self): - self.reqparse = reqparse.RequestParser() - self.reqparse.add_argument('KernelVersion', type=str, required=False, - help='No task title provided', - location='json') - self.reqparse.add_argument('UUID', type=str, required=False, - help='No task title provided', - location='json') - super(SendLivePatch, self).__init__() - pass - - def get(self): - args = self.reqparse.parse_args() - print("get livepatch: " + str(args)) - # check if is a valid UUID request - args['UUID'] = check_uuid(args['UUID']) - uuid_dir = get_uuid_dir(args['UUID']) - - livepatch_full_path = os.path.join(uuid_dir, 'kpatch-main.ko') - try: - with open(livepatch_full_path, 'rb') as fp: - response = make_response(fp.read()) - response.headers['content-type'] = 'application/octet-stream' - return response - except: - return make_response(jsonify({'message': 'These are not the \ - patches you are looking for'}), 403) - - def post(self): - return make_response(jsonify({'message': 'These are not the \ - patches you are looking for'}), 403) - - -class GetFiles(Resource): - - def __init__(self): - self.reqparse = reqparse.RequestParser() - self.reqparse.add_argument('KernelVersion', type=str, required=False, - help='No task title provided', - location='headers') - self.reqparse.add_argument('UUID', type=str, required=False, - help='No task title provided', - location='headers') - super(GetFiles, self).__init__() - pass - - def get(self): - return make_response(jsonify({'message': 'These are not the \ - patches you are looking for'}), 403) - - def post(self): - args = self.reqparse.parse_args() - args['UUID'] = check_uuid(args['UUID']) - parse = reqparse.RequestParser() - parse.add_argument('patch', action='append', type=werkzeug.datastructures.FileStorage, - location='files') - parse.add_argument('main_patch', action='append', type=werkzeug.datastructures.FileStorage, - location='files') - parse.add_argument('config', type=werkzeug.datastructures.FileStorage, - location='files') - file_args = parse.parse_args() - - lpatch = PaTch() - - print("file get config: " + str(file_args)) - configFile = file_args['config'] - configFile_name = file_args['config'].filename - - # saving config file - configFile_name = os.path.join('/tmp','elivepatch-' + args['UUID'], configFile_name) - if os.path.exists('/tmp/elivepatch-' + args['UUID']): - print('the folder: "/tmp/elivepatch-' + args['UUID'] + '" is already present') - return {'the request with ' + args['UUID'] + ' is already present'}, 201 - else: - print('creating: "/tmp/elivepatch-' + args['UUID']) - os.makedirs('/tmp/elivepatch-' + args['UUID']) - - configFile.save(configFile_name) - - - # saving incremental patches - incremental_patches_directory = os.path.join('/tmp', 'elivepatch-' + args['UUID'], 'etc', 'portage', 'patches', - 'sys-kernel', 'gentoo-sources') - if os.path.exists(incremental_patches_directory): - print('the folder: "/tmp/elivepatch-' + args['UUID'] + '" is already present') - return {'the request with ' + args['UUID'] + ' is already present'}, 201 - else: - print('creating: '+incremental_patches_directory) - os.makedirs(incremental_patches_directory) - try: - for patch in file_args['patch']: - print(str(patch)) - patchfile = patch - patchfile_name = patch.filename - patch_fulldir_name = os.path.join(incremental_patches_directory, patchfile_name) - patchfile.save(patch_fulldir_name) - except: - print('no incremental patches') - - # saving main patch - print(str(file_args['main_patch'])) - main_patchfile = file_args['main_patch'][0] - main_patchfile_name = main_patchfile.filename - main_patch_fulldir_name = os.path.join('/tmp','elivepatch-' + args['UUID'], main_patchfile_name) - main_patchfile.save(main_patch_fulldir_name) - - # check vmlinux presence if not rebuild the kernel - kernel_sources_status = lpatch.get_kernel_sources(args['UUID'], args['KernelVersion']) - if not kernel_sources_status: - return make_response(jsonify({'message': 'gentoo-sources not available'}), 403) - lpatch.build_livepatch(args['UUID'], 'vmlinux') - - pack = { - 'id': packs['id'] + 1, - 'KernelVersion': None, - 'UUID' : args['UUID'] - } - return {'get_config': marshal(pack, pack_fields)}, 201
\ No newline at end of file diff --git a/elivepatch_server/resources/livepatch.py b/elivepatch_server/resources/livepatch.py deleted file mode 100644 index d499d9b..0000000 --- a/elivepatch_server/resources/livepatch.py +++ /dev/null @@ -1,134 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -# (c) 2017, Alice Ferrazzi <alice.ferrazzi@gmail.com> -# Distributed under the terms of the GNU General Public License v2 or later - -import subprocess -import os -import fileinput -import tempfile - - -class PaTch(object): - - def __init__(self): - pass - - def build_livepatch(self, uuid, vmlinux, debug=True): - """ - Function for building the livepatch - - :param uuid: UUID session identification - :param vmlinux: path to the vmlinux file - :param debug: copy build.log in the uuid directory - :return: void - """ - kernel_source = os.path.join('/tmp/', 'elivepatch-' + uuid, 'usr/src/linux/') - uuid_dir = os.path.join('/tmp/', 'elivepatch-' + uuid) - vmlinux_source = os.path.join(kernel_source, vmlinux) - kpatch_cachedir = os.path.join(uuid_dir, 'kpatch') - - os.makedirs(kpatch_cachedir) - if not os.path.isfile(vmlinux_source): - self.build_kernel(uuid) - - bashCommand = ['kpatch-build'] - bashCommand.extend(['-s', kernel_source]) - bashCommand.extend(['-v', vmlinux_source]) - bashCommand.extend(['-c', 'config']) - bashCommand.extend(['main.patch']) - bashCommand.extend(['--skip-gcc-check']) - if debug: - bashCommand.extend(['--skip-cleanup']) - bashCommand.extend(['--debug']) - _command(bashCommand, uuid_dir, {'CACHEDIR': kpatch_cachedir}) - if debug: - _command(['cp', '-f', os.path.join(kpatch_cachedir, 'build.log'), uuid_dir]) - - def get_kernel_sources(self, uuid, kernel_version, debug=True): - """ - Function for download the kernel sources - - :return: void - """ - try: - _command(['git', 'clone', 'https://github.com/aliceinwire/gentoo-sources_overlay.git']) - except: - print('git clone failed.') - - uuid_dir = os.path.join('/tmp/', 'elivepatch-' + uuid) - ebuild_path = os.path.join('gentoo-sources_overlay', 'sys-kernel', 'gentoo-sources', 'gentoo-sources-' + - kernel_version + '.ebuild') - print(ebuild_path) - if os.path.isfile(ebuild_path): - # Use a private tmpdir for portage - with tempfile.TemporaryDirectory(dir=uuid_dir) as portage_tmpdir: - print('uuid_dir: ' + str(uuid_dir) + ' PORTAGE_TMPDIR: ' + str(portage_tmpdir)) - # portage_tmpdir is not always working with root privileges - if debug: - if os.geteuid() != 0: - env = {'ROOT': uuid_dir, 'PORTAGE_CONFIGROOT': uuid_dir, 'PORTAGE_TMPDIR': portage_tmpdir, - 'PORTAGE_DEBUG': '1'} - else: - env = {'ROOT': uuid_dir, 'PORTAGE_CONFIGROOT': uuid_dir, 'PORTAGE_TMPDIR': uuid_dir, - 'PORTAGE_DEBUG': '1'} - else: - if os.geteuid() != 0: - env = {'ROOT': uuid_dir, 'PORTAGE_CONFIGROOT': uuid_dir, 'PORTAGE_TMPDIR': portage_tmpdir} - else: - env = {'ROOT': uuid_dir, 'PORTAGE_CONFIGROOT': uuid_dir, 'PORTAGE_TMPDIR': uuid_dir} - _command(['ebuild', ebuild_path, 'digest', 'clean', 'merge'], env=env) - kernel_sources_status = True - else: - print('ebuild not present') - kernel_sources_status = None - return kernel_sources_status - - def build_kernel(self, uuid): - kernel_source_dir = '/tmp/elivepatch-' + uuid + '/usr/src/linux/' - uuid_dir_config = '/tmp/elivepatch-' + uuid + '/config' - if 'CONFIG_DEBUG_INFO=y' in open(uuid_dir_config).read(): - print("DEBUG_INFO correctly present") - elif 'CONFIG_DEBUG_INFO=n' in open(uuid_dir_config).read(): - print("changing DEBUG_INFO to yes") - for line in fileinput.input(uuid_dir_config, inplace=1): - print(line.replace("CONFIG_DEBUG_INFO=n", "CONFIG_DEBUG_INFO=y")) - else: - print("Adding DEBUG_INFO for getting kernel debug symbols") - for line in fileinput.input(uuid_dir_config, inplace=1): - print(line.replace("# CONFIG_DEBUG_INFO is not set", "CONFIG_DEBUG_INFO=y")) - _command(['cp', '/tmp/elivepatch-' + uuid + '/config', kernel_source_dir + '.config']) - # olddefconfig default everything that is new from the configuration file - _command(['make', 'olddefconfig'], kernel_source_dir) - _command(['make'], kernel_source_dir) - _command(['make', 'modules'], kernel_source_dir) - - -def _command(bashCommand, kernel_source_dir=None, env=None): - """ - Popen override function - - :param bashCommand: List of command arguments to execute - :param kernel_source_dir: String with the directory where the command is executed - :param env: Dictionary for setting system environment variable - :return: void - """ - # Inherit the parent environment and update the private copy - if env: - process_env = os.environ.copy() - process_env.update(env) - env = process_env - - if kernel_source_dir: - print(bashCommand) - process = subprocess.Popen(bashCommand, stdout=subprocess.PIPE, cwd=kernel_source_dir, env=env) - output, error = process.communicate() - for output_line in output.split(b'\n'): - print(output_line.strip()) - else: - print(bashCommand) - process = subprocess.Popen(bashCommand, stdout=subprocess.PIPE, env=env) - output, error = process.communicate() - for output_line in output.split(b'\n'): - print(output_line.strip()) diff --git a/elivepatch_server/setup.py b/elivepatch_server/setup.py deleted file mode 100644 index 6de3be4..0000000 --- a/elivepatch_server/setup.py +++ /dev/null @@ -1,12 +0,0 @@ -from setuptools import setup, find_packages - -setup( - name='elivepatch_server', - version='0.01', - description='Patching differents gentoo distributions', - url='https://gentoo.org', - author='Alice Ferrazzi', - author_email='alice.ferrazzi@gmail.com', - license='GNU GPLv2+', - packages=find_packages(), -) |