From e1b0b071fecfa80fa7eb4e4cc13a2e07f50dc51b Mon Sep 17 00:00:00 2001 From: root Date: Thu, 22 Jun 2017 21:14:44 +0300 Subject: [PATCH] mail subject, mail content mail send params added..plugins can change mail content with their values.. --- opt/ahenk/base/database/ahenk_db_service.py | 3 + opt/ahenk/base/plugin/plugin.py | 26 ++ opt/ahenk/plugins/backup/backup_task.py | 14 + opt/ahenk/plugins/backup/backup_util.py | 160 ++++++++ opt/ahenk/plugins/backup/main.py | 17 + opt/ahenk/plugins/backup/policy.py | 13 + opt/ahenk/plugins/browser/main.py | 18 + opt/ahenk/plugins/browser/policy.py | 150 +++++++ opt/ahenk/plugins/disk-quota/get_quota.py | 57 +++ opt/ahenk/plugins/disk-quota/init.py | 24 ++ opt/ahenk/plugins/disk-quota/main.py | 16 + opt/ahenk/plugins/disk-quota/policy.py | 262 +++++++++++++ opt/ahenk/plugins/firewall/get-rules.py | 47 +++ opt/ahenk/plugins/firewall/init.py | 39 ++ opt/ahenk/plugins/firewall/main.py | 16 + opt/ahenk/plugins/firewall/policy.py | 60 +++ opt/ahenk/plugins/firewall/shutdown.py | 35 ++ opt/ahenk/plugins/local-user/add_user.py | 132 +++++++ opt/ahenk/plugins/local-user/delete_user.py | 54 +++ opt/ahenk/plugins/local-user/edit_user.py | 146 +++++++ opt/ahenk/plugins/local-user/get_groups.py | 44 +++ opt/ahenk/plugins/local-user/get_users.py | 107 +++++ opt/ahenk/plugins/local-user/init.py | 24 ++ opt/ahenk/plugins/local-user/main.py | 16 + .../local-user/scripts/find_locked_users.sh | 3 + .../local-user/scripts/remove_locked_users.sh | 3 + .../plugins/network-inventory/installahenk.py | 114 ++++++ opt/ahenk/plugins/network-inventory/main.py | 16 + .../multiple-file-transfer.py | 101 +++++ .../plugins/network-inventory/scannetwork.py | 188 +++++++++ opt/ahenk/plugins/network-manager/add_dns.py | 48 +++ .../plugins/network-manager/add_domain.py | 42 ++ opt/ahenk/plugins/network-manager/add_host.py | 49 +++ .../plugins/network-manager/add_network.py | 73 ++++ .../network-manager/change_hostname.py | 42 ++ .../plugins/network-manager/delete_dns.py | 67 ++++ .../plugins/network-manager/delete_domain.py | 57 +++ .../plugins/network-manager/delete_host.py | 70 ++++ .../plugins/network-manager/delete_network.py | 87 ++++ .../get_network_information.py | 54 +++ opt/ahenk/plugins/network-manager/main.py | 15 + .../plugins/package-manager/check_package.py | 63 +++ .../package-manager/get_execution_info.py | 247 ++++++++++++ opt/ahenk/plugins/package-manager/init.py | 46 +++ .../package-manager/installed_packages.py | 53 +++ opt/ahenk/plugins/package-manager/main.py | 16 + .../package-manager/package_archive.py | 44 +++ .../package-manager/package_management.py | 87 ++++ .../package-manager/package_sources.py | 79 ++++ opt/ahenk/plugins/package-manager/packages.py | 133 +++++++ .../plugins/package-manager/repositories.py | 50 +++ .../package-manager/scripts/sourcelist.sh | 10 + .../package-manager/show_package_archive.py | 67 ++++ opt/ahenk/plugins/remote-access/main.py | 19 + .../plugins/remote-access/setup-vnc-server.py | 115 ++++++ opt/ahenk/plugins/resource-usage/main.py | 16 + .../resource-usage/resource_info_alert.py | 79 ++++ .../resource-usage/resource_info_fetcher.py | 51 +++ opt/ahenk/plugins/resource-usage/send_mail.py | 31 ++ opt/ahenk/plugins/resource-usage/shutdown.py | 45 +++ opt/ahenk/plugins/rsyslog/main.py | 16 + opt/ahenk/plugins/rsyslog/policy.py | 116 ++++++ opt/ahenk/plugins/screensaver/main.py | 16 + opt/ahenk/plugins/screensaver/policy.py | 82 ++++ opt/ahenk/plugins/screenshot/main.py | 16 + .../plugins/screenshot/take-screenshot.py | 145 +++++++ opt/ahenk/plugins/script/execute_script.py | 94 +++++ opt/ahenk/plugins/script/main.py | 16 + opt/ahenk/plugins/service/get_services.py | 132 +++++++ opt/ahenk/plugins/service/init.py | 21 + opt/ahenk/plugins/service/main.py | 15 + opt/ahenk/plugins/service/service_list.py | 81 ++++ .../plugins/service/service_management.py | 69 ++++ opt/ahenk/plugins/sudoers/main.py | 17 + opt/ahenk/plugins/sudoers/policy.py | 67 ++++ opt/ahenk/plugins/sudoers/safe.py | 22 ++ opt/ahenk/plugins/usb/init.py | 34 ++ opt/ahenk/plugins/usb/logout.py | 25 ++ opt/ahenk/plugins/usb/main.py | 16 + opt/ahenk/plugins/usb/manage-usb.py | 90 +++++ opt/ahenk/plugins/usb/policy.py | 268 +++++++++++++ .../plugins/usb/scripts/DISABLED_printer.sh | 13 + .../plugins/usb/scripts/DISABLED_usbhid.sh | 37 ++ .../usb/scripts/DISABLED_usbstorage.sh | 46 +++ .../plugins/usb/scripts/DISABLED_webcam.sh | 23 ++ .../plugins/usb/scripts/ENABLED_printer.sh | 3 + .../plugins/usb/scripts/ENABLED_usbhid.sh | 14 + .../plugins/usb/scripts/ENABLED_usbstorage.sh | 16 + .../plugins/usb/scripts/ENABLED_webcam.sh | 3 + opt/ahenk/plugins/user-privilege/init.py | 94 +++++ opt/ahenk/plugins/user-privilege/main.py | 16 + opt/ahenk/plugins/user-privilege/policy.py | 371 ++++++++++++++++++ opt/ahenk/plugins/user-privilege/safe.py | 73 ++++ opt/ahenk/plugins/user-privilege/shutdown.py | 95 +++++ opt/ahenk/plugins/wol/init.py | 30 ++ opt/ahenk/plugins/wol/main.py | 16 + opt/ahenk/plugins/wol/shut-down-machine.py | 40 ++ opt/ahenk/plugins/wol/shutdown.py | 25 ++ opt/ahenk/plugins/wol/wake-machine.py | 105 +++++ opt/ahenk/test.txt | 0 100 files changed, 6138 insertions(+) create mode 100644 opt/ahenk/plugins/backup/backup_task.py create mode 100644 opt/ahenk/plugins/backup/backup_util.py create mode 100644 opt/ahenk/plugins/backup/main.py create mode 100644 opt/ahenk/plugins/backup/policy.py create mode 100644 opt/ahenk/plugins/browser/main.py create mode 100644 opt/ahenk/plugins/browser/policy.py create mode 100644 opt/ahenk/plugins/disk-quota/get_quota.py create mode 100644 opt/ahenk/plugins/disk-quota/init.py create mode 100644 opt/ahenk/plugins/disk-quota/main.py create mode 100644 opt/ahenk/plugins/disk-quota/policy.py create mode 100644 opt/ahenk/plugins/firewall/get-rules.py create mode 100644 opt/ahenk/plugins/firewall/init.py create mode 100644 opt/ahenk/plugins/firewall/main.py create mode 100644 opt/ahenk/plugins/firewall/policy.py create mode 100644 opt/ahenk/plugins/firewall/shutdown.py create mode 100644 opt/ahenk/plugins/local-user/add_user.py create mode 100644 opt/ahenk/plugins/local-user/delete_user.py create mode 100644 opt/ahenk/plugins/local-user/edit_user.py create mode 100644 opt/ahenk/plugins/local-user/get_groups.py create mode 100644 opt/ahenk/plugins/local-user/get_users.py create mode 100644 opt/ahenk/plugins/local-user/init.py create mode 100644 opt/ahenk/plugins/local-user/main.py create mode 100755 opt/ahenk/plugins/local-user/scripts/find_locked_users.sh create mode 100755 opt/ahenk/plugins/local-user/scripts/remove_locked_users.sh create mode 100644 opt/ahenk/plugins/network-inventory/installahenk.py create mode 100644 opt/ahenk/plugins/network-inventory/main.py create mode 100644 opt/ahenk/plugins/network-inventory/multiple-file-transfer.py create mode 100644 opt/ahenk/plugins/network-inventory/scannetwork.py create mode 100644 opt/ahenk/plugins/network-manager/add_dns.py create mode 100644 opt/ahenk/plugins/network-manager/add_domain.py create mode 100644 opt/ahenk/plugins/network-manager/add_host.py create mode 100644 opt/ahenk/plugins/network-manager/add_network.py create mode 100644 opt/ahenk/plugins/network-manager/change_hostname.py create mode 100644 opt/ahenk/plugins/network-manager/delete_dns.py create mode 100644 opt/ahenk/plugins/network-manager/delete_domain.py create mode 100644 opt/ahenk/plugins/network-manager/delete_host.py create mode 100644 opt/ahenk/plugins/network-manager/delete_network.py create mode 100644 opt/ahenk/plugins/network-manager/get_network_information.py create mode 100644 opt/ahenk/plugins/network-manager/main.py create mode 100644 opt/ahenk/plugins/package-manager/check_package.py create mode 100644 opt/ahenk/plugins/package-manager/get_execution_info.py create mode 100644 opt/ahenk/plugins/package-manager/init.py create mode 100644 opt/ahenk/plugins/package-manager/installed_packages.py create mode 100644 opt/ahenk/plugins/package-manager/main.py create mode 100644 opt/ahenk/plugins/package-manager/package_archive.py create mode 100644 opt/ahenk/plugins/package-manager/package_management.py create mode 100644 opt/ahenk/plugins/package-manager/package_sources.py create mode 100644 opt/ahenk/plugins/package-manager/packages.py create mode 100644 opt/ahenk/plugins/package-manager/repositories.py create mode 100755 opt/ahenk/plugins/package-manager/scripts/sourcelist.sh create mode 100644 opt/ahenk/plugins/package-manager/show_package_archive.py create mode 100644 opt/ahenk/plugins/remote-access/main.py create mode 100644 opt/ahenk/plugins/remote-access/setup-vnc-server.py create mode 100644 opt/ahenk/plugins/resource-usage/main.py create mode 100644 opt/ahenk/plugins/resource-usage/resource_info_alert.py create mode 100644 opt/ahenk/plugins/resource-usage/resource_info_fetcher.py create mode 100644 opt/ahenk/plugins/resource-usage/send_mail.py create mode 100644 opt/ahenk/plugins/resource-usage/shutdown.py create mode 100644 opt/ahenk/plugins/rsyslog/main.py create mode 100644 opt/ahenk/plugins/rsyslog/policy.py create mode 100644 opt/ahenk/plugins/screensaver/main.py create mode 100644 opt/ahenk/plugins/screensaver/policy.py create mode 100644 opt/ahenk/plugins/screenshot/main.py create mode 100644 opt/ahenk/plugins/screenshot/take-screenshot.py create mode 100644 opt/ahenk/plugins/script/execute_script.py create mode 100644 opt/ahenk/plugins/script/main.py create mode 100644 opt/ahenk/plugins/service/get_services.py create mode 100644 opt/ahenk/plugins/service/init.py create mode 100644 opt/ahenk/plugins/service/main.py create mode 100644 opt/ahenk/plugins/service/service_list.py create mode 100644 opt/ahenk/plugins/service/service_management.py create mode 100644 opt/ahenk/plugins/sudoers/main.py create mode 100644 opt/ahenk/plugins/sudoers/policy.py create mode 100644 opt/ahenk/plugins/sudoers/safe.py create mode 100644 opt/ahenk/plugins/usb/init.py create mode 100644 opt/ahenk/plugins/usb/logout.py create mode 100644 opt/ahenk/plugins/usb/main.py create mode 100644 opt/ahenk/plugins/usb/manage-usb.py create mode 100644 opt/ahenk/plugins/usb/policy.py create mode 100755 opt/ahenk/plugins/usb/scripts/DISABLED_printer.sh create mode 100755 opt/ahenk/plugins/usb/scripts/DISABLED_usbhid.sh create mode 100755 opt/ahenk/plugins/usb/scripts/DISABLED_usbstorage.sh create mode 100755 opt/ahenk/plugins/usb/scripts/DISABLED_webcam.sh create mode 100755 opt/ahenk/plugins/usb/scripts/ENABLED_printer.sh create mode 100755 opt/ahenk/plugins/usb/scripts/ENABLED_usbhid.sh create mode 100755 opt/ahenk/plugins/usb/scripts/ENABLED_usbstorage.sh create mode 100755 opt/ahenk/plugins/usb/scripts/ENABLED_webcam.sh create mode 100644 opt/ahenk/plugins/user-privilege/init.py create mode 100644 opt/ahenk/plugins/user-privilege/main.py create mode 100644 opt/ahenk/plugins/user-privilege/policy.py create mode 100644 opt/ahenk/plugins/user-privilege/safe.py create mode 100644 opt/ahenk/plugins/user-privilege/shutdown.py create mode 100644 opt/ahenk/plugins/wol/init.py create mode 100644 opt/ahenk/plugins/wol/main.py create mode 100644 opt/ahenk/plugins/wol/shut-down-machine.py create mode 100644 opt/ahenk/plugins/wol/shutdown.py create mode 100644 opt/ahenk/plugins/wol/wake-machine.py create mode 100644 opt/ahenk/test.txt diff --git a/opt/ahenk/base/database/ahenk_db_service.py b/opt/ahenk/base/database/ahenk_db_service.py index 4d4c14d..e61d9ca 100644 --- a/opt/ahenk/base/database/ahenk_db_service.py +++ b/opt/ahenk/base/database/ahenk_db_service.py @@ -53,6 +53,9 @@ class AhenkDbService(object): 'timestamp TEXT', 'choice TEXT']) self.check_and_create_table('session', ['username TEXT', 'display TEXT', 'desktop TEXT', 'timestamp TEXT']) + self.check_and_create_table('mail', ['id INTEGER PRIMARY KEY AUTOINCREMENT', 'command TEXT', 'mailstatus INTEGER', 'timestamp TEXT']) + + def get_cols(self, table_name): if table_name == 'agreement': return ['contract_id', 'username', 'timestamp', 'choice'] diff --git a/opt/ahenk/base/plugin/plugin.py b/opt/ahenk/base/plugin/plugin.py index 286ceae..889507f 100644 --- a/opt/ahenk/base/plugin/plugin.py +++ b/opt/ahenk/base/plugin/plugin.py @@ -20,6 +20,9 @@ class Context(object): def __init__(self): self.data = dict() self.scope = Scope().get_instance() + self.mail_send = False + self.mail_subject = '' + self.mail_content = '' def put(self, var_name, data): self.data[var_name] = data @@ -53,6 +56,24 @@ class Context(object): return success + def is_mail_send(self): + return self.mail_send + + def set_mail_send(self, mail_send): + self.mail_send=mail_send + + def get_mail_subject(self): + return self.mail_subject + + def set_mail_subject(self, mail_subject): + self.mail_subject=mail_subject + + def get_mail_content(self): + return self.mail_content + + def set_mail_content(self, mail_content): + self.mail_content = mail_content + class Plugin(threading.Thread): """ @@ -95,6 +116,11 @@ class Plugin(threading.Thread): task_data = item_obj.get_parameter_map() + # check if mail send is actve or not and set mail params to context object.. plugins get mail params via context object + self.context.set_mail_send(task_data['mailSend'] if 'mailSend' in task_data else False) + self.context.set_mail_subject(task_data['mailSubject'] if 'mailSubject' in task_data else '') + self.context.set_mail_content(task_data['mailContent'] if 'mailContent' in task_data else '') + self.logger.debug('[Plugin] Sending notify to user about task process') if System.Sessions.user_name() is not None and len(System.Sessions.user_name()) > 0: diff --git a/opt/ahenk/plugins/backup/backup_task.py b/opt/ahenk/plugins/backup/backup_task.py new file mode 100644 index 0000000..7902f66 --- /dev/null +++ b/opt/ahenk/plugins/backup/backup_task.py @@ -0,0 +1,14 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- +# Author: Seren Piri + +import sys +import os.path + +sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__)))) + +from backup_util import BackupUtil + +def handle_task(task, context): + backup = BackupUtil(task, context, 'task') + backup.backup() \ No newline at end of file diff --git a/opt/ahenk/plugins/backup/backup_util.py b/opt/ahenk/plugins/backup/backup_util.py new file mode 100644 index 0000000..3bb5fd4 --- /dev/null +++ b/opt/ahenk/plugins/backup/backup_util.py @@ -0,0 +1,160 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- +# Author: Seren Piri + +import pexpect + +from base.plugin.abstract_plugin import AbstractPlugin + + +class BackupUtil(AbstractPlugin): + def __init__(self, data, context, type): + super(AbstractPlugin, self).__init__() + self.data = data + self.context = context + self.logger = self.get_logger() + self.message_code = self.get_message_code() + self.content_type = self.get_content_type() + self.__type = type + + def backup(self): + + if self.__type == "task": + type = "task" + resp_code = self.message_code.TASK_PROCESSED.value + resp_err_code = self.message_code.TASK_ERROR.value + else: + type = "profile" + resp_code = self.message_code.POLICY_PROCESSED.value + resp_err_code = self.message_code.POLICY_ERROR.value + + self.logger.debug("Starting to backup... Reading backup " + type + " json") + + backup_profile = self.data + + self.logger.debug("Successfully read backup " + type + " json.") + destination_path = str(backup_profile['username']) + '@' + str(backup_profile['destHost']) + ':' + str( + backup_profile['destPath']) + self.logger.debug("Destination path ==> " + str(destination_path)) + + for source in backup_profile['directories']: + self.logger.debug("Trying to backup for source ==> " + str(source['sourcePath'])) + options = '' + path = source['sourcePath'] + ' ' + destination_path + command = '' + + if backup_profile['useLvmShadow']: + logicalVolumeSize = str(source['logicalVolumeSize']) + logicalVolume = str(source['logicalVolume']) + virtualGroup = str(source['virtualGroup']) + create_lv_command = 'lvcreate -L ' + logicalVolumeSize + ' -s -n ' + logicalVolume + ' ' + virtualGroup + (result_code, p_out, p_err) = self.execute(create_lv_command, shell=True) + if (result_code == 0): + self.logger.debug('Logical volume created successfully. LV ==>' + str(logicalVolume)) + (result_code, p_out, p_err) = self.execute('mkdir -p ' + source['sourcePath'], shell=True) + (result_code, p_out, p_err) = self.execute( + 'mount ' + logicalVolume + ' ' + source['sourcePath'], shell=True) + self.logger.debug('Mount path created successfully. Mount path ==>' + source['sourcePath']) + + if source['recursive']: + options = options + ' -r ' + if source['preserveGroup']: + options = options + ' -g ' + if source['preserveOwner']: + options = options + ' -o ' + if source['preservePermissions']: + options = options + ' -p ' + if source['archive']: + options = options + ' -a ' + if source['compress']: + options = options + ' -z ' + if source['existingOnly']: + options = options + ' --existing ' + if source['excludePattern']: + options = options + ' --exclude "' + source['excludePattern'] + '" ' + + try: + result_code = -1 + if (backup_profile['useSsh']): + sshOptions = ' ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null --progress -p ' + str( + backup_profile['destPort']) + command = 'rsync ' + options + ' -e "' + sshOptions + '" ' + path + self.logger.debug("Command ==> " + command) + (result_code, p_out, p_err) = self.execute(command, shell=True) + else: + sshOptions = ' ssh -q -oStrictHostKeyChecking=no -oUserKnownHostsFile=/dev/null -oPubkeyAuthentication=no -p ' + str( + backup_profile['destPort']) + command = 'rsync ' + options + ' -e "' + sshOptions + '" ' + path + self.logger.debug("Command ==> " + command) + result_code = self.runCommandWithPassword(command, backup_profile['password']) + + if result_code == 0: + self.logger.info("Sync is successfull for source ==> " + str(source['sourcePath'])) + resp_message = "Backup işlemi başarıyla tamamlandı." + else: + self.logger.error( + "The backup process is unsuccessfull for destination ==> " + destination_path + " and source ==> " + str( + source['sourcePath']) + + " \n" + self.getExitStatus(int(result_code))) + resp_code = resp_err_code + resp_message = "Hata mesajı: " + self.getExitStatus(int(result_code)) + " \n[Kaynak: " + str( + source['sourcePath']) + " Hedef: " + destination_path + "]" + + except Exception as e: + self.logger.error("Exception ==> " + str(e)) + resp_code = resp_err_code + resp_message = str(e) + + self.context.create_response(code=resp_code, message=resp_message, + content_type=self.content_type.APPLICATION_JSON.value) + + def runCommandWithPassword(self, command, password, timeout=30): + try: + child = pexpect.spawn(command, timeout=timeout) + i = child.expect(['password: ', pexpect.EOF, pexpect.TIMEOUT]) + if i == 0: + child.sendline(password) + child.expect(pexpect.EOF) + child.close() + return child.exitstatus + elif i == 1: + return 999 + elif i == 2: + return 888 + except Exception as e: + self.logger.warning('runCommandWithPassword Error: {0}'.format(str(e))) + if i == 0: + return 888 + else: + child.close() + return child.exitstatus + + def getExitStatus(self, exitCode): + switcher = { + # 0 : "Success", + 1: "Syntax or usage error", + 2: "Protocol incompatibility", + 3: "Errors selecting input / output files, dirs", + 4: "Requested action not supported: an attempt was made to manipulate 64 - bit files on a platform" + "\n that cannot support them; or an option was specified that is supported by the client and not by the server.", + 5: "Error starting client - server protocol", + 6: "Daemon unable to append to log - file", + 10: "Error in socket I / O", + 11: "Error in file I / O", + 12: "Error in rsync protocol data stream", + 13: "Errors with program diagnostics", + 14: "Error in IPC code", + 20: "Received SIGUSR1 or SIGINT", + 21: "Some error returned by waitpid()", + 22: "Error allocating core memory buffers", + 23: "Partial transfer due to error", + 24: "Partial transfer due to vanished source files", + 25: "The --max-delete limit stopped deletions", + 30: "Timeout in data send / receive", + 35: "Timeout waiting for daemon connection", + 255: "Please make certain of the backup parameters you have entered.", + 888: "Timeout exceeded. Destination could be unreachable \n or Please make certain of Password, Destination Host/Port, Dest./Source Path values you have entered.", + 999: "Rsync command returns EOF! Destination could be unreachable \n or Please make certain of Destination Host/Port you have entered." + } + return switcher.get(exitCode, + "Exit Status Message for exit code '" + str(exitCode) + "' of rsync command is not found!") diff --git a/opt/ahenk/plugins/backup/main.py b/opt/ahenk/plugins/backup/main.py new file mode 100644 index 0000000..2099634 --- /dev/null +++ b/opt/ahenk/plugins/backup/main.py @@ -0,0 +1,17 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- +# Author: + + +def info(): + inf = dict() + inf['name'] = 'backup' + inf['version'] = '1.0.0' + inf['support'] = 'debian' + inf['description'] = '' + inf['task'] = True + inf['user_oriented'] = True + inf['machine_oriented'] = True + inf['developer'] = '' + + return inf diff --git a/opt/ahenk/plugins/backup/policy.py b/opt/ahenk/plugins/backup/policy.py new file mode 100644 index 0000000..404cf59 --- /dev/null +++ b/opt/ahenk/plugins/backup/policy.py @@ -0,0 +1,13 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- +# Author: Seren Piri + +import sys +import os.path +sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__)))) + +from backup_util import BackupUtil + +def handle_policy(profile_data, context): + backup = BackupUtil(profile_data, context, "policy") + backup.backup() diff --git a/opt/ahenk/plugins/browser/main.py b/opt/ahenk/plugins/browser/main.py new file mode 100644 index 0000000..6704d94 --- /dev/null +++ b/opt/ahenk/plugins/browser/main.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# Author: > +# Author: Volkan Şahin + + +def info(): + inf = dict() + inf['name'] = 'browser' + inf['version'] = '1.0.0' + inf['support'] = 'debian' + inf['description'] = 'Browser plugin provides to managing user or global firefox profile like setting homepage etc.' + inf['task'] = True + inf['user_oriented'] = True + inf['machine_oriented'] = True + inf['developer'] = 'bm.volkansahin@gmail.com' + + return inf diff --git a/opt/ahenk/plugins/browser/policy.py b/opt/ahenk/plugins/browser/policy.py new file mode 100644 index 0000000..0b0bf01 --- /dev/null +++ b/opt/ahenk/plugins/browser/policy.py @@ -0,0 +1,150 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# Author: > +# Author: Volkan Şahin + +import json + +from base.plugin.abstract_plugin import AbstractPlugin + + +class Browser(AbstractPlugin): + """docstring for Browser""" + + def __init__(self, data, context): + super(AbstractPlugin, self).__init__() + self.data = data + self.context = context + self.logger = self.get_logger() + self.message_code = self.get_message_code() + self.mozilla_config_file = 'mozilla.cfg' + self.local_settings_JS_file = 'local-settings.js' + self.local_settings_JS_path = 'defaults/pref/' + self.logger.info('Parameters were initialized.') + + def handle_policy(self): + self.logger.info('Browser plugin handling...') + try: + username = self.context.get('username') + self.logger.info('Username: {}'.format(username)) + if username is not None: + self.logger.debug('Writing preferences to user profile') + self.write_to_user_profile(username) + self.context.create_response(code=self.message_code.POLICY_PROCESSED.value, message='Kullanıcı browser profili başarıyla uygulandı.') + else: + self.logger.debug('Writing preferences to global profile') + self.write_to_global_profile() + self.context.create_response(code=self.message_code.POLICY_PROCESSED.value, message='Ajan browser profili başarıyla uygulandı.') + self.logger.info('Browser profile is handled successfully') + except Exception as e: + self.logger.error('A problem occurred while handling browser profile: {0}'.format(str(e))) + self.context.create_response(code=self.message_code.POLICY_ERROR.value, message='Browser profili uygulanırken bir hata oluştu.') + + def write_to_user_profile(self, username): + + try: + username = str(username).strip() + profile_paths = self.find_user_preference_paths(username) + + # User might have multiple firefox profile directories + for path in profile_paths: + path = str(path) + '/user.js' + user_jss = open(path, 'w') + preferences = json.loads(self.data)['preferences'] + self.logger.debug('Writing preferences to user.js file ...') + for pref in preferences: + if pref['value'].isdigit() or str(pref['value']) == 'false' or str(pref['value']) == 'true': + value = pref['value'] + else: + value = '\"' + pref['value'] + '\"' + line = 'user_pref("' + str(pref['preferenceName']) + '",' + value + ');\n' + user_jss.write(line) + + self.logger.debug('User preferences were wrote successfully') + user_jss.close() + change_owner = 'chown ' + username + ':' + username + ' ' + path + self.execute(change_owner) + self.logger.debug('Preferences file owner is changed') + + except Exception as e: + self.logger.error('A problem occurred while writing user profile: {0}'.format(str(e))) + # Remove global lock files to tell Firefox to load the user file + installation_path = self.find_firefox_installation_path() + if installation_path is None: + self.logger.error('Firefox installation directory could not be found! Finishing task...') + return + self.silent_remove(str(installation_path) + self.mozilla_config_file) + self.silent_remove(str(installation_path) + self.local_settings_JS_path + self.local_settings_JS_file) + self.logger.debug('User profiles have been set successfully') + + def write_to_global_profile(self): + firefox_installation_path = self.find_firefox_installation_path() + preferences = None + try: + preferences = json.loads(str(self.data))['preferences'] + except Exception as e: + self.logger.error('Problem occurred while getting preferences. Error Message: {}'.format(str(e))) + + mozilla_cfg = open(str(firefox_installation_path) + self.mozilla_config_file, 'w') + self.logger.debug('Mozilla configuration file is created') + for pref in preferences: + if pref['value'].isdigit() or str(pref['value']) == 'false' or str(pref['value']) == 'true': + value = pref['value'] + else: + value = '\"' + pref['value'] + '\"' + line = 'lockPref("' + str(pref['preferenceName']) + '",' + value + ');\n' + mozilla_cfg.write(line) + mozilla_cfg.close() + self.logger.debug('Preferences were wrote to Mozilla configuration file') + + local_settings_path = str(firefox_installation_path) + self.local_settings_JS_path + if not self.is_exist(local_settings_path): + self.logger.debug('Firefox local setting path not found, it will be created') + self.create_directory(local_settings_path) + local_settings_js = open(local_settings_path + self.local_settings_JS_file, 'w') + local_settings_js.write( + 'pref("general.config.obscure_value", 0);\npref("general.config.filename", "mozilla.cfg");\n') + local_settings_js.close() + self.logger.debug('Firefox local settings were configured') + + def silent_remove(self, filename): + try: + if self.is_exist(filename): + self.delete_file(filename) + self.logger.debug('{0} removed successfully'.format(filename)) + else: + self.logger.warning('{0} was tried to delete but not found.'.format(filename)) + except Exception as e: + self.logger.error('Problem occurred while removing file {0}. Exception Message is: {1}'.format(filename, str(e))) + + def find_user_preference_paths(self, user_name): + + paths = [] + firefox_path = '/home/' + user_name + '/.mozilla/firefox/' + profile_ini_file = open(firefox_path + 'profiles.ini', 'r') + profile_ini_file_lines = profile_ini_file.readlines() + for line in profile_ini_file_lines: + if 'Path' in line: + paths.append(firefox_path + str(line.split('=')[1]).strip()) + if len(paths) > 0: + self.logger.debug('User preferences path found successfully') + return paths + else: + self.logger.error('User preferences path not found') + + def find_firefox_installation_path(self): + installation_path = '/usr/lib/firefox/' + if not self.is_exist(installation_path): + installation_path = '/opt/firefox/' + if not self.is_exist(installation_path): + installation_path = '/usr/lib/iceweasel/' + if not self.is_exist(installation_path): + self.logger.error('Firefox installation path not found') + return None + self.logger.debug('Firefox installation path found successfully') + return installation_path + + +def handle_policy(profile_data, context): + browser = Browser(profile_data, context) + browser.handle_policy() diff --git a/opt/ahenk/plugins/disk-quota/get_quota.py b/opt/ahenk/plugins/disk-quota/get_quota.py new file mode 100644 index 0000000..aef2c69 --- /dev/null +++ b/opt/ahenk/plugins/disk-quota/get_quota.py @@ -0,0 +1,57 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- +# Author:Mine DOGAN + +import json + +from base.plugin.abstract_plugin import AbstractPlugin + + +class GetQuota(AbstractPlugin): + def __init__(self, task, context): + super(AbstractPlugin, self).__init__() + self.task = task + self.context = context + self.logger = self.get_logger() + self.message_code = self.get_message_code() + + self.get_quota = 'repquota -a -s | tail -n +6 | awk \'{print $1,$4,$5,$6}\'' + + self.logger.debug('Parameters were initialized.') + + def handle_task(self): + try: + + result_code, p_out, p_err = self.execute(self.get_quota) + + user_list = [] + lines = str(p_out).split('\n') + + for line in lines: + detail = line.split(' ') + + if str(detail[0]).strip() is not None and str(detail[0]).strip() != '': + user = {'user': str(detail[0]).strip(), 'soft_quota': str(detail[1]).strip(), + 'hard_quota': str(detail[2]).strip(), 'disk_usage': str(detail[3]).strip()} + user_list.append(user) + + self.logger.debug( + 'user: {0}, soft_quota: {1}, hard_quota: {2}, disk_usage: {3}' + .format(str(detail[0]).strip(), str(detail[1]).strip(), str(detail[2]).strip(), + str(detail[3]).strip())) + + self.logger.info('DISK-QUOTA task is handled successfully') + self.context.create_response(code=self.message_code.TASK_PROCESSED.value, + message='Kota bilgileri başarıyla alındı.', + data=json.dumps({'users': user_list}), + content_type=self.get_content_type().APPLICATION_JSON.value) + + except Exception as e: + self.logger.error('A problem occured while handling DISK-QUOTA task: {0}'.format(str(e))) + self.context.create_response(code=self.message_code.TASK_ERROR.value, + message='DISK-QUOTA görevi uygulanırken bir hata oluştu.') + + +def handle_task(task, context): + gq = GetQuota(task, context) + gq.handle_task() diff --git a/opt/ahenk/plugins/disk-quota/init.py b/opt/ahenk/plugins/disk-quota/init.py new file mode 100644 index 0000000..f78d92f --- /dev/null +++ b/opt/ahenk/plugins/disk-quota/init.py @@ -0,0 +1,24 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- +# Author:Mine DOGAN + +from base.plugin.abstract_plugin import AbstractPlugin + + +class Init(AbstractPlugin): + def __init__(self, context): + super(Init, self).__init__() + self.context = context + self.logger = self.get_logger() + + self.logger.debug('Parameters were initialized.') + + def handle_init_mode(self): + if self.is_installed('quota') is False: + self.logger.debug('Installing quota with apt-get...') + self.install_with_apt_get('quota') + + +def handle_mode(context): + init = Init(context) + init.handle_init_mode() diff --git a/opt/ahenk/plugins/disk-quota/main.py b/opt/ahenk/plugins/disk-quota/main.py new file mode 100644 index 0000000..e73a873 --- /dev/null +++ b/opt/ahenk/plugins/disk-quota/main.py @@ -0,0 +1,16 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- + + +def info(): + inf = dict() + inf['name'] = 'disk-quota' + inf['version'] = '1.0.0' + inf['support'] = 'debian' + inf['description'] = 'Disk-Quota plugin provides to get current soft - hard quota and changing them.' + inf['task'] = True + inf['user_oriented'] = True + inf['machine_oriented'] = False + inf['developer'] = 'mine.dogan@agem.com.tr' + + return inf \ No newline at end of file diff --git a/opt/ahenk/plugins/disk-quota/policy.py b/opt/ahenk/plugins/disk-quota/policy.py new file mode 100644 index 0000000..8d73e84 --- /dev/null +++ b/opt/ahenk/plugins/disk-quota/policy.py @@ -0,0 +1,262 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- +# Author:Mine DOGAN + +import os +import re +import tempfile +import json + +from base.plugin.abstract_plugin import AbstractPlugin + + +class DiskQuota(AbstractPlugin): + def __init__(self, data, context): + super(AbstractPlugin, self).__init__() + self.data = data + self.context = context + self.logger = self.get_logger() + self.message_code = self.get_message_code() + + self.username = self.context.get('username') + + self.mount = 'mount -o remount {}' + self.quotaon_all = 'quotaon --all' + self.quotaon_avug = 'quotaon -avug' + self.set_quota = 'setquota --always-resolve -u {0} {1} {2} 0 0 --all' + + self.parameters = json.loads(self.data) + + self.soft_quota = str(int(self.parameters['soft-quota']) * 1024) + self.hard_quota = str(int(self.parameters['hard-quota']) * 1024) + + self.logger.debug('Parameters were initialized.') + + def handle_policy(self): + self.logger.debug('Policy handling...') + try: + # Check fstab & append 'usrquota' option if not exists + fs = Fstab() + fs.read('/etc/fstab') + fstab_entries = [] + fslines = fs.lines + for line in fslines: + if line.has_filesystem() and 'usrquota' not in line.options: + if line.dict['directory'] == '/' or line.dict['directory'] == '/home/': + self.logger.debug('Appending \'usrquota\' option to {}'.format(line.dict['directory'])) + line.options += ['usrquota'] + fstab_entries.append(line.dict['directory']) + fs.write('/etc/fstab') + + # Re-mount necessary fstab entries + for entry in fstab_entries: + self.execute(self.mount.format(entry)) + self.logger.debug('Remounting fstab entry {}'.format(entry)) + + self.execute(self.quotaon_all) + self.logger.debug('{}'.format(self.quotaon_all)) + + self.execute(self.quotaon_avug) + self.logger.debug('{}'.format(self.quotaon_avug)) + + self.execute(self.set_quota.format(self.username, self.soft_quota, self.hard_quota)) + self.logger.debug( + 'Set soft and hard quota. Username: {0}, Soft Quota: {1}, Hard Quota: {2}'.format(self.username, + self.soft_quota, + self.hard_quota)) + + self.context.create_response(code=self.get_message_code().POLICY_PROCESSED.value, + message='Kotalar başarıyla güncellendi.') + + except Exception as e: + self.logger.error('[DiskQuota] A problem occurred while handling browser profile: {0}'.format(str(e))) + self.context.create_response(code=self.get_message_code().POLICY_ERROR.value, + message='Disk Quota profili uygulanırken bir hata oluştu.') + + +class Line(object): + """A line in an /etc/fstab line. + + Lines may or may not have a filesystem specification in them. The + has_filesystem method tells the user whether they do or not; if they + do, the attributes device, directory, fstype, options, dump, and + fsck contain the values of the corresponding fields, as instances of + the sub-classes of the LinePart class. For non-filesystem lines, + the attributes have the None value. + + Lines may or may not be syntactically correct. If they are not, + they are treated as as non-filesystem lines. + + """ + + # Lines split this way to shut up coverage.py. + attrs = ("ws1", "device", "ws2", "directory", "ws3", "fstype") + attrs += ("ws4", "options", "ws5", "dump", "ws6", "fsck", "ws7") + + def __init__(self, raw): + self.dict = {} + self.raw = raw + + def __getattr__(self, name): + if name in self.dict: + return self.dict[name] + else: + raise AttributeError(name) + + def __setattr__(self, name, value): + forbidden = ("dict", "dump", "fsck", "options") + if name not in forbidden and name in self.dict: + if self.dict[name] is None: + raise Exception("Cannot set attribute %s when line dies not " + "contain filesystem specification" % name) + self.dict[name] = value + else: + object.__setattr__(self, name, value) + + def get_dump(self): + return int(self.dict["dump"]) + + def set_dump(self, value): + self.dict["dump"] = str(value) + + dump = property(get_dump, set_dump) + + def get_fsck(self): + return int(self.dict["fsck"]) + + def set_fsck(self, value): + self.dict["fsck"] = str(value) + + fsck = property(get_fsck, set_fsck) + + def get_options(self): + return self.dict["options"].split(",") + + def set_options(self, list): + self.dict["options"] = ",".join(list) + + options = property(get_options, set_options) + + def set_raw(self, raw): + match = False + + if raw.strip() != "" and not raw.strip().startswith("#"): + pat = r"^(?P\s*)" + pat += r"(?P\S*)" + pat += r"(?P\s+)" + pat += r"(?P\S+)" + pat += r"(?P\s+)" + pat += r"(?P\S+)" + pat += r"(?P\s+)" + pat += r"(?P\S+)" + pat += r"(?P\s+)" + pat += r"(?P\d+)" + pat += r"(?P\s+)" + pat += r"(?P\d+)" + pat += r"(?P\s*)$" + + match = re.match(pat, raw) + if match: + self.dict.update((attr, match.group(attr)) for attr in self.attrs) + + if not match: + self.dict.update((attr, None) for attr in self.attrs) + + self.dict["raw"] = raw + + def get_raw(self): + if self.has_filesystem(): + return "".join(self.dict[attr] for attr in self.attrs) + else: + return self.dict["raw"] + + raw = property(get_raw, set_raw) + + def has_filesystem(self): + """Does this line have a filesystem specification?""" + return self.device is not None + + +class Fstab(object): + """An /etc/fstab file.""" + + def __init__(self): + self.lines = [] + + def open_file(self, filespec, mode): + if isinstance(filespec, str): + return open(filespec, mode=mode) + else: + return filespec + + def close_file(self, f, filespec): + if isinstance(filespec, str): + f.close() + + def get_perms(self, filename): + return os.stat(filename).st_mode # pragma: no cover + + def chmod_file(self, filename, mode): + os.chmod(filename, mode) # pragma: no cover + + def link_file(self, oldname, newname): + if os.path.exists(newname): + os.remove(newname) + os.link(oldname, newname) + + def rename_file(self, oldname, newname): + os.rename(oldname, newname) # pragma: no cover + + def read(self, filespec): + """Read in a new file. + + If filespec is a string, it is used as a filename. Otherwise + it is used as an open file. + + The existing content is replaced. + + """ + + f = self.open_file(filespec, "r") + lines = [] + for line in f: + lines.append(Line(line)) + self.lines = lines + self.close_file(filespec, f) + + def write(self, filespec): + """Write out a new file. + + If filespec is a string, it is used as a filename. Otherwise + it is used as an open file. + + """ + + if isinstance(filespec, str): + # We create the temporary file in the directory (/etc) that the + # file exists in. This is so that we can do an atomic rename + # later, and that only works inside one filesystem. Some systems + # have /tmp and /etc on different filesystems, for good reasons, + # and we need to support that. + dirname = os.path.dirname(filespec) + prefix = os.path.basename(filespec) + "." + fd, tempname = tempfile.mkstemp(dir=dirname, prefix=prefix) + os.close(fd) + else: + tempname = filespec + + f = self.open_file(tempname, "w") + for line in self.lines: + f.write(line.raw) + self.close_file(filespec, f) + + if isinstance(filespec, str): + self.chmod_file(tempname, self.get_perms(filespec)) + self.link_file(filespec, filespec + ".bak") + self.rename_file(tempname, filespec) + + +def handle_policy(profile_data, context): + dq = DiskQuota(profile_data, context) + dq.handle_policy() + diff --git a/opt/ahenk/plugins/firewall/get-rules.py b/opt/ahenk/plugins/firewall/get-rules.py new file mode 100644 index 0000000..80b4795 --- /dev/null +++ b/opt/ahenk/plugins/firewall/get-rules.py @@ -0,0 +1,47 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- +# Author:Mine DOGAN + +import json + +from base.plugin.abstract_plugin import AbstractPlugin + + +class FirewallRules(AbstractPlugin): + def __init__(self, task, context): + super(FirewallRules, self).__init__() + self.task = task + self.context = context + self.logger = self.get_logger() + self.message_code = self.get_message_code() + + self.temp_file_name = str(self.generate_uuid()) + self.export_path = '{0}{1}'.format(str(self.Ahenk.received_dir_path()), self.temp_file_name) + + self.logger.debug('[FIREWALL] Parameters were initialized.') + + def handle_task(self): + try: + self.create_file(self.export_path) + self.logger.debug('[FIREWALL] Export rules to a temporary file...') + self.execute('/sbin/iptables-save > {}'.format(self.export_path)) + + self.logger.debug('[FIREWALL] Reading the file...') + with open(self.export_path, "r") as rules_file: + firewall_rules = rules_file.readlines() + + self.logger.info('[FIREWALL] Firewall task is handled successfully') + self.context.create_response(code=self.message_code.TASK_PROCESSED.value, + message='Güvenlik Duvarı kuralları başarıyla okundu.', + data=json.dumps({'firewallRules': firewall_rules}), + content_type=self.get_content_type().APPLICATION_JSON.value) + + except Exception as e: + self.logger.error('[FIREWALL] A problem occured while handling Firewall task: {0}'.format(str(e))) + self.context.create_response(code=self.message_code.TASK_ERROR.value, + message='Güvenlik Duvarı görevi çalıştırılırken bir hata oluştu.') + + +def handle_task(task, context): + get_rules = FirewallRules(task, context) + get_rules.handle_task() diff --git a/opt/ahenk/plugins/firewall/init.py b/opt/ahenk/plugins/firewall/init.py new file mode 100644 index 0000000..d949df6 --- /dev/null +++ b/opt/ahenk/plugins/firewall/init.py @@ -0,0 +1,39 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- +import os +from base.plugin.abstract_plugin import AbstractPlugin + + +class Init(AbstractPlugin): + def __init__(self, context): + super(Init, self).__init__() + self.context = context + self.logger = self.get_logger() + self.plugin_path = os.path.abspath(os.path.join(os.path.dirname(__file__))) + self.initial_rules_file_path = self.plugin_path + '/iptables.rules' + self.logger.debug('[FIREWALL - init] Parameters were initialized.') + + def handle_mode(self): + + if self.is_installed('iptables-persistent') is False: + self.install_with_apt_get('iptables-persistent') + pass + + try: + if self.is_exist(self.initial_rules_file_path): + self.logger.debug('[FIREWALL - init] Adding initial rules temp file to iptables-restore as parameter...') + self.execute('/sbin/iptables-restore < {}'.format(self.initial_rules_file_path)) + + self.logger.debug('[FIREWALL - init] Save the rules...') + self.execute('service netfilter-persistent save') + + self.logger.debug('[FIREWALL - init] Restart the service...') + self.execute('service netfilter-persistent restart') + + except Exception as e: + self.logger.error('[FIREWALL - init] A problem occured while handling Firewall init.py: {0}'.format(str(e))) + + +def handle_mode(context): + init = Init(context) + init.handle_mode() diff --git a/opt/ahenk/plugins/firewall/main.py b/opt/ahenk/plugins/firewall/main.py new file mode 100644 index 0000000..ab5a4ac --- /dev/null +++ b/opt/ahenk/plugins/firewall/main.py @@ -0,0 +1,16 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- + + +def info(): + inf = dict() + inf['name'] = 'firewall' + inf['version'] = '1.0.0' + inf['support'] = 'debian' + inf['description'] = 'Firewall plugin provides to get firewall rules and changing them.' + inf['task'] = True + inf['user_oriented'] = False + inf['machine_oriented'] = True + inf['developer'] = 'mine.dogan@agem.com.tr' + + return inf \ No newline at end of file diff --git a/opt/ahenk/plugins/firewall/policy.py b/opt/ahenk/plugins/firewall/policy.py new file mode 100644 index 0000000..dc30038 --- /dev/null +++ b/opt/ahenk/plugins/firewall/policy.py @@ -0,0 +1,60 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- +# Author:Mine DOGAN + +import json +import os +from base.plugin.abstract_plugin import AbstractPlugin + + +class FirewallRules(AbstractPlugin): + def __init__(self, profile_data, context): + super(FirewallRules, self).__init__() + self.profile_data = profile_data + self.context = context + self.logger = self.get_logger() + self.message_code = self.get_message_code() + + self.parameters = json.loads(self.profile_data) + self.plugin_path = os.path.abspath(os.path.join(os.path.dirname(__file__))) + self.rules = self.parameters['rules'] + self.temp_file_name = str(self.generate_uuid()) + self.file_path = '{0}{1}'.format(str(self.Ahenk.received_dir_path()), self.temp_file_name) + self.initial_rules_file_path = self.plugin_path + '/iptables.rules' + self.logger.debug('[FIREWALL] Parameters were initialized.') + + def handle_policy(self): + try: + if not self.is_exist(self.initial_rules_file_path): + self.logger.debug('[FIREWALL] Export initial rules to a temporary file...') + self.execute('/sbin/iptables-save > {}'.format(self.initial_rules_file_path)) + + self.logger.debug('[FIREWALL] Writing rules to temporary file...') + self.write_file(self.file_path, '{0}{1}'.format(self.rules, '\n')) + + self.logger.debug('[FIREWALL] Adding temp file to iptables-restore as parameter...') + result_code, p_out, p_err = self.execute('/sbin/iptables-restore < {}'.format(self.file_path)) + + if p_err != '': + raise Exception(p_err) + + self.logger.debug('[FIREWALL] Save the rules...') + self.execute('service netfilter-persistent save') + + self.logger.debug('[FIREWALL] Restart the service...') + self.execute('service netfilter-persistent restart') + + self.context.create_response(code=self.message_code.POLICY_PROCESSED.value, + message='Güvenlik Duvarı kuralları başarıyla kaydedildi.') + self.logger.info('[FIREWALL] Firewall policy is handled successfully') + + except Exception as e: + self.logger.error( + '[FIREWALL] A problem occured while handling Firewall policy: {0}'.format(str(e))) + self.context.create_response(code=self.message_code.POLICY_ERROR.value, + message='Güvenlik Duvarı profili uygulanırken bir hata oluştu: ' + str(e)) + + +def handle_policy(profile_data, context): + set_rules = FirewallRules(profile_data, context) + set_rules.handle_policy() diff --git a/opt/ahenk/plugins/firewall/shutdown.py b/opt/ahenk/plugins/firewall/shutdown.py new file mode 100644 index 0000000..b697b27 --- /dev/null +++ b/opt/ahenk/plugins/firewall/shutdown.py @@ -0,0 +1,35 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- +# Author:Mine DOGAN + +from base.plugin.abstract_plugin import AbstractPlugin +import os + +class Shutdown(AbstractPlugin): + def __init__(self, context): + super(Shutdown, self).__init__() + self.context = context + self.logger = self.get_logger() + self.plugin_path = os.path.abspath(os.path.join(os.path.dirname(__file__))) + self.initial_rules_file_path = self.plugin_path + '/iptables.rules' + self.logger.debug('[FIREWALL - shutdown] Parameters were initialized.') + + def handle_shutdown_mode(self): + try: + if self.is_exist(self.initial_rules_file_path): + self.logger.debug('[FIREWALL - shutdown] Adding initial rules temp file to iptables-restore as parameter...') + self.execute('/sbin/iptables-restore < {}'.format(self.initial_rules_file_path)) + + self.logger.debug('[FIREWALL - shutdown] Save the rules...') + self.execute('service netfilter-persistent save') + + self.logger.debug('[FIREWALL - shutdown] Restart the service...') + self.execute('service netfilter-persistent restart') + + except Exception as e: + self.logger.error('[FIREWALL - shutdown] A problem occured while handling Firewall shutdown.py: {0}'.format(str(e))) + + +def handle_mode(context): + shutdown = Shutdown(context) + shutdown.handle_shutdown_mode() \ No newline at end of file diff --git a/opt/ahenk/plugins/local-user/add_user.py b/opt/ahenk/plugins/local-user/add_user.py new file mode 100644 index 0000000..85d58d7 --- /dev/null +++ b/opt/ahenk/plugins/local-user/add_user.py @@ -0,0 +1,132 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- +# Author:Mine DOGAN + +from base.plugin.abstract_plugin import AbstractPlugin + + +class AddUser(AbstractPlugin): + def __init__(self, task, context): + super(AddUser, self).__init__() + self.task = task + self.context = context + self.logger = self.get_logger() + self.message_code = self.get_message_code() + + self.username = self.task['username'] + self.password = self.task['password'] + self.home = self.task['home'] + self.active = self.task['active'] + self.groups = self.task['groups'] + self.desktop_write_permission = self.task['desktop_write_permission'] + self.kiosk_mode = self.task['kiosk_mode'] + + self.script = '/bin/bash ' + self.Ahenk.plugins_path() + 'local-user/scripts/{0}' + + self.add_user = 'useradd -d {0} {1}' + self.check_home_owner = 'stat -c \'%U\' {}' + self.enable_user = 'passwd -u {}' + self.disable_user = 'passwd -l {}' + self.add_user_to_groups = 'usermod -a -G {0} {1}' + self.create_shadow_password = 'mkpasswd -m sha-512 {}' + self.change_password = 'usermod -p {0} {1}' + self.change_shell = 'usermod -s /bin/bash {}' + self.change_owner = 'chown {0}.{0} {1}' + self.change_permission = 'chmod 755 {}' + + self.desktop_path = '' + self.logger.debug('Parameters were initialized.') + + def handle_task(self): + try: + if not self.is_exist(self.home): + self.create_directory(self.home) + self.execute(self.add_user.format(self.home, self.username)) + self.logger.debug('Added new user: {0}, home: {1}'.format(self.username, self.home)) + + self.execute(self.change_owner.format(self.username, self.home)) + self.execute(self.change_permission.format(self.home)) + self.logger.debug('Changed owner and permission for home directory.') + + if self.groups != "": + self.execute(self.add_user_to_groups.format(self.groups, self.username)) + self.logger.debug('Added user to these groups: {}'.format(self.groups)) + + if str(self.password).strip() != "": + result_code, p_out, p_err = self.execute(self.create_shadow_password.format(self.password)) + shadow_password = p_out.strip() + self.execute(self.change_password.format('\'{}\''.format(shadow_password), self.username)) + self.logger.debug('Changed password.') + + self.execute(self.change_shell.format(self.username)) + self.logger.debug('Changed user shell to /bin/bash') + + if self.active == "true": + self.execute(self.enable_user.format(self.username)) + self.logger.debug('The user has been enabled.') + elif self.active == "false": + self.execute(self.disable_user.format(self.username)) + self.logger.debug('The user has been disabled.') + + self.execute("mkdir " + self.home + "/Masaüstü") + self.desktop_path = self.home + "/Masaüstü" + + if self.desktop_write_permission == "true": + self.execute('chown -R {0}:{1} {2}'.format(self.username, self.username, self.desktop_path)) + self.logger.debug('chown -R {0}:{1} {2}'.format(self.username, self.username, self.desktop_path)) + + elif self.desktop_write_permission == "false": + self.execute('chown -R root:root {0}'.format(self.desktop_path)) + self.logger.debug('chown -R root:root {0}'.format(self.desktop_path)) + + # + # Handle kiosk mode + # + result_code, p_out, p_err = self.execute(self.script.format('find_locked_users.sh'), result=True) + if result_code != 0: + self.logger.error( + 'Error occurred while managing kiosk mode.') + self.context.create_response(code=self.message_code.TASK_ERROR.value, + message='Masaüstü kilidi ayarlanırken hata oluştu.') + return + locked_users = [] + if p_out: + self.logger.debug('pout {0}'.format(str(p_out))) + locked_users = p_out.strip().split(';') + if self.kiosk_mode == "true": + self.logger.debug('Kiosk mode is active {0}'.format(str(locked_users))) + if self.username not in locked_users: + self.logger.debug('Adding user {0} to locked users'.format(self.username)) + locked_users.append(self.username) + locked_users_str = ";".join(locked_users) + self.logger.debug('Users: {0}'.format(locked_users_str)) + comm = "sed -i 's/^.*" + '' + "/' /etc/xdg/xfce4/xfconf/xfce-perchannel-xml/xfce4-panel.xml" + result_code1, p_out1, p_err1 = self.execute(comm) + elif self.kiosk_mode == "false": + self.logger.debug('Kiok mode is NOT active') + if self.username in locked_users: + self.logger.debug('Removing user {0} from locked users'.format(self.username)) + locked_users.remove(self.username) + if locked_users: + locked_users_str = ";".join(locked_users) + comm = "sed -i 's/^.*" + '' + "/' /etc/xdg/xfce4/xfconf/xfce-perchannel-xml/xfce4-panel.xml" + result_code1, p_out1, p_err1 = self.execute(comm) + else: + self.execute(self.script.format('remove_locked_users.sh ')) + + self.logger.info('User has been added successfully.') + + self.context.create_response(code=self.message_code.TASK_PROCESSED.value, + message='Kullanıcı başarıyla eklendi.') + + + + except Exception as e: + self.logger.error('A problem occurred while handling Local-User task: {0}'.format(str(e))) + self.context.create_response(code=self.message_code.TASK_ERROR.value, + message='Local-User görevi çalıştırılırken bir hata oluştu.') + + +def handle_task(task, context): + add_user = AddUser(task, context) + add_user.handle_task() diff --git a/opt/ahenk/plugins/local-user/delete_user.py b/opt/ahenk/plugins/local-user/delete_user.py new file mode 100644 index 0000000..7b0e668 --- /dev/null +++ b/opt/ahenk/plugins/local-user/delete_user.py @@ -0,0 +1,54 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- +# Author:Mine DOGAN + +from base.plugin.abstract_plugin import AbstractPlugin + + +class DeleteUser(AbstractPlugin): + def __init__(self, task, context): + super(DeleteUser, self).__init__() + self.task = task + self.context = context + self.logger = self.get_logger() + self.message_code = self.get_message_code() + + self.username = self.task['username'] + self.home = self.task['home'] + self.delete_home = self.task['delete_home'] + + self.delete_user_home = 'rm -r {}' + self.delete_user = 'userdel {}' + self.logout_user = 'pkill -u {}' + self.kill_all_process = 'killall -KILL -u {}' + + self.logger.debug('Parameters were initialized.') + + def handle_task(self): + try: + self.execute(self.logout_user.format(self.username)) + self.execute(self.kill_all_process.format(self.username)) + self.logger.debug('Killed all processes for {}'.format(self.username)) + + if self.delete_home is True: + self.execute(self.delete_user.format(self.username)) + self.execute(self.delete_user_home.format(self.home)) + self.logger.debug('Deleted user with home: {}'.format(self.username)) + elif self.delete_home is False: + self.execute(self.delete_user.format(self.username)) + self.logger.debug('Deleted user: {}'.format(self.username)) + + self.logger.info('User has been deleted successfully.') + self.context.create_response(code=self.message_code.TASK_PROCESSED.value, + message='Kullanıcı başarıyla silindi.') + + except Exception as e: + self.logger.error( + 'A problem occured while handling Local-User task: {0}'.format(str(e))) + self.context.create_response(code=self.message_code.TASK_ERROR.value, + message='Local-User görevi çalıştırılırken bir hata oluştu.') + + +def handle_task(task, context): + delete_user = DeleteUser(task, context) + delete_user.handle_task() diff --git a/opt/ahenk/plugins/local-user/edit_user.py b/opt/ahenk/plugins/local-user/edit_user.py new file mode 100644 index 0000000..07b219b --- /dev/null +++ b/opt/ahenk/plugins/local-user/edit_user.py @@ -0,0 +1,146 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- +# Author:Mine DOGAN + +from base.plugin.abstract_plugin import AbstractPlugin + + +class EditUser(AbstractPlugin): + def __init__(self, task, context): + super(EditUser, self).__init__() + self.task = task + self.context = context + self.logger = self.get_logger() + self.message_code = self.get_message_code() + + self.username = self.task['username'] + self.new_username = self.task['new_username'] + self.password = self.task['password'] + self.home = self.task['home'] + self.active = self.task['active'] + self.groups = self.task['groups'] + self.desktop_write_permission = self.task['desktop_write_permission'] + self.kiosk_mode = self.task['kiosk_mode'] + self.current_home = self.execute('eval echo ~{0}'.format(self.username))[1] + + self.script = '/bin/bash ' + self.Ahenk.plugins_path() + 'local-user/scripts/{0}' + + self.kill_processes = 'pkill -u {}' + self.change_username = 'usermod -l {0} {1}' + self.create_shadow_password = 'mkpasswd -m sha-512 {}' + self.change_password = 'usermod -p {0} {1}' + self.change_home = 'usermod -m -d {0} {1}' + self.enable_user = 'passwd -u {}' + self.disable_user = 'passwd -l {}' + self.change_groups = 'usermod -G {0} {1}' + self.remove_all_groups = 'usermod -G "" {}' + self.change_owner = 'chown {0}.{0} {1}' + self.change_permission = 'chmod 755 {}' + self.logout_user = 'pkill -u {}' + self.kill_all_process = 'killall -KILL -u {}' + + self.message = '' + self.message_code_level = 1 + self.logger.debug('Parameters were initialized.') + + def handle_task(self): + try: + self.execute(self.logout_user.format(self.username)) + self.execute(self.kill_all_process.format(self.username)) + self.logger.debug('Killed all processes for {}'.format(self.username)) + + if str(self.new_username).strip() != "": + self.execute(self.kill_processes.format(self.username)) + self.execute(self.change_username.format(self.new_username, self.username)) + self.logger.debug('Changed username {0} to {1}'.format(self.username, self.new_username)) + self.username = self.new_username + + if str(self.password).strip() != "": + result_code, p_out, p_err = self.execute(self.create_shadow_password.format(self.password)) + shadow_password = p_out.strip() + self.execute(self.change_password.format('\'{}\''.format(shadow_password), self.username)) + self.logger.debug('Changed password.') + + if self.current_home != self.home: + self.execute(self.kill_processes.format(self.username)) + self.execute(self.change_home.format(self.home, self.username)) + self.logger.debug('Changed home directory to: {}'.format(self.home)) + + self.execute(self.change_owner.format(self.username, self.home)) + self.execute(self.change_permission.format(self.home)) + self.logger.debug('Changed owner and permission for home directory.') + + if self.active == "true": + self.execute(self.enable_user.format(self.username)) + self.logger.debug('The user has been enabled.') + elif self.active == "false": + self.execute(self.disable_user.format(self.username)) + self.logger.debug('The user has been disabled.') + + if self.groups != "": + self.execute(self.change_groups.format(self.groups, self.username)) + self.logger.debug('Added user to these groups: {}'.format(self.groups)) + else: + self.execute(self.remove_all_groups.format(self.username)) + self.logger.debug('Removed all groups for user: {}'.format(self.username)) + + if self.desktop_write_permission == "true": + self.execute('chown -R {0}:{0} {1}/Masaüstü'.format(self.username, self.current_home)) + self.logger.debug('Desktop write permission is true'); + + elif self.desktop_write_permission == "false": + self.execute('chown -R root:root {0}/Masaüstü'.format(self.current_home)) + self.logger.debug('Desktop write permission is false') + + # + # Handle kiosk mode + # + result_code, p_out, p_err = self.execute(self.script.format('find_locked_users.sh'), result=True) + if result_code != 0: + self.logger.error('Error occurred while managing kiosk mode.') + self.message_code_level += 1 + self.message = 'Masaüstü kilidi ayarlanırken hata oluştu.' + locked_users = [] + if p_out: + self.logger.debug('pout {0}'.format(str(p_out))) + locked_users = p_out.strip().split(';') + if self.kiosk_mode == "true": + self.logger.debug('Kiosk mode is active {0}'.format(str(locked_users))) + if self.username not in locked_users: + self.logger.debug('Adding user {0} to locked users'.format(self.username)) + locked_users.append(self.username) + locked_users_str = ";".join(locked_users) + self.logger.debug('Users: {0}'.format(locked_users_str)) + comm = "sed -i 's/^.*" + '' + "/' /etc/xdg/xfce4/xfconf/xfce-perchannel-xml/xfce4-panel.xml" + result_code1, p_out1, p_err1 = self.execute(comm) + elif self.kiosk_mode == "false": + self.logger.debug('Kiok mode is NOT active') + if self.username in locked_users: + self.logger.debug('Removing user {0} from locked users'.format(self.username)) + locked_users.remove(self.username) + if locked_users: + locked_users_str = ";".join(locked_users) + comm = "sed -i 's/^.*" + '' + "/' /etc/xdg/xfce4/xfconf/xfce-perchannel-xml/xfce4-panel.xml" + result_code1, p_out1, p_err1 = self.execute(comm) + else: + self.execute(self.script.format('remove_locked_users.sh ')) + + self.logger.info('User has been edited successfully.') + + if self.message_code_level == 1: + response_code = self.message_code.TASK_PROCESSED.value + response_message = 'Kullanıcı başarıyla düzenlendi.' + else: + response_code = self.message_code.TASK_WARNING.value + response_message = 'Kullanıcı düzenlendi; fakat {0}'.format(self.message) + self.context.create_response(code=response_code, message=response_message) + + except Exception as e: + self.logger.error('A problem occurred while handling Local-User task: {0}'.format(str(e))) + self.context.create_response(code=self.message_code.TASK_ERROR.value, + message='Local-User görevi çalıştırılırken bir hata oluştu.') + + +def handle_task(task, context): + edit_user = EditUser(task, context) + edit_user.handle_task() diff --git a/opt/ahenk/plugins/local-user/get_groups.py b/opt/ahenk/plugins/local-user/get_groups.py new file mode 100644 index 0000000..3f7cd48 --- /dev/null +++ b/opt/ahenk/plugins/local-user/get_groups.py @@ -0,0 +1,44 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- +# Author:Mine DOGAN + +import json + +from base.plugin.abstract_plugin import AbstractPlugin + + +class GetGroups(AbstractPlugin): + def __init__(self, task, context): + super(GetGroups, self).__init__() + self.task = task + self.context = context + self.logger = self.get_logger() + self.message_code = self.get_message_code() + + self.command_get_groups = 'cut -d: -f1 /etc/group' + + self.logger.debug('Parameters were initialized.') + + def handle_task(self): + + try: + result_code, p_out, p_err = self.execute(self.command_get_groups) + groups = p_out.split('\n') + groups.pop() + + self.logger.debug('groups: {0}'.format(groups)) + + self.logger.info('Local User \'get_groups\' task is handled successfully') + self.context.create_response(code=self.message_code.TASK_PROCESSED.value, + message='Grup listesi başarıyla getirildi.', + data=json.dumps({'groups': groups}), + content_type=self.get_content_type().APPLICATION_JSON.value) + + except Exception as e: + self.logger.error('A problem occurred while handling Local-User \'get_groups\' task: {0}'.format(str(e))) + self.context.create_response(code=self.message_code.TASK_ERROR.value, + message='Local-User \'get_groups\' görevi çalıştırılırken bir hata oluştu.') + +def handle_task(task, context): + get_groups = GetGroups(task, context) + get_groups.handle_task() \ No newline at end of file diff --git a/opt/ahenk/plugins/local-user/get_users.py b/opt/ahenk/plugins/local-user/get_users.py new file mode 100644 index 0000000..1822815 --- /dev/null +++ b/opt/ahenk/plugins/local-user/get_users.py @@ -0,0 +1,107 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- +# Author:Mine DOGAN + +import json + +from base.plugin.abstract_plugin import AbstractPlugin + + +class GetUsers(AbstractPlugin): + def __init__(self, task, context): + super(GetUsers, self).__init__() + self.task = task + self.context = context + self.logger = self.get_logger() + self.message_code = self.get_message_code() + + self.script = '/bin/bash ' + self.Ahenk.plugins_path() + 'local-user/scripts/{0}' + + self.command_users = 'awk -F: \'{print $1 ":" $6 ":" $7}\' /etc/passwd | grep /bin/bash' + self.command_user_groups = 'groups {}' + self.command_not_active = 'egrep \':\!\' /etc/shadow |awk -F: \'{print $1}\'' + self.desktop_path = '/home/agem/Masaüstü' + + self.logger.debug('Parameters were initialized.') + + def handle_task(self): + + try: + user_list = [] + + result_code, p_out, p_err = self.execute(self.command_users) + lines = p_out.split('\n') + lines.pop() + + for line in lines: + detail = line.split(':') + + result_code, p_out, p_err = self.execute(self.command_user_groups.format(str(detail[0]).strip())) + groups = p_out.split(':') + groups[1] = str(groups[1]).strip() + groups[1] = groups[1].replace("'", "").replace(" ", ", ") + + is_active = 'true' + + result_code, p_out, p_err = self.execute(self.command_not_active) + users = p_out.split('\n') + + if str(detail[0]).strip() in users: + is_active = 'false' + + self.desktop_path = '' + if self.is_exist("{0}/Masaüstü/".format(str(detail[1]).strip())): + self.desktop_path = "{0}/Masaüstü/".format(str(detail[1]).strip()) + self.logger.debug("Desktop path for user '{0}' : {1}".format(str(detail[0]).strip(), self.desktop_path)) + elif self.is_exist("{0}/Desktop/".format(str(detail[1]).strip())): + self.desktop_path = "{0}/Desktop/".format(str(detail[1]).strip()) + self.logger.debug("Desktop path for user '{0}' : {1}".format(str(detail[0]).strip(), self.desktop_path)) + else: + self.logger.debug( + 'Desktop write permission could not get. Desktop path not found for user "{0}"'.format( + str(detail[0]).strip())) + + is_desktop_write_permission_exists = 'false' + self.logger.debug("sudo -u " + str(detail[0]).strip() + " touch -c " + self.desktop_path + " 2>&1 | grep 'Permission denied'") + result_code, p_out, p_err = self.execute(" touch -c " + self.desktop_path + " 2>&1 | grep 'Permission denied'", as_user=str(detail[0]).strip()) + self.logger.debug("result codeee : " + str(result_code).strip()) + if result_code == 1: + is_desktop_write_permission_exists = 'true' + + is_kiosk_mode_on = 'false' + self.logger.debug('Kiosk mode info will be taken') + result_code, p_out, p_err = self.execute(self.script.format('find_locked_users.sh'), result=True) + if result_code != 0: + self.logger.error( + 'Error occurred while finding locked users.') + if p_out: + self.logger.debug('locked users are {0}'.format(str(p_out))) + locked_users = p_out.strip().split(';') + # self.logger.debug("user is " + str(detail[0]).strip()) + # self.logger.debug("locked users are " + str(locked_users)) + if str(detail[0]).strip() in locked_users: + is_kiosk_mode_on = 'true' + self.logger.debug('Kiosk mode info is taken') + + user = {'user': str(detail[0]).strip(), 'groups': groups[1], 'home': detail[1], 'is_active': is_active, 'is_desktop_write_permission_exists': is_desktop_write_permission_exists, 'is_kiosk_mode_on': is_kiosk_mode_on} + user_list.append(user) + + self.logger.debug( + 'user: {0}, groups: {1}, home: {2}, is_active: {3}'.format(str(detail[0]).strip(), groups[1], + detail[1], is_active)) + + self.logger.info('Local User task is handled successfully') + self.context.create_response(code=self.message_code.TASK_PROCESSED.value, + message='Kullanıcı listesi başarıyla getirildi.', + data=json.dumps({'users': user_list}), + content_type=self.get_content_type().APPLICATION_JSON.value) + + except Exception as e: + self.logger.error('A problem occurred while handling Local-User task: {0}'.format(str(e))) + self.context.create_response(code=self.message_code.TASK_ERROR.value, + message='Local-User görevi çalıştırılırken bir hata oluştu.') + + +def handle_task(task, context): + get_users = GetUsers(task, context) + get_users.handle_task() diff --git a/opt/ahenk/plugins/local-user/init.py b/opt/ahenk/plugins/local-user/init.py new file mode 100644 index 0000000..f69217d --- /dev/null +++ b/opt/ahenk/plugins/local-user/init.py @@ -0,0 +1,24 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- +# Author:Mine DOGAN + +from base.plugin.abstract_plugin import AbstractPlugin + + +class Init(AbstractPlugin): + def __init__(self, context): + super(Init, self).__init__() + self.context = context + self.logger = self.get_logger() + + self.logger.debug('Parameters were initialized.') + + def handle_mode(self): + if self.is_installed('whois') is False: + self.install_with_apt_get('whois') + self.logger.debug('whois has been installed with apt-get.') + + +def handle_mode(context): + init = Init(context) + init.handle_mode() diff --git a/opt/ahenk/plugins/local-user/main.py b/opt/ahenk/plugins/local-user/main.py new file mode 100644 index 0000000..a34310f --- /dev/null +++ b/opt/ahenk/plugins/local-user/main.py @@ -0,0 +1,16 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- + + +def info(): + inf = dict() + inf['name'] = 'local-user' + inf['version'] = '1.0.0' + inf['support'] = 'debian' + inf['description'] = 'Local-User plugin provides to listing users and adding, editing, deleting a local user.' + inf['task'] = True + inf['user_oriented'] = False + inf['machine_oriented'] = False + inf['developer'] = 'mine.dogan@agem.com.tr' + + return inf diff --git a/opt/ahenk/plugins/local-user/scripts/find_locked_users.sh b/opt/ahenk/plugins/local-user/scripts/find_locked_users.sh new file mode 100755 index 0000000..92a70b8 --- /dev/null +++ b/opt/ahenk/plugins/local-user/scripts/find_locked_users.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +sed -n 's/^.*locked="\([A-Za-z0-9; ]*\)".*$/\1/p' /etc/xdg/xfce4/xfconf/xfce-perchannel-xml/xfce4-panel.xml diff --git a/opt/ahenk/plugins/local-user/scripts/remove_locked_users.sh b/opt/ahenk/plugins/local-user/scripts/remove_locked_users.sh new file mode 100755 index 0000000..0f62891 --- /dev/null +++ b/opt/ahenk/plugins/local-user/scripts/remove_locked_users.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +sed -i 's/\(^.*\)\(locked="[A-Za-z; ]*"\)\(.*$\)/\1\3/' /etc/xdg/xfce4/xfconf/xfce-perchannel-xml/xfce4-panel.xml diff --git a/opt/ahenk/plugins/network-inventory/installahenk.py b/opt/ahenk/plugins/network-inventory/installahenk.py new file mode 100644 index 0000000..a6965bb --- /dev/null +++ b/opt/ahenk/plugins/network-inventory/installahenk.py @@ -0,0 +1,114 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- +# Author:Mine DOGAN + +import os +import urllib.request + +import paramiko + +from base.plugin.abstract_plugin import AbstractPlugin + + +class InstallAhenk(AbstractPlugin): + def __init__(self, task, context): + super(AbstractPlugin, self).__init__() + self.task = task + self.context = context + self.logger = self.get_logger() + self.message_code = self.get_message_code() + + self.access_method = self.task['accessMethod'] + self.install_method = self.task['installMethod'] + self.ipList = self.task['ipList'] + self.username = self.task['username'] + + if self.access_method == 'USERNAME_PASSWORD': + self.password = self.task['password'] + elif self.access_method == 'PRIVATE_KEY': + self.passphrase = self.task['passphrase'] + self.key_path = self.task['privateKeyPath'] + + if self.install_method == 'APT_GET': + self.install_command = 'sudo apt-get install -y --force-yes ahenk' # TODO name for ahenk + + elif self.install_method == 'WGET': + self.download_url = self.task['downloadUrl'] + + self.deb_path = '/tmp/ahenk.deb' + self.command = 'gdebi -n {}'.format(self.deb_path) + + self.logger.debug('Initialized') + + def handle_task(self): + try: + if self.access_method == 'USERNAME_PASSWORD': + for i, val in enumerate(self.ipList): + self.use_username_password(val) + elif self.access_method == 'PRIVATE_KEY': + for i, val in enumerate(self.ipList): + self.use_key(val) + + self.context.create_response(code=self.message_code.TASK_PROCESSED.value, + message='NETWORK INVENTORY görevi başarıyla çalıştırıldı.') + self.logger.info('NETWORK INVENTORY task is handled successfully') + except Exception as e: + self.logger.error( + 'A problem occured while handling NETWORK INVENTORY task: {0}'.format(str(e))) + self.context.create_response(code=self.message_code.TASK_ERROR.value, + message='NETWORK INVENTORY görevi çalıştırılırken bir hata oluştu.') + + def use_username_password(self, host): + ssh = paramiko.SSHClient() + ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + ssh.connect(host, username=self.username, password=self.password) + + transport = ssh.get_transport() + session = transport.open_session() + session.set_combine_stderr(True) + session.get_pty() + + self.logger.debug('SSH connection has been started.') + + if self.install_method == 'WGET': + urllib.request.urlretrieve(self.download_url, self.deb_path) + sftp = ssh.open_sftp() + sftp.put(self.deb_path, self.deb_path) + session.exec_command(self.command) + stdout = session.makefile('rb', -1) + + elif self.install_method == 'APT_GET': + session.exec_command(self.install_command) + stdin = session.makefile('wb', -1) + stdout = session.makefile('rb', -1) + stdin.write(self.password + '\n') + stdin.flush() + + self.logger.debug('Ahenk has been installed.') + + def use_key(self, host): + ssh = paramiko.SSHClient() + ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + + privatekeyfile = os.path.expanduser(self.key_path) + key = paramiko.RSAKey.from_private_key_file(privatekeyfile) + ssh.connect(host, username=self.username, pkey=key, password=self.passphrase) + + self.logger.debug('SSH connection has been started.') + + if self.install_method == 'WGET': + urllib.request.urlretrieve(self.download_url, self.deb_path) + sftp = ssh.open_sftp() + sftp.put(self.deb_path, self.deb_path) + stdin, stdout, stderr = ssh.exec_command(self.command) + + elif self.install_method == 'APT_GET': + stdin, stdout, stderr = ssh.exec_command(self.install_command) + # TODO need to write user password (because of sudo command) + + self.logger.debug('Ahenk has been installed.') + + +def handle_task(task, context): + install = InstallAhenk(task, context) + install.handle_task() diff --git a/opt/ahenk/plugins/network-inventory/main.py b/opt/ahenk/plugins/network-inventory/main.py new file mode 100644 index 0000000..664b767 --- /dev/null +++ b/opt/ahenk/plugins/network-inventory/main.py @@ -0,0 +1,16 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- + + +def info(): + inf = dict() + inf['name'] = 'network-inventory' + inf['version'] = '1.0.0' + inf['support'] = 'debian' + inf['description'] = '' + inf['task'] = True + inf['user_oriented'] = False + inf['machine_oriented'] = False + inf['developer'] = '' + + return inf \ No newline at end of file diff --git a/opt/ahenk/plugins/network-inventory/multiple-file-transfer.py b/opt/ahenk/plugins/network-inventory/multiple-file-transfer.py new file mode 100644 index 0000000..c20ff10 --- /dev/null +++ b/opt/ahenk/plugins/network-inventory/multiple-file-transfer.py @@ -0,0 +1,101 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- +# Author: Caner Feyzullahoglu +""" +Style Guide is PEP-8 +https://www.python.org/dev/peps/pep-0008/ +""" + +from base.plugin.abstract_plugin import AbstractPlugin + + +class GetFile(AbstractPlugin): + def __init__(self, task, context): + super(AbstractPlugin, self).__init__() + + self.logger = self.get_logger() + self.logger.debug('Initialized') + + self.task = task + self.context = context + self.message_code = self.get_message_code() + + def handle_task(self): + parameter_map = self.task + self.logger.debug('Handling task') + + self.logger.debug('Fetching file from: {0} to {1}'.format(parameter_map['remotePath'], + parameter_map['localPath'])) + + try: + self.context.fetch_file(parameter_map['remotePath'], local_path=parameter_map['localPath'], + file_name=parameter_map['fileName']) + + if parameter_map['editUserPermissions'] \ + or parameter_map['editGroupPermissions'] \ + or parameter_map['editOtherPermissions']: + permissions = '' + warning_message = '' + if parameter_map['editUserPermissions']: + permissions += 'u+r' if parameter_map['readUser'] else 'u-r' + permissions += '+w' if parameter_map['writeUser'] else '-w' + permissions += '+x,' if parameter_map['executeUser'] else '-x,' + if parameter_map['ownerUser']: + chown_command = 'chown ' + parameter_map['ownerUser'] + ': ' + parameter_map['localPath'] \ + + parameter_map['fileName'] + self.logger.debug('Executing chown: ' + chown_command) + result_code, p_out, p_err = self.execute(chown_command) + if result_code != 0: + self.logger.error('Error occurred while executing chown command') + self.logger.error('Error message: {0}'.format(str(p_err))) + warning_message = 'Dosyanın sahibi değiştirilemedi, ' \ + + parameter_map['ownerUser'] + ' kullanıcısının varolduğundan emin olun. ' + if parameter_map['editGroupPermissions']: + permissions += 'g+r' if parameter_map['readGroup'] else 'g-r' + permissions += '+w' if parameter_map['writeGroup'] else '-w' + permissions += '+x,' if parameter_map['executeGroup'] else '-x,' + if parameter_map['ownerGroup']: + chown_command = 'chown ' + ':' + parameter_map['ownerGroup'] + ' ' \ + + parameter_map['localPath'] \ + + parameter_map['fileName'] + self.logger.debug('Executing chown: ' + chown_command) + result_code, p_out, p_err = self.execute(chown_command) + if result_code != 0: + self.logger.error('Error occurred while executing chown command') + self.logger.error('Error message: {0}'.format(str(p_err))) + warning_message = 'Dosyanın sahibi değiştirilemedi, ' \ + + parameter_map['ownerGroup'] + ' grubunun varolduğundan emin olun. ' + if parameter_map['editOtherPermissions']: + permissions += 'o+r' if parameter_map['readOther'] else 'o-r' + permissions += '+w' if parameter_map['writeOther'] else '-w' + permissions += '+x' if parameter_map['executeOther'] else '-x' + if permissions: + chmod_command = 'chmod ' + permissions + ' ' + parameter_map['localPath'] \ + + parameter_map['fileName'] + self.logger.debug('Executing chmod: ' + chmod_command) + result_code, p_out, p_err = self.execute(chmod_command) + if result_code != 0: + self.logger.error('Error occurred while executing chmod command') + self.logger.error('Error message: {0}'.format(str(p_err))) + warning_message = 'Dosyanın hakları değiştirilirken hata oluştu.' + if warning_message: + self.context.create_response( + code= + self.message_code.TASK_WARNING.value, + message= + 'NETWORK INVENTORY dosya paylaşım görevi başarıyla çalıştırıldı. {0}'.format(warning_message)) + else: + self.context.create_response( + code= + self.message_code.TASK_PROCESSED.value, + message= + 'NETWORK INVENTORY dosya paylaşım görevi başarıyla çalıştırıldı.') + + except Exception as e: + self.context.create_response(code=self.message_code.TASK_ERROR.value, + message='NETWORK INVENTORY dosya paylaşım görevi çalıştırılırken hata oluştu.') + + +def handle_task(task, context): + scan = GetFile(task, context) + scan.handle_task() diff --git a/opt/ahenk/plugins/network-inventory/scannetwork.py b/opt/ahenk/plugins/network-inventory/scannetwork.py new file mode 100644 index 0000000..2edb46a --- /dev/null +++ b/opt/ahenk/plugins/network-inventory/scannetwork.py @@ -0,0 +1,188 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- +# Author:Mine DOGAN +# Author: Caner Feyzullahoglu +""" +Style Guide is PEP-8 +https://www.python.org/dev/peps/pep-0008/ +""" + +import json + +from base.plugin.abstract_plugin import AbstractPlugin + + +class ScanNetwork(AbstractPlugin): + def __init__(self, task, context): + super(AbstractPlugin, self).__init__() + + self.logger.debug('Initialized') + self.task = task + self.context = context + self.logger = self.get_logger() + self.message_code = self.get_message_code() + + self.logger.debug('Creating nmap command') + uuid = self.generate_uuid() + self.file_path = self.Ahenk.received_dir_path() + uuid + self.command = self.get_nmap_command() + + def handle_task(self): + self.logger.debug('Handling task') + try: + self.logger.debug('Executing command: {0}'.format(self.command)) + result_code, p_out, p_err = self.execute(self.command) + + if result_code != 0: + self.logger.error('Error occurred while executing nmap command') + self.logger.error('Error message: {0}'.format(str(p_err))) + self.context.create_response(code=self.message_code.TASK_ERROR.value, + message='NETWORK INVENTORY Nmap komutu çalıştırılırken hata oluştu') + else: + self.logger.debug('Nmap command successfully executed') + + data = {} + self.logger.debug('Getting md5 of file') + md5sum = self.get_md5_file(str(self.file_path)) + + self.logger.debug('{0} renaming to {1}'.format(self.file_path, md5sum)) + self.rename_file(self.file_path, self.Ahenk.received_dir_path() + md5sum) + self.logger.debug('Renamed file.') + + data['md5'] = md5sum + + self.logger.debug('Creating response message') + self.context.create_response(code=self.message_code.TASK_PROCESSED.value, + message='NETWORK INVENTORY görevi başarıyla çalıştırıldı.', + data=json.dumps(data), + content_type=self.get_content_type().TEXT_PLAIN.value) + + self.logger.info('NETWORK INVENTORY task is handled successfully') + except Exception as e: + self.logger.error( + 'A problem occured while handling NETWORK INVENTORY task: {0}'.format(str(e))) + self.context.create_response(code=self.message_code.TASK_ERROR.value, + message='NETWORK INVENTORY görevi çalıştırılırken bir hata oluştu.') + + def get_result(self, root): + self.logger.debug('Parsing nmap xml output') + result_list = {} + index = 1 + + for host in root.findall('host'): + result = {} + + host_names = host.find('hostnames') + ports = host.find('ports') + os = host.find('os') + distance = host.find('distance') + status = host.find('status') + self.logger.debug('STATUS: ++++++ ' + str(status)) + + self.logger.debug('Getting hostname list') + result['hostnames'] = self.get_hostname_list(host_names) + self.logger.debug('Getting port list') + result['ports'] = self.get_port_list(ports) + self.logger.debug('Getting os list') + result['os'] = self.get_os_list(os) + self.logger.debug('Getting distance list') + result['distance'] = self.get_distance(distance) + self.logger.debug('Getting IP, MAC and MAC provider list') + result['ipAddress'], result['macAddress'], result['macProvider'] = self.get_addresses(host) + self.logger.debug('Getting status') + result['status'] = self.get_status(host) + + result_list[index] = result + index += 1 + + return result_list + + def get_addresses(self, host): + ip_address = '' + mac_address = '' + mac_provider = '' + if host is not None: + for address in host.findall('address'): + if address.get('addrtype') == 'ipv4': + ip_address = address.get('addr') + if address.get('addrtype') == 'mac': + mac_address = address.get('addr') + mac_provider = address.get('vendor') + return ip_address, mac_address, mac_provider + + def get_hostname_list(self, hostnames): + hostname_list = '' + if hostnames is not None: + for hostname in hostnames.findall('hostname'): + name = hostname.get('name') + if hostname_list != '': + hostname_list = hostname_list + ', ' + name + else: + hostname_list = name + + return hostname_list + + def get_port_list(self, ports): + port_list = '' + if ports is not None: + for port in ports.findall('port'): + service = port.find('service') + service_name = service.get('name') + port_id = port.get('portid') + '/' + port.get('protocol') + ' ' + service_name + if port_list != '': + port_list = port_list + ', ' + port_id + else: + port_list = port_id + + return port_list + + def get_status(self, host): + state = False + if host is not None: + for status in host.findall('status'): + if status.get('state') == 'up': + state = True + if status.get('state') == 'down': + state = False + + return state + + def get_os_list(self, os): + os_list = '' + if os is not None: + for os_match in os.findall('osmatch'): + name = os_match.get('name') + if os_list != '': + os_list = os_list + ', ' + name + else: + os_list = name + + return os_list + + def get_distance(self, distance): + if distance is not None: + return distance.get('value') + return '' + + def get_nmap_command(self): + command = 'nmap -v -oX' + command += ' - ' + self.task['ipRange'] + if self.task['timingTemplate']: + command += ' -T' + str(self.task['timingTemplate']) + else: + # average speed + command += ' -T3' + + if self.task['ports']: + command += ' -p' + self.task['ports'] + else: + command += ' --top-ports 10' + + command += ' > ' + self.file_path + + return command + + +def handle_task(task, context): + scan = ScanNetwork(task, context) + scan.handle_task() diff --git a/opt/ahenk/plugins/network-manager/add_dns.py b/opt/ahenk/plugins/network-manager/add_dns.py new file mode 100644 index 0000000..f925346 --- /dev/null +++ b/opt/ahenk/plugins/network-manager/add_dns.py @@ -0,0 +1,48 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- +# Author:Mine DOGAN + +from base.plugin.abstract_plugin import AbstractPlugin + + +class AddDNS(AbstractPlugin): + def __init__(self, task, context): + super(AddDNS, self).__init__() + self.task = task + self.context = context + self.logger = self.get_logger() + self.message_code = self.get_message_code() + + self.dns_file = '/etc/resolv.conf' + + self.ip = self.task['ip'] + self.is_active = self.task['is_active'] + + self.logger.debug('Parameters were initialized.') + + def handle_task(self): + try: + if self.is_active is True: + content = 'nameserver {}\n'.format(self.ip) + self.logger.debug('Created active dns content.') + else: + content = '#nameserver {}\n'.format(self.ip) + self.logger.debug('Created passive dns content.') + + self.logger.debug('Writing to file...') + self.write_file(self.dns_file, content, 'a') + + self.logger.info('NETWORK-MANAGER - ADD_DNS task is handled successfully.') + self.context.create_response(code=self.message_code.TASK_PROCESSED.value, + message='DNS bilgisi başarıyla eklendi.') + + except Exception as e: + self.logger.error( + 'A problem occured while handling NETWORK-MANAGER task: {0}'.format(str(e))) + self.context.create_response(code=self.message_code.TASK_ERROR.value, + message='NETWORK-MANAGER görevi uygulanırken bir hata oluştu.') + + +def handle_task(task, context): + dns = AddDNS(task, context) + dns.handle_task() diff --git a/opt/ahenk/plugins/network-manager/add_domain.py b/opt/ahenk/plugins/network-manager/add_domain.py new file mode 100644 index 0000000..2da5deb --- /dev/null +++ b/opt/ahenk/plugins/network-manager/add_domain.py @@ -0,0 +1,42 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- +# Author:Mine DOGAN + +from base.plugin.abstract_plugin import AbstractPlugin + + +class AddDomain(AbstractPlugin): + def __init__(self, task, context): + super(AddDomain, self).__init__() + self.task = task + self.context = context + self.logger = self.get_logger() + self.message_code = self.get_message_code() + + self.dns_file = '/etc/resolv.conf' + + self.domain = self.task['domain'] + + self.logger.debug('Parameters were initialized.') + + def handle_task(self): + try: + content = 'domain {0}\nsearch {0}\n'.format(self.domain) + + self.logger.debug('Writing to file...') + self.write_file(self.dns_file, content, 'a') + + self.logger.info('NETWORK-MANAGER - ADD_DOMAIN task is handled successfully.') + self.context.create_response(code=self.message_code.TASK_PROCESSED.value, + message='Alan adı bilgisi başarıyla eklendi.') + + except Exception as e: + self.logger.error( + 'A problem occured while handling NETWORK-MANAGER task: {0}'.format(str(e))) + self.context.create_response(code=self.message_code.TASK_ERROR.value, + message='NETWORK-MANAGER görevi uygulanırken bir hata oluştu.') + + +def handle_task(task, context): + domain = AddDomain(task, context) + domain.handle_task() diff --git a/opt/ahenk/plugins/network-manager/add_host.py b/opt/ahenk/plugins/network-manager/add_host.py new file mode 100644 index 0000000..37f1687 --- /dev/null +++ b/opt/ahenk/plugins/network-manager/add_host.py @@ -0,0 +1,49 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- +# Author:Mine DOGAN + +from base.plugin.abstract_plugin import AbstractPlugin + + +class AddHost(AbstractPlugin): + def __init__(self, task, context): + super(AddHost, self).__init__() + self.task = task + self.context = context + self.logger = self.get_logger() + self.message_code = self.get_message_code() + + self.hosts_file = '/etc/hosts' + + self.ip = self.task['ip'] + self.hostname = self.task['hostname'] + self.is_active = self.task['is_active'] + + self.logger.debug('Parameters were initialized.') + + def handle_task(self): + try: + if self.is_active is True: + content = '{0} {1}\n'.format(self.ip, self.hostname) + self.logger.debug('Created active host content.') + else: + content = '#{0} {1}\n'.format(self.ip, self.hostname) + self.logger.debug('Created passive host content.') + + self.logger.debug('Writing to file...') + self.write_file(self.hosts_file, content, 'a') + + self.logger.info('NETWORK-MANAGER - ADD_HOST task is handled successfully.') + self.context.create_response(code=self.message_code.TASK_PROCESSED.value, + message='Sunucu bilgisi başarıyla eklendi.') + + except Exception as e: + self.logger.error( + 'A problem occured while handling NETWORK-MANAGER task: {0}'.format(str(e))) + self.context.create_response(code=self.message_code.TASK_ERROR.value, + message='NETWORK-MANAGER görevi uygulanırken bir hata oluştu.') + + +def handle_task(task, context): + host = AddHost(task, context) + host.handle_task() diff --git a/opt/ahenk/plugins/network-manager/add_network.py b/opt/ahenk/plugins/network-manager/add_network.py new file mode 100644 index 0000000..783d7c5 --- /dev/null +++ b/opt/ahenk/plugins/network-manager/add_network.py @@ -0,0 +1,73 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- +# Author:Mine DOGAN + +from base.plugin.abstract_plugin import AbstractPlugin + + +class AddNetwork(AbstractPlugin): + def __init__(self, task, context): + super(AddNetwork, self).__init__() + self.task = task + self.context = context + self.logger = self.get_logger() + self.message_code = self.get_message_code() + + self.nic_file = '/etc/network/interfaces' + + self.type = self.task['type'] + self.name = self.task['name'] + self.is_active = self.task['is_active'] + + if self.type == 'STATIC': + self.ip = self.task['ip'] + self.netmask = self.task['netmask'] + self.gateway = self.task['gateway'] + + self.content = '' + + self.logger.debug('Parameters were initialized.') + + def handle_task(self): + try: + if self.type == 'STATIC': + if self.is_active is True: + self.content = 'iface {0} inet static\n address {1}\n netmask {2}\n gateway {3}\n'.format(self.name, + self.ip, + self.netmask, + self.gateway) + else: + self.content = 'iface {0} inet static\n#address {1}\n#netmask {2}\n#gateway {3}\n'.format(self.name, + self.ip, + self.netmask, + self.gateway) + + self.logger.debug('Created content for STATIC type.') + elif self.type == 'DHCP': + self.content = 'iface {} inet dhcp\n'.format(self.name) + self.logger.debug('Created content for DHCP type.') + elif self.type == 'LOOPBACK': + self.content = 'iface {} inet loopback\n'.format(self.name) + self.logger.debug('Created content for LOOPBACK type.') + + if self.is_active is False: + self.logger.debug('Network interface is not active.') + self.content = '#{}'.format(self.content) + + self.logger.debug('Writing to file...') + self.write_file(self.nic_file, self.content, 'a') + + self.logger.info('NETWORK-MANAGER - ADD_NETWORK task is handled successfully.') + self.context.create_response(code=self.message_code.TASK_PROCESSED.value, + message='Yeni ağ arayüzü başarıyla eklendi.') + + except Exception as e: + self.logger.error( + 'A problem occured while handling NETWORK-MANAGER task: {0}'.format(str(e))) + self.context.create_response(code=self.message_code.TASK_ERROR.value, + message='NETWORK-MANAGER görevi uygulanırken bir hata oluştu.') + + +def handle_task(task, context): + network = AddNetwork(task, context) + network.handle_task() diff --git a/opt/ahenk/plugins/network-manager/change_hostname.py b/opt/ahenk/plugins/network-manager/change_hostname.py new file mode 100644 index 0000000..54f8288 --- /dev/null +++ b/opt/ahenk/plugins/network-manager/change_hostname.py @@ -0,0 +1,42 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- +# Author:Mine DOGAN + +from base.plugin.abstract_plugin import AbstractPlugin + + +class ChangeHostname(AbstractPlugin): + def __init__(self, task, context): + super(ChangeHostname, self).__init__() + self.task = task + self.context = context + self.logger = self.get_logger() + self.message_code = self.get_message_code() + + self.hostname_file = '/etc/hostname' + + self.hostname = self.task['hostname'] + + self.logger.debug('Parameters were initialized.') + + def handle_task(self): + try: + content = '{}\n'.format(self.hostname) + + self.logger.debug('[NETWORK-MANAGER - ADD_HOST] Writing to file...') + self.write_file(self.hostname_file, content) + + self.logger.info('NETWORK-MANAGER - CHANGE_HOSTNAME task is handled successfully.') + self.context.create_response(code=self.message_code.TASK_PROCESSED.value, + message='Sunucu ismi başarıyla değiştirildi.') + + except Exception as e: + self.logger.error( + 'A problem occured while handling NETWORK-MANAGER task: {0}'.format(str(e))) + self.context.create_response(code=self.message_code.TASK_ERROR.value, + message='NETWORK-MANAGER görevi uygulanırken bir hata oluştu.') + + +def handle_task(task, context): + hostname = ChangeHostname(task, context) + hostname.handle_task() diff --git a/opt/ahenk/plugins/network-manager/delete_dns.py b/opt/ahenk/plugins/network-manager/delete_dns.py new file mode 100644 index 0000000..71548f9 --- /dev/null +++ b/opt/ahenk/plugins/network-manager/delete_dns.py @@ -0,0 +1,67 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- +# Author:Mine DOGAN + +import re + +from base.plugin.abstract_plugin import AbstractPlugin + + +class DeleteDNS(AbstractPlugin): + def __init__(self, task, context): + super(DeleteDNS, self).__init__() + self.task = task + self.context = context + self.logger = self.get_logger() + self.message_code = self.get_message_code() + + self.dns_file = '/etc/resolv.conf' + + self.ip = self.task['ip'] + self.is_active = self.task['is_active'] + + self.logger.debug('Parameters were initialized.') + + def handle_task(self): + try: + + lines = self.read_file_by_line(self.dns_file) + f = open(self.dns_file, "w") + + for line in lines: + line = str(line).strip(" ") + # to remove multiple spaces + line = re.sub(' +', ' ', line) + + if self.is_active is True: + if line != 'nameserver {}\n'.format(self.ip): + self.logger.debug( + 'Writing a line to dns file... Line: {}'.format(line)) + f.write(line) + else: + self.logger.debug('Line has been deleted from dns file. Line: {}'.format(line)) + else: + if line != '#nameserver {}\n'.format(self.ip) and line != '# nameserver {}\n'.format(self.ip): + self.logger.debug( + 'Writing a line to dns file... Line: {}'.format(line)) + f.write(line) + else: + self.logger.debug( + 'Line has been deleted from dns file. Line: {}'.format(line)) + + f.close() + + self.logger.info('NETWORK-MANAGER - DELETE_DNS task is handled successfully.') + self.context.create_response(code=self.message_code.TASK_PROCESSED.value, + message='DNS bilgisi başarıyla silindi.') + + except Exception as e: + self.logger.error( + 'A problem occured while handling NETWORK-MANAGER task: {0}'.format(str(e))) + self.context.create_response(code=self.message_code.TASK_ERROR.value, + message='NETWORK-MANAGER görevi uygulanırken bir hata oluştu.') + + +def handle_task(task, context): + dns = DeleteDNS(task, context) + dns.handle_task() diff --git a/opt/ahenk/plugins/network-manager/delete_domain.py b/opt/ahenk/plugins/network-manager/delete_domain.py new file mode 100644 index 0000000..46faa8b --- /dev/null +++ b/opt/ahenk/plugins/network-manager/delete_domain.py @@ -0,0 +1,57 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- +# Author:Mine DOGAN + +import re + +from base.plugin.abstract_plugin import AbstractPlugin + + +class DeleteDomain(AbstractPlugin): + def __init__(self, task, context): + super(DeleteDomain, self).__init__() + self.task = task + self.context = context + self.logger = self.get_logger() + self.message_code = self.get_message_code() + + self.dns_file = '/etc/resolv.conf' + + self.domain = self.task['domain'] + + self.logger.debug('Parameters were initialized.') + + def handle_task(self): + try: + lines = self.read_file_by_line(self.dns_file) + f = open(self.dns_file, "w") + + for line in lines: + line = str(line).strip(" ") + # to remove multiple spaces + line = re.sub(' +', ' ', line) + + if line != 'domain {}\n'.format(self.domain) and line != 'search {}\n'.format(self.domain): + self.logger.debug( + 'Writing a line to dns file... Line: {}'.format(line)) + f.write(line) + else: + self.logger.debug( + 'Line has been deleted from dns file. Line: {}'.format(line)) + + f.close() + + self.logger.info('NETWORK-MANAGER - DELETE_DOMAIN task is handled successfully.') + self.context.create_response(code=self.message_code.TASK_PROCESSED.value, + message='Alan adı bilgisi başarıyla silindi.') + + except Exception as e: + self.logger.error( + 'A problem occured while handling NETWORK-MANAGER task: {0}'.format(str(e))) + self.context.create_response(code=self.message_code.TASK_ERROR.value, + message='NETWORK-MANAGER görevi uygulanırken bir hata oluştu.') + + +def handle_task(task, context): + domain = DeleteDomain(task, context) + domain.handle_task() diff --git a/opt/ahenk/plugins/network-manager/delete_host.py b/opt/ahenk/plugins/network-manager/delete_host.py new file mode 100644 index 0000000..963351d --- /dev/null +++ b/opt/ahenk/plugins/network-manager/delete_host.py @@ -0,0 +1,70 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- +# Author:Mine DOGAN + +import re + +from base.plugin.abstract_plugin import AbstractPlugin + + +class DeleteHost(AbstractPlugin): + def __init__(self, task, context): + super(DeleteHost, self).__init__() + self.task = task + self.context = context + self.logger = self.get_logger() + self.message_code = self.get_message_code() + + self.hosts_file = '/etc/hosts' + + self.ip = self.task['ip'] + self.hostname = self.task['hostname'] + self.is_active = self.task['is_active'] + + self.logger.debug('Parameters were initialized.') + + def handle_task(self): + try: + + lines = self.read_file_by_line(self.hosts_file) + f = open(self.hosts_file, "w") + + for line in lines: + line = str(line).strip(" ") + # to remove multiple spaces + line = re.sub(' +', ' ', line) + + if self.is_active is True: + if line != '{0} {1}\n'.format(self.ip, self.hostname): + self.logger.debug( + 'Writing a line to hosts file... Line: {}'.format(line)) + f.write(line) + else: + self.logger.debug( + 'Line has been deleted from hosts file. Line: {}'.format(line)) + else: + if line != '#{0} {1}\n'.format(self.ip, self.hostname) and line != '# {0} {1}\n'.format(self.ip, + self.hostname): + self.logger.debug( + 'Writing a line to hosts file... Line: {}'.format(line)) + f.write(line) + else: + self.logger.debug( + 'Line has been deleted from hosts file. Line: {}'.format(line)) + + f.close() + + self.logger.info('NETWORK-MANAGER - DELETE_HOST task is handled successfully.') + self.context.create_response(code=self.message_code.TASK_PROCESSED.value, + message='Sunucu bilgisi başarıyla silindi.') + + except Exception as e: + self.logger.error( + 'A problem occured while handling NETWORK-MANAGER task: {0}'.format(str(e))) + self.context.create_response(code=self.message_code.TASK_ERROR.value, + message='NETWORK-MANAGER görevi uygulanırken bir hata oluştu.') + + +def handle_task(task, context): + host = DeleteHost(task, context) + host.handle_task() diff --git a/opt/ahenk/plugins/network-manager/delete_network.py b/opt/ahenk/plugins/network-manager/delete_network.py new file mode 100644 index 0000000..762a0da --- /dev/null +++ b/opt/ahenk/plugins/network-manager/delete_network.py @@ -0,0 +1,87 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- +# Author:Mine DOGAN + +import fileinput +import re + +from base.plugin.abstract_plugin import AbstractPlugin + + +class DeleteNetwork(AbstractPlugin): + def __init__(self, task, context): + super(DeleteNetwork, self).__init__() + self.task = task + self.context = context + self.logger = self.get_logger() + self.message_code = self.get_message_code() + + self.nic_file = '/etc/network/interfaces' + + self.type = self.task['type'] + self.name = self.task['name'] + self.is_active = self.task['is_active'] + + if self.type == 'STATIC': + self.ip = self.task['ip'] + self.netmask = self.task['netmask'] + self.gateway = self.task['gateway'] + + self.content = '' + + self.logger.debug('Parameters were initialized.') + + def handle_task(self): + try: + counter = 0 + for line in fileinput.input(self.nic_file, inplace=True): + line = str(line).strip(" ") + # to remove multiple spaces + line = re.sub(' +', ' ', line) + + if not counter: + if self.type == 'static': + if self.is_active is True: + self.content = 'iface {0} inet static\n'.format(self.name) + else: + self.content = '#iface {0} inet static\n'.format(self.name) + + if line.startswith(self.content): + counter = 3 + else: + print(str(line).strip()) + + elif self.type == 'dhcp': + if self.is_active is True: + self.content = 'iface {} inet dhcp\n'.format(self.name) + else: + self.content = '#iface {} inet dhcp\n'.format(self.name) + + if not line.startswith(self.content): + print(str(line).strip()) + + elif self.type == 'loopback': + if self.is_active is True: + self.content = 'iface {} inet loopback\n'.format(self.name) + else: + self.content = '#iface {} inet loopback\n'.format(self.name) + + if not line.startswith(self.content): + print(str(line).strip()) + else: + counter -= 1 + + self.logger.info('NETWORK-MANAGER - DELETE_NETWORK task is handled successfully.') + self.context.create_response(code=self.message_code.TASK_PROCESSED.value, + message='Ağ arayüzü başarıyla silindi.') + + except Exception as e: + self.logger.error( + 'A problem occured while handling NETWORK-MANAGER task: {0}'.format(str(e))) + self.context.create_response(code=self.message_code.TASK_ERROR.value, + message='NETWORK-MANAGER görevi uygulanırken bir hata oluştu.') + + +def handle_task(task, context): + network = DeleteNetwork(task, context) + network.handle_task() diff --git a/opt/ahenk/plugins/network-manager/get_network_information.py b/opt/ahenk/plugins/network-manager/get_network_information.py new file mode 100644 index 0000000..814b8b3 --- /dev/null +++ b/opt/ahenk/plugins/network-manager/get_network_information.py @@ -0,0 +1,54 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- +# Author:Mine DOGAN + +import json + +from base.plugin.abstract_plugin import AbstractPlugin + + +class NetworkInformation(AbstractPlugin): + def __init__(self, task, context): + super(NetworkInformation, self).__init__() + self.task = task + self.context = context + self.logger = self.get_logger() + self.message_code = self.get_message_code() + + self.nic_file = '/etc/network/interfaces' + self.hosts_file = '/etc/hosts' + self.dns_file = '/etc/resolv.conf' + self.hostname_file = '/etc/hostname' + + self.logger.debug('Parameters were initialized.') + + def handle_task(self): + try: + interfaces = self.read_file(self.nic_file) + self.logger.debug('Read interfaces file.') + + hosts = self.read_file(self.hosts_file) + self.logger.debug('Read hosts file.') + + dns = self.read_file(self.dns_file) + self.logger.debug('Read dns file.') + + machine_hostname = self.read_file(self.hostname_file) + self.logger.debug('Read hostname file.') + + self.logger.info('NETWORK-MANAGER task is handled successfully.') + self.context.create_response(code=self.message_code.TASK_PROCESSED.value, + message='Ağ dosyaları başarıyla okundu.', + data=json.dumps({'interfaces': interfaces, 'hosts': hosts, 'dns': dns, + 'machine_hostname': machine_hostname}), + content_type=self.get_content_type().APPLICATION_JSON.value) + + except Exception as e: + self.logger.error('A problem occured while handling NETWORK-MANAGER task: {0}'.format(str(e))) + self.context.create_response(code=self.message_code.TASK_ERROR.value, + message='NETWORK-MANAGER görevi uygulanırken bir hata oluştu.') + + +def handle_task(task, context): + ni = NetworkInformation(task, context) + ni.handle_task() diff --git a/opt/ahenk/plugins/network-manager/main.py b/opt/ahenk/plugins/network-manager/main.py new file mode 100644 index 0000000..04e85b2 --- /dev/null +++ b/opt/ahenk/plugins/network-manager/main.py @@ -0,0 +1,15 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- + +def info(): + inf = dict() + inf['name'] = 'network-manager' + inf['version'] = '1.0.0' + inf['support'] = 'debian' + inf['description'] = 'Network-Manager plugin provides to managing host, domain, dns and other network settings.' + inf['task'] = True + inf['user_oriented'] = False + inf['machine_oriented'] = False + inf['developer'] = 'mine.dogan@agem.com.tr' + + return inf \ No newline at end of file diff --git a/opt/ahenk/plugins/package-manager/check_package.py b/opt/ahenk/plugins/package-manager/check_package.py new file mode 100644 index 0000000..490ceef --- /dev/null +++ b/opt/ahenk/plugins/package-manager/check_package.py @@ -0,0 +1,63 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Author: Cemre ALPSOY + +import json + +from base.plugin.abstract_plugin import AbstractPlugin + + +class CheckPackage(AbstractPlugin): + def __init__(self, data, context): + super(AbstractPlugin, self).__init__() + self.data = data + self.context = context + self.logger = self.get_logger() + self.message_code = self.get_message_code() + + def handle_task(self): + try: + package_name = str((self.data)['packageName']) + package_version = str((self.data)['packageVersion']) + dn = self.Ahenk.dn() + res = {} + if dn is None: + dn = " " + result_code, result, p_err = self.execute('dpkg -s {} | grep Version'.format(package_name)) + data = result.split(': ') + self.logger.debug(data) + + if data[0] == 'Version': # Package is installed + if package_version is None or len(package_version) == 0: + result = 'Paket yüklü' + res['version'] = data[1] + elif data[1] is not None and (package_version + '\n') in data[ + 1]: # Package version is the same with wanted version + result = 'Paket yüklü' + res['version'] = data[1] + else: + result = 'Paket yüklü; fakat başka bir versiyonla' + res['version'] = data[1] + else: # Package is not installed + result = 'Paket yüklü değil' + res['version'] = '' + + res["dn"] = dn + res["res"] = result + + self.logger.debug("Result is: - {}".format(result)) + self.context.create_response(code=self.message_code.TASK_PROCESSED.value, + message='{0} - {1}'.format(package_name, result), + data=json.dumps(res), + content_type=self.get_content_type().APPLICATION_JSON.value) + self.logger.debug("Package Info has sent") + except Exception as e: + self.logger.debug(str(e)) + self.context.create_response(code=self.message_code.TASK_ERROR.value, + message='Paket Bilgilerini transferde beklenmedik hata!', + content_type=self.get_content_type().APPLICATION_JSON.value) + + +def handle_task(task, context): + plugin = CheckPackage(task, context) + plugin.handle_task() diff --git a/opt/ahenk/plugins/package-manager/get_execution_info.py b/opt/ahenk/plugins/package-manager/get_execution_info.py new file mode 100644 index 0000000..6c9f5b3 --- /dev/null +++ b/opt/ahenk/plugins/package-manager/get_execution_info.py @@ -0,0 +1,247 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Author: Cemre ALPSOY + +import json + +from base.plugin.abstract_plugin import AbstractPlugin + + +class GetExecutionInfo(AbstractPlugin): + def __init__(self, data, context): + super(AbstractPlugin, self).__init__() + self.data = data + self.context = context + self.logger = self.get_logger() + self.message_code = self.get_message_code() + self.command_execution_statistic_list = [] + self.version_list = [] + self.result_message = '' + self.commands = [] + self.logger.debug('Execution info initialized') + self.temp_file_name = str(self.generate_uuid()) + self.file_path = '{0}{1}'.format(str(self.Ahenk.received_dir_path()), self.temp_file_name) + self.isRecordExist = 1 + + def handle_task(self): + + self.logger.debug('Task handling') + try: + result_record_number = None + commands = self.data['command'] + user = self.data['user'] + is_strict_match = self.data['isStrictMatch'] + self.create_file(self.file_path) + # if commands fields is not empty + if commands: + if is_strict_match is False: + lastcomm_command = 'lastcomm ' + for command in commands.split(): + lastcomm_command += ' --command {0} '.format(command) + if user: + lastcomm_command += " --user {}".format(user) + self.logger.debug( + ' {0} command will be executed'.format(lastcomm_command)) + result_code, result, error = self.execute(lastcomm_command + ' > /tmp/result.txt') + self.logger.debug( + ' {0} command is executed'.format(lastcomm_command)) + result_record_number = self.check_output(result_code) + else: + for command in commands.split(): + self.logger.debug(command) + lastcomm_command = 'lastcomm --command {0} '.format(command) + if user: + lastcomm_command += " --user {}".format(user) + lastcomm_command += " --strict-match" + self.logger.debug(' {0} command will be executed'.format( + lastcomm_command)) + result_code, result, error = self.execute(lastcomm_command + ' > /tmp/result.txt') + self.logger.debug( + ' {0} command is executed'.format(lastcomm_command)) + result_record_number = self.check_output(result_code) + # if command does not exist and user is exist + elif user: + lastcomm_command = 'lastcomm --user {0} '.format(user) + if is_strict_match is True: + lastcomm_command += ' --strict-match' + self.logger.debug( + ' {0} command will be executed'.format(lastcomm_command)) + result_code, result, error = self.execute(lastcomm_command + ' > /tmp/result.txt') + self.logger.debug( + ' {0} command is executed + result_code = {1}'.format( + lastcomm_command, result_code) + ' > /tmp/result.txt') + result_record_number = self.check_output(result_code) + + # Record not found + if result_record_number is None: + self.context.create_response(code=self.message_code.TASK_ERROR.value, + message='İstenilene uygun veri bulunamadı') + elif self.is_exist(self.file_path): + self.execute("sed -i '$ d' " + self.file_path) + self.execute('echo "]," >> ' + self.file_path) + self.execute('echo \\"versionList\\" :[ >> ' + self.file_path) + for command_name in self.commands: + self.check_version_list(command_name) + self.execute('echo "]" >> ' + self.file_path) + self.execute('echo "}" >> ' + self.file_path) + data = {} + md5sum = self.get_md5_file(str(self.file_path)) + self.logger.debug('{0} renaming to {1}'.format(self.temp_file_name, md5sum)) + self.rename_file(self.file_path, self.Ahenk.received_dir_path() + '/' + md5sum) + self.logger.debug('Renamed.') + data['md5'] = md5sum + self.context.create_response(code=self.message_code.TASK_PROCESSED.value, + message='Uygulama çalıştırma bilgileri başarıyla sisteme geçirildi.', + data=json.dumps(data), + content_type=self.get_content_type().TEXT_PLAIN.value) + self.logger.debug("Execution Info fetched succesfully. ") + self.logger.debug("Execution Info has sent") + else: + raise Exception('File not found on this path: {}'.format(self.file_path)) + + except Exception as e: + self.logger.debug( + ' Unexpected error in get_execution.py. Error message : {0}'.format( + str(e))) + self.context.create_response(code=self.message_code.TASK_ERROR.value, + message='Uygulama çalıştırma bilgilerini getirirken beklenmedik hata!') + + def check_version_list(self, command): + is_exist = False + for version in self.version_list: + if version.commandName == command: + is_exist = True + if not is_exist: + result_code, result, p_err = self.execute('whereis {0}'.format(command)) + if result_code == 0 and "komut yok" not in result and len(result.split(':')) >= 2 and result[ + len(result) - 2] != ':': + self.logger.debug('SON HARF' + str(result[len(result) - 2])) + result = result.split(':')[1] + if result.split() is None or len(result.split()) == 0: + self.logger.debug(' Command installed place is not found') + self.result_message += 'Command {0} could not found'.format(command) + else: + if len(self.version_list) > 0: + self.execute('echo , >> ' + self.file_path) + self.logger.debug(' Command installed place is found') + + self.logger.debug(' Result = {0}'.format(str(result))) + result = result.split() + self.logger.debug(' Result split= {0}'.format(str(result))) + result = result[0] + self.logger.debug( + ' Result split 0 = {0}'.format(str(result))) + + result_code, result, p_err = self.execute('dpkg-query -S {0}'.format(result)) + if result_code == 0: # Command exists + self.logger.debug( + ' Command related package name is found') + result = result.split(': ')[0] + result_code, p_result, p_err = self.execute('dpkg -s {0} | grep Version'.format(result)) + if result_code == 0: + res = p_result.splitlines() + self.logger.debug( + ' Command related package version is found') + t_command = 'echo "{ \\"c\\": \\"' + command + '\\", \\"p\\": \\"' + result + '\\", \\"v\\":\\"' + \ + res[0].split(': ')[1] + '\\"}" >> ' + self.file_path + self.logger.debug( + ' Command is : {0}'.format(t_command)) + self.execute(t_command) + self.logger.debug( + ' Appending to version list') + self.version_list.append(VersionInfoItem(command, result, res[0].split(': ')[1])) + else: + self.logger.debug( + ' Command related package version is not found') + self.result_message += 'Command\'s related package version could not be parsed(Deb : {0}).'.format( + result) + t_command = 'echo "{ \\"c\\": \\"' + command + '\\", \\"p\\": \\"' + result + '\\", \\"v\\":\\" - \\"}" >> ' + self.file_path + self.logger.debug( + ' Command is : {0}'.format(t_command)) + self.execute(t_command) + self.logger.debug( + ' Appending to version list') + self.version_list.append(VersionInfoItem(command, result, '-')) + else: # command not exists + self.logger.debug( + ' Command related package name is not found') + self.result_message += 'Command\'s related package could not be found(Command : {0})'.format( + result) + t_command = 'echo "{ \\"c\\": \\"' + command + '\\", \\"p\\": \\" - \\", \\"v\\":\\" - \\"}" >> ' + self.file_path + self.logger.debug( + ' Command is : {0}'.format(t_command)) + self.execute(t_command) + self.logger.debug( + ' Appending to version list') + self.version_list.append(VersionInfoItem(command, '-', '-')) + else: # command not exists + self.logger.debug(' Command installed place is not found') + self.result_message += 'Command {0} could not found'.format(command) + + def check_output(self, result_code): + try: + if result_code == 0: + self.logger.debug( + ' lastcomm execution has returned with no error') + f = open("/tmp/result.txt", "r") + lines = f.readlines() + i = 0 + for line in lines: + if self.isRecordExist == 1: + self.execute('echo { \\"commandExecutionInfoList\\" :[ >> ' + self.file_path) + self.logger.debug(' line parsing has done') + output_columns = line.split() + self.logger.debug(' Column parsing has done') + command_name = output_columns[0] + user = output_columns[len(output_columns) - 8] + process_time = output_columns[len(output_columns) - 6] + start_date = output_columns[len(output_columns) - 4] + ' ' + output_columns[ + len(output_columns) - 3] + ' ' + output_columns[len(output_columns) - 2] + ' ' + \ + output_columns[len(output_columns) - 1] + self.logger.debug( + ' CommandExecutionInfoItem attributes are ready for adding to result list') + self.execute( + 'echo "{ \\"p\\": \\"' + process_time + '\\", \\"c\\": \\"' + command_name + '\\", \\"u\\":\\"' + user + '\\", \\"s\\":\\"' + start_date + '\\"}" >> ' + self.file_path) + self.logger.debug( + ' CommandExecutionInfoItem is created and added to result list') + self.commands.append(command_name) + self.logger.debug(str(len(lines)) + '------------' + str(i)) + self.execute('echo "," >> ' + self.file_path) + self.isRecordExist += 1 + i += 1 + if i >= 1: + return 'Basarili' + if self.isRecordExist > 0: + return 'Basarili' + return None + else: + self.logger.debug( + ' lastcomm command has not return with a result') + self.context.create_response(code=self.message_code.TASK_ERROR.value, + message='Uygulama çalıştırma bilgilerini getirirken beklenmedik hata!') + return None + + except Exception as e: + self.logger.debug('[ PACKAGE MANAGER ]Error in check_output method {}'.format(str(e))) + self.context.create_response(code=self.message_code.TASK_ERROR.value, + message='Uygulama çalıştırma bilgilerini getirirken beklenmedik hata!') + + +class VersionInfoItem: + def __init__(self, command_name, package_name, package_version): + self.commandName = command_name + self.packageName = package_name + self.packageVersion = package_version + + +class CommandExecutionInfoItem: + def __init__(self, command_name, user, process_time, start_date): + self.commandName = command_name + self.user = user + self.processTime = process_time + self.startDate = start_date + + +def handle_task(task, context): + plugin = GetExecutionInfo(task, context) + plugin.handle_task() diff --git a/opt/ahenk/plugins/package-manager/init.py b/opt/ahenk/plugins/package-manager/init.py new file mode 100644 index 0000000..acda1aa --- /dev/null +++ b/opt/ahenk/plugins/package-manager/init.py @@ -0,0 +1,46 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- + +from base.plugin.abstract_plugin import AbstractPlugin + + +class Init(AbstractPlugin): + def __init__(self, context): + super(Init, self).__init__() + self.context = context + self.logger = self.get_logger() + + def handle_mode(self): + try: + if self.is_installed('chkconfig') is False: + result_code, result, error = self.install_with_apt_get('chkconfig') + if result_code != 0: + self.logger.error('Package chkconfig can not be installed') + else: + self.logger.debug("[PACKAGE MANAGER -INIT] Package chkconfig installed successfully") + if self.is_installed('acct') is False: + result_code, result, error = self.install_with_apt_get('acct') + if result_code != 0: + self.logger.error("Package acct can not be installed") + else: + self.logger.debug("Package acct installed successfully") + except Exception as e: + self.logger.error('Error while installing chkconfig and acct packages. Error message : {0}'.format(str(e))) + result_code, result, error = self.execute('chkconfig acct on') + try: + if result_code == 0: + result_code, result, error = self.execute('/etc/init.d/acct start') + if result_code == 0: + self.logger.debug('acct service started successfully') + else: + self.logger.error( + 'acct service could not be started - Error while executing /etc/init.d/acct start command') + else: + self.logger.error('chkconfig acct on command could not executed') + except Exception as e: + self.logger.error('Error while starting acct service. Error message : {0}'.format(str(e))) + + +def handle_mode(context): + init = Init(context) + init.handle_mode() diff --git a/opt/ahenk/plugins/package-manager/installed_packages.py b/opt/ahenk/plugins/package-manager/installed_packages.py new file mode 100644 index 0000000..5865194 --- /dev/null +++ b/opt/ahenk/plugins/package-manager/installed_packages.py @@ -0,0 +1,53 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Author: Cemre ALPSOY + +import json + +from base.plugin.abstract_plugin import AbstractPlugin + + +class InstalledPackages(AbstractPlugin): + def __init__(self, data, context): + super(AbstractPlugin, self).__init__() + self.data = data + self.context = context + self.logger = self.get_logger() + self.message_code = self.get_message_code() + + self.temp_file_name = str(self.generate_uuid()) + self.file_path = '{0}{1}'.format(str(self.Ahenk.received_dir_path()), self.temp_file_name) + + def handle_task(self): + try: + self.logger.debug('Executing command for package list.') + self.execute( + 'dpkg-query -f=\'${{Status}},${{binary:Package}},${{Version}}\n\' -W \'*\' | sed \'s/install ok installed/i/\' | sed \'s/unknown ok not-installed/u/\' | sed \'s/deinstall ok config-files/u/\' | grep -v ahenk > {0}'.format( + self.file_path)) + self.logger.debug('Command executed.') + + if self.is_exist(self.file_path): + data = {} + md5sum = self.get_md5_file(str(self.file_path)) + self.logger.debug('{0} renaming to {1}'.format(self.temp_file_name, md5sum)) + self.rename_file(self.file_path, self.Ahenk.received_dir_path() + '/' + md5sum) + self.logger.debug('Renamed.') + data['md5'] = md5sum + json_data = json.dumps(data) + self.context.create_response(code=self.message_code.TASK_PROCESSED.value, + message='Paket listesi başarıyla okundu.', + data=json_data, content_type=self.get_content_type().TEXT_PLAIN.value) + self.logger.debug('Package list created successfully') + else: + raise Exception('File not found on this path: {}'.format(self.file_path)) + + except Exception as e: + self.logger.error(str(e)) + self.context.create_response(code=self.message_code.TASK_ERROR.value, + message='Paket listesi oluşturulurken hata oluştu: ' + str(e), + content_type=self.get_content_type().APPLICATION_JSON.value) + + +def handle_task(task, context): + plugin = InstalledPackages(task, context) + plugin.handle_task() diff --git a/opt/ahenk/plugins/package-manager/main.py b/opt/ahenk/plugins/package-manager/main.py new file mode 100644 index 0000000..d1a9c3c --- /dev/null +++ b/opt/ahenk/plugins/package-manager/main.py @@ -0,0 +1,16 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- + + +def info(): + inf = dict() + inf['name'] = 'package-manager' + inf['version'] = '1.0.0' + inf['support'] = 'debian' + inf['description'] = 'General repository and package operations (like repo/package installing/uninstalling, searching repo/package...etc)' + inf['task'] = True + inf['user_oriented'] = False + inf['machine_oriented'] = False + inf['developer'] = 'cemre.alpsoy@agem.com.tr' + + return inf diff --git a/opt/ahenk/plugins/package-manager/package_archive.py b/opt/ahenk/plugins/package-manager/package_archive.py new file mode 100644 index 0000000..9e68c56 --- /dev/null +++ b/opt/ahenk/plugins/package-manager/package_archive.py @@ -0,0 +1,44 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Author: Cemre ALPSOY + +from base.plugin.abstract_plugin import AbstractPlugin + + +class PackageArchive(AbstractPlugin): + def __init__(self, data, context): + super(AbstractPlugin, self).__init__() + self.data = data + self.context = context + self.logger = self.get_logger() + self.message_code = self.get_message_code() + + def handle_task(self): + self.logger.debug('Handling Package Archive Task') + try: + resultMessage = '' + package_name = str((self.data)['packageName']) + package_version = str((self.data)['packageVersion']) + self.logger.debug("Installing new package... {0}".format(package_name)) + result_code, p_result, p_err = self.install_with_apt_get(package_name, package_version) + if result_code == 0: + resultMessage += 'Paket başarıyla kuruldu - {0}={1}'.format(package_name, package_version) + self.logger.debug(resultMessage) + self.context.create_response(code=self.message_code.TASK_PROCESSED.value, + message=resultMessage) + else: + self.logger.debug(resultMessage) + self.context.create_response(code=self.message_code.TASK_ERROR.value, + message='Önceki paket sürümü kurulumunda beklenmedik hata!', + content_type=self.get_content_type().APPLICATION_JSON.value) + + except Exception as e: + self.logger.debug(str(e)) + self.context.create_response(code=self.message_code.TASK_ERROR.value, + message='Önceki paket sürümü kurulumunda beklenmedik hata!', + content_type=self.get_content_type().APPLICATION_JSON.value) + + +def handle_task(task, context): + plugin = PackageArchive(task, context) + plugin.handle_task() diff --git a/opt/ahenk/plugins/package-manager/package_management.py b/opt/ahenk/plugins/package-manager/package_management.py new file mode 100644 index 0000000..534170b --- /dev/null +++ b/opt/ahenk/plugins/package-manager/package_management.py @@ -0,0 +1,87 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Author: Cemre ALPSOY + +import json + +from base.plugin.abstract_plugin import AbstractPlugin + + +class PackageManagement(AbstractPlugin): + def __init__(self, data, context): + super(AbstractPlugin, self).__init__() + self.data = data + self.context = context + self.logger = self.get_logger() + self.message_code = self.get_message_code() + + def handle_task(self): + try: + items = self.data['packageInfoList'] + result_message = '' + installed_packages = '' + uninstalled_packages = '' + failed_packages = '' + + for item in items: + + # Install package + if item['tag'] == 'i': + self.logger.debug("Installing package: {0}".format(item['packageName'])) + try: + result_code, p_result, p_err = self.install_with_apt_get(item['packageName'], item['version']) + if result_code == 0: + self.logger.debug("Installed package: {0}".format(item['packageName'])) + installed_packages += ' ' + item['packageName'] + else: + self.logger.debug("Couldnt Installed package: {0}".format(item['packageName'])) + failed_packages += ' ' + item['packageName'] + + except Exception as e1: + self.logger.error(str(e1)) + failed_packages += ' ' + item['packageName'] + + # Uninstall package + elif item['tag'] == 'u': + self.logger.debug("Uninstalling package: {0}".format(item['packageName'])) + try: + result_code, p_result, p_err = self.uninstall_package(item['packageName'], item['version']) + if result_code == 0: + self.logger.debug("Uninstalled package: {0}".format(item['packageName'])) + uninstalled_packages += ' ' + item['packageName'] + else: + self.logger.debug( + "Couldnt Uninstalled package: {0}".format(item['packageName'])) + failed_packages += ' ' + item['packageName'] + except Exception as e2: + self.logger.error(str(e2)) + failed_packages += ' ' + item['packageName'] + + # Result message + if installed_packages: + result_message += ' Kurulan paketler: (' + installed_packages + ' )' + if uninstalled_packages: + result_message += ' Kaldırılan paketler: (' + uninstalled_packages + ' )' + if failed_packages: + result_message += ' Hata alan paketler: (' + failed_packages + ' )' + self.context.create_response(code=self.message_code.TASK_ERROR.value, + message='Paket işlemleri sırasında hata oluştu: ' + result_message, + data=json.dumps({'Result': result_message}), + content_type=self.get_content_type().APPLICATION_JSON.value) + else: + self.context.create_response(code=self.message_code.TASK_PROCESSED.value, + message='Paket işlemleri başarıyla gerçekleştirildi: ' + result_message, + data=json.dumps({'Result': result_message}), + content_type=self.get_content_type().APPLICATION_JSON.value) + # TODO return package list! + + except Exception as e: + self.logger.error(str(e)) + self.context.create_response(code=self.message_code.TASK_ERROR.value, + message='Paket kur/kaldır işlemleri gerçekleştirilirken hata oluştu:' + str(e), + content_type=self.get_content_type().APPLICATION_JSON.value) + + +def handle_task(task, context): + plugin = PackageManagement(task, context) + plugin.handle_task() diff --git a/opt/ahenk/plugins/package-manager/package_sources.py b/opt/ahenk/plugins/package-manager/package_sources.py new file mode 100644 index 0000000..c3e0d68 --- /dev/null +++ b/opt/ahenk/plugins/package-manager/package_sources.py @@ -0,0 +1,79 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Author: Cemre ALPSOY + +import json + +from base.plugin.abstract_plugin import AbstractPlugin + + +class PackageSources(AbstractPlugin): + def __init__(self, data, context): + super(AbstractPlugin, self).__init__() + self.data = data + self.context = context + self.logger = self.get_logger() + self.message_code = self.get_message_code() + + def handle_task(self): + added_items = self.data['addedItems'] + deleted_items = self.data['deletedItems'] + error_message = "" + try: + # Add desired repositories + for item in added_items: + command = '(find /etc/apt/ -name \*.list -type f | xargs grep -q \'' + str( + item) + '\') || echo \'' + str(item) + '\' >> /etc/apt/sources.list.d/liderahenk.list' + result_code, p_out, p_err = self.execute(command) + if result_code != 0: + self.logger.error("Error occurred while adding repository: " + str(p_err)) + error_message += " Paket deposu eklenirken hata oluştu: " + str(p_err) + self.logger.debug("Added repositories") + + # Remove desired repositories + for item in deleted_items: + command = 'find /etc/apt/ -name \*.list -type f -exec sed -i \'/' + str(item).replace("/", + "\\/") + '/d\' \{\} \;' + result_code, p_out, p_err = self.execute(command) + + if result_code != 0: + self.logger.error("Error occurred while removing repository: " + str(p_err)) + error_message += " Paket deposu silinirken hata oluştu: " + str(p_err) + self.logger.debug("Removed repositories") + + # Update package lists + self.execute('apt-get update') + self.logger.debug("Updated package lists") + + # Read package repositories + command = '/bin/bash {0}package-manager/scripts/sourcelist.sh'.format(self.Ahenk.plugins_path()) + result_code, p_out, p_err = self.execute(command) + data = {} + + if result_code != 0: + self.logger.error("Error occurred while listing repositories: " + str(p_err)) + error_message += " Paket depoları okunurken hata oluştu: " + str(p_err) + else: + data['packageSource'] = p_out + self.logger.debug("Repositories are listed") + + if not error_message: + self.context.create_response(code=self.message_code.TASK_PROCESSED.value, + message='Paket depoları başarıyla güncellendi.', + data=json.dumps(data), + content_type=self.get_content_type().APPLICATION_JSON.value) + else: + self.context.create_response(code=self.message_code.TASK_ERROR.value, + message=error_message, + content_type=self.get_content_type().APPLICATION_JSON.value) + + except Exception as e: + self.logger.debug(str(e)) + self.context.create_response(code=self.message_code.TASK_ERROR.value, + message="Paket depoları güncellenirken hata oluştu: " + str(e), + content_type=self.get_content_type().APPLICATION_JSON.value) + + +def handle_task(task, context): + plugin = PackageSources(task, context) + plugin.handle_task() diff --git a/opt/ahenk/plugins/package-manager/packages.py b/opt/ahenk/plugins/package-manager/packages.py new file mode 100644 index 0000000..959c3b0 --- /dev/null +++ b/opt/ahenk/plugins/package-manager/packages.py @@ -0,0 +1,133 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Author: Cemre ALPSOY + +import os +from glob import glob + +from base.plugin.abstract_plugin import AbstractPlugin + + +class Packages(AbstractPlugin): + def __init__(self, data, context): + super(AbstractPlugin, self).__init__() + self.data = data + self.context = context + self.logger = self.get_logger() + self.message_code = self.get_message_code() + + def handle_task(self): + self.logger.debug('Handling Packages Task') + try: + cn = '{0}\r\n'.format(self.Ahenk.dn().split(',')[0]) + + items = (self.data)['packageInfoList'] + for item in items: + try: + if self.has_attr_json(item, 'tag') and self.has_attr_json(item, 'source'): + array = item['source'].split() + source = ' ' + source = source.join(array) + + ## REPO ADD / CHECK + + self.logger.debug( + "Checking source {0}".format(item['source'])) + + if self.is_repo_exist(source): + self.logger.debug('{0} Source already exists'.format(source)) + else: + self.logger.debug('Source adding...') + try: + self.add_source(source) + except Exception as e: + self.logger.error('Source could not added') + self.context.create_response(code=self.message_code.TASK_ERROR.value, + message='{0}\n Kaynaklar eklenmeye çalışırken hata oluştu. Hata Mesajı:{1}'.format( + cn, str(e))) + return + + self.logger.debug('{0} Source added'.format(source)) + + return_code_update, result_update, error_update = self.execute('apt-get update') + if return_code_update == 0: + self.logger.debug('Packages were updated') + else: + self.logger.error('Packages could not updated') + self.context.create_response(code=self.message_code.TASK_ERROR.value, + message='{0}\n Kaynaklar güncellenmeye çalışırken hata oluştu. Hata Mesajı: {1}'.format( + cn, str(error_update))) + return + + ## INSTALL/REMOVE PACKAGE + + if item['tag'] == 'Yükle' or item['tag'] == 'Install': + self.logger.debug( + "Installing new package... {0}".format(item['packageName'])) + result_code, p_result, p_err = self.install_with_apt_get(item['packageName'], + item['version']) + if result_code == 0: + self.logger.debug( + "Package installed : {0}={1}".format(item['packageName'], + item['version'])) + else: + self.logger.error( + "Package could not be installed : {0}={1} " + ". Error Message:{2}".format( + item['packageName'], item['version'], str(p_err))) + self.context.create_response(code=self.message_code.TASK_ERROR.value, + message='{0}\n Source eklendi fakat paket kurulurken ' + 'hata oluştu. Hata Mesajı: {1}'.format( + cn, str(p_err))) + return + elif item['tag'] == 'Kaldır' or item['tag'] == 'Uninstall': + result_code, p_result, p_err = self.uninstall_package(item['packageName'], + item['version']) + + if result_code == 0: + self.logger.debug( + "Package installed : {0}={1}".format(item['packageName'], + item['version'])) + else: + self.logger.error( + "Package could not be installed : {0}={1}".format( + item['packageName'], + item['version'])) + self.context.create_response(code=self.message_code.TASK_ERROR.value, + message='{0}\n Paket kaldırılırken ' + 'hata oluştu. Hata Mesajı: {1}'.format( + cn, str(p_err))) + except Exception as e: + self.logger.error('Unpredictable error exists. Error Message: {0}'.format(str(e))) + self.context.create_response(code=self.message_code.TASK_ERROR.value, + message='{0}.\nÖngörülemeyen bir hata oluştu.Hata mesajı:{1}'.format( + cn, str(e))) + return + + self.logger.debug('Task handled successfully') + self.context.create_response(code=self.message_code.TASK_PROCESSED.value, + message='{0}\nTüm paket işlemleri başarıyla çalıştırıldı'.format(cn)) + except Exception as e: + self.logger.error('Unpredictable error exists. Error Message: {0}'.format(str(e))) + self.context.create_response(code=self.message_code.TASK_ERROR.value, + message='{0}\nGörev çalıştırılırken beklenmedik bir hata oluştu. Hata Mesajı: {1}'.format( + cn, + str(e))) + + def is_repo_exist(self, source): + if source in open('/etc/apt/sources.list').read(): + return True + + for f_list_path in glob('/etc/apt/sources.list.d/*'): + if os.path.isfile(f_list_path): + if source in open(f_list_path).read(): + return True + return False + + def add_source(self, source): + self.write_file('/etc/apt/sources.list.d/ahenk.list', source, 'a+') + + +def handle_task(task, context): + plugin = Packages(task, context) + plugin.handle_task() diff --git a/opt/ahenk/plugins/package-manager/repositories.py b/opt/ahenk/plugins/package-manager/repositories.py new file mode 100644 index 0000000..a38b338 --- /dev/null +++ b/opt/ahenk/plugins/package-manager/repositories.py @@ -0,0 +1,50 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Author: Cemre ALPSOY + +import json + +from base.plugin.abstract_plugin import AbstractPlugin + + +class PackageSourcesList(AbstractPlugin): + def __init__(self, data, context): + super(AbstractPlugin, self).__init__() + self.data = data + self.context = context + self.logger = self.get_logger() + self.message_code = self.get_message_code() + + def handle_task(self): + error_message = "" + try: + result_code, p_out, p_err = self.execute( + '/bin/bash {}package-manager/scripts/sourcelist.sh'.format(self.Ahenk.plugins_path())) + data = {} + + if result_code != 0: + self.logger.error("Error occurred while listing repositories: " + str(p_err)) + error_message += " Paket depoları okunurken hata oluştu: " + str(p_err) + else: + data['packageSource'] = p_out + self.logger.debug("Repositories are listed") + + if not error_message: + self.context.create_response(code=self.message_code.TASK_PROCESSED.value, + message='Paket depoları başarıyla okundu.', + data=json.dumps(data), content_type=self.get_content_type().APPLICATION_JSON.value) + else: + self.context.create_response(code=self.message_code.TASK_ERROR.value, + message=error_message, + content_type=self.get_content_type().APPLICATION_JSON.value) + + except Exception as e: + self.logger.debug(str(e)) + self.context.create_response(code=self.message_code.TASK_ERROR.value, + message="Paket depoları okunurken hata oluştu: " + str(e), + content_type=self.get_content_type().APPLICATION_JSON.value) + + +def handle_task(task, context): + plugin = PackageSourcesList(task, context) + plugin.handle_task() diff --git a/opt/ahenk/plugins/package-manager/scripts/sourcelist.sh b/opt/ahenk/plugins/package-manager/scripts/sourcelist.sh new file mode 100755 index 0000000..28c4c9d --- /dev/null +++ b/opt/ahenk/plugins/package-manager/scripts/sourcelist.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +for APT in `find /etc/apt/ -name \*.list`; do + grep -Po "(?<=^deb\s).*?(?=#|$)" $APT | while read ENTRY ; do + HOST=`echo $ENTRY | cut -d/ -f3` + USER=`echo $ENTRY | cut -d/ -f4` + PPA=`echo $ENTRY | cut -d/ -f5` + echo deb ${ENTRY} + done +done diff --git a/opt/ahenk/plugins/package-manager/show_package_archive.py b/opt/ahenk/plugins/package-manager/show_package_archive.py new file mode 100644 index 0000000..6a7543e --- /dev/null +++ b/opt/ahenk/plugins/package-manager/show_package_archive.py @@ -0,0 +1,67 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Author: Cemre ALPSOY + +import json + +from base.plugin.abstract_plugin import AbstractPlugin + + +class ShowPackageArchive(AbstractPlugin): + def __init__(self, data, context): + super(AbstractPlugin, self).__init__() + self.data = data + self.context = context + self.logger = self.get_logger() + self.message_code = self.get_message_code() + + def handle_task(self): + try: + package_name = str((self.data)['packageName']) + self.logger.debug('Package Installation History query is executing...') + a, result, b = self.execute( + ' cat /var/log/dpkg*.log | grep {} | grep "install \|upgrade"'.format(package_name)) + data = {} + res = [] + message = "" + self.logger.debug('Package archive info is being parsed...') + + if result is not None: + result_lines = result.splitlines() + for line in result_lines: + result_array = line.split(' ') + obj = {"installationDate": '{0} {1}'.format(result_array[0], result_array[1]), + "version": result_array[5], "operation": result_array[2], + "packageName": (result_array[3].split(':'))[0]} + res.append(obj) + + if a == 0 and len(res) > 0: + data = {"Result": res} + message = 'Paket arşivi başarıyla getirildi' + + self.context.create_response(code=self.message_code.TASK_PROCESSED.value, + message=message, + data=json.dumps(data), + content_type=self.get_content_type().APPLICATION_JSON.value) + elif a != 0: + message = 'Paket bulunamadı' + self.context.create_response(code=self.message_code.TASK_ERROR.value, + message=message, + data=json.dumps(data), + content_type=self.get_content_type().APPLICATION_JSON.value) + else: + self.context.create_response(code=self.message_code.TASK_PROCESSED.value, + message=message, + data=json.dumps(data), + content_type=self.get_content_type().APPLICATION_JSON.value) + self.logger.debug('Getting Package Archive task is handled successfully') + except Exception as e: + self.logger.debug(str(e)) + self.context.create_response(code=self.message_code.TASK_ERROR.value, + message='Paket arşivi getirilirken beklenmedik hata!', + content_type=self.get_content_type().APPLICATION_JSON.value) + + +def handle_task(task, context): + plugin = ShowPackageArchive(task, context) + plugin.handle_task() diff --git a/opt/ahenk/plugins/remote-access/main.py b/opt/ahenk/plugins/remote-access/main.py new file mode 100644 index 0000000..ec4e026 --- /dev/null +++ b/opt/ahenk/plugins/remote-access/main.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# Author: > +# Author: Volkan Şahin + + +def info(): + inf = dict() + inf['name'] = 'remote-access' + inf['version'] = '1.0.0' + inf['support'] = 'debian' + inf[ + 'description'] = 'Remote Access provides controlling remote Ahenk machine simultaneously. It uses VNC technology.' + inf['task'] = True + inf['user_oriented'] = False + inf['machine_oriented'] = False + inf['developer'] = 'bm.volkansahin@gmail.com' + + return inf diff --git a/opt/ahenk/plugins/remote-access/setup-vnc-server.py b/opt/ahenk/plugins/remote-access/setup-vnc-server.py new file mode 100644 index 0000000..ae05581 --- /dev/null +++ b/opt/ahenk/plugins/remote-access/setup-vnc-server.py @@ -0,0 +1,115 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- +# Author:Mine DOGAN +# Author: Volkan Şahin + +from base64 import b64encode +from os import urandom +import json + +from base.plugin.abstract_plugin import AbstractPlugin + + +class SetupVnc(AbstractPlugin): + """docstring for SetupVnc""" + + def __init__(self, task, context): + super(AbstractPlugin, self).__init__() + self.task = task + self.context = context + self.logger = self.get_logger() + self.password = self.create_password(10) + self.port = self.get_port_number() + self.logger.debug('Parameters were initialized') + + def handle_task(self): + self.logger.debug('Handling task') + try: + self.run_vnc_server() + self.logger.info('VNC Server running') + ip_addresses = str(self.Hardware.Network.ip_addresses()).replace('[', '').replace(']', '').replace("'", '') + + data = {} + data['port'] = self.port + data['password'] = self.password + data['host'] = ip_addresses + + self.logger.debug('Response data created') + self.context.create_response(code=self.get_message_code().TASK_PROCESSED.value, + message='VNC başarılı bir şekilde yapılandırıldı!\nUzak makine kullanıcısının izni için lütfen bekleyiniz...', + data=json.dumps(data), + content_type=self.get_content_type().APPLICATION_JSON.value) + except Exception as e: + self.logger.error('A problem occurred while running VNC server. Error Message: {}'.format(str(e))) + self.context.create_response(code=self.get_message_code().TASK_ERROR.value, + message='VNC sunucusu çalışırken bir hata oluştu.') + + def run_vnc_server(self): + + self.logger.debug('Is VNC server installed?') + + if self.is_installed('x11vnc') is False: + self.logger.debug('VNC server not found, it is installing') + self.install_with_apt_get('x11vnc') + + self.logger.debug('VNC server was installed') + + self.logger.debug('Killing running VNC proceses') + self.execute("ps aux | grep x11vnc | grep 'port " + self.port + "' | awk '{print $2}' | xargs kill -9", + result=False) + self.logger.debug('Running VNC proceses were killed') + + self.logger.debug('Getting display and username...') + + arr = self.get_username_display() + + if len(arr) < 1: + raise NameError('Display not found!') + + params = str(arr[0]).split(' ') + + self.logger.debug('Username:{0} Display:{1}'.format(params[0], params[1])) + + if self.is_exist('/tmp/vncahenk{0}'.format(params[0])) is True: + self.logger.debug('Cleaning previous configurations.') + self.delete_folder('/tmp/vncahenk{0}'.format(params[0])) + + self.logger.debug('Creating user VNC conf file as user') + self.execute('su - {0} -c "mkdir -p /tmp/vncahenk{1}"'.format(params[0], params[0]), result=False) + + self.logger.debug('Creating password as user') + self.execute( + 'su - {0} -c "x11vnc -storepasswd {1} /tmp/vncahenk{2}/x11vncpasswd"'.format(params[0], self.password, + params[0]), result=False) + + self.logger.debug('Running VNC server as user.') + self.execute( + 'su - {0} -c "x11vnc -accept \'popup\' -rfbport {1} -rfbauth /tmp/vncahenk{2}/x11vncpasswd -o /tmp/vncahenk{3}/vnc.log -display :{4}"'.format( + params[0], self.port, params[0], params[0], params[1]), result=False) + + def get_username_display(self): + result_code, p_out, p_err = self.execute("who | awk '{print $1, $5}' | sed 's/(://' | sed 's/)//'", result=True) + + self.logger.debug('Getting display result code:{0}'.format(str(result_code))) + + result = [] + lines = str(p_out).split('\n') + for line in lines: + arr = line.split(' ') + if len(arr) > 1 and str(arr[1]).isnumeric() is True: + result.append(line) + return result + + def create_password(self, pass_range): + self.logger.debug('Password created') + random_bytes = urandom(pass_range) + return b64encode(random_bytes).decode('utf-8') + + def get_port_number(self): + self.logger.debug('Target port is 5999') + return '5999' + + +def handle_task(task, context): + vnc = SetupVnc(task, context) + vnc.handle_task() diff --git a/opt/ahenk/plugins/resource-usage/main.py b/opt/ahenk/plugins/resource-usage/main.py new file mode 100644 index 0000000..41743b8 --- /dev/null +++ b/opt/ahenk/plugins/resource-usage/main.py @@ -0,0 +1,16 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- + + +def info(): + inf = dict() + inf['name'] = 'resource-usage' + inf['version'] = '1.0.0' + inf['support'] = 'debian' + inf['description'] = 'Resource Usage Info and Resource Usage Controls and Warnings are handled with this plugin' + inf['task'] = True + inf['user_oriented'] = False + inf['machine_oriented'] = False + inf['developer'] = 'cemre.alpsoy@agem.com.tr' + + return inf diff --git a/opt/ahenk/plugins/resource-usage/resource_info_alert.py b/opt/ahenk/plugins/resource-usage/resource_info_alert.py new file mode 100644 index 0000000..3a7f613 --- /dev/null +++ b/opt/ahenk/plugins/resource-usage/resource_info_alert.py @@ -0,0 +1,79 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Author: Cemre ALPSOY +# Author: Emre Akkaya + +from base.plugin.abstract_plugin import AbstractPlugin +from threading import Thread +import time +import psutil +import json + + +class ResourceUsage(AbstractPlugin): + def __init__(self, data, context): + super(AbstractPlugin, self).__init__() + self.data = data + self.context = context + self.logger = self.get_logger() + self.message_code = self.get_message_code() + self.is_running = False + self._threadCep = None + + def handle_task(self): + try: + action = self.data['action'] + self.logger.debug("Action: {0}".format(action)) + + if action == "start_timer": + self.is_running = True + with open('is_running.txt', 'w') as f: + f.write("%s" % str('true')) + self._threadCep = Thread(target=self.run_timer, + args=(int(self.data['interval']), self.context.get('task_id'))) + self._threadCep.start() + data = {"status": "started"} + self.context.create_response(code=self.message_code.TASK_PROCESSED.value, + message='Kaynak kullanım bilgileri toplanmaya başlandı.', data=json.dumps(data), content_type=self.get_content_type().APPLICATION_JSON.value) + elif action == "stop_timer": + self.is_running = False + with open('is_running.txt', 'w') as f: + f.write("%s" % str('false')) + data = {"action": "stop"} + self.context.create_response(code=self.message_code.TASK_PROCESSED.value, + message='Kaynak kullanım bilgilerinin toplanması durduruldu.', + data=json.dumps(data), content_type=self.get_content_type().APPLICATION_JSON.value) + except Exception as e: + self.logger.error(str(e)) + self.context.create_response(code=self.message_code.TASK_ERROR.value, + message='Kaynak kullanım bilgileri işlenirken hata oluştu: ' + str(e)) + + def run_timer(self, interval, task_id): + while self.is_running: + self.gather_resource_usage(task_id) + time.sleep(interval) + with open('is_running.txt', 'r') as f: + if f.read() == 'false': + self.is_running = False + + def gather_resource_usage(self, task_id): + # Memory usage + memory_usage = psutil.virtual_memory() + self.logger.debug("Memory usage: {0}".format(memory_usage)) + # Disk usage + disk_usage = psutil.disk_usage('/') + self.logger.debug("Disk usage: {0}".format(disk_usage)) + # CPU usage + cpu_percentage = psutil.cpu_percent(interval=1) + self.logger.debug("CPU percentage: {0}".format(cpu_percentage)) + + data = {'memoryUsage': str(memory_usage), 'diskUsage': str(disk_usage), 'cpuPercentage': str(cpu_percentage)} + command = 'python3 /opt/ahenk/ahenkd.py send -t {0} -m {1} -s'.format(task_id, json.dumps(str(data))) + result_code, p_out, p_err = self.execute(command) + if result_code != 0: + self.logger.error("Error occurred while sending message: " + str(p_err)) + + +def handle_task(task, context): + plugin = ResourceUsage(task, context) + plugin.handle_task() diff --git a/opt/ahenk/plugins/resource-usage/resource_info_fetcher.py b/opt/ahenk/plugins/resource-usage/resource_info_fetcher.py new file mode 100644 index 0000000..d905f04 --- /dev/null +++ b/opt/ahenk/plugins/resource-usage/resource_info_fetcher.py @@ -0,0 +1,51 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Author: Cemre ALPSOY +# Author: Emre Akkaya + +from base.plugin.abstract_plugin import AbstractPlugin +import json + + +class ResourceUsage(AbstractPlugin): + def __init__(self, data, context): + super(AbstractPlugin, self).__init__() + self.data = data + self.context = context + self.logger = self.get_logger() + self.message_code = self.get_message_code() + + def handle_task(self): + try: + device = "" + self.logger.debug("Gathering resource usage for disk, memory and CPU.") + for part in self.Hardware.Disk.partitions(): + if len(device) != 0: + device += ", " + device = device + part.device + data = {'System': self.Os.name(), 'Release': self.Os.kernel_release(), + 'Version': self.Os.distribution_version(), 'Machine': self.Os.architecture(), + 'CPU Physical Core Count': self.Hardware.Cpu.physical_core_count(), + 'Total Memory': self.Hardware.Memory.total(), + 'Usage': self.Hardware.Memory.used(), + 'Total Disc': self.Hardware.Disk.total(), + 'Usage Disc': self.Hardware.Disk.used(), + 'Processor': self.Hardware.Cpu.brand(), + 'Device': device, + 'CPU Logical Core Count': self.Hardware.Cpu.logical_core_count(), + 'CPU Actual Hz': self.Hardware.Cpu.hz_actual(), + 'CPU Advertised Hz': self.Hardware.Cpu.hz_advertised() + } + self.logger.debug("Resource usage info gathered.") + self.context.create_response(code=self.message_code.TASK_PROCESSED.value, + message='Anlık kaynak kullanım bilgisi başarıyla toplandı.', + data=json.dumps(data), content_type=self.get_content_type().APPLICATION_JSON.value) + except Exception as e: + self.logger.error(str(e)) + self.context.create_response(code=self.message_code.TASK_ERROR.value, + message='Anlık kaynak kullanım bilgisi toplanırken hata oluştu: {0}'.format(str(e))) + + +def handle_task(task, context): + plugin = ResourceUsage(task, context) + plugin.handle_task() diff --git a/opt/ahenk/plugins/resource-usage/send_mail.py b/opt/ahenk/plugins/resource-usage/send_mail.py new file mode 100644 index 0000000..c381f72 --- /dev/null +++ b/opt/ahenk/plugins/resource-usage/send_mail.py @@ -0,0 +1,31 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Author: Cemre ALPSOY + +from base.plugin.abstract_plugin import AbstractPlugin +import json + + +class SendMail(AbstractPlugin): + def __init__(self, data, context): + super(AbstractPlugin, self).__init__() + self.data = data + self.context = context + self.logger = self.get_logger() + self.message_code = self.get_message_code() + + def handle_task(self): + try: + self.logger.debug("[RESOURCE USAGE] Send mail task is started.") + self.context.create_response(code=self.message_code.TASK_PROCESSED.value, + message='E posta gönderim bilgileri başarıyla iletildi', + data=json.dumps(self.data), content_type=self.get_content_type().APPLICATION_JSON.value) + except Exception as e: + self.logger.error(str(e)) + self.context.create_response(code=self.message_code.TASK_ERROR.value, + message='e posta gönderim bilgileri edinilirken hata oluştu: {0}'.format(str(e))) + + +def handle_task(task, context): + plugin = SendMail(task, context) + plugin.handle_task() diff --git a/opt/ahenk/plugins/resource-usage/shutdown.py b/opt/ahenk/plugins/resource-usage/shutdown.py new file mode 100644 index 0000000..d7a9505 --- /dev/null +++ b/opt/ahenk/plugins/resource-usage/shutdown.py @@ -0,0 +1,45 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- +# Author:Mine DOGAN + +from base.plugin.abstract_plugin import AbstractPlugin +from base.system.system import System +import json + + +class ShutDownMachine(AbstractPlugin): + def __init__(self, task, context): + super(AbstractPlugin, self).__init__() + self.task = task + self.context = context + self.logger = self.get_logger() + self.message_code = self.get_message_code() + + self.shut_down_command = 'sleep 5s; shutdown -h now' + + self.logger.debug('[RESOURCE USAGE - Shut Down Machine] Parameters were initialized.') + + def handle_task(self): + try: + self.logger.debug('[RESOURCE USAGE - Shut Down Machine] Shutting down the machine...') + self.execute(self.shut_down_command, result=False) + + response = 'Shutdown komutu başarıyla çalıştırıldı. Bilgisayar kapatılacak. Mac Adres(ler)i: {0}, Ip Adres(ler)i: {1}' \ + .format(System.Hardware.Network.mac_addresses(), System.Hardware.Network.ip_addresses()) + data = {"shutdown": "true"} + self.context.create_response(code=self.message_code.TASK_PROCESSED.value, + data=json.dumps(data), message=response, + content_type=self.get_content_type().APPLICATION_JSON.value) + self.logger.info('[SEOURCE USAGE - Shut Down Machine] task is handled successfully') + + except Exception as e: + self.logger.error( + '[RESOURCE USAGE - Shut Down Machine] A problem occured while handling Shutdown task: {0}'.format( + str(e))) + self.context.create_response(code=self.message_code.TASK_ERROR.value, + message='Makina kapatılırken bir hata oluştu: {0}'.format(str(e))) + + +def handle_task(task, context): + shut_down = ShutDownMachine(task, context) + shut_down.handle_task() diff --git a/opt/ahenk/plugins/rsyslog/main.py b/opt/ahenk/plugins/rsyslog/main.py new file mode 100644 index 0000000..23c42e1 --- /dev/null +++ b/opt/ahenk/plugins/rsyslog/main.py @@ -0,0 +1,16 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- + + +def info(): + inf = dict() + inf['name'] = 'rsyslog' + inf['version'] = '1.0.0' + inf['support'] = 'debian' + inf['description'] = 'System Log file configuration and rotation info are defined with this plugin.' + inf['task'] = False + inf['user_oriented'] = False + inf['machine_oriented'] = True + inf['developer'] = 'cemre.alpsoy@agem.com.tr' + + return inf diff --git a/opt/ahenk/plugins/rsyslog/policy.py b/opt/ahenk/plugins/rsyslog/policy.py new file mode 100644 index 0000000..2c392fa --- /dev/null +++ b/opt/ahenk/plugins/rsyslog/policy.py @@ -0,0 +1,116 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + + +# Author: Cemre ALPSOY + +import json + +from base.plugin.abstract_plugin import AbstractPlugin + + +class Rsyslog(AbstractPlugin): + def __init__(self, data, context): + super(AbstractPlugin, self).__init__() + self.data = data + self.context = context + self.logger = self.get_logger() + self.message_code = self.get_message_code() + self.rsyslog_path = '/etc/rsyslog.d/ahenk.conf' + self.default_config = "# /etc/rsyslog.conf\tConfiguration file for rsyslog.\n#\n#\t\t\tFor more information see\n#\t\t\t/usr/share/doc/rsyslog-doc/html/rsyslog_conf.html\n#\n# Default logging rules can be found in /etc/rsyslog.d/50-default.conf\n\n\n#################\n#### MODULES ####\n#################\n\n$ModLoad imuxsock # provides support for local system logging\n$ModLoad imklog # provides kernel logging support\n#$ModLoad immark # provides --MARK-- message capability\n\n# provides UDP syslog reception\n#$ModLoad imudp\n#$UDPServerRun 514\n\n# provides TCP syslog reception\n$ModLoad imtcp\n$InputTCPServerRun 514\n\n# Enable non-kernel facility klog messages\n$KLogPermitNonKernelFacility on\n\n###########################\n#### GLOBAL DIRECTIVES ####\n###########################\n\n#\n# Use traditional timestamp format.\n# To enable high precision timestamps, comment out the following line.\n#\n$ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat\n\n# Filter duplicated messages\n$RepeatedMsgReduction on\n\n#\n# Set the default permissions for all log files.\n#\n$FileOwner syslog\n$FileGroup adm\n$FileCreateMode 0640\n$DirCreateMode 0755\n$Umask 0022\n$PrivDropToUser syslog\n$PrivDropToGroup syslog\n\n#\n# Where to place spool and state files\n#\n$WorkDirectory /var/spool/rsyslog\n\n#\n# Include all config files in /etc/rsyslog.d/\n#\n$IncludeConfig /etc/rsyslog.d/*.conf\n\n#RULE_STR#\n\n#\n# Logging for the mail system. Split it up so that\n# it is easy to write scripts to parse these files.\n#\n#mail.info\t\t\t-/var/log/mail.info\n#mail.warn\t\t\t-/var/log/mail.warn\nmail.err\t\t\t/var/log/mail.err\n\n#\n# Logging for INN news system.\n#\nnews.crit\t\t\t/var/log/news/news.crit\nnews.err\t\t\t/var/log/news/news.err\nnews.notice\t\t\t-/var/log/news/news.notice\n\n#\n# Some \"catch-all\" log files.\n#\n#*.=debug;\\\n#\tauth,authpriv.none;\\\n#\tnews.none;mail.none\t-/var/log/debug\n#*.=info;*.=notice;*.=warn;\\\n#\tauth,authpriv.none;\\\n#\tcron,daemon.none;\\\n#\tmail,news.none\t\t-/var/log/messages\n\n#\n# Emergencies are sent to everybody logged in.\n#\n*.emerg :omusrmsg:*\n\n#\n# I like to have messages displayed on the console, but only on a virtual\n# console I usually leave idle.\n#\n#daemon,mail.*;\\\n#\tnews.=crit;news.=err;news.=notice;\\\n#\t*.=debug;*.=info;\\\n#\t*.=notice;*.=warn\t/dev/tty8\n\n# The named pipe /dev/xconsole is for the `xconsole\' utility. To use it,\n# you must invoke `xconsole\' with the `-file\' option:\n# \n# $ xconsole -file /dev/xconsole [...]\n#\n# NOTE: adjust the list below, or you\'ll go crazy if you have a reasonably\n# busy site..\n#\ndaemon.*;mail.*;\\\n\tnews.err;\\\n\t*.=debug;*.=info;\\\n\t*.=notice;*.=warn\t|/dev/xconsole" + self.rsyslog_conf = "" + self.remote_conf = "" + self.protocol = '@@' + + self.rsyslog_conf_file_path = '/etc/rsyslog.conf' + self.remote_conf_file_path = '/etc/rsyslog.d/remote.conf' + self.log_rotate_conf_file_path = '/etc/logrotate.conf' + + def handle_policy(self): + try: + if str(json.loads(self.data)['PROTOCOL']) == 'UDP': + self.protocol = '@' + self.logger.debug('Handling profile ...') + items = json.loads(self.data)['items'] + for item in items: + if str(item['isLocal']).upper() == 'EVET' or str(item['isLocal']).upper() == 'YES': + self.rsyslog_conf += str(item['recordDescription']) + '\t' + str(item['logFilePath']) + '\n' + else: + self.remote_conf += str(item['recordDescription']) + ' ' + self.protocol + str( + json.loads(self.data)['ADDRESS']) + ':' + str(json.loads(self.data)['PORT']) + '\n' + self.rsyslog_conf = self.default_config.replace("#RULE_STR#", self.rsyslog_conf) + self.logger.debug('Rsyslog config files are ready') + (result_code, p_out, p_err) = self.execute( + "find /etc/rsyslog.d/ -name '*.conf' -exec bash -c 'sudo mv ${0/conf/conf.orig}' {} \;", shell=True) + if str(result_code) == '0': + self.logger.debug('Backup up old config files.') + else: + self.logger.debug('Error while backing up old config files') + + rsyslog_conf_contents = str(self.rsyslog_conf).strip() + self.logger.debug(self.rsyslog_conf_file_path + ': \n' + rsyslog_conf_contents + '\n') + + config_file = open(self.rsyslog_conf_file_path, 'w+') + config_file.write(rsyslog_conf_contents) + config_file.close() + remote_conf_contents = str(self.remote_conf).strip() + # self.logger.debug(self.remote_conf_file_path + ': \n' + remote_conf_contents + '\n') + if remote_conf_contents and not remote_conf_contents.isspace(): + self.logger.debug('Updating remote.conf') + remote_config_file = open(self.remote_conf_file_path, 'w+') + remote_config_file.write(remote_conf_contents) + remote_config_file.close() + else: + self.logger.debug('CANNOT update remote.conf') + self.execute('service rsyslog restart', shell=True) + self.logger.debug('Rsyslog service restarted.') + self.logger.debug('Processing logrotate config') + rotation_interval = str(json.loads(self.data)['rotationInterval']) + keep_back_logs = str(json.loads(self.data)['keepBacklogs']) + max_size = str(json.loads(self.data)['maxSize']) + create_new_log_files = json.loads(self.data)['createNewLogFiles'] + compress_old_log_files = json.loads(self.data)['compressOldLogFiles'] + missing_ok = json.loads(self.data)['missingOk'] + f = open(self.log_rotate_conf_file_path, 'w') + if rotation_interval: + f.write(rotation_interval + '\n') + else: + f.write('weekly\n') + if keep_back_logs: + f.write('rotate ' + keep_back_logs + '\n') + else: + f.write('rotate 4\n') + if max_size: + f.write('maxsize ' + max_size + 'M\n') + if create_new_log_files: + f.write('create\n') + if compress_old_log_files: + f.write('compress\n') + if missing_ok: + f.write('missingok\n') + f.write('include /etc/logrotate.d\n') + f.close() + self.logger.debug('Rsyslog Profile Processed') + self.context.create_response(code=self.message_code.POLICY_PROCESSED.value, + message='Ajan Rsyslog Profili başarıyla uygulandı.', + content_type=self.get_content_type().APPLICATION_JSON.value) + except Exception as e: + self.logger.error( + 'A problem occurred while applying rsyslog profile. Error Message: {0}'.format(str(e))) + self.context.create_response(code=self.message_code.POLICY_ERROR.value, + message='Rsyslog Profili uygulanırken bir hata oluştu.', + content_type=self.get_content_type().APPLICATION_JSON.value) + + +def handle_policy(profile_data, context): + plugin = Rsyslog(profile_data, context) + plugin.handle_policy() + + +class Item(object): + record_description = "" + log_file_path = "" + + def __init__(self, record_description, log_file_path): + self.record_description = record_description + self.log_file_path = log_file_path diff --git a/opt/ahenk/plugins/screensaver/main.py b/opt/ahenk/plugins/screensaver/main.py new file mode 100644 index 0000000..e4d71a1 --- /dev/null +++ b/opt/ahenk/plugins/screensaver/main.py @@ -0,0 +1,16 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- + + +def info(): + inf = dict() + inf['name'] = 'screensaver' + inf['version'] = '1.0.0' + inf['support'] = 'debian' + inf['description'] = 'Screensaver plugin provides to changing Xscreensaver config file.' + inf['task'] = False + inf['user_oriented'] = True + inf['machine_oriented'] = True + inf['developer'] = 'mine.dogan@agem.com.tr' + + return inf \ No newline at end of file diff --git a/opt/ahenk/plugins/screensaver/policy.py b/opt/ahenk/plugins/screensaver/policy.py new file mode 100644 index 0000000..e91bfa1 --- /dev/null +++ b/opt/ahenk/plugins/screensaver/policy.py @@ -0,0 +1,82 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- +# Author: Mine Dogan + +import json + +from base.plugin.abstract_plugin import AbstractPlugin + + +class Screensaver(AbstractPlugin): + def __init__(self, data, context): + super(Screensaver, self).__init__() + self.data = data + self.context = context + self.logger = self.get_logger() + self.message_code = self.get_message_code() + + self.logger.debug('Parameters were initialized.') + + def user_xscreen_conf_path(self, username): + self.logger.debug('u1') + user_home_path = self.execute('echo $( getent passwd "{0}" | cut -d: -f6 )'.format(username))[1] + return '{0}/.xscreensaver'.format(user_home_path.strip()) + + def create_content(self): + data = json.loads(self.data) + self.logger.debug('c1') + return 'mode: {0}\ntimeout: {1}\ncycle: {2}\nlock: {3}\nlockTimeout: {4}\ngrabDesktopImages: {5}\n' \ + 'grabVideoFrames: {6}\ndpmsEnabled: {7}\ndpmsStandby: {8}\ndpmsSuspend: {9}\ndpmsOff: {10}' \ + '\ndpmsQuickOff: {11}\ntextMode: {12}\ntextLiteral: {13}\ntextUrl: {14}\nfade: {15}\nunfade:' \ + ' {16}\nfadeSeconds: {17}\ninstallColormap: {18}\n'.format(data['mode'], data['timeout'], + data['cycle'], data['lock'], + data['lockTimeout'], + data['grabDesktopImages'], + data['grabVideoFrames'], + data['dpmsEnabled'], + data['dpmsStandby'], + data['dpmsSuspend'], + data['dpmsOff'], + data['dpmsQuickOff'], + data['textMode'], + data['textLiteral'], + data['textUrl'], data['fade'], + data['unfade'], + data['fadeSeconds'], + data['installColormap']) + + def handle_policy(self): + + try: + username = self.context.get('username') + content = self.create_content() + + if username is not None: + xfile_path = self.user_xscreen_conf_path(username) + self.delete_file(xfile_path) + self.write_file(xfile_path, content, 'w+') + + self.logger.debug('Config file content: \n{0}'.format(content)) + self.execute('chown {0}:{0} {1}'.format(username, xfile_path)) + self.logger.debug('.xscreensaver owner is changed.') + self.logger.info('Screensaver profile is handled successfully for user.') + + else: + for user in self.Sessions.user_name(): + self.delete_file(self.user_xscreen_conf_path(user)) + self.write_file(self.user_xscreen_conf_path(user), content, 'w+') + # self.write_file('/etc/X11/app-defaults/XScreenSaver', content, 'w') + self.logger.error('Screensaver profile is handled successfully for machine.') + self.execute('xscreensaver-command -restart',as_user=self.context.get_username()) + self.context.create_response(code=self.message_code.POLICY_PROCESSED.value, + message='Kullanıcı screensaver profili başarıyla çalıştırıldı.') + + except Exception as e: + self.logger.error('A problem occured while handling screensaver profile: {0}'.format(str(e))) + self.context.create_response(code=self.message_code.POLICY_ERROR.value, + message='Screensaver profili çalıştırılırken bir hata oluştu.') + + +def handle_policy(profile_data, context): + screensaver = Screensaver(profile_data, context) + screensaver.handle_policy() \ No newline at end of file diff --git a/opt/ahenk/plugins/screenshot/main.py b/opt/ahenk/plugins/screenshot/main.py new file mode 100644 index 0000000..bf0732e --- /dev/null +++ b/opt/ahenk/plugins/screenshot/main.py @@ -0,0 +1,16 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- + + +def info(): + inf = dict() + inf['name'] = 'screenshot' + inf['version'] = '1.0.0' + inf['support'] = 'debian' + inf['description'] = '' + inf['task'] = True + inf['user_oriented'] = False + inf['machine_oriented'] = False + inf['developer'] = '' + + return inf diff --git a/opt/ahenk/plugins/screenshot/take-screenshot.py b/opt/ahenk/plugins/screenshot/take-screenshot.py new file mode 100644 index 0000000..38e280e --- /dev/null +++ b/opt/ahenk/plugins/screenshot/take-screenshot.py @@ -0,0 +1,145 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- +# Author: Mine DOGAN +# Author: Emre Akkaya + + +from base.plugin.abstract_plugin import AbstractPlugin +import json +import traceback + + +class TakeScreenshot(AbstractPlugin): + def __init__(self, data, context): + super(TakeScreenshot, self).__init__() + self.data = data + self.context = context + self.logger = self.get_logger() + self.message_code = self.get_message_code() + + self.temp_file_name = str(self.generate_uuid()) + self.shot_path = '{0}{1}'.format(str(self.Ahenk.received_dir_path()), self.temp_file_name) + self.take_screenshot = 'xwd -root -display :{0} | convert - jpg:- > ' + self.shot_path + + def handle_task(self): + try: + user_name = None + + if self.has_attr_json(self.data, self.Ahenk.dn()) and self.data[self.Ahenk.dn()] is not None: + user_name = self.data[self.Ahenk.dn()] + + if not user_name: + self.logger.debug('Taking screenshot with default display.') + arr = self.get_username_display() + self.logger.debug('Default username: {0} display: {1}'.format(arr[0], arr[1])) + if arr is None: + self.context.create_response(code=self.message_code.TASK_ERROR.value, + message='Ekran görüntüsü alırken hata oluştu: Varsayılan display\'e erişilemedi.') + return + + ##permission + self.logger.debug( + 'Asking for screenshot to user {0} on {1} display'.format(arr[0], arr[1])) + + user_answer = self.ask_permission(':'+arr[1], arr[0], + "Ekran görüntüsünün alınmasına izin veriyor musunuz?", + "Ekran Görüntüsü") + + if user_answer is None: + self.logger.error('User answer could not kept.') + self.context.create_response(code=self.message_code.TASK_ERROR.value, + message='Ekran görüntüsü alırken hata oluştu: Kullanıcı iznine erişilemedi.') + return + elif user_answer is True: + self.logger.debug('User accepted for screenshot') + self.logger.debug('Taking screenshot with specified display: {0}'.format(arr[1])) + self.logger.debug( + 'Executing take screenshot command with user: {0} and display: {1}'.format(arr[0], arr[1])) + self.logger.debug(str(self.take_screenshot.format(arr[1]))) + result_code, p_out, p_err = self.execute(self.take_screenshot.format(arr[1]), as_user=arr[0]) + + if result_code != 0: + self.logger.error( + 'A problem occurred while running take screenshot command with default display') + self.context.create_response(code=self.message_code.TASK_ERROR.value, + message='Ekran görüntüsü alırken hata oluştu: Komut başarıyla çalıştırılamadı.') + return + + else: + self.logger.warning('User decline to take screenshot.') + self.context.create_response(code=self.message_code.TASK_WARNING.value, + message='Eklenti başarıyla çalıştı; fakat kullanıcı ekran görüntüsü alınmasına izin vermedi.') + return + + else: + user_display = self.Sessions.display(user_name) + if not user_display: + user_display = '0' + + ##permission + self.logger.debug( + 'Asking for screenshot to user {0} on {1} display'.format(user_name, user_display)) + + user_answer = self.ask_permission(user_display, user_name, + "Ekran görüntüsünün alınmasına izin veriyor musunuz?", + "Ekran Görüntüsü") + + if user_answer is None: + self.logger.error('User answer could not kept.') + self.context.create_response(code=self.message_code.TASK_ERROR.value, + message='Ekran görüntüsü alırken hata oluştu: Kullanıcı iznine erişilemedi.') + return + + elif user_answer is True: + self.logger.debug('User accepted for screenshot') + self.logger.debug('Taking screenshot with specified display: {0}'.format(user_display)) + + self.execute(self.take_screenshot.format(user_display.replace(':', '')), as_user=user_name) + + self.logger.debug('Screenshot command executed.') + else: + self.logger.warning('User decline to take screenshot.') + self.context.create_response(code=self.message_code.TASK_WARNING.value, + message='Eklenti başarıyla çalıştı; fakat kullanıcı ekran görüntüsü alınmasına izin vermedi.') + return + ##permission### + + if self.is_exist(self.shot_path): + self.logger.debug('Screenshot file found.') + + data = {} + md5sum = self.get_md5_file(str(self.shot_path)) + self.logger.debug('{0} renaming to {1}'.format(self.temp_file_name, md5sum)) + self.rename_file(self.shot_path, self.Ahenk.received_dir_path() + md5sum) + self.logger.debug('Renamed.') + data['md5'] = md5sum + self.context.create_response(code=self.message_code.TASK_PROCESSED.value, + message='Ekran görüntüsü başarıyla alındı.', + data=json.dumps(data), + content_type=self.get_content_type().IMAGE_JPEG.value) + self.logger.debug('SCREENSHOT task is handled successfully') + else: + raise Exception('Image not found this path: {0}'.format(self.shot_path)) + + except Exception as e: + self.logger.error( + 'A problem occured while handling SCREENSHOT task: {0}'.format(traceback.format_exc())) + self.context.create_response(code=self.message_code.TASK_ERROR.value, + message='Ekran görüntüsü alırken hata oluştu: {0}'.format(str(e))) + + def get_username_display(self): + result_code, p_out, p_err = self.execute("who | awk '{print $1, $5}' | sed 's/(://' | sed 's/)//'", result=True) + + if result_code != 0: + return None + lines = str(p_out).split('\n') + for line in lines: + arr = line.split(' ') + if len(arr) > 1 and str(arr[1]).isnumeric() is True and arr[0] != 'root': + return arr + return None + + +def handle_task(task, context): + screenshot = TakeScreenshot(task, context) + screenshot.handle_task() diff --git a/opt/ahenk/plugins/script/execute_script.py b/opt/ahenk/plugins/script/execute_script.py new file mode 100644 index 0000000..926ec18 --- /dev/null +++ b/opt/ahenk/plugins/script/execute_script.py @@ -0,0 +1,94 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Author: Emre Akkaya + +from base.plugin.abstract_plugin import AbstractPlugin +import json + + +class ExecuteScript(AbstractPlugin): + def __init__(self, data, context): + super(AbstractPlugin, self).__init__() + self.data = data + self.context = context + self.logger = self.get_logger() + self.message_code = self.get_message_code() + + self.temp_file_name = str(self.generate_uuid()) + self.base_file_path = '{0}{1}'.format(str(self.Ahenk.received_dir_path()), self.temp_file_name) + + def handle_task(self): + try: + script_type = self.data['SCRIPT_TYPE'] + script_contents = self.format_contents(self.data['SCRIPT_CONTENTS']) + script_params = self.data['SCRIPT_PARAMS'] + file_path = self.base_file_path + + # Determine script extension and command + command = '' + if script_type == 'BASH': + file_path += '.sh' + command += 'bash' + elif script_type == 'PYTHON': + file_path += '.py' + command += 'python' + elif script_type == 'PERL': + file_path += '.pl' + command += 'perl' + elif script_type == 'RUBY': + file_path += '.rb' + command += 'ruby' + + self.create_script_file(file_path, script_contents) + + result_code, p_out, p_err = self.execute_script_file(command, file_path, script_params) + if result_code != 0: + self.logger.error("Error occurred while executing script: " + str(p_err)) + self.context.create_response(code=self.message_code.TASK_ERROR.value, + message='Betik çalıştırılırken hata oluştu', + data=json.dumps({'Result': p_err}), + content_type=self.get_content_type().APPLICATION_JSON.value) + else: + self.logger.debug("Executed script file.") + self.context.create_response(code=self.message_code.TASK_PROCESSED.value, + message='Betik başarıyla çalıştırıldı.', + data=json.dumps({'Result': p_out}), + content_type=self.get_content_type().APPLICATION_JSON.value) + + except Exception as e: + self.logger.error(str(e)) + self.context.create_response(code=self.message_code.TASK_ERROR.value, + message='Betik çalıştırılırken hata oluştu:' + str(e), + content_type=self.get_content_type().APPLICATION_JSON.value) + + def create_script_file(self, file_path, script_contents): + self.logger.debug("Creating script file.") + # Create temporary script file with the provided content + self.write_file(file_path, script_contents) + + # Make the file executable + self.make_executable(file_path) + self.logger.debug("Created script file: {0}".format(file_path)) + + def execute_script_file(self, command, file_path, script_params): + self.logger.debug("Executing script file.") + # Execute the file + if not script_params: + return self.execute('{0} {1}'.format(command, file_path)) + else: + return self.execute('{0} {1} {2}'.format(command, file_path, script_params)) + + @staticmethod + def format_contents(contents): + tmp = contents + replacements = list() + replacements.append(('&dbq;', '\"')) + replacements.append(('&sgq;', '\'')) + for r, n in replacements: + tmp = tmp.replace(r, n) + return tmp + + +def handle_task(task, context): + plugin = ExecuteScript(task, context) + plugin.handle_task() diff --git a/opt/ahenk/plugins/script/main.py b/opt/ahenk/plugins/script/main.py new file mode 100644 index 0000000..fb986d0 --- /dev/null +++ b/opt/ahenk/plugins/script/main.py @@ -0,0 +1,16 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- + + +def info(): + inf = dict() + inf['name'] = 'script' + inf['version'] = '1.0.0' + inf['support'] = 'debian' + inf['description'] = '' + inf['task'] = True + inf['user_oriented'] = False + inf['machine_oriented'] = False + inf['developer'] = '' + + return inf diff --git a/opt/ahenk/plugins/service/get_services.py b/opt/ahenk/plugins/service/get_services.py new file mode 100644 index 0000000..f7686b7 --- /dev/null +++ b/opt/ahenk/plugins/service/get_services.py @@ -0,0 +1,132 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Author: Cemre ALPSOY + +import json +import subprocess +from base.plugin.abstract_plugin import AbstractPlugin + + +class ServiceList(object): + def __init__(self): + self.service_list = [] + + +class ServiceListItem: + def __init__(self, service_name, status, auto): + self.serviceName = service_name + self.serviceStatus = status + self.startAuto = auto + + +def encode_service_object(obj): + if isinstance(obj, ServiceListItem): + return obj.__dict__ + return obj + + +class GetServices(AbstractPlugin): + def __init__(self, data, context): + super(AbstractPlugin, self).__init__() + self.data = data + self.context = context + self.logger = self.get_logger() + self.message_code = self.get_message_code() + + self.temp_file_name = str(self.generate_uuid()) + self.file_path = '{0}{1}'.format(str(self.Ahenk.received_dir_path()), self.temp_file_name) + self.service_status = 'service {} status' + self.isRecordExist = 0 + + def handle_task(self): + try: + self.logger.debug('Executing command for service list.') + self.get_service_status() + + self.logger.debug('Command executed.') + + if self.is_exist(self.file_path): + data = {} + self.logger.debug(str(self.file_path)) + md5sum = self.get_md5_file(str(self.file_path)) + self.logger.debug('{0} renaming to {1}'.format(self.temp_file_name, md5sum)) + self.rename_file(self.file_path, self.Ahenk.received_dir_path() + '/' + md5sum) + self.logger.debug('Renamed.' + self.Ahenk.received_dir_path() + '/' + md5sum) + data['md5'] = md5sum + self.context.create_response(code=self.message_code.TASK_PROCESSED.value, + message='Servis listesi başarıyla okundu.', + data=json.dumps(data), + content_type=self.get_content_type().TEXT_PLAIN.value) + self.logger.debug("Execution Info fetched succesfully. ") + self.logger.debug("Execution Info has sent") + else: + self.context.create_response(code=self.message_code.TASK_ERROR.value, + message='Servis listesi getirilemedi') + self.logger.debug('Service list created successfully') + except Exception as e: + self.logger.error(str(e)) + self.context.create_response(code=self.message_code.TASK_ERROR.value, + message='Servis listesi oluşturulurken hata oluştu: ' + str(e)) + + def add_file(self, name, status, auto_start): + if self.isRecordExist == 0: + self.execute('echo { \\"service_list\\" :[ >> ' + self.file_path) + self.isRecordExist = 1 + t_command = 'echo "{ \\"serviceName\\": \\"' + name + '\\", \\"serviceStatus\\": \\"' + status + '\\", \\"startAuto\\":\\"' + auto_start + '\\"}" >> ' + self.file_path + self.execute(t_command) + self.execute('echo , >> ' + self.file_path) + + def get_service_status(self): + (result_code, p_out, p_err) = self.execute("service --status-all") + self.create_file(self.file_path) + # service_list = ServiceList() + p_err = ' ' + p_err + p_out = ' ' + p_out + lines = p_out.split('\n') + for line in lines: + line_split = line.split(' ') + if len(line_split) >= 5: + proc = subprocess.Popen('chkconfig --list | grep 2:on | grep ' + line_split[len(line_split) - 1], + shell=True) + auto = "INACTIVE" + name = line_split[len(line_split) - 1] + + if proc.wait() == 0: + auto = "ACTIVE" + + result, out, err = self.execute(self.service_status.format(name)) + + if 'Unknown job' not in str(err): + if line_split[len(line_split) - 4] == '+': + self.add_file(name, "ACTIVE", auto) + # service_list.service_list.append(ServiceListItem(name, "ACTIVE", auto)) + elif line_split[len(line_split) - 4] == '-': + self.add_file(name, "INACTIVE", auto) + # service_list.service_list.append(ServiceListItem(name, "INACTIVE", auto)) + else: + self.logger.debug( + 'Service \'{0}\' has been not added to the list because of the its {1}'.format(name, err)) + + line_err = p_err.split(',') + + for line in line_err: + line_split = line.split(' ') + if len(line_split) >= 6: + proc = subprocess.Popen('chkconfig --list | grep 2:on | grep ' + line_split[len(line_split) - 1], + shell=True) + auto = "INACTIVE" + if proc.wait() == 0: + auto = "ACTIVE" + self.add_file(line_split[len(line_split) - 1], "unknown", auto) + # service_list.service_list.append(ServiceListItem(line_split[len(line_split)-1], "unknown", auto)) + + # result_service_list = json.dumps(service_list.__dict__, default=encode_service_object) + # self.logger.debug('[SERVICE]' + 'Service list: ' + str(result_service_list)) + if self.isRecordExist == 1: + self.execute("sed -i '$ d' " + self.file_path) + self.execute('echo "]}" >> ' + self.file_path) + + +def handle_task(task, context): + plugin = GetServices(task, context) + plugin.handle_task() diff --git a/opt/ahenk/plugins/service/init.py b/opt/ahenk/plugins/service/init.py new file mode 100644 index 0000000..2834b1f --- /dev/null +++ b/opt/ahenk/plugins/service/init.py @@ -0,0 +1,21 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- + +from base.plugin.abstract_plugin import AbstractPlugin + + +class Init(AbstractPlugin): + def __init__(self, context): + super(Init, self).__init__() + self.context = context + self.logger = self.get_logger() + + def handle_mode(self): + if self.is_installed('chkconfig') is False: + self.install_with_apt_get('chkconfig') + pass + + +def handle_mode(context): + init = Init(context) + init.handle_mode() diff --git a/opt/ahenk/plugins/service/main.py b/opt/ahenk/plugins/service/main.py new file mode 100644 index 0000000..fef57eb --- /dev/null +++ b/opt/ahenk/plugins/service/main.py @@ -0,0 +1,15 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- + +def info(): + inf = dict() + inf['name'] = 'service' + inf['version'] = '1.0.0' + inf['support'] = 'debian' + inf['description'] = 'Agent machine all service settings (service start/stop operations, run a service/services as a start-up service...etc.) are defined with this plugin.' + inf['task'] = True + inf['user_oriented'] = False + inf['machine_oriented'] = False + inf['developer'] = 'cemre.alpsoy@agem.com.tr' + + return inf diff --git a/opt/ahenk/plugins/service/service_list.py b/opt/ahenk/plugins/service/service_list.py new file mode 100644 index 0000000..647a45a --- /dev/null +++ b/opt/ahenk/plugins/service/service_list.py @@ -0,0 +1,81 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Author: Cemre ALPSOY + +import json + +from base.plugin.abstract_plugin import AbstractPlugin + + +class ServiceList(AbstractPlugin): + def __init__(self, data, context): + super(AbstractPlugin, self).__init__() + self.data = data + self.context = context + self.logger = self.get_logger() + self.message_code = self.get_message_code() + + def start_stop_service(self, service_name, service_action): + (result_code, p_out, p_err) = self.execute('service {0} {1}'.format(service_name, service_action)) + if result_code == 0: + message = 'Service start/stop action was successful: '.format(service_action) + + else: + message = 'Service action was unsuccessful: {0}, return code {1}'.format(service_action, str(result_code)) + + self.logger.debug(message) + return result_code, message + + def set_startup_service(self, service_name, action): + (result_code, p_out, p_err) = self.execute('update-rc.d {0} {1}'.format(service_name, action)) + if result_code == 0: + message = 'Service startup action was successful: {}'.format(service_name) + else: + message = 'Service action was unsuccessful: {0}, return code {1}'.format(service_name, str(result_code)) + + self.logger.debug(message) + return result_code, message + + def handle_task(self): + self.logger.debug('Handling Service Task') + try: + items = (self.data)['serviceRequestParameters'] + resultMessage = "" + for item in items: + try: + if item['serviceStatus'] is not None and ( + str(item['serviceStatus']) == 'Başlat' or str(item['serviceStatus']) == 'Start'): + resultcode, message = self.start_stop_service(str(item['serviceName']), "start") + resultMessage += message + if item['serviceStatus'] is not None and ( + str(item['serviceStatus']) == 'Durdur' or str(item['serviceStatus']) == 'Stop'): + resultcode, message = self.start_stop_service(str(item['serviceName']), "stop") + resultMessage += message + if item['startAuto'] is not None and ( + str(item['startAuto']) == 'Başlat' or str(item['startAuto']) == 'Start'): + resultcode, message = self.set_startup_service(str(item['serviceName']), "defaults") + resultMessage += message + if item['startAuto'] is not None and ( + str(item['startAuto']) == 'Durdur' or str(item['startAuto']) == 'Stop'): + resultcode, message = self.set_startup_service(str(item['serviceName']), "remove") + resultMessage += message + + except Exception as e: + resultMessage += '{0} servisinin isteklerini gerçekleştirirken hata ile karşılaşıldı. Hata : {1}\r\n'.format( + str(item['serviceName']), str(e)) + self.logger.debug(resultMessage) + data = {'ResultMessage': resultMessage} + + self.context.create_response(code=self.message_code.TASK_PROCESSED.value, + message='Servis istekleri gerçekleştirildi', + data=json.dumps(data), + content_type=self.get_content_type().APPLICATION_JSON.value) + except Exception as e: + self.logger.debug('Service List Exception :' + str(e)) + self.context.create_response(code=self.message_code.TASK_ERROR.value, + message='Servis istekleri gerçekleştirilirken beklenmedik hata!') + + +def handle_task(task, context): + plugin = ServiceList(task, context) + plugin.handle_task() diff --git a/opt/ahenk/plugins/service/service_management.py b/opt/ahenk/plugins/service/service_management.py new file mode 100644 index 0000000..38a2667 --- /dev/null +++ b/opt/ahenk/plugins/service/service_management.py @@ -0,0 +1,69 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Author: Cemre ALPSOY + +from base.plugin.abstract_plugin import AbstractPlugin +import json + + +class ServiceManagement(AbstractPlugin): + def __init__(self, data, context): + super(AbstractPlugin, self).__init__() + self.data = data + self.context = context + self.logger = self.get_logger() + self.message_code = self.get_message_code() + + def start_stop_service(self, service_name, service_action): + (result_code, p_out, p_err) = self.execute('service {0} {1}'.format(service_name, service_action)) + if result_code == 0: + message = 'Service start/stop action was successful: '.format(service_action) + + else: + message = 'Service action was unsuccessful: {0}, return code {1}'.format(service_action, str(result_code)) + + self.logger.debug(message) + return result_code, message + + def set_startup_service(self, service_name): + (result_code, p_out, p_err) = self.execute('update-rc.d {} defaults'.format(service_name)) + + if result_code == 0: + message = 'Service startup action was successful: {}'.format(service_name) + else: + message = 'Service action was unsuccessful: {0}, return code {1}'.format(service_name, str(result_code)) + + self.logger.debug('SERVICE' + message) + return result_code, message + + def handle_task(self): + try: + self.logger.debug("Service Management task is started.") + service_name = str((self.data)['serviceName']) + service_status = str((self.data)['serviceStatus']) + start_auto = bool((self.data)['startAuto']) + if service_status == 'Start' or service_status == 'Başlat': + service_action = 'start' + else: + service_action = 'stop' + result_code, message = self.start_stop_service(service_name, service_action) + if result_code == 0 and start_auto is True: + result_code, message = self.set_startup_service(service_name) + if result_code == 0: + self.context.create_response(code=self.message_code.TASK_PROCESSED.value, + message='Servis başlatma/durdurma/otomatik başlatma işlemi başarıyla gerçekleştirildi', + data=json.dumps(self.data), + content_type=self.get_content_type().APPLICATION_JSON.value) + else: + self.context.create_response(code=self.message_code.TASK_ERROR.value, message=message) + + except Exception as e: + self.logger.error(str(e)) + self.context.create_response(code=self.message_code.TASK_ERROR.value, + message='Servis başlatma/durdurma/otomatik başlatma işlemi sırasında bir hata oluştu: {0}'.format( + str(e))) + + +def handle_task(task, context): + plugin = ServiceManagement(task, context) + plugin.handle_task() diff --git a/opt/ahenk/plugins/sudoers/main.py b/opt/ahenk/plugins/sudoers/main.py new file mode 100644 index 0000000..31c4168 --- /dev/null +++ b/opt/ahenk/plugins/sudoers/main.py @@ -0,0 +1,17 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# Author: Mine Dogan + + +def info(): + inf = dict() + inf['name'] = 'sudoers' + inf['version'] = '1.0.0' + inf['support'] = 'debian' + inf['description'] = '' + inf['task'] = False + inf['user_oriented'] = True + inf['machine_oriented'] = False + inf['developer'] = '' + + return inf diff --git a/opt/ahenk/plugins/sudoers/policy.py b/opt/ahenk/plugins/sudoers/policy.py new file mode 100644 index 0000000..109c6ab --- /dev/null +++ b/opt/ahenk/plugins/sudoers/policy.py @@ -0,0 +1,67 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- +# Author: Mine Dogan + +import json + +from base.plugin.abstract_plugin import AbstractPlugin + + +class GrantSudoAccess(AbstractPlugin): + def __init__(self, data, context): + super(AbstractPlugin, self).__init__() + self.data = data + self.context = context + self.sudoer_line = '{0} ALL = NOPASSWD : /usr/bin/apt-get , /usr/bin/aptitude' + self.sudoer_file_path = '/etc/sudoers' + self.logger = self.get_logger() + + def handle_policy(self): + + username = self.context.get('username') + + try: + if username is not None: + json_data = json.loads(self.data) + + if str(json_data['privilege']) == 'True': + + sudoer_data = self.read_file(self.sudoer_file_path) + self.write_file(self.sudoer_file_path, sudoer_data.replace(self.sudoer_line.format(username), + '') + '\n' + self.sudoer_line.format( + username) + '\n') + + self.logger.debug('User sudoers set privilege to {0}.'.format(username)) + + self.logger.debug('Creating response...') + self.context.create_response(self.get_message_code().POLICY_PROCESSED.value, + 'User sudoers set privilege to {} successfully.'.format(username)) + + elif str(json_data['privilege']) == 'False': + + sudoer_data = self.read_file(self.sudoer_file_path) + self.write_file(self.sudoer_file_path, sudoer_data.replace(self.sudoer_line.format(username), '')) + self.logger.debug('User sudoers removed privilege from {0}.'.format(username)) + + self.logger.debug('Creating response...') + self.context.create_response(self.get_message_code().POLICY_PROCESSED.value, + 'User sudoers removed privilege from {0} successfully.'.format( + username)) + + else: + self.context.create_response(self.get_message_code().POLICY_PROCESSED.value, 'Missing parameter error.') + + self.logger.debug('Sudoers profile is handled successfully.') + else: + self.logger.error('Username parameter is missing.') + self.context.create_response(self.get_message_code().POLICY_ERROR.value, 'Username is missing') + + except Exception as e: + self.logger.error('A problem occurred while handling sudoers profile: {0}'.format(str(e))) + self.context.create_response(self.get_message_code().POLICY_ERROR.value, + 'A problem occurred while handling sudoers profile: {0}'.format(str(e))) + + +def handle_policy(profile_data, context): + quota = GrantSudoAccess(profile_data, context) + quota.handle_policy() diff --git a/opt/ahenk/plugins/sudoers/safe.py b/opt/ahenk/plugins/sudoers/safe.py new file mode 100644 index 0000000..448a5b4 --- /dev/null +++ b/opt/ahenk/plugins/sudoers/safe.py @@ -0,0 +1,22 @@ +from base.plugin.abstract_plugin import AbstractPlugin + + +class Safe(AbstractPlugin): + def __init__(self, context): + super(Safe, self).__init__() + self.context = context + self.username = str(context.get_username()) + self.logger = self.get_logger() + self.sudoer_line = '{0} ALL = NOPASSWD : /usr/bin/apt-get , /usr/bin/aptitude' + self.sudoer_file_path = '/etc/sudoers' + self.logger.debug('Parameters were initialized.') + + def handle_safe_mode(self): + sudoer_data = self.read_file(self.sudoer_file_path) + self.write_file(self.sudoer_file_path, sudoer_data.replace(self.sudoer_line.format(self.username), '')) + self.logger.debug('User sudoers removed privilege from {0}.'.format(self.username)) + + +def handle_mode(context): + init = Safe(context) + init.handle_safe_mode() diff --git a/opt/ahenk/plugins/usb/init.py b/opt/ahenk/plugins/usb/init.py new file mode 100644 index 0000000..9870fed --- /dev/null +++ b/opt/ahenk/plugins/usb/init.py @@ -0,0 +1,34 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- +# Author:Mine DOGAN + +from base.plugin.abstract_plugin import AbstractPlugin + + +class Init(AbstractPlugin): + def __init__(self, context): + super(Init, self).__init__() + self.context = context + self.logger = self.get_logger() + + self.script = '/bin/bash ' + self.Ahenk.plugins_path() + 'usb/scripts/{0}' + + self.logger.debug('Parameters were initialized.') + + def handle_init_mode(self): + self.execute(self.script.format('ENABLED_webcam.sh'), result=True) + self.logger.debug('Enabled webcam.') + + self.execute(self.script.format('ENABLED_printer.sh'), result=True) + self.logger.debug('Enabled printer.') + + self.execute(self.script.format('ENABLED_usbstorage.sh'), result=True) + self.logger.debug('Enabled usb storage.') + + self.execute(self.script.format('ENABLED_usbhid.sh'), result=True) + self.logger.debug('Enabled usb hid.') + + +def handle_mode(context): + init = Init(context) + init.handle_init_mode() diff --git a/opt/ahenk/plugins/usb/logout.py b/opt/ahenk/plugins/usb/logout.py new file mode 100644 index 0000000..47899a9 --- /dev/null +++ b/opt/ahenk/plugins/usb/logout.py @@ -0,0 +1,25 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- +# Author:Mine DOGAN + +from base.plugin.abstract_plugin import AbstractPlugin + + +class Logout(AbstractPlugin): + def __init__(self, context): + super(Logout, self).__init__() + self.context = context + self.logger = self.get_logger() + + self.logger.debug('Parameters were initialized.') + + def handle_logout_mode(self): + if self.is_exist("/etc/udev/rules.d/99-whitelist.rules"): + self.delete_file("/etc/udev/rules.d/99-whitelist.rules") + if self.is_exist("/etc/udev/rules.d/99-blacklist.rules"): + self.delete_file("/etc/udev/rules.d/99-blacklist.rules") + + +def handle_mode(context): + logout = Logout(context) + logout.handle_logout_mode() \ No newline at end of file diff --git a/opt/ahenk/plugins/usb/main.py b/opt/ahenk/plugins/usb/main.py new file mode 100644 index 0000000..bd67b79 --- /dev/null +++ b/opt/ahenk/plugins/usb/main.py @@ -0,0 +1,16 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- + + +def info(): + inf = dict() + inf['name'] = 'usb' + inf['version'] = '1.0.0' + inf['support'] = 'debian' + inf['description'] = 'USB plugin provides to managing usb devices like printer, mouse etc.' + inf['task'] = True + inf['user_oriented'] = False + inf['machine_oriented'] = True + inf['developer'] = 'mine.dogan@agem.com.tr' + + return inf diff --git a/opt/ahenk/plugins/usb/manage-usb.py b/opt/ahenk/plugins/usb/manage-usb.py new file mode 100644 index 0000000..4dd4170 --- /dev/null +++ b/opt/ahenk/plugins/usb/manage-usb.py @@ -0,0 +1,90 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- +# Author:Mine DOGAN + +from base.plugin.abstract_plugin import AbstractPlugin + + +class ManageUsb(AbstractPlugin): + def __init__(self, task, context): + super(AbstractPlugin, self).__init__() + self.task = task + self.context = context + self.logger = self.get_logger() + self.message_code = self.get_message_code() + + if self.has_attr_json(task, 'webcam') is True: + self.webcam = self.task['webcam'] + + if self.has_attr_json(task, 'mouseKeyboard') is True: + self.mouse_keyboard = self.task['mouseKeyboard'] + + if self.has_attr_json(task, 'printer') is True: + self.printer = self.task['printer'] + + if self.has_attr_json(task, 'storage') is True: + self.storage = self.task['storage'] + + self.script = '/bin/bash ' + self.Ahenk.plugins_path() + 'usb/scripts/{0}' + + self.logger.debug('Parameters were initialized.') + + def handle_task(self): + try: + self.logger.debug('Changing permissions...') + + if self.has_attr_json(self.task, 'webcam') is True: + if self.webcam == '1': + self.execute(self.script.format('ENABLED_webcam.sh'), result=True) + elif self.webcam == '0': + self.execute(self.script.format('DISABLED_webcam.sh'), result=True) + + self.logger.debug('Applied permission change for parameter "webcam"') + else: + self.logger.debug('Task has no parameter "webcam"') + + if self.has_attr_json(self.task, 'printer') is True: + if self.printer == '1': + self.execute(self.script.format('ENABLED_printer.sh'), result=True) + elif self.printer == '0': + self.execute(self.script.format('DISABLED_printer.sh'), result=True) + + self.logger.debug('Applied permission change for parameter "printer"') + else: + self.logger.debug('Task has no parameter "printer"') + + if self.has_attr_json(self.task, 'storage') is True: + if self.storage == '1': + self.execute(self.script.format('ENABLED_usbstorage.sh'), result=True) + elif self.storage == '0': + self.execute(self.script.format('DISABLED_usbstorage.sh'), result=True) + + self.logger.debug('Applied permission change for parameter "storage"') + else: + self.logger.debug('Task has no parameter "storage"') + + if self.has_attr_json(self.task, 'mouseKeyboard') is True: + if self.mouse_keyboard == '1': + self.execute(self.script.format('ENABLED_usbhid.sh'), result=True) + elif self.mouse_keyboard == '0': + self.execute(self.script.format('DISABLED_usbhid.sh'), result=True) + + self.logger.debug('Applied permission change for parameter "mouseKeyboard"') + else: + self.logger.debug('Task has no parameter "mouseKeyboard"') + + self.logger.debug('Applied permission changes.') + + self.logger.info('USB task is handled successfully') + self.context.create_response(code=self.message_code.TASK_PROCESSED.value, + message='USB izinleri başarıyla güncellendi.') + + except Exception as e: + self.logger.error('A problem occured while handling USB task: {0}'.format(str(e))) + self.context.create_response(code=self.message_code.TASK_ERROR.value, + message='USB izinleri güncellenirken bir hata oluştu.') + + +def handle_task(task, context): + manage = ManageUsb(task, context) + manage.handle_task() diff --git a/opt/ahenk/plugins/usb/policy.py b/opt/ahenk/plugins/usb/policy.py new file mode 100644 index 0000000..53bb4af --- /dev/null +++ b/opt/ahenk/plugins/usb/policy.py @@ -0,0 +1,268 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- +# Author:Mine DOGAN + +import json + +from base.plugin.abstract_plugin import AbstractPlugin + + +class Usb(AbstractPlugin): + def __init__(self, data, context): + super(Usb, self).__init__() + self.data = data + self.context = context + self.logger = self.get_logger() + self.message_code = self.get_message_code() + + self.parameters = json.loads(self.data) + self.script = '/bin/bash ' + self.Ahenk.plugins_path() + 'usb/scripts/{0}' + self.script_path = self.Ahenk.plugins_path() + 'usb/scripts/{0}' + self.items = [] + + self.command_vendor = "grep -lw '{0}' /sys/bus/usb/devices/*/manufacturer | grep -o -P '.{{0,}}/.{{0,0}}'" + self.command_model = "grep -lw '{0}' {1}product" + self.command_serial = "grep -lw '{0}' {1}serial" + self.command_authorized = "echo '{0}' > {1}authorized" + + self.command_serial_is_exist = 'if test -e {0}serial; then echo "exist"; else echo "not found"; fi' + + self.logger.debug('Parameters were initialized.') + + def handle_policy(self): + try: + self.logger.debug('Permissions will be applied for profile.') + self.manage_permissions() + if self.has_attr_json(self.parameters, 'items') is True: + self.items = self.parameters['items'] + self.logger.debug('Blacklist/Whitelist will be created for profile.') + if self.has_attr_json(self.parameters, 'type') is True: + self.logger.debug('BlackList Whitelist will be created....') + self.create_blacklist_whitelist() + + self.logger.info('USB profile is handled successfully.') + self.context.create_response(code=self.message_code.POLICY_PROCESSED.value, + message='USB izinleri başarıyla güncellendi.') + + except Exception as e: + self.logger.error('A problem occurred while handling USB policy. Error Message: {0}'.format(str(e))) + self.context.create_response(code=self.message_code.POLICY_ERROR.value, + message='USB politikası uygulanırken bir hata oluştu: {0}'.format(str(e))) + + def manage_permissions(self): + + self.logger.debug('Changing permissions...') + + if self.has_attr_json(self.parameters, 'webcam') is True: + if self.parameters['webcam'] == '1': + self.execute(self.script.format('ENABLED_webcam.sh'), result=True) + elif self.parameters['webcam'] == '0': + self.execute(self.script.format('DISABLED_webcam.sh'), result=True) + + self.logger.debug('Applied permission change for parameter "webcam"') + else: + self.logger.debug('Data has no parameter "webcam"') + + if self.has_attr_json(self.parameters, 'printer') is True: + if self.parameters['printer'] == '1': + self.execute(self.script.format('ENABLED_printer.sh'), result=True) + elif self.parameters['printer'] == '0': + self.execute(self.script.format('DISABLED_printer.sh'), result=True) + + self.logger.debug('Applied permission change for parameter "printer"') + else: + self.logger.debug('Data has no parameter "printer"') + + if self.has_attr_json(self.parameters, 'storage') is True: + if self.parameters['storage'] == '1': + self.execute(self.script.format('ENABLED_usbstorage.sh'), result=True) + elif self.parameters['storage'] == '0': + self.execute(self.script.format('DISABLED_usbstorage.sh'), result=True) + + self.logger.debug('Applied permission change for parameter "storage"') + else: + self.logger.debug('Data has no parameter "storage"') + + if self.has_attr_json(self.parameters, 'mouseKeyboard') is True: + if self.parameters['mouseKeyboard'] == '1': + self.execute(self.script.format('ENABLED_usbhid.sh'), result=True) + elif self.parameters['mouseKeyboard'] == '0': + self.execute(self.script.format('DISABLED_usbhid.sh'), result=True) + + self.logger.debug('Applied permission change for parameter "mouseKeyboard"') + else: + self.logger.debug('Data has no parameter "mouseKeyboard"') + + self.logger.debug('Permissions were applied.') + + def organize_rule_files(self, is_whitelist): + if is_whitelist == 0: + if self.is_exist("/etc/udev/rules.d/99-whitelist.rules"): + self.delete_file("/etc/udev/rules.d/99-whitelist.rules") + self.execute('> /etc/udev/rules.d/99-blacklist.rules') + else: + if self.is_exist("/etc/udev/rules.d/99-blacklist.rules"): + self.delete_file("/etc/udev/rules.d/99-blacklist.rules") + self.execute('> /etc/udev/rules.d/99-whitelist.rules') + + def write_whitelist_line(self, vendor, model, serial_number, is_first_line): + command_blackandwhitelist = 'echo ' + "'" + symbol = '=' + authorized = '1' + if is_first_line is True: + command_blackandwhitelist = 'ex -sc ' + "'1i|" + symbol = '!' + authorized = '0' + command_blackandwhitelist += 'ACTION==\"add|change\" , SUBSYSTEM==\"usb\" , ' + if vendor is not None and len(vendor) > 0: + command_blackandwhitelist += ' ATTR{manufacturer}' + symbol + '=\"' + vendor + '\" , ' + if model is not None and len(model) > 0: + command_blackandwhitelist += ' ATTR{product}' + symbol + '=\"' + model + '\" , ' + if serial_number is not None and len(serial_number) > 0: + command_blackandwhitelist += ' ATTR{serial}' + symbol + '=\"' + serial_number + '\" , ' + command_blackandwhitelist += ' ATTR{authorized}=\"' + authorized + '\" ' + "'" + if is_first_line is False: + command_blackandwhitelist += ' >> ' + else: + command_blackandwhitelist += ' -cx ' + command_blackandwhitelist += '/etc/udev/rules.d/99-whitelist.rules' + self.logger.debug(command_blackandwhitelist) + self.write_rule_line(command_blackandwhitelist) + + def write_rule_line(self, command): + p_result_code, p_out, p_err = self.execute(command) + if p_result_code == 0: + self.logger.debug('Rule line is added successfully') + elif p_result_code != 0: + self.logger.debug('Error while adding rule line to /etc/udev/rules.d/ , Error message : {0}'.format(p_err)) + + def create_rule_line(self, vendor, model, serial_number, is_whitelist): + if is_whitelist == 0: + command_blackandwhitelist = 'echo ' + "'" + 'ACTION ==\"add|change\" , SUBSYSTEM==\"usb\" , ' + if vendor is not None and len(vendor) > 0: + command_blackandwhitelist += ' ATTR{manufacturer}==\"' + vendor + '\" , ' + if model is not None and len(model) > 0: + command_blackandwhitelist += ' ATTR{product}==\"' + model + '\" , ' + if serial_number is not None and len(serial_number) > 0: + command_blackandwhitelist += ' ATTR{serial}==\"' + serial_number + '\" , ' + command_blackandwhitelist += ' ATTR{authorized}=\"0\" ' + "'" + '>> /etc/udev/rules.d/99-blacklist.rules' + self.write_rule_line(command_blackandwhitelist) + else: + self.write_whitelist_line(vendor, model, serial_number, True) + self.write_whitelist_line(vendor, model, serial_number, False) + + def create_blacklist_whitelist(self): + self.logger.debug('usb storage will be enabled') + self.execute(self.script.format('ENABLED_usbstorage.sh'), result=True) + self.logger.debug('usb storage enabled') + if self.parameters['type'] == 'blacklist': + is_whitelist = 0 + else: + is_whitelist = 1 + self.logger.debug('Rule files are organizing....') + self.organize_rule_files(is_whitelist) + self.logger.debug('Rule files are organized') + + for item in self.items: + item_parameters = json.loads(str(json.dumps(item))) + vendor = item_parameters['vendor'] + model = item_parameters['model'] + serial_number = item_parameters['serialNumber'] + + self.create_rule_line(vendor, model, serial_number, is_whitelist) + + self.logger.debug('vendor, model and serial number is set....') + self.logger.debug(self.command_vendor.format(vendor)) + result_code, p_out, p_err = self.execute(self.command_vendor.format(vendor), result=True) + folder_list = str(p_out).split('\n') + folder_list.pop() + + if p_out == '' and vendor != '': + self.logger.debug('Device has not been found because of vendor. Vendor: {0}'.format(vendor)) + + if vendor == '': + folder_list = [] + folder_list.append('/sys/bus/usb/devices/*/') + + for folder in folder_list: + + result_code, p_out, p_err = self.execute(self.command_model.format(model, folder), result=True) + + if p_out == '' and model != '': + self.logger.debug( + 'Device model has not been found in this directory. Directory: {0}, Vendor: {1}, Model: {2}'.format( + folder, vendor, model)) + + else: + model_folder_list = str(p_out).split('\n') + model_folder_list.pop() + + if p_out == '': + model_folder_list.append(folder) + + if vendor == '' and model == '': + model_folder_list = [] + model_folder_list.append('/sys/bus/usb/devices/*/') + + for model_folder in model_folder_list: + if 'product' in model_folder: + model_folder = model_folder.strip('product') + + if model_folder != '/sys/bus/usb/devices/*/': + result_code, p_out, p_err = self.execute(self.command_serial_is_exist.format(model_folder), + result=True) + + if 'exist' in p_out or model_folder == '/sys/bus/usb/devices/*/': + result_code, p_out, p_err = self.execute( + self.command_serial.format(serial_number, model_folder), + result=True) + if p_out == '' and serial_number != '': + self.logger.debug( + 'Device serial number has not been found in this directory. Directory: {0}, Vendor: {1}, Model: {2}, Serial Number: {3}'.format( + model_folder, vendor, + model, serial_number)) + else: + serial_folder_list = str(p_out).split('\n') + serial_folder_list.pop() + + if p_out == '': + serial_folder_list.append(model_folder) + + for serial_folder in serial_folder_list: + serial_folder = serial_folder.strip('serial') + if self.parameters['type'] == 'whitelist': + self.execute(self.command_authorized.format('1', serial_folder), result=True) + self.logger.debug( + 'Enabled the device. Directory: {0}, Vendor: {1}, Model: {2}, Serial Number: {3}'.format( + serial_folder, vendor, model, serial_number)) + elif self.parameters['type'] == 'blacklist': + self.execute(self.command_authorized.format('0', serial_folder), result=True) + self.logger.debug( + 'Disabled the device. Directory: {0}, Vendor: {1}, Model: {2}, Serial Number: {3}'.format( + serial_folder, vendor, model, serial_number)) + + elif 'not found' in p_out: + dir = '' + if model != '': + dir = model_folder + elif vendor != '': + dir = folder + + if self.parameters['type'] == 'whitelist': + self.execute(self.command_authorized.format('1', dir), result=True) + self.logger.debug( + 'Enabled the device. Directory: {0}, Vendor: {1}, Model: {2}, Serial Number: {3}'.format( + dir, vendor, model, serial_number)) + elif self.parameters['type'] == 'blacklist': + self.execute(self.command_authorized.format('0', dir), result=True) + self.logger.debug( + 'Disabled the device. Directory: {0}, Vendor: {1}, Model: {2}, Serial Number: {3}'.format( + dir, vendor, model, serial_number)) + + self.execute('udevadm control --reload-rules') + self.logger.debug('Blacklist/Whitelist was created.') + + +def handle_policy(profile_data, context): + manage = Usb(profile_data, context) + manage.handle_policy() diff --git a/opt/ahenk/plugins/usb/scripts/DISABLED_printer.sh b/opt/ahenk/plugins/usb/scripts/DISABLED_printer.sh new file mode 100755 index 0000000..62a8a08 --- /dev/null +++ b/opt/ahenk/plugins/usb/scripts/DISABLED_printer.sh @@ -0,0 +1,13 @@ +#!/bin/bash +var=$(lsmod | awk '{print $1}'| grep usblp) + +service cups stop + +if [ -z "$var" ] +then +echo "USB printer devices are already blocked" +else +rmmod usblp +sleep 2 +fi + diff --git a/opt/ahenk/plugins/usb/scripts/DISABLED_usbhid.sh b/opt/ahenk/plugins/usb/scripts/DISABLED_usbhid.sh new file mode 100755 index 0000000..0105c05 --- /dev/null +++ b/opt/ahenk/plugins/usb/scripts/DISABLED_usbhid.sh @@ -0,0 +1,37 @@ +#!/bin/bash + +var=$(lsmod | grep usbhid) + +if [ -z "$var" ] +then +echo "USB HID devices are already blocked" +else +for device in /sys/bus/usb/drivers/usbhid/* ; do + if [[ $device == *:* ]] + then + echo "${device##*/}" + echo "${device##*/}" | tee -a /sys/bus/usb/drivers/usbhid/unbind + fi +done + +sleep 2 +rmmod usbhid +echo blacklist usbhid >> /etc/modprobe.d/blockusbhid.conf +fi + +var=$(lsmod | grep psmouse) + +if [ -z "$var" ] +then +echo "psmouse is already blocked" +else +rmmod psmouse +echo blacklist psmouse >> /etc/modprobe.d/blockusbhid.conf +fi + +#for ld in `who | grep $1 | egrep -o " \(:[0-9]+\)" | egrep -o ":[0-9]+"`; do +# export DISPLAY="$ld" +# for hid in `sudo -u $1 xinput --list | grep slave | grep -o 'id=[0-9]\+' | grep -o '[0-9]\+'`; do + # sudo -u $1 xinput set-int-prop $hid "Device Enabled" 8 0 + #done +#done diff --git a/opt/ahenk/plugins/usb/scripts/DISABLED_usbstorage.sh b/opt/ahenk/plugins/usb/scripts/DISABLED_usbstorage.sh new file mode 100755 index 0000000..d875243 --- /dev/null +++ b/opt/ahenk/plugins/usb/scripts/DISABLED_usbstorage.sh @@ -0,0 +1,46 @@ +#!/bin/bash + +var=$(lsmod | awk '{print $1}'| grep usb_storage) + +if [ -z "$var" ] +then +echo "USB storage devices are already blocked" +else +rm /etc/modprobe.d/blockusbstorages.conf +for device in /sys/bus/usb/drivers/usb-storage/* ; do + if [[ $device == *:* ]] + then + echo "${device##*/}" + echo "${device##*/}" | tee -a /sys/bus/usb/drivers/usb-storage/unbind + fi +done + +sleep 2 + +for usb_dev in /dev/disk/by-id/usb-*; do + dev=$(readlink -f $usb_dev) + grep -q ^$dev /proc/mounts && umount -f $dev +done + +sleep 2 + +var=$(lsmod | grep usb_storage | awk '{print $4}') + +if [ ! -z "$var" ] +then +IFS=',' read -ra deps <<< "$var" +for i in "${deps[@]}"; do + modprobe -r "$i" + echo blacklist "$i" >> /etc/modprobe.d/blockusbstorages.conf +done +fi + +sleep 2 + +modprobe -r usb_storage +echo blacklist usb_storage >> /etc/modprobe.d/blockusbstorages.conf +sleep 2 +fi + + + diff --git a/opt/ahenk/plugins/usb/scripts/DISABLED_webcam.sh b/opt/ahenk/plugins/usb/scripts/DISABLED_webcam.sh new file mode 100755 index 0000000..4f24bd4 --- /dev/null +++ b/opt/ahenk/plugins/usb/scripts/DISABLED_webcam.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +var=$(lsof -t /dev/video0) + +if [ -z "$var" ] +then +echo "Webcam is not in use" +else +kill -9 "$var" +sleep 2 +fi + +var=$(lsmod | awk '{print $1}'| grep uvcvideo) + +if [ -z "$var" ] +then +echo "Webcam is already blocked" +else +rmmod uvcvideo +sleep 2 +fi + + diff --git a/opt/ahenk/plugins/usb/scripts/ENABLED_printer.sh b/opt/ahenk/plugins/usb/scripts/ENABLED_printer.sh new file mode 100755 index 0000000..59571f9 --- /dev/null +++ b/opt/ahenk/plugins/usb/scripts/ENABLED_printer.sh @@ -0,0 +1,3 @@ +#!/bin/bash +modprobe usblp +service cups start \ No newline at end of file diff --git a/opt/ahenk/plugins/usb/scripts/ENABLED_usbhid.sh b/opt/ahenk/plugins/usb/scripts/ENABLED_usbhid.sh new file mode 100755 index 0000000..ecd3110 --- /dev/null +++ b/opt/ahenk/plugins/usb/scripts/ENABLED_usbhid.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +modprobe usbhid +modprobe psmouse + + +#for ld in `who | grep $1 | egrep -o " \(:[0-9]+\)" | egrep -o ":[0-9]+"`; do +# export DISPLAY="$ld" +# for hid in `sudo -u $1 xinput --list | grep slave | grep -o 'id=[0-9]\+' | grep -o '[0-9]\+'`; do +# sudo -u $1 xinput set-int-prop $hid "Device Enabled" 8 1 +# done +#done + +echo "" > /etc/modprobe.d/blockusbhid.conf diff --git a/opt/ahenk/plugins/usb/scripts/ENABLED_usbstorage.sh b/opt/ahenk/plugins/usb/scripts/ENABLED_usbstorage.sh new file mode 100755 index 0000000..00b19e2 --- /dev/null +++ b/opt/ahenk/plugins/usb/scripts/ENABLED_usbstorage.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +while read line +do + IFS=' ' read -a module <<< "$line" + modprobe "${module[1]}" +done < /etc/modprobe.d/blockusbstorages.conf + +echo "" | tee -a /etc/modprobe.d/blockusbstorages.conf + +modprobe usb_storage + +for usb_dev in /dev/disk/by-id/usb-*; do + dev=$(readlink -f $usb_dev) + grep -q ^$dev /proc/mounts && mount -f $dev +done \ No newline at end of file diff --git a/opt/ahenk/plugins/usb/scripts/ENABLED_webcam.sh b/opt/ahenk/plugins/usb/scripts/ENABLED_webcam.sh new file mode 100755 index 0000000..f649f99 --- /dev/null +++ b/opt/ahenk/plugins/usb/scripts/ENABLED_webcam.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +modprobe uvcvideo \ No newline at end of file diff --git a/opt/ahenk/plugins/user-privilege/init.py b/opt/ahenk/plugins/user-privilege/init.py new file mode 100644 index 0000000..b2dbea4 --- /dev/null +++ b/opt/ahenk/plugins/user-privilege/init.py @@ -0,0 +1,94 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- +""" +Style Guide is PEP-8 +https://www.python.org/dev/peps/pep-0008/ +""" + +import glob +import json +import os + +from base.plugin.abstract_plugin import AbstractPlugin + + +class UserPrivilegeInitMode(AbstractPlugin): + def __init__(self, context): + super(AbstractPlugin, self).__init__() + self.context = context + self.logger = self.get_logger() + + def handle_for_this_user(self, username): + + p_path = self.Ahenk.plugins_path() + + privilege_file = p_path + 'user-privilege/privilege.changes/' + username + '.changes' + + if self.is_exist(privilege_file): + self.logger.debug('Reading privilege_file: ' + privilege_file) + with open(privilege_file) as data_file: + self.logger.debug('Creating object from JSON data file.') + data = json.load(data_file) + + command_path_list = data['command_path_list'] + added_user_list = data['added_user_list'] + deleted_user_list = data['deleted_user_list'] + + if len(command_path_list) != 0: + self.logger.debug('Removing wrapper files and renaming original files.') + + for command_path in command_path_list: + if os.path.exists(command_path + '-ahenk'): + self.logger.debug('Executing: ' + '"rm ' + command_path + '"') + self.execute('rm ' + command_path) + self.logger.debug( + 'Executing: ' + '"mv ' + command_path + '-ahenk ' + command_path + '"') + self.execute('mv ' + command_path + '-ahenk ' + command_path) + else: + self.logger.debug( + 'File will not be deleted because ' + command_path + 'does not exists.') + + if len(added_user_list) != 0: + self.logger.debug('Removing user from groups that it has been added in advance.') + + for group_name in added_user_list: + self.logger.debug( + 'Executing: ' + '"deluser ' + str(username) + ' ' + group_name + '"') + self.execute('deluser ' + str(username) + ' ' + group_name) + + if len(deleted_user_list) != 0: + self.logger.debug('Adding user to groups that it has been removed in advance.') + + for group_name in deleted_user_list: + self.logger.debug( + 'Executing: ' + '"adduser ' + str(username) + ' ' + group_name + '"') + self.execute('adduser ' + str(username) + ' ' + group_name) + else: + self.logger.debug('Changes file not found for {} user.'.format(username)) + + def handle_init_mode(self): + self.logger.debug('Handling init mode.') + + changes_file_arr = self.Ahenk.plugins_path() + 'user-privilege/privilege.changes/*.changes' + change_files = glob.glob(changes_file_arr) + + if change_files is not None and len(change_files) > 0: + self.logger.debug('Some user changes found.') + for file in change_files: + tmp = file.replace(self.Ahenk.plugins_path() + 'user-privilege/privilege.changes/', '') + tmp = tmp.replace('.changes', '') + self.logger.debug('Handling init for user {0}'.format(tmp)) + try: + self.handle_for_this_user(tmp) + self.logger.debug('Handled init for user {0}'.format(tmp)) + except Exception as e: + self.logger.error( + 'A problem occurred while handling init action for user {0}. Error Message: {1}'.format( + tmp, str(e))) + else: + self.logger.debug('Changes files not found.') + + +def handle_mode(context): + user_privilege = UserPrivilegeInitMode(context) + user_privilege.handle_init_mode() diff --git a/opt/ahenk/plugins/user-privilege/main.py b/opt/ahenk/plugins/user-privilege/main.py new file mode 100644 index 0000000..759ab5b --- /dev/null +++ b/opt/ahenk/plugins/user-privilege/main.py @@ -0,0 +1,16 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- + + +def info(): + inf = dict() + inf['name'] = 'user-privilege' + inf['version'] = '1.0.0' + inf['support'] = 'debian' + inf['description'] = '' + inf['task'] = False + inf['user_oriented'] = True + inf['machine_oriented'] = False + inf['developer'] = '' + + return inf diff --git a/opt/ahenk/plugins/user-privilege/policy.py b/opt/ahenk/plugins/user-privilege/policy.py new file mode 100644 index 0000000..9ddbb55 --- /dev/null +++ b/opt/ahenk/plugins/user-privilege/policy.py @@ -0,0 +1,371 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- +# Author: Caner Feyzullahoglu +""" +Style Guide is PEP-8 +https://www.python.org/dev/peps/pep-0008/ +""" +import json +import os + +from base.plugin.abstract_plugin import AbstractPlugin + + +class UserPrivilege(AbstractPlugin): + def __init__(self, profile_data, context): + super(AbstractPlugin, self).__init__() + self.profile_data = profile_data + self.context = context + self.logger = self.get_logger() + + # self.logger = self.context.logger + + self.polkit_action_folder_path = '/usr/share/polkit-1/actions/' + self.polkit_pkla_folder_path = '/etc/polkit-1/localauthority/50-local.d/' + self.default_action_pref = 'tr.org.pardus.mys.pkexec.' + + # self.permission_file_path = self.agent_config.get("UserPolicyPlugin", "userpolicyplugin.policyfile") + # The below line was like above line at old version. + self.permission_file_path = '/etc/ahenk/userpolicies' + # "permission_file"_path was being taken from a config file which has been created by "agentconfig.py" + # but this py is not present in new version. So I created it as a static string. + + def limit_ahenk(self, item): + + if self.has_attr_json(item, 'cpu') and item['cpu'] is not None and item['cpu'] is not '': + self.logger.debug('Limiting ahenk cpu usage. Cpu limit value: {0}'.format(item['cpu'])) + self.execute('cpulimit -p {0} -l {1} -z &'.format(str(self.Ahenk.get_pid_number()), str(item['cpu'])), + result=False) + self.logger.debug('Limited ahenk cpu usage. Cpu limit value: {0}'.format(item['cpu'])) + + def handle_policy(self): + print('Handling policy') + self.logger.debug('Handling policy.') + # Get username. + # It is actually user UID in LDAP. The message being created in PolicySubscriberImpl by using + # MessageFactoryImpl at server side. + # At agent side Plugin.py takes a message from queue as an item, finds related plugin module by using + # Scope (with parameters from the item such as plugin name and plugin version), puts "username" to context and + # triggers "handle_policy" method of related plugin. + username = self.context.get('username') + + try: + result_message = '' + + if username is not None: + self.logger.debug('Getting profile data.') + data = json.loads(self.profile_data) + privilege_items = data['items'] + + # Lists that will keep user names for cleaning on logout + add_user_list = list() + del_user_list = list() + # List that will keep command paths + command_path_list = list() + + if len(privilege_items) > 0: + self.logger.debug('Iterating over privilege items.') + + for item in privilege_items: + command_path = item['cmd'].strip() + if command_path == "/opt/ahenk/ahenkd": + self.limit_ahenk(item) + continue + + if self.is_exist(command_path) is False: + self.logger.warning( + '{0} command path not found. User privilege execution will not processed for this command.'.format( + command_path)) + continue + + polkit_status = item['polkitStatus'] + + # Create polkit for each item + if polkit_status == 'privileged': + + self.logger.debug('Parsing command.') + command = str(self.parse_command(command_path)) + + action_id = self.default_action_pref + command + + if not os.path.exists(action_id + '.policy'): + self.logger.debug( + 'Creating action; command: ' + command + ', action_id: ' + action_id + + ', command_path: ' + command_path) + self.create_action(command, action_id, command_path) + + self.logger.debug( + 'Executing: "getent group ' + command + ' || groupadd ' + command + '"') + self.execute('getent group ' + command + ' || groupadd ' + command) + + self.logger.debug( + 'Executing: "adduser ' + str(username) + ' ' + command + '"') + self.execute('adduser ' + str(username) + ' ' + command) + + self.logger.debug('Adding command to add_user_list') + add_user_list.append(command) + + if not os.path.exists(action_id + '.pkla'): + self.logger.debug( + 'Creating pkla; command: ' + command + ', action_id: ' + action_id) + self.create_pkla(command, action_id) + + self.logger.debug('Executing: "grep "pkexec" ' + str(command_path) + '"') + (result_code, p_out, p_err) = self.execute('grep "pkexec" ' + str(command_path)) + + if result_code != 0: + # Get resource limit choice + limit_resource_usage = item['limitResourceUsage'] + # Get CPU and memory usage parameters + cpu = item['cpu'] + memory = item['memory'] + + # Create wrapper command with resource limits + self.logger.debug( + 'Creating wrapper command; command_path: ' + command_path + + ', limit_resource_usage: ' + str(limit_resource_usage) + ', cpu: ' + + str(cpu) + ', memory: ' + str(memory)) + (wrapper_result, p_out, p_err) = self.create_wrapper_command(command_path, + polkit_status, + limit_resource_usage, + cpu, memory, + command_path_list) + + if wrapper_result == 0: + self.logger.debug('Wrapper created successfully.') + self.logger.debug('Adding item result to result_message.') + result_message += command_path + ' | Ayrıcalıklı | Başarılı, ' + else: + self.logger.debug('Adding item result to result_message.') + result_message += command_path + ' | Ayrıcalıklı | Başarısız, ' + + elif polkit_status == 'unprivileged': + + self.logger.debug('Parsing command.') + command = str(self.parse_command(command_path)) + + action_id = self.default_action_pref + command + + if not os.path.exists(action_id + '.policy'): + self.logger.debug( + 'Creating action; command: ' + command + ', action_id: ' + action_id + + ', command_path: ' + command_path) + self.create_action(command, action_id, command_path) + + self.logger.debug( + 'Executing: "getent group ' + command + ' || groupadd ' + command + '"') + self.execute('getent group ' + command + ' || groupadd ' + command) + + self.logger.debug( + 'Executing: "deluser ' + str(username) + ' ' + command + '"') + self.execute('deluser ' + str(username) + ' ' + command) + + self.logger.debug('Adding command to del_user_list') + del_user_list.append(command) + + if not os.path.exists(action_id + '.pkla'): + self.logger.debug( + 'Creating pkla; command: ' + command + ', action_id: ' + action_id) + self.create_pkla(command, action_id) + + self.logger.debug('Executing: "grep "pkexec" ' + str(command_path) + '"') + (result_code, p_out, p_err) = self.execute('grep "pkexec" ' + str(command_path)) + + if result_code != 0: + # Get resource limit choice + limit_resource_usage = item['limitResourceUsage'] + # Get CPU and memory usage parameters + cpu = item['cpu'] + memory = item['memory'] + + # Create wrapper command with resource limits + self.logger.debug( + 'Creating wrapper command; command_path: ' + command_path + + ', limit_resource_usage: ' + str(limit_resource_usage) + ', cpu: ' + + str(cpu) + ', memory: ' + str(memory)) + (wrapper_result, p_out, p_err) = self.create_wrapper_command(command_path, + polkit_status, + limit_resource_usage, + cpu, memory, + command_path_list) + if wrapper_result == 0: + self.logger.debug('Wrapper created successfully.') + self.logger.debug('Adding item result to result_message.') + result_message += command_path + ' | Ayrıcalıksız | Başarılı, ' + else: + self.logger.debug('Adding item result to result_message.') + result_message += command_path + ' | Ayrıcalıksız | Başarısız, ' + + elif polkit_status == 'na': + + self.logger.debug( + 'polkit_status is: na, no action or pkla will be created.') + + # Get resource limit choice + limit_resource_usage = item['limitResourceUsage'] + # Get CPU and memory usage parameters + cpu = item['cpu'] + memory = item['memory'] + + # Create wrapper command with resource limits + self.logger.debug( + 'Creating wrapper command; command_path: ' + command_path + + ', limit_resource_usage: ' + str(limit_resource_usage) + ', cpu: ' + + str(cpu) + ', memory: ' + str(memory)) + (wrapper_result, p_out, p_err) = self.create_wrapper_command(command_path, polkit_status, + limit_resource_usage, + cpu, memory, command_path_list) + + if wrapper_result == 0: + self.logger.debug('Wrapper created successfully.') + self.logger.debug('Adding item result to result_message.') + result_message += command_path + ' | Ayrıcalıklı | Başarılı, ' + else: + self.logger.debug('Adding item result to result_message.') + result_message += command_path + ' | Ayrıcalıklı | Başarısız, ' + + self.logger.debug('Getting plugin path.') + + p_path = self.Ahenk.plugins_path() + + self.logger.debug('Creating logout files.') + self.create_logout_files(username, p_path, add_user_list, del_user_list, command_path_list) + + self.logger.debug('Creating response.') + self.context.create_response(code=self.get_message_code().POLICY_PROCESSED.value, + message=result_message) + + self.logger.debug('User Privilege profile is handled successfully.') + + else: + self.logger.debug('Creating response.') + self.context.create_response(code=self.get_message_code().POLICY_WARNING.value, + message='Kullanıcı adı olmadan USER PRIVILEGE profili çalıştırılamaz.') + + except Exception as e: + self.context.create_response(code=self.get_message_code().POLICY_ERROR.value, + message='USER PRIVILEGE profili uygulanırken bir hata oluştu.') + self.logger.error( + 'A problem occurred while handling User Privilege profile: {0}'.format(str(e))) + + def parse_command(self, command_path): + splitted_command_str = str(command_path).split('/') + return splitted_command_str[-1] + + def create_action(self, command, command_id, command_path): + command_path += '-ahenk' + action_str = ' \n' \ + ' \n' \ + ' \n' \ + ' \n' \ + ' Please enter the password for this action \n' \ + ' {cmd} \n' \ + ' \n' \ + ' auth_admin \n' \ + ' auth_admin \n' \ + ' auth_admin \n' \ + ' \n' \ + ' {cmd_path} \n' \ + ' true \n' \ + ' \n' \ + ' \n'.format(action_id=command_id, cmd=command, cmd_path=command_path) + + action_file_path = self.polkit_action_folder_path + command_id + '.policy' + action_file = open(action_file_path, 'w') + action_file.write(action_str) + action_file.close() + + def create_pkla(self, command, action_id): + pkla_str = '[Normal Staff Permissions]\n' \ + 'Identity=unix-group:{grp}\n' \ + 'Action={actionId}\n' \ + 'ResultAny=no\n' \ + 'ResultInactive=no\n' \ + 'ResultActive=yes\n'.format(grp=command, actionId=action_id) + + pkla_file_path = self.polkit_pkla_folder_path + action_id + '.pkla' + pkla_file = open(pkla_file_path, 'w') + pkla_file.write(pkla_str) + pkla_file.close() + + def create_wrapper_command(self, command_path, polkit_status, limit_resource_usage, cpu, memory, command_path_list): + self.logger.debug( + 'Executing: "' + 'mv ' + str(command_path) + ' ' + str(command_path) + '-ahenk"') + (result_code, p_out, p_err) = self.execute( + 'mv ' + str(command_path) + ' ' + str(command_path) + '-ahenk') + + if result_code == 0: + + command_path_str = str(command_path).strip() + + line = 'if [ \( "$USER" = "root" \) -o \( "$USER" = "" \) ]; then \n' + str(command_path) + '-ahenk $@' + if limit_resource_usage: + line += '\nelse\n' + line += self.add_resource_limits(command_path, polkit_status, cpu, memory) + else: + if polkit_status == 'na': + line = line + '\nelse\n' + str(command_path) + '-ahenk $@\n' + else: + line += '\nelse\nCOMMAND=\"' + str(command_path) + '-ahenk $@\"\n' + line += 'pkexec --user $USER $COMMAND\n' + line += 'fi' + + self.logger.debug('Writing to newly created file: ' + command_path_str) + self.write_file(command_path_str, line) + self.set_permission(command_path_str, "755") + + self.logger.debug('Command created successfully ' + command_path) + + self.logger.debug('Adding command to command_path_list') + command_path_list.append(command_path) + + return 0, p_out, p_err + else: + self.logger.debug('Wrap could not created ' + command_path) + return 1, p_out, p_err + + def add_resource_limits(self, command_path, polkit_status, cpu, memory): + self.logger.debug('Adding resource limits to wrapper command.') + lines = '' + if cpu and memory is not None: + self.logger.debug('Adding both CPU and memory limits.') + lines = 'ulimit -Sv ' + str(memory) + '\n' + lines += 'COMMAND=\"' + str(command_path) + '-ahenk $@\"\n' + lines += 'nohup pkexec --user $USER $COMMAND &\n' + lines += 'U_PID=$!\n' + lines += 'cpulimit -p $U_PID -l ' + str(cpu) + ' -z\n' + elif cpu is not None: + self.logger.debug('Adding only CPU limit.') + lines = 'COMMAND=\"' + str(command_path) + '-ahenk $@\"\n' + lines += 'nohup pkexec --user $USER $COMMAND &\n' + lines += 'U_PID=$!\n' + lines += 'cpulimit -p $U_PID -l ' + str(cpu) + ' -z\n' + elif memory is not None: + self.logger.debug('Adding only memory limit.') + lines = 'ulimit -Sv ' + str(memory) + '\n' + lines += 'COMMAND=\"' + str(command_path) + '-ahenk $@\"\n' + lines += 'nohup pkexec --user $USER $COMMAND &\n' + + return lines + + def create_logout_files(self, username, path_of_plugin, add_user_list, del_user_list, command_path_list): + path_of_changes = path_of_plugin + 'user-privilege/privilege.changes' + if not os.path.exists(path_of_changes): + self.create_directory(path_of_changes) + + self.logger.debug('Creating JSON data for user privilege changes.') + data = {'added_user_list': add_user_list, 'deleted_user_list': del_user_list, + 'command_path_list': command_path_list} + + path_of_user_changes = path_of_changes + '/' + username + '.changes' + self.logger.debug('Creating file: ' + path_of_user_changes) + with open(path_of_user_changes, 'w') as f: + self.logger.debug('Writing JSON data to: ' + path_of_user_changes) + json.dump(data, f) + + +def handle_policy(profile_data, context): + user_privilege = UserPrivilege(profile_data, context) + user_privilege.handle_policy() diff --git a/opt/ahenk/plugins/user-privilege/safe.py b/opt/ahenk/plugins/user-privilege/safe.py new file mode 100644 index 0000000..41c57b4 --- /dev/null +++ b/opt/ahenk/plugins/user-privilege/safe.py @@ -0,0 +1,73 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- +# Author: Caner Feyzullahoglu +""" +Style Guide is PEP-8 +https://www.python.org/dev/peps/pep-0008/ +""" + +import json +import os +from base.plugin.abstract_plugin import AbstractPlugin + + +class UserPrivilegeSafeMode(AbstractPlugin): + def __init__(self, context): + super(AbstractPlugin, self).__init__() + self.username = str(context.get_username()) + self.context = context + self.logger = self.get_logger() + + def handle_safe_mode(self): + self.logger.debug('Handling safe mode.') + + self.logger.debug('Getting plugin path.') + p_path = self.Ahenk.plugins_path() + privilege_file = p_path + 'user-privilege/privilege.changes/' + self.username + '.changes' + + if self.is_exist(privilege_file): + self.logger.debug('Reading privilege_file: ' + privilege_file) + with open(privilege_file) as data_file: + self.logger.debug('Creating object from JSON data file.') + data = json.load(data_file) + + command_path_list = data['command_path_list'] + added_user_list = data['added_user_list'] + deleted_user_list = data['deleted_user_list'] + + if len(command_path_list) != 0: + self.logger.debug('Removing wrapper files and renaming original files.') + + for command_path in command_path_list: + if os.path.exists(command_path + '-ahenk'): + self.logger.debug('Executing: ' + '"rm ' + command_path + '"') + self.execute('rm ' + command_path) + self.logger.debug( + 'Executing: ' + '"mv ' + command_path + '-ahenk ' + command_path + '"') + self.execute('mv ' + command_path + '-ahenk ' + command_path) + else: + self.logger.debug( + 'File will not be deleted because ' + command_path + 'does not exists.') + + if len(added_user_list) != 0: + self.logger.debug('Removing user from groups that it has been added in advance.') + + for group_name in added_user_list: + self.logger.debug( + 'Executing: ' + '"deluser ' + str(self.username) + ' ' + group_name + '"') + self.execute('deluser ' + str(self.username) + ' ' + group_name) + + if len(deleted_user_list) != 0: + self.logger.debug('Adding user to groups that it has been removed in advance.') + + for group_name in deleted_user_list: + self.logger.debug( + 'Executing: ' + '"adduser ' + str(self.username) + ' ' + group_name + '"') + self.execute('adduser ' + str(self.username) + ' ' + group_name) + else: + self.logger.debug('Changes file not found for {} user.'.format(self.username)) + + +def handle_mode(context): + user_privilege = UserPrivilegeSafeMode(context) + user_privilege.handle_safe_mode() diff --git a/opt/ahenk/plugins/user-privilege/shutdown.py b/opt/ahenk/plugins/user-privilege/shutdown.py new file mode 100644 index 0000000..b734dcd --- /dev/null +++ b/opt/ahenk/plugins/user-privilege/shutdown.py @@ -0,0 +1,95 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- +""" +Style Guide is PEP-8 +https://www.python.org/dev/peps/pep-0008/ +""" + +import glob +import json +import os + +from base.plugin.abstract_plugin import AbstractPlugin + + +class UserPrivilegeShutdownMode(AbstractPlugin): + def __init__(self, context): + super(AbstractPlugin, self).__init__() + self.context = context + self.logger = self.get_logger() + + def handle_for_this_user(self, username): + + p_path = self.Ahenk.plugins_path() + + privilege_file = p_path + 'user-privilege/privilege.changes/' + username + '.changes' + + if self.is_exist(privilege_file): + self.logger.debug('Reading privilege_file: ' + privilege_file) + with open(privilege_file) as data_file: + self.logger.debug('Creating object from JSON data file.') + data = json.load(data_file) + + command_path_list = data['command_path_list'] + added_user_list = data['added_user_list'] + deleted_user_list = data['deleted_user_list'] + + if len(command_path_list) != 0: + self.logger.debug('Removing wrapper files and renaming original files.') + + for command_path in command_path_list: + if os.path.exists(command_path + '-ahenk'): + self.logger.debug('Executing: ' + '"rm ' + command_path + '"') + self.execute('rm ' + command_path) + self.logger.debug( + 'Executing: ' + '"mv ' + command_path + '-ahenk ' + command_path + '"') + self.execute('mv ' + command_path + '-ahenk ' + command_path) + else: + self.logger.debug( + 'File will not be deleted because ' + command_path + 'does not exists.') + + if len(added_user_list) != 0: + self.logger.debug( + 'Removing user from groups that it has been added in advance.') + + for group_name in added_user_list: + self.logger.debug( + 'Executing: ' + '"deluser ' + str(username) + ' ' + group_name + '"') + self.execute('deluser ' + str(username) + ' ' + group_name) + + if len(deleted_user_list) != 0: + self.logger.debug('Adding user to groups that it has been removed in advance.') + + for group_name in deleted_user_list: + self.logger.debug( + 'Executing: ' + '"adduser ' + str(username) + ' ' + group_name + '"') + self.execute('adduser ' + str(username) + ' ' + group_name) + else: + self.logger.debug('Changes file not found for {} user.'.format(username)) + + def handle_shutdown_mode(self): + self.logger.debug('Handling shutdown mode.') + + changes_file_arr = self.Ahenk.plugins_path() + 'user-privilege/privilege.changes/*.changes' + change_files = glob.glob(changes_file_arr) + + if change_files is not None and len(change_files) > 0: + self.logger.debug('Some user changes found.') + for file in change_files: + tmp = file.replace(self.Ahenk.plugins_path() + 'user-privilege/privilege.changes/', '') + tmp = tmp.replace('.changes', '') + self.logger.debug('Handling init for user {0}'.format(tmp)) + try: + self.handle_for_this_user(tmp) + self.logger.debug('Handled init for user {0}'.format(tmp)) + except Exception as e: + self.logger.error( + 'A problem occurred while handling shutdown action for user {0}. Error Message: {1}'.format( + tmp, str(e))) + else: + self.logger.debug('Changes files not found.') + + +def handle_mode(context): + user_privilege = UserPrivilegeShutdownMode(context) + user_privilege.handle_shutdown_mode() diff --git a/opt/ahenk/plugins/wol/init.py b/opt/ahenk/plugins/wol/init.py new file mode 100644 index 0000000..c8f704e --- /dev/null +++ b/opt/ahenk/plugins/wol/init.py @@ -0,0 +1,30 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- +# Author:Mine DOGAN + +from base.plugin.abstract_plugin import AbstractPlugin + + +class Init(AbstractPlugin): + def __init__(self, context): + super(Init, self).__init__() + self.context = context + self.logger = self.get_logger() + + self.logger.debug('Parameters were initialized.') + + def handle_init_mode(self): + + if self.is_installed('wakeonlan') is False: + self.logger.debug('Installing wakeonlan with apt-get...') + self.install_with_apt_get('wakeonlan') + + for interface in self.Hardware.Network.interfaces(): + self.logger.debug('Activating magic packet for ' + str(interface)) + self.execute('ethtool -s ' + str(interface) + ' wol g') + self.logger.debug('Activated magic packet for ' + str(interface)) + + +def handle_mode(context): + init = Init(context) + init.handle_init_mode() diff --git a/opt/ahenk/plugins/wol/main.py b/opt/ahenk/plugins/wol/main.py new file mode 100644 index 0000000..0ebc9a3 --- /dev/null +++ b/opt/ahenk/plugins/wol/main.py @@ -0,0 +1,16 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- + + +def info(): + inf = dict() + inf['name'] = 'wol' + inf['version'] = '1.0.0' + inf['support'] = 'debian' + inf['description'] = 'Wake-on-LAN plugin provides to waking up and shutting down machines.' + inf['task'] = True + inf['user_oriented'] = False + inf['machine_oriented'] = False + inf['developer'] = 'mine.dogan@agem.com.tr' + + return inf diff --git a/opt/ahenk/plugins/wol/shut-down-machine.py b/opt/ahenk/plugins/wol/shut-down-machine.py new file mode 100644 index 0000000..05a45d5 --- /dev/null +++ b/opt/ahenk/plugins/wol/shut-down-machine.py @@ -0,0 +1,40 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- +# Author:Mine DOGAN + +from base.plugin.abstract_plugin import AbstractPlugin + + +class ShutDownMachine(AbstractPlugin): + def __init__(self, task, context): + super(AbstractPlugin, self).__init__() + self.task = task + self.context = context + self.logger = self.get_logger() + self.message_code = self.get_message_code() + + self.shut_down_command = 'sleep 5s; shutdown -h now' + + self.logger.debug('Parameters were initialized.') + + def handle_task(self): + try: + self.logger.debug('Shutting down the machine...') + self.execute(self.shut_down_command, result=False) + + response = 'Shutdown komutu başarıyla çalıştırıldı. Bilgisayar kapatılacak. Mac Adres(ler)i: {0}, Ip Adres(ler)i: {1}' \ + .format(self.Hardware.Network.mac_addresses(), self.Hardware.Network.ip_addresses()) + + self.context.create_response(code=self.message_code.TASK_PROCESSED.value, + message=response) + self.logger.info('WOL task is handled successfully') + + except Exception as e: + self.logger.error('A problem occured while handling WOL task: {0}'.format(str(e))) + self.context.create_response(code=self.message_code.TASK_ERROR.value, + message='WOL görevi uygulanırken bir hata oluştu: {0}'.format(str(e))) + + +def handle_task(task, context): + shut_down = ShutDownMachine(task, context) + shut_down.handle_task() diff --git a/opt/ahenk/plugins/wol/shutdown.py b/opt/ahenk/plugins/wol/shutdown.py new file mode 100644 index 0000000..7bc042b --- /dev/null +++ b/opt/ahenk/plugins/wol/shutdown.py @@ -0,0 +1,25 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- +# Author:Mine DOGAN + +from base.plugin.abstract_plugin import AbstractPlugin + + +class Shutdown(AbstractPlugin): + def __init__(self, context): + super(Shutdown, self).__init__() + self.context = context + self.logger = self.get_logger() + + self.logger.debug('Parameters were initialized.') + + def handle_shutdown_mode(self): + for interface in self.Hardware.Network.interfaces(): + self.logger.debug('Activating magic packet for ' + str(interface)) + self.execute('ethtool -s ' + str(interface) + ' wol g') + self.logger.debug('Activated magic packet for ' + str(interface)) + + +def handle_mode(context): + shutdown = Shutdown(context) + shutdown.handle_shutdown_mode() diff --git a/opt/ahenk/plugins/wol/wake-machine.py b/opt/ahenk/plugins/wol/wake-machine.py new file mode 100644 index 0000000..2da69c2 --- /dev/null +++ b/opt/ahenk/plugins/wol/wake-machine.py @@ -0,0 +1,105 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- +# Author:Mine DOGAN + +import time + +from base.plugin.abstract_plugin import AbstractPlugin + + +class WakeMachine(AbstractPlugin): + def __init__(self, task, context): + super(AbstractPlugin, self).__init__() + self.task = task + self.context = context + self.logger = self.get_logger() + self.message_code = self.get_message_code() + + self.mac_address_list = self.task['macAddress'] + self.ip_address_list = self.task['ipAddress'] + self.port_list = self.task['port'] + self.time_list = self.task['time'] + + self.wake_command = 'wakeonlan {}' + self.port_control = 'nmap -p {0} {1} | grep {2}/tcp' + + self.logger.debug('Parameters were initialized.') + + def handle_task(self): + try: + result_list = [] + is_open = None + + if self.mac_address_list: + + for i, val in enumerate(self.mac_address_list): + mac_addresses = str(val).split(',') + for j, mac in enumerate(mac_addresses): + mac = mac.replace("'", "") + + for _ in range(5): + self.logger.debug('Sending magic package to: {}'.format(mac)) + result_code_wake, p_out_wake, p_err_wake = self.execute(self.wake_command.format(mac)) + + if p_err_wake != '': + self.logger.debug( + 'An error occured while sending magic package. Mac Address: {}'.format(mac)) + raise Exception(p_err_wake) + + time.sleep(int(self.time_list[i])) + + is_open = False + + if self.ip_address_list: + ip_addresses = str(self.ip_address_list[i]).split(',') + + if self.port_list: + ports = str(self.port_list[i]).split(',') + for j, ip in enumerate(ip_addresses): + for port in ports: + self.logger.debug('Scanning the port. Port: {0}, IP: {1}'.format(port, ip)) + result_code, out, err = self.execute(self.port_control.format(port, ip, port)) + + if err != '': + self.logger.debug( + 'An error occured while scanning the port. Mac Address(es): {0}, Ip Address: {1}, Port: {2}'.format( + val, ip, port)) + + if 'open' in out: + self.logger.debug( + 'Machine is awake. Mac Address(es): {0}, Ip Address: {1}, Port: {2}'.format( + val, ip, port)) + result_list.append( + 'Bilgisayar açık. Mac Adres(ler)i: {0}, Ip Adres(ler)i: {1}, Port: {2}'.format( + val, ip, port)) + is_open = True + else: + self.logger.debug('Port list is empty! Waking control could not be done!') + else: + self.logger.debug('Ip address list is empty! Waking control could not be done!') + + if is_open == False: + self.logger.debug('The machine is not awake or ip adresses are wrong ' \ + 'or ports are close. Mac Address(es): {0}, Ip Address(es): {1}, Port(s): {2}'.format( + val, self.ip_address_list[i], self.port_list[i])) + result_list.append('Bilgisayar açık değil, belirtilen ip adresleri yanlış ya da ' \ + 'portlar kapalı. Mac Adres(ler)i: {0}, Ip Adres(ler)i: {1}, Port(lar): {2}'.format( + val, self.ip_address_list[i], self.port_list[i])) + + response = ' - '.join(result_list) + self.context.create_response(code=self.message_code.TASK_PROCESSED.value, + message=response) + self.logger.info('WOL task is handled successfully') + + else: + raise Exception('Mac address list is empty!') + + except Exception as e: + self.logger.error('A problem occured while handling WOL task: {0}'.format(str(e))) + self.context.create_response(code=self.message_code.TASK_ERROR.value, + message='WOL görevi uygulanırken bir hata oluştu.') + + +def handle_task(task, context): + wake = WakeMachine(task, context) + wake.handle_task() diff --git a/opt/ahenk/test.txt b/opt/ahenk/test.txt new file mode 100644 index 0000000..e69de29