diff --git a/pymanager/client.py b/pymanager/client.py index 4e6a39a..c7ac43b 100755 --- a/pymanager/client.py +++ b/pymanager/client.py @@ -146,6 +146,17 @@ def cmp_to_key(): return K +class HTTPConnection(http.client.HTTPConnection): + """ + Class HTTPConnection + """ + def __init__(self, + host, + port, + timeout=10): + http.client.HTTPConnection.__init__(self, host, port, timeout) + + class HTTPSConnectionCertificate(http.client.HTTPConnection): """ Class HTTP connection with check certificate (if certicate is defined) """ def __init__(self, key_file, cert_file, ca_cert, host='localhost', port=8000, timeout=10): @@ -194,6 +205,7 @@ class Client(): self.certfile = None self.ca_cert = None self.timeout = 10 + self.method = 'http' if username: self.username = username if not password_comand_line: @@ -249,6 +261,10 @@ class Client(): self.timeout = config[name]['timeout'] except KeyError: pass + try: + self.method = config[name]['method'] + except KeyError: + pass def send_json(self, jsonin={}, @@ -265,12 +281,20 @@ class Client(): :param bool raw_data: show result without analyze :param bool remove_color: at end string send color to disable background & color """ - conn = HTTPSConnectionCertificate(host=self.address, - port=self.port, - key_file=self.keyfile, - cert_file=self.certfile, - ca_cert=self.ca_cert, - timeout=self.timeout) + if self.method == 'http': + conn = HTTPConnection(host=self.address, + port=self.port, + timeout=self.timeout) + elif self.method == 'https': + conn = HTTPSConnectionCertificate(host=self.address, + port=self.port, + key_file=self.keyfile, + cert_file=self.certfile, + ca_cert=self.ca_cert, + timeout=self.timeout) + else: + logging.error("Bad value 'method' (%s)" % str(self.method)) + raise ValueError conn.putrequest(command, path) out = json.dumps(jsonin) if self.username: diff --git a/pymanager/manager.py b/pymanager/manager.py index 1a38a2a..3ccb835 100755 --- a/pymanager/manager.py +++ b/pymanager/manager.py @@ -42,6 +42,9 @@ This script need configuration file (see below for model):: # address listen (default all port) address = + # method : http or https + method = https + # Admin Executor Service [command:aes] @@ -139,7 +142,12 @@ import json import fcntl import os import base64 -import bcrypt + +try: + import bcrypt + __DISABLE_BCRYPT__ = False +except ImportError: + __DISABLE_BCRYPT__ = True __VERSION__ = '1.0' @@ -346,6 +354,9 @@ class ManageHttpRequest(http.server.SimpleHTTPRequestHandler): def check_authentication(self): if not self.server.authentification: return True + if __DISABLE_BCRYPT__: + logging.error("Error module python bcrypt not installed") + return False try: auth_header = self.headers['Authorization'].split() if auth_header[0] != 'Basic': @@ -460,7 +471,7 @@ class ServerHttp(multiprocessing.Process): * define Dictionnary queueIn & queueOut (with key as section's name in configuration) """ def __init__(self, keyfile, certfile, ca_cert, address='', - port=8000, authentification=True, users={}): + port=8000, authentification=True, method='http', users={}): multiprocessing.Process.__init__(self) self.listQueueIn = {} self.listQueueOut = {} @@ -472,6 +483,7 @@ class ServerHttp(multiprocessing.Process): self.address = address self.authentification = authentification self.users = users + self.method = method def run(self): server_address = (self.address, self.port) @@ -482,20 +494,26 @@ class ServerHttp(multiprocessing.Process): ManageHttpRequest, self.authentification, self.users) - if self.ca_cert: - httpd.socket = ssl.wrap_socket(httpd.socket, - keyfile=self.key_file, - certfile=self.cert_file, - ca_certs=self.ca_cert, - cert_reqs=ssl.CERT_REQUIRED, - ssl_version=ssl.PROTOCOL_TLSv1_2, - server_side=True) + if self.method == 'http': + logging.info('http listen') + elif self.method == 'https': + if self.ca_cert: + httpd.socket = ssl.wrap_socket(httpd.socket, + keyfile=self.key_file, + certfile=self.cert_file, + ca_certs=self.ca_cert, + cert_reqs=ssl.CERT_REQUIRED, + ssl_version=ssl.PROTOCOL_TLSv1_2, + server_side=True) + else: + httpd.socket = ssl.wrap_socket(httpd.socket, + keyfile=self.key_file, + certfile=self.cert_file, + server_side=True) + logging.info('https listen') else: - httpd.socket = ssl.wrap_socket(httpd.socket, - keyfile=self.key_file, - certfile=self.cert_file, - server_side=True) - logging.info('https listen') + logging.error("Bad value 'method' (%s)" % str(self.method)) + raise ValueError httpd.serve_forever() def append(self, name, queueIn, queueOut, event): @@ -823,6 +841,10 @@ class Manager(): self.passwordfile = config[name]['passwordfile'] except (TypeError, KeyError): self.passwordfile = None + try: + self.method = config[name]['method'] + except (TypeError, KeyError): + self.method = 'http' else: head, value = name.split(':', maxsplit=1) if head == 'command' and 'command' in config[name]: @@ -862,6 +884,7 @@ class Manager(): self.address, self.port, authentification=self.authentification, + method=self.method, users=self.users) def runCommand(self, name, command, path, logsize, bufsize, queueIn, queueOut, event): diff --git a/tests/test.cfg b/tests/test.cfg index 410e6e2..a82c57b 100644 --- a/tests/test.cfg +++ b/tests/test.cfg @@ -23,6 +23,9 @@ # Define port listen (default 8000) port = 8000 +# Method : http or https +method = https + # key keyfile = /home/gameserver/ca/appli/private/serverkey.pem @@ -41,6 +44,7 @@ passwordfile = /home/gameserver/passwordfile [config:client] port = 8000 +method = https keyfile = /home/gameserver/ca/appli/private/clientkey.pem certfile = /home/gameserver/ca/appli/certs/clientcert.pem ca_cert = /home/gameserver/ca/appli/certs/cachaincert.pem diff --git a/tests/test_client.py b/tests/test_client.py index 19fbc96..9e0cfa6 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -107,12 +107,14 @@ class TestClient(unittest.TestCase): config.set('config:server', 'ca_cert', '/home/gameserver/ca/appli/certs/cachaincert.pem') config.set('config:server', 'address', '') config.set('config:server', 'authentification', 'yes') + config.set('config:server', 'method', 'https') config.add_section('config:client') config.set('config:client', 'port', '8000') config.set('config:client', 'keyfile', '/home/gameserver/ca/appli/private/clientkey.pem') config.set('config:client', 'certfile', '/home/gameserver/ca/appli/certs/clientcert.pem') config.set('config:client', 'ca_cert', '/home/gameserver/ca/appli/certs/cachaincert.pem') config.set('config:client', 'address', '127.0.0.1') + config.set('config:client', 'method', 'https') config.add_section('command:test') config.set('command:test', 'path', '/home/gameserver') config.set('command:test', 'command', '/bin/sleep 10') @@ -199,12 +201,14 @@ class TestClient(unittest.TestCase): config.set('config:server', 'keyfile', os.path.join(workdir_cert_appli, 'private', 'serverkey.pem')) config.set('config:server', 'certfile', os.path.join(workdir_cert_appli, 'certs', 'servercert.pem')) config.set('config:server', 'ca_cert', os.path.join(workdir_cert_appli, 'certs', 'cachaincert.pem')) + config.set('config:server', 'method', 'https') config.add_section('config:client') config.set('config:client', 'port', '8000') config.set('config:client', 'keyfile', os.path.join(workdir_cert_appli, 'private', 'clientkey.pem')) config.set('config:client', 'certfile', os.path.join(workdir_cert_appli, 'certs', 'clientcert.pem')) config.set('config:client', 'ca_cert', os.path.join(workdir_cert_appli, 'certs', 'cachaincert.pem')) config.set('config:client', 'address', '127.0.0.1') + config.set('config:client', 'method', 'https') config.add_section('config:user') config.set('config:user', 'usename', 'filter_all, filter_admin') try: diff --git a/tests/test_client_manager.py b/tests/test_client_manager.py index 7904c33..6526101 100644 --- a/tests/test_client_manager.py +++ b/tests/test_client_manager.py @@ -70,12 +70,14 @@ class TestManager(unittest.TestCase): config.set('config:server', 'keyfile', os.path.join(workdir_cert_appli, 'private', 'serverkey.pem')) config.set('config:server', 'certfile', os.path.join(workdir_cert_appli, 'certs', 'servercert.pem')) config.set('config:server', 'ca_cert', os.path.join(workdir_cert_appli, 'certs', 'cachaincert.pem')) + config.set('config:server', 'method', 'https') config.add_section('config:client') config.set('config:server', 'port', str(port)) config.set('config:client', 'keyfile', os.path.join(workdir_cert_appli, 'private', 'clientkey.pem')) config.set('config:client', 'certfile', os.path.join(workdir_cert_appli, 'certs', 'clientcert.pem')) config.set('config:client', 'ca_cert', os.path.join(workdir_cert_appli, 'certs', 'cachaincert.pem')) config.set('config:client', 'address', '127.0.0.1') + config.set('config:client', 'method', 'https') config.add_section('command:test') config.set('command:test', 'path', workdir) config.set('command:test', 'command', self.program) diff --git a/tests/test_http.cfg b/tests/test_http.cfg new file mode 100644 index 0000000..2651234 --- /dev/null +++ b/tests/test_http.cfg @@ -0,0 +1,63 @@ +# +# Configuration management program khaganat +# +# Copyright (C) 2017 AleaJactaEst +# +# 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 3 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, see . + +# +# Global parameter : use bu ymanager +# +[config:server] +# Define port listen (default 8000) +port = 8000 +method = http + +# address listen (default all network) +address = + +# activate authentification (yes or no) +authentification = no + +[config:client] +# you can use curl as client +# like: curl -XGET http://127.0.0.1:8000/STATUSALL +# curl -XPOST http://127.0.0.1:8000/STARTALL +port = 8000 +method = http +address = 127.0.0.1 + + +############################## +# List all program we manage # +############################## + +[command:test1] +# command to launch the program +command = /home/gameserver/test1 + +# Admin Executor Service +[command:test2] +# command to launch the program +command = /home/gameserver/test2 +# size buffer log for each program launched (number line stdout) +logsize = 1000 +# buffer size (define value bufsize on subprocess.Popen, this buffer is use before read by manager) +bufsize = 100 + +# Admin Executor Service +[command:sleep] +# command to launch the program +command = sleep 10 + diff --git a/tests/test_manager.py b/tests/test_manager.py index 98bccc6..5502b5a 100644 --- a/tests/test_manager.py +++ b/tests/test_manager.py @@ -79,12 +79,14 @@ class TestManager(unittest.TestCase): config.set('config:server', 'ca_cert', '/home/gameserver/ca/appli/certs/cachaincert.pem') config.set('config:server', 'address', '') config.set('config:server', 'authentification', 'yes') + config.set('config:server', 'method', 'https') config.add_section('config:client') config.set('config:client', 'port', '8000') config.set('config:client', 'keyfile', '/home/gameserver/ca/appli/private/clientkey.pem') config.set('config:client', 'certfile', '/home/gameserver/ca/appli/certs/clientcert.pem') config.set('config:client', 'ca_cert', '/home/gameserver/ca/appli/certs/cachaincert.pem') config.set('config:client', 'address', '127.0.0.1') + config.set('config:client', 'method', 'https') config.add_section('command:test') config.set('command:test', 'path', '/home/gameserver') config.set('command:test', 'command', '/bin/sleep 10') @@ -142,6 +144,7 @@ class TestManager(unittest.TestCase): config.set('config:client', 'certfile', '/home/gameserver/ca/appli/certs/clientcert.pem') config.set('config:client', 'ca_cert', '/home/gameserver/ca/appli/certs/cachaincert.pem') config.set('config:client', 'address', '127.0.0.1') + config.set('config:client', 'method', 'https') config.add_section('config:user') config.add_section('command:test') config.set('command:test', 'command', '/bin/sleep 10') @@ -312,6 +315,9 @@ class TestManager(unittest.TestCase): queueOut, event, maxWaitEnd = 2) + except: + self.fail('Error initialize object ManageCommand') + try: res = manageCommand.start() self.assertEqual(res, 'started') wait = True @@ -332,8 +338,8 @@ class TestManager(unittest.TestCase): res = manageCommand.status() self.assertEqual(res, 'stopped') self.assertTrue(True) - except: - self.fail('Error initialize object ManageCommand') + except Exception as e: + self.fail('Error when run test', e) def test_execute_command_crashed(self): try: