forked from shaba/openuds
Advancing on new UDS actor
This commit is contained in:
parent
e967d994b1
commit
282816b4eb
@ -54,7 +54,7 @@ class UDSConfigDialog(QDialog):
|
||||
def __init__(self):
|
||||
QDialog.__init__(self, None)
|
||||
# Get local config config
|
||||
config: udsactor.types.ActorConfigurationType = udsactor.store.readConfig()
|
||||
config: udsactor.types.ActorConfigurationType = udsactor.platform.store.readConfig()
|
||||
self.ui = Ui_UdsActorSetupDialog()
|
||||
self.ui.setupUi(self)
|
||||
self.ui.host.setText(config.host)
|
||||
@ -109,13 +109,13 @@ class UDSConfigDialog(QDialog):
|
||||
|
||||
def registerWithUDS(self):
|
||||
# Get network card. Will fail if no network card is available, but don't mind (not contempled)
|
||||
data: udsactor.types.InterfaceInfoType = next(udsactor.operations.getNetworkInfo())
|
||||
data: udsactor.types.InterfaceInfoType = next(udsactor.platform.operations.getNetworkInfo())
|
||||
try:
|
||||
token = self.api.register(
|
||||
self.ui.authenticators.currentData().auth,
|
||||
self.ui.username.text(),
|
||||
self.ui.password.text(),
|
||||
udsactor.operations.getComputerName(),
|
||||
udsactor.platform.operations.getComputerName(),
|
||||
data.ip or '', # IP
|
||||
data.mac or '', # MAC
|
||||
self.ui.preCommand.text(),
|
||||
@ -124,7 +124,7 @@ class UDSConfigDialog(QDialog):
|
||||
self.ui.logLevelComboBox.currentIndex() # Loglevel
|
||||
)
|
||||
# Store parameters on register for later use, notify user of registration
|
||||
udsactor.store.writeConfig(
|
||||
udsactor.platform.store.writeConfig(
|
||||
udsactor.types.ActorConfigurationType(
|
||||
host=self.ui.host.text(),
|
||||
validateCertificate=self.ui.validateCertificate.currentIndex() == 1,
|
||||
@ -148,7 +148,7 @@ if __name__ == "__main__":
|
||||
|
||||
app = QApplication(sys.argv)
|
||||
|
||||
if udsactor.store.checkPermissions() is False:
|
||||
if udsactor.platform.operations.checkPermissions() is False:
|
||||
QMessageBox.critical(None, 'UDS Actor', 'This Program must be executed as administrator', QMessageBox.Ok)
|
||||
sys.exit(1)
|
||||
|
||||
|
@ -28,23 +28,11 @@
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
import sys
|
||||
|
||||
from . import types
|
||||
from . import rest
|
||||
|
||||
if sys.platform == 'win32':
|
||||
from .windows import operations, store
|
||||
else:
|
||||
from .linux import operations, store
|
||||
|
||||
from .info import VERSION
|
||||
|
||||
from . import platform
|
||||
|
||||
__title__ = 'udsactor'
|
||||
__version__ = VERSION
|
||||
__build__ = 0x010756
|
||||
__author__ = 'Adolfo Gómez <dkmaster@dkmon.com>'
|
||||
__license__ = "BSD 3-clause"
|
||||
__copyright__ = "Copyright 2014-2019 VirtualCable S.L.U."
|
||||
|
||||
|
@ -25,12 +25,10 @@
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
from __future__ import unicode_literals
|
||||
|
||||
# pylint: disable=invalid-name
|
||||
import logging
|
||||
import os
|
||||
import tempfile
|
||||
@ -40,14 +38,16 @@ import six
|
||||
OTHER, DEBUG, INFO, WARN, ERROR, FATAL = (10000 * (x + 1) for x in six.moves.xrange(6)) # @UndefinedVariable
|
||||
|
||||
|
||||
class LocalLogger(object):
|
||||
class LocalLogger: # pylint: disable=too-few-public-methods
|
||||
linux = False
|
||||
windows = True
|
||||
|
||||
def __init__(self):
|
||||
# tempdir is different for "user application" and "service"
|
||||
# service wil get c:\windows\temp, while user will get c:\users\XXX\temp
|
||||
# Try to open logger at /var/log path
|
||||
# If it fails (access denied normally), will try to open one at user's home folder, and if
|
||||
# agaim it fails, open it at the tmpPath
|
||||
|
||||
for logDir in ('/var/log', os.path.expanduser('~'), tempfile.gettempdir()):
|
||||
try:
|
||||
fname = os.path.join(logDir, 'udsactor.log')
|
||||
@ -66,15 +66,9 @@ class LocalLogger(object):
|
||||
# Logger can't be set
|
||||
self.logger = None
|
||||
|
||||
def log(self, level, message):
|
||||
def log(self, level: int, message: str) -> None:
|
||||
# Debug messages are logged to a file
|
||||
# our loglevels are 10000 (other), 20000 (debug), ....
|
||||
# logging levels are 10 (debug), 20 (info)
|
||||
# OTHER = logging.NOTSET
|
||||
self.logger.log(int(level / 1000) - 10, message)
|
||||
|
||||
def isWindows(self):
|
||||
return False
|
||||
|
||||
def isLinux(self):
|
||||
return True
|
||||
|
@ -106,6 +106,10 @@ def _getIpAndMac(ifname: str) -> typing.Tuple[typing.Optional[str], typing.Optio
|
||||
return (ip, mac)
|
||||
|
||||
|
||||
def checkPermissions() -> bool:
|
||||
return os.getuid() == 0
|
||||
|
||||
|
||||
def getComputerName() -> str:
|
||||
'''
|
||||
Returns computer name, with no domain
|
||||
|
@ -25,10 +25,10 @@
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
# pylint: disable=invalid-name
|
||||
import os
|
||||
import configparser
|
||||
import base64
|
||||
@ -38,15 +38,15 @@ from .. import types
|
||||
|
||||
CONFIGFILE = '/etc/udsactor/udsactor.cfg'
|
||||
|
||||
def checkPermissions() -> bool:
|
||||
return os.getuid() == 0
|
||||
|
||||
def readConfig() -> types.ActorConfigurationType:
|
||||
try:
|
||||
cfg = configparser.ConfigParser()
|
||||
cfg.read(CONFIGFILE)
|
||||
uds: configparser.SectionProxy = cfg['uds']
|
||||
# Extract data:
|
||||
base64Config = uds.get('config', None)
|
||||
config = pickle.loads(base64.b64decode(base64Config.encode())) if base64Config else None
|
||||
|
||||
base64Data = uds.get('data', None)
|
||||
data = pickle.loads(base64.b64decode(base64Data.encode())) if base64Data else None
|
||||
|
||||
@ -59,6 +59,7 @@ def readConfig() -> types.ActorConfigurationType:
|
||||
runonce_command=uds.get('runonce_command', None),
|
||||
post_command=uds.get('post_command', None),
|
||||
log_level=int(uds.get('log_level', '1')),
|
||||
config=config,
|
||||
data=data
|
||||
)
|
||||
except Exception:
|
||||
@ -80,6 +81,9 @@ def writeConfig(config: types.ActorConfigurationType) -> None:
|
||||
writeIfValue(config.post_command, 'post_command')
|
||||
writeIfValue(config.runonce_command, 'runonce_command')
|
||||
uds['log_level'] = str(config.log_level)
|
||||
if config.config: # Special case, encoded & dumped
|
||||
uds['config'] = base64.b64encode(pickle.dumps(config.config)).decode()
|
||||
|
||||
if config.data: # Special case, encoded & dumped
|
||||
uds['data'] = base64.b64encode(pickle.dumps(config.data)).decode()
|
||||
|
||||
|
36
actor/src/udsactor/platform.py
Normal file
36
actor/src/udsactor/platform.py
Normal file
@ -0,0 +1,36 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
import sys
|
||||
|
||||
if sys.platform == 'win32':
|
||||
from .windows import operations, store # pylint: disable=unused-import
|
||||
else:
|
||||
from .linux import operations, store # pylint: disable=unused-import
|
@ -37,6 +37,7 @@ import typing
|
||||
import requests
|
||||
|
||||
from . import types
|
||||
from .info import VERSION
|
||||
|
||||
class RESTError(Exception):
|
||||
ERRCODE = 0
|
||||
@ -177,3 +178,31 @@ class REST:
|
||||
pass
|
||||
|
||||
raise RESTError(result.content)
|
||||
|
||||
def initialize(self, token: str, interfaces: typing.Iterable[types.InterfaceInfoType]) -> types.InitializationResultType:
|
||||
# Generate id list from netork cards
|
||||
payload = {
|
||||
'token': token,
|
||||
'version': VERSION,
|
||||
'id': [{'mac': i.mac, 'ip': i.ip} for i in interfaces]
|
||||
}
|
||||
try:
|
||||
result = requests.post(self.url + 'actor/v2/initialize', data=json.dumps(payload), headers=self._headers, verify=self.validateCert)
|
||||
if result.ok:
|
||||
r = result.json()['result']
|
||||
return types.InitializationResultType(
|
||||
own_token=r['own_token'],
|
||||
unique_id=r['unique_id'],
|
||||
max_idle=r['max_idle'],
|
||||
os=r['os']
|
||||
)
|
||||
except requests.ConnectionError as e:
|
||||
raise RESTConnectionError(str(e))
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
raise RESTError(result.content)
|
||||
|
||||
def ready(self, own_token: str, interfaces: typing.Iterable[types.InterfaceInfoType]) -> None:
|
||||
# TODO: implement ready
|
||||
return
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 201 Virtual Cable S.L.
|
||||
# Copyright (c) 2019 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -25,27 +25,23 @@
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
|
||||
# pylint: disable-msg=E1101,W0703
|
||||
# pylint: disable=invalid-name
|
||||
import threading
|
||||
|
||||
from udsactor.log import logger
|
||||
|
||||
import threading
|
||||
import six
|
||||
|
||||
|
||||
class ScriptExecutorThread(threading.Thread):
|
||||
def __init__(self, script):
|
||||
def __init__(self, script: str) -> None:
|
||||
super(ScriptExecutorThread, self).__init__()
|
||||
self.script = script
|
||||
|
||||
def run(self):
|
||||
def run(self) -> None:
|
||||
try:
|
||||
logger.debug('Executing script: {}'.format(self.script))
|
||||
six.exec_(self.script, globals(), None)
|
||||
exec(self.script, globals(), None) # pylint: disable=exec-used
|
||||
except Exception as e:
|
||||
logger.error('Error executing script: {}'.format(e))
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# Copyright (c) 2014-2019 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -25,21 +25,10 @@
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from udsactor.log import logger
|
||||
|
||||
from . import operations
|
||||
from . import store
|
||||
from . import REST
|
||||
from . import ipc
|
||||
from . import httpserver
|
||||
from .scriptThread import ScriptExecutorThread
|
||||
from .utils import exceptionToMessage
|
||||
# pylint: disable=invalid-name
|
||||
|
||||
import socket
|
||||
import time
|
||||
@ -49,51 +38,39 @@ import subprocess
|
||||
import shlex
|
||||
import stat
|
||||
import json
|
||||
import typing
|
||||
|
||||
IPC_PORT = 39188
|
||||
|
||||
cfg = None
|
||||
from . import platform
|
||||
from . import rest
|
||||
from . import types
|
||||
from .script_thread import ScriptExecutorThread
|
||||
from .utils import exceptionToMessage
|
||||
from .log import logger
|
||||
|
||||
|
||||
def initCfg():
|
||||
global cfg # pylint: disable=global-statement
|
||||
cfg = store.readConfig()
|
||||
# def setup() -> None:
|
||||
# cfg = platform.store.readConfig()
|
||||
|
||||
if logger.logger.isWindows():
|
||||
# Logs will also go to windows event log for services
|
||||
logger.logger.serviceLogger = True
|
||||
# if logger.logger.windows:
|
||||
# # Logs will also go to windows event log for services
|
||||
# logger.logger.serviceLogger = True
|
||||
|
||||
if cfg is not None:
|
||||
logger.setLevel(cfg.get('logLevel', 20000))
|
||||
else:
|
||||
logger.setLevel(20000)
|
||||
cfg = {}
|
||||
|
||||
# If ANY var is missing, reset cfg
|
||||
for v in ('host', 'ssl', 'masterKey'):
|
||||
if v not in cfg:
|
||||
cfg = None
|
||||
break
|
||||
|
||||
return cfg
|
||||
# if cfg.x:
|
||||
# logger.setLevel(cfg.get('logLevel', 20000))
|
||||
# else:
|
||||
# logger.setLevel(20000)
|
||||
|
||||
|
||||
class CommonService(object):
|
||||
class CommonService:
|
||||
_isAlive: bool = True
|
||||
_rebootRequested: bool = False
|
||||
_loggedIn = False
|
||||
_cfg: types.ActorConfigurationType
|
||||
_api: rest.REST
|
||||
_interfaces: typing.List[types.InterfaceInfoType]
|
||||
|
||||
def __init__(self):
|
||||
self.isAlive = True
|
||||
self.api = None
|
||||
self.ipc = None
|
||||
self.httpServer = None
|
||||
self.rebootRequested = False
|
||||
self.knownIps = []
|
||||
self.loggedIn = False
|
||||
socket.setdefaulttimeout(20)
|
||||
|
||||
def reboot(self):
|
||||
self.rebootRequested = True
|
||||
|
||||
def execute(self, cmdLine, section): # pylint: disable=no-self-use
|
||||
@staticmethod
|
||||
def execute(cmdLine: str, section: str):
|
||||
cmd = shlex.split(cmdLine, posix=False)
|
||||
|
||||
if os.path.isfile(cmd[0]):
|
||||
@ -105,70 +82,59 @@ class CommonService(object):
|
||||
return False
|
||||
logger.info('Result of executing cmd was {}'.format(res))
|
||||
return True
|
||||
else:
|
||||
logger.error('{} file exists but it it is not executable (needs execution permission by admin/root)'.format(section))
|
||||
logger.error('{} file exists but it it is not executable (needs execution permission by admin/root)'.format(section))
|
||||
else:
|
||||
logger.error('{} file not found & not executed'.format(section))
|
||||
|
||||
return False
|
||||
|
||||
def setReady(self):
|
||||
self.api.setReady([(v.mac, v.ip) for v in operations.getNetworkInfo()])
|
||||
def __init__(self):
|
||||
self._cfg = platform.store.readConfig()
|
||||
self._interfaces = []
|
||||
self._api = rest.REST(self._cfg.host, self._cfg.validateCert)
|
||||
|
||||
def interactWithBroker(self):
|
||||
'''
|
||||
Returns True to continue to main loop, false to stop & exit service
|
||||
'''
|
||||
# If no configuration is found, stop service
|
||||
if cfg is None:
|
||||
logger.fatal('No configuration found, stopping service')
|
||||
socket.setdefaulttimeout(20)
|
||||
|
||||
def reboot(self) -> None:
|
||||
self._rebootRequested = True
|
||||
|
||||
def setReady(self) -> None:
|
||||
if self._cfg.own_token and self._interfaces:
|
||||
self._api.ready(self._cfg.own_token, self._interfaces)
|
||||
|
||||
def initialize(self) -> bool:
|
||||
if not self._cfg.host: # Not configured
|
||||
return False
|
||||
|
||||
self.api = REST.Api(cfg['host'], cfg['masterKey'], cfg['ssl'])
|
||||
|
||||
# Wait for Broker to be ready
|
||||
counter = 0
|
||||
while self.isAlive:
|
||||
try:
|
||||
# getNetworkInfo is a generator function
|
||||
netInfo = tuple(operations.getNetworkInfo())
|
||||
self.knownIps = dict(((i.mac, i.ip) for i in netInfo))
|
||||
ids = ','.join([i.mac for i in netInfo])
|
||||
if ids == '':
|
||||
# Wait for any network interface to be ready
|
||||
logger.debug('No valid network interfaces found, retrying in a while...')
|
||||
raise Exception()
|
||||
logger.debug('Ids: {}'.format(ids))
|
||||
self.api.init(ids)
|
||||
# Set remote logger to notify log info to broker
|
||||
logger.setRemoteLogger(self.api)
|
||||
while self._isAlive:
|
||||
if not self._interfaces:
|
||||
self._interfaces = list(platform.operations.getNetworkInfo())
|
||||
continue
|
||||
|
||||
break
|
||||
except REST.InvalidKeyError:
|
||||
logger.fatal('Can\'t sync with broker: Invalid broker Master Key')
|
||||
return False
|
||||
except REST.UnmanagedHostError:
|
||||
# Maybe interface that is registered with broker is not enabled already?
|
||||
# Right now, we thing that the interface connected to broker is
|
||||
# the interface that broker will know, let's see how this works
|
||||
logger.fatal('This host is not managed by UDS Broker (ids: {})'.format(ids))
|
||||
return False # On unmanaged hosts, there is no reason right now to continue running
|
||||
except Exception as e:
|
||||
logger.debug('Exception on network info: retrying')
|
||||
# Any other error is expectable and recoverable, so let's wait a bit and retry again
|
||||
# but, if too many errors, will log it (one every minute, for
|
||||
# example)
|
||||
counter += 1
|
||||
if counter % 60 == 0: # Every 5 minutes, raise a log
|
||||
logger.info('Trying to inititialize connection with broker (last error: {})'.format(exceptionToMessage(e)))
|
||||
# Wait a bit before next check
|
||||
self.doWait(5000)
|
||||
try:
|
||||
# If master token is present, initialize and get configuration data
|
||||
if self._cfg.master_token:
|
||||
initResult: types.InitializationResultType = self._api.initialize(self._cfg.master_token, self._interfaces)
|
||||
if not initResult.own_token: # Not managed
|
||||
logger.fatal('This host is not managed by UDS Broker (ids: {})'.format(ids))
|
||||
return False
|
||||
break # Initial configuration done..
|
||||
except rest.RESTConnectionError:
|
||||
logger.info('Trying to inititialize connection with broker (last error: {})'.format(exceptionToMessage(e)))
|
||||
self.doWait(5000) # Wait a bit and retry
|
||||
except rest.RESTError as e: # Invalid key?
|
||||
logger.error('Error validating with broker. (Invalid token?): {}'.format(e))
|
||||
|
||||
self._cfg.own_token = initResult.own_token
|
||||
self._cfg.master_token = None
|
||||
|
||||
# Now try to run the "runonce" element
|
||||
runOnce = store.runApplication()
|
||||
if runOnce is not None:
|
||||
if self._cfg.runonce_command:
|
||||
logger.info('Executing runOnce app: {}'.format(runOnce))
|
||||
if self.execute(runOnce, 'RunOnce') is True:
|
||||
if self.execute(self._cfg.runonce_command, 'RunOnce'):
|
||||
self._cfg.runonce_command = None
|
||||
platform.store.writeConfig(self._cfg)
|
||||
# operations.reboot()
|
||||
return False
|
||||
|
||||
|
@ -13,6 +13,20 @@ class AuthenticatorType(typing.NamedTuple):
|
||||
priority: int
|
||||
isCustom: bool
|
||||
|
||||
class ActorOsConfigurationType(typing.NamedTuple):
|
||||
action: str
|
||||
name: str
|
||||
username: typing.Optional[str] = None
|
||||
password: typing.Optional[str] = None
|
||||
new_password: typing.Optional[str] = None
|
||||
ad: typing.Optional[str] = None
|
||||
ou: typing.Optional[str] = None
|
||||
|
||||
class ActorDataConfigurationType(typing.NamedTuple):
|
||||
unique_id: typing.Optional[str] = None
|
||||
max_idle: typing.Optional[int] = None
|
||||
os: typing.Optional[ActorOsConfigurationType] = None
|
||||
|
||||
class ActorConfigurationType(typing.NamedTuple):
|
||||
host: str
|
||||
validateCertificate: bool
|
||||
@ -25,4 +39,9 @@ class ActorConfigurationType(typing.NamedTuple):
|
||||
|
||||
log_level: int = 0
|
||||
|
||||
data: typing.Optional[typing.Dict[str, str]] = None
|
||||
config: typing.Optional[ActorDataConfigurationType] = None
|
||||
|
||||
data: typing.Optional[typing.Dict[str, typing.Any]] = None
|
||||
|
||||
class InitializationResultType(ActorDataConfigurationType):
|
||||
own_token: typing.Optional[str] = None
|
||||
|
@ -25,35 +25,40 @@
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import servicemanager # @UnresolvedImport, pylint: disable=import-error
|
||||
# pylint: disable=invalid-name
|
||||
import logging
|
||||
import os
|
||||
import tempfile
|
||||
|
||||
import servicemanager # @UnresolvedImport, pylint: disable=import-error
|
||||
|
||||
# Valid logging levels, from UDS Broker (uds.core.utils.log)
|
||||
OTHER, DEBUG, INFO, WARN, ERROR, FATAL = (10000 * (x + 1) for x in range(6))
|
||||
|
||||
class LocalLogger: # pylint: disable=too-few-public-methods
|
||||
linux = False
|
||||
windows = True
|
||||
|
||||
class LocalLogger(object):
|
||||
def __init__(self):
|
||||
# tempdir is different for "user application" and "service"
|
||||
# service wil get c:\windows\temp, while user will get c:\users\XXX\temp
|
||||
logging.basicConfig(
|
||||
filename=os.path.join(tempfile.gettempdir(), 'udsactor.log'),
|
||||
filemode='a',
|
||||
format='%(levelname)s %(asctime)s %(message)s',
|
||||
level=logging.INFO
|
||||
)
|
||||
try:
|
||||
logging.basicConfig(
|
||||
filename=os.path.join(tempfile.gettempdir(), 'udsactor.log'),
|
||||
filemode='a',
|
||||
format='%(levelname)s %(asctime)s %(message)s',
|
||||
level=logging.INFO
|
||||
)
|
||||
except Exception:
|
||||
logging.basicConfig() # basic init
|
||||
|
||||
self.logger = logging.getLogger('udsactor')
|
||||
self.serviceLogger = False
|
||||
|
||||
def log(self, level, message):
|
||||
def log(self, level: int, message: str) -> None:
|
||||
# Debug messages are logged to a file
|
||||
# our loglevels are 10000 (other), 20000 (debug), ....
|
||||
# logging levels are 10 (debug), 20 (info)
|
||||
@ -69,9 +74,3 @@ class LocalLogger(object):
|
||||
servicemanager.LogWarningMsg(message)
|
||||
else: # Error & Fatal
|
||||
servicemanager.LogErrorMsg(message)
|
||||
|
||||
def isWindows(self):
|
||||
return True
|
||||
|
||||
def isLinux(self):
|
||||
return False
|
||||
|
@ -35,6 +35,7 @@ from ctypes.wintypes import DWORD, LPCWSTR
|
||||
import typing
|
||||
|
||||
import win32com.client
|
||||
from win32com.shell import shell # pylint: disable=no-name-in-module,import-error
|
||||
import win32net
|
||||
import win32security
|
||||
import win32api
|
||||
@ -43,6 +44,9 @@ import win32con
|
||||
from .. import types
|
||||
from ..log import logger
|
||||
|
||||
def checkPermissions() -> bool:
|
||||
return shell.IsUserAnAdmin()
|
||||
|
||||
def getErrorMessage(resultCode: int = 0) -> str:
|
||||
# sys_fs_enc = sys.getfilesystemencoding() or 'mbcs'
|
||||
msg = win32api.FormatMessage(resultCode)
|
||||
|
@ -34,16 +34,11 @@ import pickle
|
||||
import winreg as wreg
|
||||
import win32security
|
||||
|
||||
from win32com.shell import shell # pylint: disable=no-name-in-module,import-error
|
||||
|
||||
from .. import types
|
||||
|
||||
PATH = 'Software\\UDSActor'
|
||||
BASEKEY = wreg.HKEY_LOCAL_MACHINE
|
||||
|
||||
def checkPermissions() -> bool:
|
||||
return shell.IsUserAnAdmin()
|
||||
|
||||
def fixRegistryPermissions(handle) -> None:
|
||||
# Fix permissions so users can't read this key
|
||||
v = win32security.GetSecurityInfo(handle, win32security.SE_REGISTRY_KEY, win32security.DACL_SECURITY_INFORMATION)
|
||||
@ -65,7 +60,6 @@ def fixRegistryPermissions(handle) -> None:
|
||||
None
|
||||
)
|
||||
|
||||
|
||||
def readConfig() -> types.ActorConfigurationType:
|
||||
try:
|
||||
key = wreg.OpenKey(BASEKEY, PATH, 0, wreg.KEY_QUERY_VALUE) # @UndefinedVariable
|
||||
|
Loading…
Reference in New Issue
Block a user