#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import absolute_import
from twisted.internet.protocol import Factory, Protocol
from twisted.internet import ssl, reactor
from OpenSSL import SSL
import json, os, sys, logging
import shutil, errno, stat
import xml.etree.ElementTree as ET
from marcopolo.bindings.polo import Polo
#umask = 0022
skeldir = '/etc/skel/.' #TODO: Get it from C
[docs]class Servlet(Protocol):
"""
A Protocol that listens for SSL connections and executes MarcoPolo-like commands
"""
def startProtocol(self):
polo_instance = Polo()
polo_instance.publish("marcousers", root=True, permanent=False)
[docs] def dataReceived(self, data):
"""
Process a new stream of information
:param bytes data: The stream of information
"""
data_dict = json.loads(data.decode('utf-8'))
#The parameters must be separated by commas
params = data_dict["Params"].split(',',3)
if data_dict["Command"] == "Create-Home":
logging.debug("I shall now create the directory %s for %d %d with the utmost pleasure" % (params[0], int(params[1]), int(params[2])))
self.create_homedir(params[0], int(params[1]), int(params[2]))
logging.debug(os.path.join(params[0], 'apache-tomcat-7.0.62'))
if os.path.exists(os.path.join(params[0], 'apache-tomcat-7.0.62')):
logging.debug("I shall now configure Tomcat")
try:
self.configure_tomcat(os.path.join(params[0], 'apache-tomcat-7.0.62'), int(params[1]))
except Exception as e:
self.transport.write(json.dumps({"Error":str(e)}).encode('utf-8'))
logging.debug("Created")
self.transport.write(json.dumps({"OK":0}).encode('utf-8'))
[docs] def create_homedir(self, name, uid, gid):
"""
Creates the home directory, setting the appropriate permissions
:param str name: The path of the directory
:param int uid: The uid of the owner
:param int gid: The gid of the owner's main group
"""
if os.path.exists(name):
logging.info("The directory %s already exists.", name)
return
try:
shutil.copytree(skeldir, name)
except OSError as e:
if e.errno == errno.ENOTDIR:
shutil.copy(src, name)
else:
logging.error("Directory not copied. Error %s" % e)
for root, dirs, files in os.walk(name):
for d in dirs:
os.chown(os.path.join(root, d), uid, gid)
for f in files:
os.chown(os.path.join(root, f), uid, gid)
try:
os.chown(name, uid, gid)
except OSError as e:
logging.error("Ownership could not be set: %s", e)
try:
os.chmod(name, stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR | stat.S_IRGRP | stat.S_IXGRP | stat.S_IROTH | stat.S_IXOTH)
except OSError as e:
logging.error("Permission could not be set: %s", e)
return
def verifyCallback(connection, x509, errnum, errdepth, ok):
"""
The OpenSSL needs the callback to determine the validity of a certificate
:param connection: The connection
:param x509: A x509 object
:param int errnum: The error number
:param int errdepth: The depth of the error
:param bool ok: Determines if the certificate is valid or not.
"""
if not ok:
logging.warning("Invalid certificate from subject ", x509.get_subject())
return False
else:
return True
[docs]def main(argv=None):
"""
Starts the factory for SSL connections
:param list argv: The parameters passed to the command-line entry point
(minus the first one)
"""
factory = Factory()
factory.protocol = Servlet
myContextFactory = ssl.DefaultOpenSSLContextFactory(
os.path.join(conf.CERT_DIR, CERT_NAME), os.path.join(conf.CERT_DIR, conf.KEY_NAME)
)
ctx = myContextFactory.getContext()
ctx.set_verify(SSL.VERIFY_PEER | SSL.VERIFY_FAIL_IF_NO_PEER_CERT,
verifyCallback
)
ctx.load_verify_locations(os.path.join(conf.CERT_DIR, conf.CA_NAME))
f = open("/var/run/polousersclient.pid", 'w')
f.write(str(os.getpid()))
f.close()
if not os.path.exists('/var/log/marcopolo'):
os.makedirs('/var/log/marcopolo')
logging.basicConfig(filename="/var/log/marcopolo/polousersclient.log", level=logging.DEBUG)
logging.info('Starting polousersclient')
reactor.listenSSL(1343, factory, myContextFactory)
reactor.run()
if __name__ == "__main__":
main(sys.argv[1:])