Commit 94a69d0f authored by Likun Zhang's avatar Likun Zhang

Add code for cmd-ctrld.

git-svn-id: svn://bind10.isc.org/svn/bind10/branches/parkinglot@492 e5f2f494-b856-4b98-b285-d166d9295462
parent d2d26060
bin_SCRIPTS = cmd-ctrld cmd-ctrld.py
1. Refine code for cmd-ctrld and bindctl
2. Add value type check.
3. Make code be robust.
4. Add ssl support.
#! /bin/sh
PYTHON_EXEC=${PYTHON_EXEC:-@PYTHON@}
export PYTHON_EXEC
CMD_CTRLD_PATH=@abs_top_srcdir@/src/bin/cmd-ctrld
PYTHONPATH=@abs_top_srcdir@/src/lib/cc/python:${abs_top_src_dir}/lib/cc/python/ISC
export PYTHONPATH
cd ${CMD_CTRLD_PATH}
python cmd-ctrld.py
import http.server
import urllib.parse
import json
import re
import ssl, socket
import ISC
import pprint
import select
import csv
import random
from hashlib import sha1
try:
import threading
except ImportError:
import dummy_threading as threading
URL_PATTERN = re.compile('/([\w]+)(?:/([\w]+))?/?')
class SecureHTTPRequestHandler(http.server.BaseHTTPRequestHandler):
'''
Process GET and POST
'''
def parse_path(self, path):
groups = URL_PATTERN.match(path)
if not groups:
return (NULL, NULL)
return (groups.group(1), groups.group(2))
def check_username(self,name):
reader = csv.reader(open("passwd.csv"), delimiter="\t", quoting=csv.QUOTE_MINIMAL)
for row in reader:
if name==row[0]:
self.user=[row[0],row[1],row[2]]
return 1
return 0
def check(self):
length = self.headers.get('content-length')
nbytes = int(length)
user_info = json.loads((self.rfile.read(nbytes)).decode())
if not user_info:
return ["error: invalid username or password"], http.client.UNAUTHORIZED
if not self.check_username(user_info['username']):
return ["error:the username doesn't exists"], http.client.UNAUTHORIZED
if sha1((user_info['password'] + self.user[2]).encode()).hexdigest() != self.user[1] :
return ["error:the username and passwd did not match!"], http.client.UNAUTHORIZED
else :
id = self.headers.get('cookie')
self.server.session[id]['username'] = user_info['username']
return ["login sucess !"], http.client.OK
def do_GET(self):
id = self.headers.get('cookie')
if id not in self.server.session:
self.server.session[id]={}
reply_value = []
if "username" not in self.server.session[id]:
reply_value = ["please post username and passwd"]
else:
identifier, module = self.parse_path(self.path)
if identifier != None:
data = self.server.get_reply_data_for_GET(identifier, module)
if data:
reply_value = data
self.send_response(200)
self.end_headers()
self.wfile.write(json.dumps(reply_value).encode())
def do_POST(self):
id = self.headers.get('cookie')
if id not in self.server.session:
self.server.session[id] = {}
reply_msg = []
rcode = 200
if self.path == '/':
reply_msg, rcode = self.check()
elif "username" not in self.server.session[id]:
reply_msg, rcode = ["please login!"], http.client.UNAUTHORIZED
else:
mod, cmd = self.parse_path(self.path)
param = None
len = self.headers.get('Content-Length')
if len:
post_str = str(self.rfile.read(int(len)).decode())
print("command parameter:%s" % post_str)
param = json.loads(post_str)
reply_msg = self.server.send_command_to_module(mod, cmd, param)
print('cmd-ctrld finish send message \'%s\' to module %s' % (cmd, mod))
#TODO, set proper rcode
self.send_response(rcode)
self.end_headers()
self.wfile.write(json.dumps(reply_msg).encode())
class CommandControl():
def __init__(self):
self.cc = ISC.CC.Session()
self.cc.group_subscribe('Cmd-Ctrld')
self.cc.group_subscribe('Boss', 'Cmd-Ctrld')
self.command_spec = self.get_cmd_specification()
self.config_spec = self.get_data_specification()
self.config_data = self.get_config_data()
def get_cmd_specification(self):
return self.send_command('ConfigManager', 'get_commands')
def get_config_data(self):
return self.send_command('ConfigManager', 'get_config')
def update_config_data(self, module_name, command_name):
if module_name == 'ConfigManager' and command_name == 'set_config':
self.config_data = self.get_config_data()
def get_data_specification(self):
return self.send_command('ConfigManager', 'get_data_spec')
def handle_recv_msg(self):
# Handle received message, if 'shutdown' is received, return False
(message, env) = self.cc.group_recvmsg(True)
while message:
if 'commands_update' in message:
self.command_spec[message['commands_update'][0]] = message['commands_update'][1]
elif 'specification_update' in message:
msgvalue = message['specification_update']
self.config_spec[msgvalue[0]] = msgvalue[1]
elif 'command' in message and message['command'][0] == 'shutdown':
return False;
(message, env) = self.cc.group_recvmsg(True)
return True
def send_command(self, module_name, command_name, params = None):
content = [command_name]
if params:
content.append(params)
msg = {'command' : content}
print('cmd-ctrld send command \'%s\' to %s' %(command_name, module_name))
try:
# Do special for Boss shutdown. TODO, avoid specicialism
if module_name == 'Boss' and command_name == 'shutdown':
self.cc.group_sendmsg(msg, module_name, 'boss')
return {}
self.cc.group_sendmsg(msg, module_name)
answer, env = self.cc.group_recvmsg(False)
if answer and 'result' in answer.keys() and type(answer['result']) == list:
# TODO: with the new cc implementation, replace "1" by 1
if answer['result'][0] == "1":
# todo: exception
print("Error: " + str(answer['result'][1]))
return {}
else:
self.update_config_data(module_name, command_name)
if len(answer['result']) > 1:
return answer['result'][1]
return {}
else:
print("Error: unexpected answer from %s" % module_name)
except Exception as e:
print(e)
print('cmd-ctrld fail send command \'%s\' to %s' % (command_name, module_name))
return {}
class SecureHTTPServer(http.server.HTTPServer):
def __init__(self, server_address, RequestHandlerClass):
http.server.HTTPServer.__init__(self, server_address, RequestHandlerClass)
self.session = {}
self.cmdctrl = CommandControl()
self.__is_shut_down = threading.Event()
self.__serving = False
def get_request(self):
newsocket, fromaddr = self.socket.accept()
try:
connstream = ssl.wrap_socket(newsocket,
server_side = True,
certfile = 'create_your_cert.pem',
keyfile = 'create_your_cert.pem',
ssl_version = ssl.PROTOCOL_SSLv23)
return (connstream, fromaddr)
except ssl.SSLError as e :
print("error happen***********")
print(e)
def get_reply_data_for_GET(self, id, module_name):
if module_name is None:
if id == 'command_spec':
return self.cmdctrl.command_spec
elif id == 'config_data':
return self.cmdctrl.config_data
elif id == 'config_spec':
return self.cmdctrl.config_spec
else:
return None
def serve_forever(self, poll_interval = 0.5):
self.__serving = True
self.__is_shut_down.clear()
while self.__serving:
if not self.cmdctrl.handle_recv_msg():
break
r, w, e = select.select([self], [], [], poll_interval)
if r:
self._handle_request_noblock()
self.__is_shut_down.set()
def shutdown(self):
self.__serving = False
self.__is_shut_down.wait()
def send_command_to_module(self, module_name, command_name, params):
return self.cmdctrl.send_command(module_name, command_name, params)
def run(server_class = SecureHTTPServer, addr = 'localhost', port = 8080):
print("cmd-ctrld module is starting on :%s port:%d" %(addr, port))
httpd = server_class((addr, port), SecureHTTPRequestHandler)
httpd.serve_forever()
if __name__ == '__main__':
try:
run()
except ISC.CC.SessionError as se:
print("[cmd-ctrld] Error creating cmd-ctrld, "
"is the command channel daemon running?")
except KeyboardInterrupt:
print("exit http server")
-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQDpICWxJGKMvUhLFPbf5n8ZWogqjYcQqqoHqHVRHYjyiey6FZdt
ZkY2s1gYh0G0NXtimlIgic+vEcFe7vdmyKntW7DYDaqAj0KrED7RKAj8324jNbSJ
HtLP4evvJep3vsoNtTvNuceQJ46vukxyxgg3DuC9kVqPuD8CZ1Rq4ATyiwIDAQAB
AoGBAOJlOtV+DUq6Y2Ou91VXRiU8GzKgAQP5iWgoe84Ljbxkn4XThBxVD2j94Fbp
u7AjpDCMx6cbzpoo9w6XqaGizAmAehIfTE3eFYs74N/FM09Wg2OSDyxMY0jgyECU
A4ukjlPwcGDbmgbmlY3i+FVHp+zCgtZEsMC1IAosMac1BoX5AkEA/lrXWaVtH8bo
mut3GBaXvubZMdaUr0BUd5a9q+tt4dQcKG1kFqgCNKhNhBIcpiMVcz+jGmOuopNA
8dnUGqv3FQJBAOqiJ54ZvOTWNDpJIe02wIXRxRmc1xhHFCqYP23KxBVrAcTYB19J
lesov/hEbnGLCbKS/naZJ1zrTImUPNRLqx8CQCzDtA7U7GWhTiKluioFH+O7IRKC
X1yQh80cPHlbT9VkzSfYSLssCmdWD35k6aHbntTPqFbmoD+AhveJjKi9BxkCQDwX
1c+/RcrSNcQr0N2hZUOgyztZGRnlsnuKTMyA3yGhK23P6mt0PEpjQG+Ej0jTVGOB
FF0pspQwy4R9C+tPif8CQH36NNlXBfVNmT7kDtyLmaE6pID0vY9duX56BJbU1R0x
SQ8/LcfJagk6gvp08OyYCPA+WZ7u/bas9R/nMTCLivc=
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
MIIDhzCCAvCgAwIBAgIJALwngNFik7ONMA0GCSqGSIb3DQEBBQUAMIGKMQswCQYD
VQQGEwJjbjEQMA4GA1UECBMHYmVpamluZzEQMA4GA1UEBxMHYmVpamluZzEOMAwG
A1UEChMFY25uaWMxDjAMBgNVBAsTBWNubmljMRMwEQYDVQQDEwp6aGFuZ2xpa3Vu
MSIwIAYJKoZIhvcNAQkBFhN6aGFuZ2xpa3VuQGNubmljLmNuMB4XDTEwMDEwNzEy
NDcxOFoXDTExMDEwNzEyNDcxOFowgYoxCzAJBgNVBAYTAmNuMRAwDgYDVQQIEwdi
ZWlqaW5nMRAwDgYDVQQHEwdiZWlqaW5nMQ4wDAYDVQQKEwVjbm5pYzEOMAwGA1UE
CxMFY25uaWMxEzARBgNVBAMTCnpoYW5nbGlrdW4xIjAgBgkqhkiG9w0BCQEWE3po
YW5nbGlrdW5AY25uaWMuY24wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOkg
JbEkYoy9SEsU9t/mfxlaiCqNhxCqqgeodVEdiPKJ7LoVl21mRjazWBiHQbQ1e2Ka
UiCJz68RwV7u92bIqe1bsNgNqoCPQqsQPtEoCPzfbiM1tIke0s/h6+8l6ne+yg21
O825x5Anjq+6THLGCDcO4L2RWo+4PwJnVGrgBPKLAgMBAAGjgfIwge8wHQYDVR0O
BBYEFJKM/O0ViGlwtb3JEci/DLTO/7DaMIG/BgNVHSMEgbcwgbSAFJKM/O0ViGlw
tb3JEci/DLTO/7DaoYGQpIGNMIGKMQswCQYDVQQGEwJjbjEQMA4GA1UECBMHYmVp
amluZzEQMA4GA1UEBxMHYmVpamluZzEOMAwGA1UEChMFY25uaWMxDjAMBgNVBAsT
BWNubmljMRMwEQYDVQQDEwp6aGFuZ2xpa3VuMSIwIAYJKoZIhvcNAQkBFhN6aGFu
Z2xpa3VuQGNubmljLmNuggkAvCeA0WKTs40wDAYDVR0TBAUwAwEB/zANBgkqhkiG
9w0BAQUFAAOBgQBh5N6isMAQAFFD+pbfpppjQlO4vUNcEdzPdeuBFaf9CsX5ZdxV
jmn1ZuGm6kRzqUPwPSxvCIAY0wuSu1g7YREPAZ3XBVwcg6262iGOA6n7E+nv5PLz
EuZ1oUg+IfykUIoflKH6xZB4MyPL+EgkMT+i9BrngaXHXF8tEO30YppMiA==
-----END CERTIFICATE-----
root e0da4e422d3f42173edfee8a0fab11f9c5f4f2bb -R%zdgw/L@E}n1WTQTw*p=3i3=C~cbsvy=s'mWEO=m)IQN]|e4-/u?rC)5cDIBLn
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment