source: ogAgent-Git/src/opengnsys/modules/server/OpenGnSys/__init__.py @ ee08932

browser-nuevodecorare-oglive-methodsexec-ogbrowserfix-urlfixes-winlgromero-filebeatlog-sess-lenmainmodulesnew-browserno-ptt-paramno-tlsogadmcliogadmclient-statusogagent-jobsogagent-macosogagentuser-sigtermogcore1oggitoggit-notlsogliveoglogoglog2override-moduleping1ping2ping3ping4py3-winpython3qndtestreport-progresssched-tasktlstls-againunification2unification3versionswindows-fixes
Last change on this file since ee08932 was 5d68449, checked in by ramon <ramongomez@…>, 9 years ago

#718: Aproximación para incluir seguridad en la comunicación OGAgent-OpenGnsys, incluyendo una clave de seguridad aleatoria en la operación de inicio de OGAgent que deberá ser utilizada posteriormente por el servidor OpenGnsys.

git-svn-id: https://opengnsys.es/svn/branches/version1.1@4978 a21b9725-9963-47de-94b9-378ad31fedc9

  • Property mode set to 100644
File size: 8.8 KB
Line 
1# -*- coding: utf-8 -*-
2#
3# Copyright (c) 2014 Virtual Cable S.L.
4# All rights reserved.
5#
6# Redistribution and use in source and binary forms, with or without modification,
7# are permitted provided that the following conditions are met:
8#
9#    * Redistributions of source code must retain the above copyright notice,
10#      this list of conditions and the following disclaimer.
11#    * Redistributions in binary form must reproduce the above copyright notice,
12#      this list of conditions and the following disclaimer in the documentation
13#      and/or other materials provided with the distribution.
14#    * Neither the name of Virtual Cable S.L. nor the names of its contributors
15#      may be used to endorse or promote products derived from this software
16#      without specific prior written permission.
17#
18# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28'''
29@author: Adolfo Gómez, dkmaster at dkmon dot com
30'''
31from __future__ import unicode_literals
32
33from opengnsys.workers import ServerWorker
34
35from opengnsys import REST, RESTError
36from opengnsys import operations
37from opengnsys.log import logger
38from opengnsys.scriptThread import ScriptExecutorThread
39
40import subprocess
41import threading
42import thread
43import os
44import platform
45import time
46import random
47import string
48
49# Error handler decorator.
50def catchBackgroundError(fnc):
51    def wrapper(*args, **kwargs):
52        this = args[0]
53        try:
54            fnc(*args, **kwargs)
55        except Exception as e:
56            this.REST.sendMessage('error?id={}'.format(kwargs.get('requestId', 'error')), {'error': '{}'.format(e)})
57    return wrapper
58
59class OpenGnSysWorker(ServerWorker):
60    name = 'opengnsys'
61    interface = None  # Binded interface for OpenGnsys
62    loggedin = False  # User session flag
63    locked = {}
64    random = None     # Random string for secure connections
65    length = 32       # Random string length
66   
67    def onActivation(self):
68        self.cmd = None
69        self.random = ''.join(random.choice(string.ascii_lowercase + string.digits) for _ in range(self.length))
70        # Ensure cfg has required configuration variables or an exception will be thrown
71       
72        self.REST = REST(self.service.config.get('opengnsys', 'remote'))
73       
74        # Get network interfaces
75        self.interface = list(operations.getNetworkInfo())[0]  # Get first network interface
76       
77        # Send an initialize message
78        #self.REST.sendMessage('initialize/{}/{}'.format(self.interface.mac, self.interface.ip))
79       
80        # Send an POST message
81        self.REST.sendMessage('ogagent/started', {'mac': self.interface.mac, 'ip': self.interface.ip, 'secret': self.random})
82       
83    def onDeactivation(self):
84        #self.REST.sendMessage('deinitialize/{}/{}'.format(self.interface.mac, self.interface.ip))
85        logger.debug('onDeactivation')
86        self.REST.sendMessage('ogagent/stopped', {'mac': self.interface.mac, 'ip': self.interface.ip})
87   
88    # Processes message "doit" (sample)   
89    #def process_doit(self, path, getParams, postParams):
90    #   # Send a sample message to client
91    #   logger.debug('Processing doit')
92    #   self.sendClientMessage('doit', {'param1': 'test', 'param2': 'test2'})
93    #   return 'Processed message for {}, {}, {}'.format(path, getParams, postParams)
94   
95    def process_script(self, path, getParams, postParams, server):
96        '''
97        Processes an script execution (script is encoded in base64)
98        '''
99        logger.debug('Processing script request')
100        script = postParams.get('script')
101        secret = getParams.get('secret')
102        if secret != self.random:
103            logger.error('Unauthorized operation.')
104            raise Exception('Unauthorized operation')
105        if postParams.get('client', 'false') == 'false':
106            thr = ScriptExecutorThread(script=script.decode('base64'))
107            thr.start()
108        else:
109            self.sendScriptMessage(script)
110           
111        return 'ok'
112   
113    def processClientMessage(self, message, data):
114        logger.debug('Got OpenGnsys message from client: {}, data {}'.format(message, data))
115   
116    def process_client_doit(self, params):
117        self.REST.sendMessage('doit_done', params)
118   
119    def onLogin(self, user):
120        logger.debug('Received login for {}'.format(user))
121        self.loggedin = True
122        self.REST.sendMessage('ogagent/loggedin', {'ip': self.interface.ip, 'user': user, 'ostype': operations.osType, 'osversion': operations.osVersion})       
123
124    def onLogout(self, user):
125        logger.debug('Received logout for {}'.format(user))
126        self.loggedin = False
127        self.REST.sendMessage('ogagent/loggedout', {'ip': self.interface.ip, 'user': user, 'ostype': operations.osType, 'osversion': operations.osVersion})       
128
129    def process_ogclient(self, path, getParams, postParams, server):
130        '''
131        This method can be overriden to provide your own message proccessor, or better you can
132        implement a method that is called exactly as "process_" + path[0] (module name has been removed from path array) and this default processMessage will invoke it
133        * Example:
134            Imagine this invocation url (no matter if GET or POST): http://example.com:9999/Sample/mazinger/Z
135            The HTTP Server will remove "Sample" from path, parse arguments and invoke this method as this:
136            module.processMessage(["mazinger","Z"], getParams, postParams)
137           
138            This method will process "mazinger", and look for a "self" method that is called "process_mazinger", and invoke it this way:
139               return self.process_mazinger(["Z"], getParams, postParams)
140               
141            In the case path is empty (that is, the path is composed only by the module name, like in "http://example.com/Sample", the "process" method
142            will be invoked directly
143           
144            The methods must return data that can be serialized to json (i.e. Ojects are not serializable to json, basic type are)
145        '''
146        if len(path) == 0:
147            return "ok"
148        try:
149            operation = getattr(self, 'ogclient_' + path[0])
150        except Exception:
151            raise Exception('Message processor for "{}" not found'.format(path[0]))
152       
153        return operation(path[1:], getParams, postParams)
154       
155    ###### EN PRUEBAS ######
156    def process_status(self, path, getParams, postParams, server):
157        '''
158        Returns client status.
159        '''
160        res = { 'status': '', 'loggedin': self.loggedin }
161        if platform.system() == 'Linux':        # GNU/Linux
162            # Check if it's OpenGnsys Client.
163            if os.path.exists('/scripts/oginit'):
164                # Check if OpenGnsys Client is busy.
165                if self.locked:
166                    res['status'] = 'BSY'
167                else:
168                    res['status'] = 'OPG'
169            else:
170                # Check if there is an active session.
171                res['status'] = 'LNX'
172        elif platform.system() == 'Windows':    # Windows
173            # Check if there is an active session.
174            res['status'] = 'WIN'
175        elif platform.system() == 'Darwin':     # Mac OS X  ??
176            res['status'] = 'OSX'
177        return res
178   
179    def process_reboot(self, path, getParams, postParams, server):
180        '''
181        Launches a system reboot operation.
182        '''
183        logger.debug('Received reboot operation')
184        def rebt():
185            operations.reboot()
186        threading.Thread(target=rebt).start()
187        return {'op': 'launched'}
188
189    def process_poweroff(self, path, getParams, postParams, server):
190        '''
191        Launches a system power off operation.
192        '''
193        logger.debug('Received poweroff operation')
194        def pwoff():
195            time.sleep(2)
196            operations.poweroff()
197        threading.Thread(target=pwoff).start()
198        return {'op': 'launched'}
199
200    def process_logoff(self, path, getParams, postParams, server):
201        '''
202        Closes user session.
203        '''
204        logger.debug('Received logoff operation')
205        self.sendClientMessage('logoff', {})
206        return 'Logoff operation was sended to client'
207
Note: See TracBrowser for help on using the repository browser.