def __init__(self, usersProvider=None): self.logger = Logger(__name__) self.userProvider = usersProvider or UsersProvider() self.settings = Settings().getSettings() self.mysql = MySQLUserCreator() self.fs = FileSystem() self.mongoForgotPass = MongoForgotPassword()
class CreateDomain: def __init__(self): self.settings = Settings().getSettings() self.logger = Logger(__name__) self.domain = Domain() def execute(self, *args): args = self._parse_arguments(*args) args.domain[0] = args.domain[0].lower() if self.domain.domain_exists(args.domain[0]) is True: self.logger.error("Domain already exists") sys.exit(1) regex = "^[a-zA-Z0-9][a-zA-Z0-9-_]{0,61}[a-zA-Z0-9]{0,1}\.([a-zA-Z]{1,6}|[a-zA-Z0-9-]{1,30}\.[a-zA-Z]{2,})$" pattern = re.compile(regex) if not pattern.match(args.domain[0]): self.logger.error("The domain you provided is not valid!") sys.exit(1) self.domain.create_domain(args.domain[0]) def _parse_arguments(self, command_name, *args): parser = ArgumentParser(description='Domains creation', prog='eyeos ' + command_name) parser.add_argument('domain', metavar='DOMAIN', nargs=1, help='DNS name of the domain to create') args = parser.parse_args(args) return args
class Application: def __init__(self, injected_proxy_ip=None, injected_api_call=None): self.proxy_ip = injected_proxy_ip or Settings().getServiceIp('proxy') self.api_call = injected_api_call or EyeosApiCall() self.logger = Logger(__name__) def insert_apps(self, apps, card): apps_url = "https://{0}/application/v1/applications".format(self.proxy_ip) self.logger.debug('POST request to: {0}'.format(apps_url)) req = self.api_call.post(apps_url, card=card, verify=False, json=apps) if req.status_code != 201: raise EyeosAPIError("Error inserting apps. API response: [ code: {0}, content: {1}]" .format(req.status_code, req.content)) self.logger.info('Apps correctly installed.') def empty_apps(self, card): apps_url = "https://{0}/application/v1/applications".format(self.proxy_ip) self.logger.debug('DELETE request to: {0}'.format(apps_url)) req = self.api_call.delete(apps_url, card=card, verify=False) if req.status_code != 200: raise EyeosAPIError("Error emptying apps. API response: [ code: {0}, content: {1}]" .format(req.status_code, req.content)) self.logger.info('Apps correctly emptied.') def save(self, apps, card): self.insert_apps(apps['eyeosApps'], card)
class Application: def __init__(self, injected_proxy_ip=None, injected_api_call=None): self.proxy_ip = injected_proxy_ip or Settings().getServiceIp('proxy') self.api_call = injected_api_call or EyeosApiCall() self.logger = Logger(__name__) def insert_apps(self, apps, card): apps_url = "https://{0}/application/v1/applications".format( self.proxy_ip) self.logger.debug('POST request to: {0}'.format(apps_url)) req = self.api_call.post(apps_url, card=card, verify=False, json=apps) if req.status_code != 201: raise EyeosAPIError( "Error inserting apps. API response: [ code: {0}, content: {1}]" .format(req.status_code, req.content)) self.logger.info('Apps correctly installed.') def empty_apps(self, card): apps_url = "https://{0}/application/v1/applications".format( self.proxy_ip) self.logger.debug('DELETE request to: {0}'.format(apps_url)) req = self.api_call.delete(apps_url, card=card, verify=False) if req.status_code != 200: raise EyeosAPIError( "Error emptying apps. API response: [ code: {0}, content: {1}]" .format(req.status_code, req.content)) self.logger.info('Apps correctly emptied.') def save(self, apps, card): self.insert_apps(apps['eyeosApps'], card)
class UserCreate: def __init__(self): self.logger = Logger(__name__) self.userManagement = UsersManagement() self.settings = Settings().getSettings() self.domain = Domain() def execute(self, *args): args = self._parse_arguments(*args) args.user[0] = args.user[0].lower() if self.validateUsername(args.user[0]) is False: self.logger.error("The username '" + args.user[0] + "' contains illegal characters. " "(A username may only contain letters, numbers, underscores, dashes, and dots)") sys.exit(1) if self.domain.domain_exists(args.domain) is False: self.logger.error("The domain " + args.domain + " does not exist. " "Cannot add user to non existing domain \n" "To create this domain execute: sudo eyeos create-domain " + args.domain) sys.exit(1) if self.userManagement.createUser(args): pass # sys.exit(0) else: sys.exit(1) def _parse_arguments(self, command_name, *args): parser = ArgumentParser(description='Users creation', prog='eyeos ' + command_name) parser.add_argument('user', metavar='USERNAME', nargs=1, help='username of the user to delete') parser.add_argument('--domain', metavar='DOMAIN', required=False, default=self.settings['general']['default_domain'], help='Insert the domain of the user') parser.add_argument('--firstname', metavar='NAME', default=False, help='Insert the firstname when create a user') parser.add_argument('--surname', metavar='SURNAME', required=True, help='Insert the surname when create a user') parser.add_argument('--password', metavar='PASSWORD', required=True, help='Insert the password when create a user') parser.add_argument('--email', metavar='EMAIL', required=True, help='Insert the email when create a user') args = parser.parse_args(args) return args def validateUsername(self, username): regex = re.compile(r"^[a-zA-Z0-9_.-]{4,192}$") if regex.match(username) is None: return False else: return True
class MySQLUserCreator(): def __init__(self): self.settings = Settings().getSettings() self.logger = Logger(__name__) def _get_db_credentials(self, username, domain): if self.settings['general']['multitenant'] == "true": username = username + "_" + domain m = hashlib.sha256() salted_user = username + self.settings['mysql']['user_salt'] m.update(str.encode(salted_user)) mysqlPassword = m.hexdigest() if self.settings['general']['multitenant'] == "true": self.logger.debug( "Creating db and user for mysql with multitenant.") m.update(str.encode(username)) dbname = m.hexdigest() username = dbname[0:16] return (username + "_dbv2", username, mysqlPassword) return (username + "_db", username, mysqlPassword) def create_user(self, username, domain): print("Creating db for", username, domain) dbname, mysqlUsername, mysqlPassword = self._get_db_credentials( username, domain) db = MySQLdb.connect(host=self.settings['mysql']['host'], user="******", passwd=self.settings['mysql']['root_password'], db="mysql") print("Connected to mysql db") with db, db.cursor() as cur: create_stmt = "CREATE USER %(username)s@'%%' IDENTIFIED BY %(password)s;" self.logger.debug("Creating mysql user " + mysqlUsername) cur.execute(create_stmt, { 'username': mysqlUsername, 'password': mysqlPassword }) self.logger.debug("Creating db " + dbname + " with user " + mysqlUsername) cur.execute("CREATE DATABASE `" + dbname + "`;") self.logger.debug("Granting privileges on " + dbname + " to user " + mysqlUsername) cur.execute( "GRANT ALL PRIVILEGES ON `" + dbname + "`.* TO %(username)s@'%%';", {'username': mysqlUsername}) cur.execute("FLUSH PRIVILEGES;") db.commit() print("Created db")
class Logout: def __init__(self, injected_proxy_ip=None, injected_eyeos_api_call=None): self.settings = Settings().getSettings() self.proxy_ip = injected_proxy_ip or self.settings['general']['public_hostname'] self.logger = Logger(__name__) self.eyeos_api_call = injected_eyeos_api_call or EyeosApiCall() def logout(self, card): self.logger.info("Retrieving a valid card...") data = { 'timestamp': int(time.time()) } logout_url = "https://{0}/relay/presence/v1/routingKey/logout/userEvent/logout".format(self.proxy_ip) self.logger.debug('POST request to: {0}'.format(logout_url)) req = self.eyeos_api_call.post(logout_url, verify=False, data=data, card=card) if req.status_code != 200: raise ValueError("Error logging out with user")
def __init__(self, injected_open=None, injected_eyeos_apps_storage=None, injected_json=None, injected_eyeos_apps_validator=None, injected_application_api=None, injected_principals_api=None, injected_base_group=None, injected_login_api=None): self.eyeos_apps_storage = injected_eyeos_apps_storage or EyeosAppsStorage( ) self.open = injected_open or open self.json = injected_json or json self.logger = Logger(__name__) self.eyeos_apps_validator = injected_eyeos_apps_validator or EyeosAppsJsonValidator( ) self.application_api = injected_application_api or Application() self.principals_api = injected_principals_api or Principals() self.principal_base_group = injected_base_group or Settings( ).getSettings()['principalservice']['base_group'] self.login_api = injected_login_api or Login()
class WaitForEyeos: def __init__(self): self.settings = Settings() self.logger = Logger(__name__) self.entrypoint = "proxy" def wait(self, timeout): logging.getLogger("requests").setLevel(logging.ERROR) starttime = time.time() while True: now = time.time() if now - starttime > timeout: raise TimeoutError("Wait timed out") try: ip = self.settings.getServiceIp(self.entrypoint) requests.get('http://{0}'.format(ip), verify=False) time.sleep(5) self.logger.info("Waited for {0} seconds".format(int(now - starttime))) break except (UnknownHostError, requests.exceptions.RequestException) as e: time.sleep(0.5) continue
class Login: def __init__(self, injected_proxy_ip=None, injected_eyeos_api_call=None): self.settings = Settings().getSettings() self.proxy_ip = injected_proxy_ip or self.settings['general'][ 'public_hostname'] self.logger = Logger(__name__) self.eyeos_api_call = injected_eyeos_api_call or EyeosApiCall() def authenticate(self, username, password, domain=False): if not domain: domain = self.settings['general']['default_domain'] self.logger.info("Retrieving a valid card...") data = { 'type': 'Basic', 'username': username, 'password': password, 'domain': domain } auth_url = "https://{0}/login/v1/methods/login/".format(self.proxy_ip) self.logger.debug('POST request to: {0}'.format(auth_url)) req = self.eyeos_api_call.post(auth_url, verify=False, json=data) if req.status_code != 200: raise ValueError( "Error authenticating with user {0} (Check if captcha is preventing access)" .format(data['username'])) try: login_card = req.json() except ValueError as e: raise EyeosAPIError("Error parsing JSON response: {0}".format( req.content)) from e try: return EyeosCard(login_card['card'], login_card['signature']) except KeyError as e: raise EyeosAPIError("Can't retrieve card form login API") from e
class MySQLUserCreator(): def __init__(self): self.settings = Settings().getSettings() self.logger = Logger(__name__) def _get_db_credentials(self, username, domain): if self.settings['general']['multitenant'] == "true": username = username + "_" + domain m = hashlib.sha256() salted_user = username + self.settings['mysql']['user_salt'] m.update(str.encode(salted_user)) mysqlPassword = m.hexdigest() if self.settings['general']['multitenant'] == "true": self.logger.debug("Creating db and user for mysql with multitenant.") m.update(str.encode(username)) dbname = m.hexdigest() username = dbname[0:16] return (username + "_dbv2", username, mysqlPassword) return (username + "_db", username, mysqlPassword) def create_user(self, username, domain): print("Creating db for", username, domain) dbname, mysqlUsername, mysqlPassword = self._get_db_credentials(username, domain) db = MySQLdb.connect(host=self.settings['mysql']['host'], user="******", passwd=self.settings['mysql']['root_password'], db="mysql") print("Connected to mysql db") with db, db.cursor() as cur: create_stmt = "CREATE USER %(username)s@'%%' IDENTIFIED BY %(password)s;" self.logger.debug("Creating mysql user " + mysqlUsername) cur.execute(create_stmt, {'username': mysqlUsername, 'password': mysqlPassword}) self.logger.debug("Creating db " + dbname + " with user " + mysqlUsername) cur.execute("CREATE DATABASE `" + dbname + "`;") self.logger.debug("Granting privileges on " + dbname + " to user " + mysqlUsername) cur.execute("GRANT ALL PRIVILEGES ON `" + dbname + "`.* TO %(username)s@'%%';", {'username': mysqlUsername}) cur.execute("FLUSH PRIVILEGES;") db.commit() print("Created db")
class WaitForEyeos: def __init__(self): self.settings = Settings() self.logger = Logger(__name__) self.entrypoint = "proxy" def wait(self, timeout): logging.getLogger("requests").setLevel(logging.ERROR) starttime = time.time() while True: now = time.time() if now - starttime > timeout: raise TimeoutError("Wait timed out") try: ip = self.settings.getServiceIp(self.entrypoint) requests.packages.urllib3.disable_warnings() requests.get('http://{0}'.format(ip), verify=False) time.sleep(5) self.logger.info("Waited for {0} seconds".format(int(now - starttime))) break except (UnknownHostError, requests.exceptions.RequestException) as e: time.sleep(0.5) continue
class Login: def __init__(self, injected_proxy_ip=None, injected_eyeos_api_call=None): self.settings = Settings().getSettings() self.proxy_ip = injected_proxy_ip or self.settings['general']['public_hostname'] self.logger = Logger(__name__) self.eyeos_api_call = injected_eyeos_api_call or EyeosApiCall() def authenticate(self, username, password, domain=False): if not domain: domain = self.settings['general']['default_domain'] self.logger.info("Retrieving a valid card...") data = { 'type': 'Basic', 'username': username, 'password': password, 'domain': domain } auth_url = "https://{0}/login/v1/methods/login/".format(self.proxy_ip) self.logger.debug('POST request to: {0}'.format(auth_url)) req = self.eyeos_api_call.post(auth_url, verify=False, json=data) if req.status_code != 200: raise ValueError("Error authenticating with user {0} (Check if captcha is preventing access)" .format(data['username'])) try: login_card = req.json() except ValueError as e: raise EyeosAPIError("Error parsing JSON response: {0}".format(req.content)) from e try: return EyeosCard(login_card['card'], login_card['signature']) except KeyError as e: raise EyeosAPIError("Can't retrieve card form login API") from e
def __init__(self, injected_open=None, injected_eyeos_apps_storage=None, injected_json=None, injected_eyeos_apps_validator=None, injected_application_api=None, injected_principals_api=None, injected_base_group=None, injected_login_api=None): self.eyeos_apps_storage = injected_eyeos_apps_storage or EyeosAppsStorage() self.open = injected_open or open self.json = injected_json or json self.logger = Logger(__name__) self.eyeos_apps_validator = injected_eyeos_apps_validator or EyeosAppsJsonValidator() self.application_api = injected_application_api or Application() self.principals_api = injected_principals_api or Principals() self.principal_base_group = injected_base_group or Settings().getSettings()['principalservice']['base_group'] self.login_api = injected_login_api or Login()
def __init__(self, injectedSettings=None, injectedSubprocess=None): self.logger = Logger(__name__) self.settings = injectedSettings or Settings().getSettings() self.subprocess = injectedSubprocess or subprocess
def __init__(self): self.settings = Settings() self.logger = Logger(__name__) self.entrypoint = "proxy"
class __Ldap: ldap = None def __init__(self, settings=None): self.settings = settings or Settings() self.logger = Logger(__name__) def getInstance(self): settings = self.settings.getSettings() user = settings['ldap']['admin_ldap_username'] password = settings['ldap']['admin_ldap_password'] host = self.settings.getServiceIp('ldap') self.logger.debug("Connecting to " + host + " with user " + user) self.dn_base = settings['ldap']['ldap_cn_base'] server = Server(host, get_info=ALL) self.ldapClient = Connection(server, user=user, password=password, raise_exceptions=True) try: self.ldapClient.bind() except ldap.LDAPSocketOpenError as e: self.logger.error("Could not connect to LDAP - SocketOpenError: " + str(e)) return self def __enter__(self): return self def __exit__(self, exc_type, exc_val, exc_tb): return self.ldapClient.unbind() def disconnect(self): self.ldapClient.unbind() def createUser(self, user, firstname, lastname, password, email): password = password.encode('utf-8') hashPassword = hashlib.md5() hashPassword.update(password) password = base64.b64encode(hashPassword.digest()) dn = "cn=" + user + "," + self.dn_base attrs = {} attrs['objectClass'] = ['inetOrgPerson', 'person', 'top', 'organizationalPerson'] attrs['cn'] = user attrs['userPassword'] = "******" + password.decode('utf-8') attrs['sn'] = lastname attrs['givenName'] = firstname attrs['mail'] = email try: self.ldapClient.add(dn, attributes=attrs) self.logger.info(self.ldapClient.result) except ldap.LDAPEntryAlreadyExistsResult: self.logger.error("Could not create user, duplicated " + user) return False except Exception as e: self.logger.error("Could not create user: "******"cn="+user+","+self.dn_base self.ldapClient.delete(deleteDN) return True def findUser(self, user): self.ldapClient.search(search_base=self.dn_base, search_filter='(&(objectClass=inetOrgPerson)(cn=' + user + '))', search_scope=SUBTREE, attributes=['cn']) usernames = [] for result in self.ldapClient.response: cn = result['attributes']['cn'][0] if cn: usernames.append(cn) return usernames
class UsersManagement: def __init__(self, usersProvider=None): self.logger = Logger(__name__) self.userProvider = usersProvider or UsersProvider() self.settings = Settings().getSettings() self.mysql = MySQLUserCreator() self.fs = FileSystem() self.mongoForgotPass = MongoForgotPassword() def createUser(self, args): with self.userProvider.connect() as usersClient: if self.settings['general']['multitenant'] == "true": email = args.user[0] + '@' + args.domain username = args.user[0] + '@' + args.domain else: email = args.user[0] + '@' + self.settings['email']['domain'] username = args.user[0] ret = usersClient.createUser(username, args.firstname, args.surname, args.password, email) if ret: self.logger.info("User created") self.mysql.create_user(args.user[0], args.domain) self.fs.create_skel(args.user[0], args.domain) self.mongoForgotPass.insert_user(args.user[0], args.email, args.domain) login_api = Login() logout_api = Logout() eyeos_card = login_api.authenticate(args.user[0], args.password, args.domain) self.logger.info("Logged in as user") logout_api.logout(eyeos_card) return ret def _send_welcome_email(self, args, email): with open('lib/Users/welcome_email/text', 'r') as content: plain_content = content.read() with open('lib/Users/welcome_email/html.html', 'r') as content: html_content = content.read() with open('lib/Users/welcome_email/subject', 'r') as content: subject = content.read() email_from = email email_to = email smtp_host = self.settings['email']['smtp_host'] def deleteUser(self, args): try: with self.userProvider.connect() as usersClient: usersClient.deleteUser(args.user[0]) self.logger.info("Delete user") return True except Exception as e: self.logger.error("Could not delete user") return False def findUser(self, args): try: with self.userProvider.connect() as usersClient: usernames = usersClient.findUser(args.user[0]) self.logger.info("Found {0} users matching '{1}'".format(len(usernames), args.user[0])) for user in usernames: print(user) return True except Exception as e: self.logger.info("Does not match any entries") return False
class EyeosApps: DEFAULT_APPS_DIR = './eyeos_apps/default' def __init__(self, injected_open=None, injected_eyeos_apps_storage=None, injected_json=None, injected_eyeos_apps_validator=None, injected_application_api=None, injected_principals_api=None, injected_base_group=None, injected_login_api=None): self.eyeos_apps_storage = injected_eyeos_apps_storage or EyeosAppsStorage( ) self.open = injected_open or open self.json = injected_json or json self.logger = Logger(__name__) self.eyeos_apps_validator = injected_eyeos_apps_validator or EyeosAppsJsonValidator( ) self.application_api = injected_application_api or Application() self.principals_api = injected_principals_api or Principals() self.principal_base_group = injected_base_group or Settings( ).getSettings()['principalservice']['base_group'] self.login_api = injected_login_api or Login() def install(self, apps_directory, admin_user, password, domain): apps_file = apps_directory + '/apps.json' with self.open(apps_file, 'r') as f: try: apps = self.json.load(f) except ValueError as e: raise ValueError("File {0} does not contain valid JSON".format( apps_file)) from e self.eyeos_apps_validator.validate(apps) try: eyeos_card = self.login_api.authenticate(admin_user, password, domain) self.logger.info('Emptying previous apps...') self.application_api.empty_apps(eyeos_card) self.logger.info('Saving apps...') self.eyeos_apps_storage.save(apps) self.application_api.save(apps, eyeos_card) group = self.principals_api.get_systemgroup( self.principal_base_group, eyeos_card) group = self._generate_new_permissions(apps, group) self.principals_api.put_systemgroup(group, eyeos_card) except (ValueError, KeyError, EyeosAPIError) as e: self.logger.error(e) exit(1) def _generate_new_permissions(self, applications, group): """ existing permissions like eyeos.application.* should be removed and then add new eyeos.applications.whatever permissions for each eyeos_apps applications. permissions like eyeos.admin.*.edit should be removed and add new ones from the control_panel applications the eyeos.admin.*.edit permissions might pose a problem in the future if there appear new permissions not tied to an application. That's a problem for future everyone :S """ permissions = group['permissions'] i = 0 while i < len(permissions): permission = permissions[i] if (re.match(r'^eyeos\.application\.[^.]*$', permission['id']) or re.match(r'^eyeos\.admin\.[^.]*\.edit$', permission['id'])): permissions.remove(permission) continue i += 1 for eyeos_application in applications['eyeosApps']: permissions.append({ "id": "eyeos.application." + eyeos_application['appID'], "name": 'Execute ' + eyeos_application['name'], "description": "Run " + eyeos_application['name'] + " application", "enabled": True }) for admin_application in applications['controlPanelApps']: permissions.append({ "id": "eyeos.admin." + admin_application['appID'] + '.edit', "name": 'Manage ' + admin_application['name'], "description": "Manage " + admin_application['name'] + " in admin panel", "enabled": False }) return group
class MailDomain: def __init__(self): self.logger = Logger(__name__) self.settings = Settings().getSettings() def create_domain(self, domain): self._prepare_db() self._prepare_table() self._insert_domain(domain) def domain_exists(self, domain): self._prepare_db() self._prepare_table() db = MySQLdb.connect(host=self.settings['email']['dbhost'], user=self.settings['email']['dbuser'], passwd=self.settings['email']['dbpwd'], db=self.settings['email']['dbname']) with db, db.cursor() as cur: cur.execute("SELECT * FROM domains WHERE domain='" + domain + "';") data = cur.fetchone() if data is not None and data[0] == domain: self.logger.debug('The domain ' + domain + ' exists.') return True else: self.logger.debug('The domain ' + domain + ' don\'t exists.') return False def _prepare_db(self): db = MySQLdb.connect(host=self.settings['mysql']['host'], user="******", passwd=self.settings['mysql']['root_password'], db="mysql") with db, db.cursor() as cur: dbname = self.settings['email']['dbname'] query = "CREATE DATABASE IF NOT EXISTS `" + dbname + "`;" self.logger.debug('Creating database ' + dbname) cur.execute(query) username = self.settings['email']['dbuser'] mysqlpassword = self.settings['email']['dbpwd'] self.logger.debug("Granting privileges on " + dbname + " to user " + username) cur.execute( "GRANT ALL PRIVILEGES ON `" + dbname + "`.* TO %(username)s@'%%' IDENTIFIED BY %(password)s;", { 'username': username, 'password': mysqlpassword }) cur.execute("FLUSH PRIVILEGES;") def _prepare_table(self): db = MySQLdb.connect(host=self.settings['email']['dbhost'], user=self.settings['email']['dbuser'], passwd=self.settings['email']['dbpwd'], db=self.settings['email']['dbname']) with db, db.cursor() as cur: cur.execute( "CREATE TABLE IF NOT EXISTS " "domains (domain varchar(50) NOT NULL,PRIMARY KEY (domain) )ENGINE=MyISAM;" ) def _insert_domain(self, domain): db = MySQLdb.connect(host=self.settings['email']['dbhost'], user=self.settings['email']['dbuser'], passwd=self.settings['email']['dbpwd'], db=self.settings['email']['dbname']) with db, db.cursor() as cur: self.logger.info('Creating domain ' + domain) cur.execute('INSERT INTO domains(domain) VALUES(\"' + domain + '\");')
class UsersManagement: def __init__(self, usersProvider=None): self.logger = Logger(__name__) self.userProvider = usersProvider or UsersProvider() self.settings = Settings().getSettings() self.mysql = MySQLUserCreator() self.fs = FileSystem() self.mongoForgotPass = MongoForgotPassword() def createUser(self, args): with self.userProvider.connect() as usersClient: if self.settings['general']['multitenant'] == "true": email = args.user[0] + '@' + args.domain username = args.user[0] + '@' + args.domain else: email = args.user[0] + '@' + self.settings['email']['domain'] username = args.user[0] ret = usersClient.createUser(username, args.firstname, args.surname, args.password, email) if ret: self.logger.info("User created") self.mysql.create_user(args.user[0], args.domain) self.fs.create_skel(args.user[0], args.domain) self.mongoForgotPass.insert_user(args.user[0], args.email, args.domain) login_api = Login() logout_api = Logout() eyeos_card = login_api.authenticate(args.user[0], args.password, args.domain) self.logger.info("Logged in as user") logout_api.logout(eyeos_card) return ret def _send_welcome_email(self, args, email): with open('lib/Users/welcome_email/text', 'r') as content: plain_content = content.read() with open('lib/Users/welcome_email/html.html', 'r') as content: html_content = content.read() with open('lib/Users/welcome_email/subject', 'r') as content: subject = content.read() email_from = email email_to = email smtp_host = self.settings['email']['smtp_host'] def deleteUser(self, args): try: with self.userProvider.connect() as usersClient: usersClient.deleteUser(args.user[0]) self.logger.info("Delete user") return True except Exception as e: self.logger.error("Could not delete user") return False def findUser(self, args): try: with self.userProvider.connect() as usersClient: usernames = usersClient.findUser(args.user[0]) self.logger.info("Found {0} users matching '{1}'".format( len(usernames), args.user[0])) for user in usernames: print(user) return True except Exception as e: self.logger.info("Does not match any entries") return False
def __init__(self, settings=None): self.settings = settings or Settings() self.logger = Logger(__name__)
def __init__(self): self.logger = Logger(__name__) self.userManagement = UsersManagement() self.settings = Settings().getSettings() self.domain = Domain()
class EyeosApps: DEFAULT_APPS_DIR = './eyeos_apps/default' def __init__(self, injected_open=None, injected_eyeos_apps_storage=None, injected_json=None, injected_eyeos_apps_validator=None, injected_application_api=None, injected_principals_api=None, injected_base_group=None, injected_login_api=None): self.eyeos_apps_storage = injected_eyeos_apps_storage or EyeosAppsStorage() self.open = injected_open or open self.json = injected_json or json self.logger = Logger(__name__) self.eyeos_apps_validator = injected_eyeos_apps_validator or EyeosAppsJsonValidator() self.application_api = injected_application_api or Application() self.principals_api = injected_principals_api or Principals() self.principal_base_group = injected_base_group or Settings().getSettings()['principalservice']['base_group'] self.login_api = injected_login_api or Login() def install(self, apps_directory, admin_user, password, domain): apps_file = apps_directory + '/apps.json' with self.open(apps_file, 'r') as f: try: apps = self.json.load(f) except ValueError as e: raise ValueError("File {0} does not contain valid JSON".format(apps_file)) from e self.eyeos_apps_validator.validate(apps) try: eyeos_card = self.login_api.authenticate(admin_user, password, domain) self.logger.info('Emptying previous apps...') self.application_api.empty_apps(eyeos_card) self.logger.info('Saving apps...') self.eyeos_apps_storage.save(apps) self.application_api.save(apps, eyeos_card) group = self.principals_api.get_systemgroup(self.principal_base_group, eyeos_card) group = self._generate_new_permissions(apps, group) self.principals_api.put_systemgroup(group, eyeos_card) except (ValueError, KeyError, EyeosAPIError) as e: self.logger.error(e) exit(1) def _generate_new_permissions(self, applications, group): """ existing permissions like eyeos.application.* should be removed and then add new eyeos.applications.whatever permissions for each eyeos_apps applications. permissions like eyeos.admin.*.edit should be removed and add new ones from the control_panel applications the eyeos.admin.*.edit permissions might pose a problem in the future if there appear new permissions not tied to an application. That's a problem for future everyone :S """ permissions = group['permissions'] i = 0 while i < len(permissions): permission = permissions[i] if (re.match(r'^eyeos\.application\.[^.]*$', permission['id']) or re.match(r'^eyeos\.admin\.[^.]*\.edit$', permission['id'])): permissions.remove(permission) continue i += 1 for eyeos_application in applications['eyeosApps']: permissions.append({ "id": "eyeos.application." + eyeos_application['appID'], "name": 'Execute ' + eyeos_application['name'], "description": "Run " + eyeos_application['name'] + " application", "enabled": True }) for admin_application in applications['controlPanelApps']: permissions.append({ "id": "eyeos.admin." + admin_application['appID'] + '.edit', "name": 'Manage ' + admin_application['name'], "description": "Manage " + admin_application['name'] + " in admin panel", "enabled": False }) return group
def __init__(self, proxy_ip=None, injected_eyeos_api_call=None): self.proxy_ip = proxy_ip or Settings().getServiceIp('proxy') self.systemgroups_url = 'https://{0}/systemgroups/v1/systemgroups'.format( self.proxy_ip) self.logger = Logger(__name__) self.eyeos_api_call = injected_eyeos_api_call or EyeosApiCall()
class FileSystem: def __init__(self, injectedSettings=None, injectedSubprocess=None): self.logger = Logger(__name__) self.settings = injectedSettings or Settings().getSettings() self.subprocess = injectedSubprocess or subprocess def clean_filesystem(self): self.logger.info("Cleaning filesystem.") self._clean_files(paths.raw_fs) self.logger.info("Cleaning databases.") self._clean_files(paths.data + "/db") self.logger.info("Cleaning LDAP.") self._clean_files(paths.data + "/ldap") self.logger.info("Cleaning elasticsearch.") self._clean_files(paths.data + "/elasticsearch") self.logger.info("Cleaning MySql.") self._clean_files(paths.data + "/mysql") self.logger.info("Cleaning Seafile Sync Files.") self._clean_files(paths.data + "/seafilesync") self.logger.info("Cleaning Seafile Raw Data.") self._clean_files(paths.data + "/seafileRawData") def _clean_files(self, path): if os.path.isdir(path): shutil.rmtree(path) if not os.path.exists(path): os.makedirs(path) def create_skel(self, username, domain): self.logger.debug("Creating folders for " + username) list_of_dirs = [ "config", "files", "local", "mailbox", "networkdrives", "workgroups" ] if self.settings['general']['multitenant'] == "true": base_path = paths.raw_fs + "/users/" + domain + "/" + username + "/" else: base_path = paths.raw_fs + "/users/" + username + "/" mode = 0o755 for directory in list_of_dirs: os.makedirs(base_path + directory, mode, exist_ok=True) self.logger.debug("Created " + base_path + directory) os.system("chmod 777 " + base_path + "mailbox")
def __init__(self): self.settings = Settings().getSettings() self.logger = Logger(__name__)
def __init__(self): self.logger = Logger(__name__) self.settings = Settings().getSettings()
class MailDomain: def __init__(self): self.logger = Logger(__name__) self.settings = Settings().getSettings() def create_domain(self, domain): self._prepare_db() self._prepare_table() self._insert_domain(domain) def domain_exists(self, domain): self._prepare_db() self._prepare_table() db = MySQLdb.connect(host=self.settings['email']['dbhost'], user=self.settings['email']['dbuser'], passwd=self.settings['email']['dbpwd'], db=self.settings['email']['dbname']) with db, db.cursor() as cur: cur.execute("SELECT * FROM domains WHERE domain='" + domain + "';") data = cur.fetchone() if data is not None and data[0] == domain: self.logger.debug('The domain ' + domain + ' exists.') return True else: self.logger.debug('The domain ' + domain + ' don\'t exists.') return False def _prepare_db(self): db = MySQLdb.connect(host=self.settings['mysql']['host'], user="******", passwd=self.settings['mysql']['root_password'], db="mysql") with db, db.cursor() as cur: dbname = self.settings['email']['dbname'] query = "CREATE DATABASE IF NOT EXISTS `" + dbname + "`;" self.logger.debug('Creating database ' + dbname) cur.execute(query) username = self.settings['email']['dbuser'] mysqlpassword = self.settings['email']['dbpwd'] self.logger.debug("Granting privileges on " + dbname + " to user " + username) cur.execute("GRANT ALL PRIVILEGES ON `" + dbname + "`.* TO %(username)s@'%%' IDENTIFIED BY %(password)s;", {'username': username, 'password': mysqlpassword}) cur.execute("FLUSH PRIVILEGES;") def _prepare_table(self): db = MySQLdb.connect(host=self.settings['email']['dbhost'], user=self.settings['email']['dbuser'], passwd=self.settings['email']['dbpwd'], db=self.settings['email']['dbname']) with db, db.cursor() as cur: cur.execute("CREATE TABLE IF NOT EXISTS " "domains (domain varchar(50) NOT NULL,PRIMARY KEY (domain) )ENGINE=MyISAM;") def _insert_domain(self, domain): db = MySQLdb.connect(host=self.settings['email']['dbhost'], user=self.settings['email']['dbuser'], passwd=self.settings['email']['dbpwd'], db=self.settings['email']['dbname']) with db, db.cursor() as cur: self.logger.info('Creating domain ' + domain) cur.execute('INSERT INTO domains(domain) VALUES(\"' + domain + '\");')
def __init__(self, subprocess=None): self.logger = Logger(__name__) self.subprocess = subprocess or global_subprocess
def __init__(self, injected_proxy_ip=None, injected_api_call=None): self.proxy_ip = injected_proxy_ip or Settings().getServiceIp('proxy') self.api_call = injected_api_call or EyeosApiCall() self.logger = Logger(__name__)
def __init__(self, injected_proxy_ip=None, injected_eyeos_api_call=None): self.settings = Settings().getSettings() self.proxy_ip = injected_proxy_ip or self.settings['general']['public_hostname'] self.logger = Logger(__name__) self.eyeos_api_call = injected_eyeos_api_call or EyeosApiCall()
class FileSystem: def __init__(self, injectedSettings=None, injectedSubprocess=None): self.logger = Logger(__name__) self.settings = injectedSettings or Settings().getSettings() self.subprocess = injectedSubprocess or subprocess def clean_filesystem(self): self.logger.info("Cleaning filesystem.") self._clean_files(paths.raw_fs) self.logger.info("Cleaning databases.") self._clean_files(paths.data + "/db") self.logger.info("Cleaning LDAP.") self._clean_files(paths.data + "/ldap") self.logger.info("Cleaning elasticsearch.") self._clean_files(paths.data + "/elasticsearch") self.logger.info("Cleaning MySql.") self._clean_files(paths.data + "/mysql") self.logger.info("Cleaning Seafile Sync Files.") self._clean_files(paths.data + "/seafilesync") self.logger.info("Cleaning Seafile Raw Data.") self._clean_files(paths.data + "/seafileRawData") self.logger.debug("Cleaning PIM Raw Data.") self._clean_files(paths.data + "/pim") def _clean_files(self, path): if os.path.isdir(path): shutil.rmtree(path) if not os.path.exists(path): os.makedirs(path) def create_skel(self, username, domain): self.logger.debug("Creating folders for " + username) list_of_dirs = ["config", "files", "local", "mailbox", "networkdrives", "workgroups"] if self.settings['general']['multitenant'] == "true": base_path = paths.raw_fs + "/users/" + domain + "/" + username + "/" else: base_path = paths.raw_fs + "/users/" + username + "/" mode = 0o755 for directory in list_of_dirs: os.makedirs(base_path + directory, mode, exist_ok=True) self.logger.debug("Created " + base_path + directory) os.system("chmod 777 " + base_path + "mailbox") os.chown(base_path + "mailbox", int(self.settings['email']['mailbox_owner_uid']), int(self.settings['email']['mailbox_owner_gid']))
def __init__(self): self.logger = Logger(__name__) self.mail = MailDomain()
def __init__(self): self.logger = Logger(__name__) self.ldap = Ldap()
def __init__(self, devenvExecutor=None, instanceResolver=None): self.instanceResolver = instanceResolver or InstanceResolver() self.logger = Logger(__name__)
class __Ldap: ldap = None def __init__(self, settings=None): self.settings = settings or Settings() self.logger = Logger(__name__) def getInstance(self): settings = self.settings.getSettings() user = settings['ldap']['admin_ldap_username'] password = settings['ldap']['admin_ldap_password'] host = self.settings.getServiceIp('ldap') self.logger.debug("Connecting to " + host + " with user " + user) self.dn_base = settings['ldap']['ldap_cn_base'] server = Server(host, get_info=ALL) self.ldapClient = Connection(server, user=user, password=password, raise_exceptions=True) try: self.ldapClient.bind() except ldap.LDAPSocketOpenError as e: self.logger.error( "Could not connect to LDAP - SocketOpenError: " + str(e)) return self def __enter__(self): return self def __exit__(self, exc_type, exc_val, exc_tb): return self.ldapClient.unbind() def disconnect(self): self.ldapClient.unbind() def createUser(self, user, firstname, lastname, password, email): password = password.encode('utf-8') hashPassword = hashlib.md5() hashPassword.update(password) password = base64.b64encode(hashPassword.digest()) dn = "cn=" + user + "," + self.dn_base attrs = {} attrs['objectClass'] = [ 'inetOrgPerson', 'person', 'top', 'organizationalPerson' ] attrs['cn'] = user attrs['userPassword'] = "******" + password.decode('utf-8') attrs['sn'] = lastname attrs['givenName'] = firstname attrs['mail'] = email try: self.ldapClient.add(dn, attributes=attrs) self.logger.info(self.ldapClient.result) except ldap.LDAPEntryAlreadyExistsResult: self.logger.error("Could not create user, duplicated " + user) return False except Exception as e: self.logger.error("Could not create user: "******"cn=" + user + "," + self.dn_base self.ldapClient.delete(deleteDN) return True def findUser(self, user): self.ldapClient.search( search_base=self.dn_base, search_filter='(&(objectClass=inetOrgPerson)(cn=' + user + '))', search_scope=SUBTREE, attributes=['cn']) usernames = [] for result in self.ldapClient.response: cn = result['attributes']['cn'][0] if cn: usernames.append(cn) return usernames
class UserCreate: def __init__(self): self.logger = Logger(__name__) self.userManagement = UsersManagement() self.settings = Settings().getSettings() self.domain = Domain() def execute(self, *args): args = self._parse_arguments(*args) args.user[0] = args.user[0].lower() if self.validateUsername(args.user[0]) is False: self.logger.error( "The username '" + args.user[0] + "' contains illegal characters. " "(A username may only contain letters, numbers, underscores, dashes, and dots)" ) sys.exit(1) if self.domain.domain_exists(args.domain) is False: self.logger.error( "The domain " + args.domain + " does not exist. " "Cannot add user to non existing domain \n" "To create this domain execute: sudo eyeos create-domain " + args.domain) sys.exit(1) if self.userManagement.createUser(args): pass # sys.exit(0) else: sys.exit(1) def _parse_arguments(self, command_name, *args): parser = ArgumentParser(description='Users creation', prog='eyeos ' + command_name) parser.add_argument('user', metavar='USERNAME', nargs=1, help='username of the user to delete') parser.add_argument('--domain', metavar='DOMAIN', required=False, default=self.settings['general']['default_domain'], help='Insert the domain of the user') parser.add_argument('--firstname', metavar='NAME', default=False, help='Insert the firstname when create a user') parser.add_argument('--surname', metavar='SURNAME', required=True, help='Insert the surname when create a user') parser.add_argument('--password', metavar='PASSWORD', required=True, help='Insert the password when create a user') parser.add_argument('--email', metavar='EMAIL', required=True, help='Insert the email when create a user') args = parser.parse_args(args) return args def validateUsername(self, username): regex = re.compile(r"^[a-zA-Z0-9_.-]{4,192}$") if regex.match(username) is None: return False else: return True