adding http (issue khaganat/mmorpg_khanat/opennel-pymanager#3)

This commit is contained in:
Jean Sorgemoel 2018-08-02 16:38:07 +02:00
parent 336b77db09
commit a9d4bbffcd
7 changed files with 149 additions and 23 deletions

View file

@ -146,6 +146,17 @@ def cmp_to_key():
return K 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 HTTPSConnectionCertificate(http.client.HTTPConnection):
""" Class HTTP connection with check certificate (if certicate is defined) """ """ 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): 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.certfile = None
self.ca_cert = None self.ca_cert = None
self.timeout = 10 self.timeout = 10
self.method = 'http'
if username: if username:
self.username = username self.username = username
if not password_comand_line: if not password_comand_line:
@ -249,6 +261,10 @@ class Client():
self.timeout = config[name]['timeout'] self.timeout = config[name]['timeout']
except KeyError: except KeyError:
pass pass
try:
self.method = config[name]['method']
except KeyError:
pass
def send_json(self, def send_json(self,
jsonin={}, jsonin={},
@ -265,12 +281,20 @@ class Client():
:param bool raw_data: show result without analyze :param bool raw_data: show result without analyze
:param bool remove_color: at end string send color to disable background & color :param bool remove_color: at end string send color to disable background & color
""" """
conn = HTTPSConnectionCertificate(host=self.address, if self.method == 'http':
port=self.port, conn = HTTPConnection(host=self.address,
key_file=self.keyfile, port=self.port,
cert_file=self.certfile, timeout=self.timeout)
ca_cert=self.ca_cert, elif self.method == 'https':
timeout=self.timeout) 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) conn.putrequest(command, path)
out = json.dumps(jsonin) out = json.dumps(jsonin)
if self.username: if self.username:

View file

@ -42,6 +42,9 @@ This script need configuration file (see below for model)::
# address listen (default all port) # address listen (default all port)
address = address =
# method : http or https
method = https
# Admin Executor Service # Admin Executor Service
[command:aes] [command:aes]
@ -139,7 +142,12 @@ import json
import fcntl import fcntl
import os import os
import base64 import base64
import bcrypt
try:
import bcrypt
__DISABLE_BCRYPT__ = False
except ImportError:
__DISABLE_BCRYPT__ = True
__VERSION__ = '1.0' __VERSION__ = '1.0'
@ -346,6 +354,9 @@ class ManageHttpRequest(http.server.SimpleHTTPRequestHandler):
def check_authentication(self): def check_authentication(self):
if not self.server.authentification: if not self.server.authentification:
return True return True
if __DISABLE_BCRYPT__:
logging.error("Error module python bcrypt not installed")
return False
try: try:
auth_header = self.headers['Authorization'].split() auth_header = self.headers['Authorization'].split()
if auth_header[0] != 'Basic': 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) * define Dictionnary queueIn & queueOut (with key as section's name in configuration)
""" """
def __init__(self, keyfile, certfile, ca_cert, address='', def __init__(self, keyfile, certfile, ca_cert, address='',
port=8000, authentification=True, users={}): port=8000, authentification=True, method='http', users={}):
multiprocessing.Process.__init__(self) multiprocessing.Process.__init__(self)
self.listQueueIn = {} self.listQueueIn = {}
self.listQueueOut = {} self.listQueueOut = {}
@ -472,6 +483,7 @@ class ServerHttp(multiprocessing.Process):
self.address = address self.address = address
self.authentification = authentification self.authentification = authentification
self.users = users self.users = users
self.method = method
def run(self): def run(self):
server_address = (self.address, self.port) server_address = (self.address, self.port)
@ -482,20 +494,26 @@ class ServerHttp(multiprocessing.Process):
ManageHttpRequest, ManageHttpRequest,
self.authentification, self.authentification,
self.users) self.users)
if self.ca_cert: if self.method == 'http':
httpd.socket = ssl.wrap_socket(httpd.socket, logging.info('http listen')
keyfile=self.key_file, elif self.method == 'https':
certfile=self.cert_file, if self.ca_cert:
ca_certs=self.ca_cert, httpd.socket = ssl.wrap_socket(httpd.socket,
cert_reqs=ssl.CERT_REQUIRED, keyfile=self.key_file,
ssl_version=ssl.PROTOCOL_TLSv1_2, certfile=self.cert_file,
server_side=True) 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: else:
httpd.socket = ssl.wrap_socket(httpd.socket, logging.error("Bad value 'method' (%s)" % str(self.method))
keyfile=self.key_file, raise ValueError
certfile=self.cert_file,
server_side=True)
logging.info('https listen')
httpd.serve_forever() httpd.serve_forever()
def append(self, name, queueIn, queueOut, event): def append(self, name, queueIn, queueOut, event):
@ -823,6 +841,10 @@ class Manager():
self.passwordfile = config[name]['passwordfile'] self.passwordfile = config[name]['passwordfile']
except (TypeError, KeyError): except (TypeError, KeyError):
self.passwordfile = None self.passwordfile = None
try:
self.method = config[name]['method']
except (TypeError, KeyError):
self.method = 'http'
else: else:
head, value = name.split(':', maxsplit=1) head, value = name.split(':', maxsplit=1)
if head == 'command' and 'command' in config[name]: if head == 'command' and 'command' in config[name]:
@ -862,6 +884,7 @@ class Manager():
self.address, self.address,
self.port, self.port,
authentification=self.authentification, authentification=self.authentification,
method=self.method,
users=self.users) users=self.users)
def runCommand(self, name, command, path, logsize, bufsize, queueIn, queueOut, event): def runCommand(self, name, command, path, logsize, bufsize, queueIn, queueOut, event):

View file

@ -23,6 +23,9 @@
# Define port listen (default 8000) # Define port listen (default 8000)
port = 8000 port = 8000
# Method : http or https
method = https
# key # key
keyfile = /home/gameserver/ca/appli/private/serverkey.pem keyfile = /home/gameserver/ca/appli/private/serverkey.pem
@ -41,6 +44,7 @@ passwordfile = /home/gameserver/passwordfile
[config:client] [config:client]
port = 8000 port = 8000
method = https
keyfile = /home/gameserver/ca/appli/private/clientkey.pem keyfile = /home/gameserver/ca/appli/private/clientkey.pem
certfile = /home/gameserver/ca/appli/certs/clientcert.pem certfile = /home/gameserver/ca/appli/certs/clientcert.pem
ca_cert = /home/gameserver/ca/appli/certs/cachaincert.pem ca_cert = /home/gameserver/ca/appli/certs/cachaincert.pem

View file

@ -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', 'ca_cert', '/home/gameserver/ca/appli/certs/cachaincert.pem')
config.set('config:server', 'address', '') config.set('config:server', 'address', '')
config.set('config:server', 'authentification', 'yes') config.set('config:server', 'authentification', 'yes')
config.set('config:server', 'method', 'https')
config.add_section('config:client') config.add_section('config:client')
config.set('config:client', 'port', '8000') config.set('config:client', 'port', '8000')
config.set('config:client', 'keyfile', '/home/gameserver/ca/appli/private/clientkey.pem') 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', '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', 'ca_cert', '/home/gameserver/ca/appli/certs/cachaincert.pem')
config.set('config:client', 'address', '127.0.0.1') config.set('config:client', 'address', '127.0.0.1')
config.set('config:client', 'method', 'https')
config.add_section('command:test') config.add_section('command:test')
config.set('command:test', 'path', '/home/gameserver') config.set('command:test', 'path', '/home/gameserver')
config.set('command:test', 'command', '/bin/sleep 10') 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', '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', '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', 'ca_cert', os.path.join(workdir_cert_appli, 'certs', 'cachaincert.pem'))
config.set('config:server', 'method', 'https')
config.add_section('config:client') config.add_section('config:client')
config.set('config:client', 'port', '8000') config.set('config:client', 'port', '8000')
config.set('config:client', 'keyfile', os.path.join(workdir_cert_appli, 'private', 'clientkey.pem')) 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', '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', 'ca_cert', os.path.join(workdir_cert_appli, 'certs', 'cachaincert.pem'))
config.set('config:client', 'address', '127.0.0.1') config.set('config:client', 'address', '127.0.0.1')
config.set('config:client', 'method', 'https')
config.add_section('config:user') config.add_section('config:user')
config.set('config:user', 'usename', 'filter_all, filter_admin') config.set('config:user', 'usename', 'filter_all, filter_admin')
try: try:

View file

@ -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', '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', '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', 'ca_cert', os.path.join(workdir_cert_appli, 'certs', 'cachaincert.pem'))
config.set('config:server', 'method', 'https')
config.add_section('config:client') config.add_section('config:client')
config.set('config:server', 'port', str(port)) 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', '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', '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', 'ca_cert', os.path.join(workdir_cert_appli, 'certs', 'cachaincert.pem'))
config.set('config:client', 'address', '127.0.0.1') config.set('config:client', 'address', '127.0.0.1')
config.set('config:client', 'method', 'https')
config.add_section('command:test') config.add_section('command:test')
config.set('command:test', 'path', workdir) config.set('command:test', 'path', workdir)
config.set('command:test', 'command', self.program) config.set('command:test', 'command', self.program)

63
tests/test_http.cfg Normal file
View file

@ -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 <http://www.gnu.org/licenses/>.
#
# 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

View file

@ -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', 'ca_cert', '/home/gameserver/ca/appli/certs/cachaincert.pem')
config.set('config:server', 'address', '') config.set('config:server', 'address', '')
config.set('config:server', 'authentification', 'yes') config.set('config:server', 'authentification', 'yes')
config.set('config:server', 'method', 'https')
config.add_section('config:client') config.add_section('config:client')
config.set('config:client', 'port', '8000') config.set('config:client', 'port', '8000')
config.set('config:client', 'keyfile', '/home/gameserver/ca/appli/private/clientkey.pem') 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', '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', 'ca_cert', '/home/gameserver/ca/appli/certs/cachaincert.pem')
config.set('config:client', 'address', '127.0.0.1') config.set('config:client', 'address', '127.0.0.1')
config.set('config:client', 'method', 'https')
config.add_section('command:test') config.add_section('command:test')
config.set('command:test', 'path', '/home/gameserver') config.set('command:test', 'path', '/home/gameserver')
config.set('command:test', 'command', '/bin/sleep 10') 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', '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', 'ca_cert', '/home/gameserver/ca/appli/certs/cachaincert.pem')
config.set('config:client', 'address', '127.0.0.1') config.set('config:client', 'address', '127.0.0.1')
config.set('config:client', 'method', 'https')
config.add_section('config:user') config.add_section('config:user')
config.add_section('command:test') config.add_section('command:test')
config.set('command:test', 'command', '/bin/sleep 10') config.set('command:test', 'command', '/bin/sleep 10')
@ -312,6 +315,9 @@ class TestManager(unittest.TestCase):
queueOut, queueOut,
event, event,
maxWaitEnd = 2) maxWaitEnd = 2)
except:
self.fail('Error initialize object ManageCommand')
try:
res = manageCommand.start() res = manageCommand.start()
self.assertEqual(res, 'started') self.assertEqual(res, 'started')
wait = True wait = True
@ -332,8 +338,8 @@ class TestManager(unittest.TestCase):
res = manageCommand.status() res = manageCommand.status()
self.assertEqual(res, 'stopped') self.assertEqual(res, 'stopped')
self.assertTrue(True) self.assertTrue(True)
except: except Exception as e:
self.fail('Error initialize object ManageCommand') self.fail('Error when run test', e)
def test_execute_command_crashed(self): def test_execute_command_crashed(self):
try: try: