forked from shaba/openuds
Advancing on new UDS Actor
This commit is contained in:
parent
282816b4eb
commit
e76df6349d
@ -190,11 +190,20 @@ class REST:
|
|||||||
result = requests.post(self.url + 'actor/v2/initialize', data=json.dumps(payload), headers=self._headers, verify=self.validateCert)
|
result = requests.post(self.url + 'actor/v2/initialize', data=json.dumps(payload), headers=self._headers, verify=self.validateCert)
|
||||||
if result.ok:
|
if result.ok:
|
||||||
r = result.json()['result']
|
r = result.json()['result']
|
||||||
|
os = r['os']
|
||||||
return types.InitializationResultType(
|
return types.InitializationResultType(
|
||||||
own_token=r['own_token'],
|
own_token=r['own_token'],
|
||||||
unique_id=r['unique_id'],
|
unique_id=r['unique_id'],
|
||||||
max_idle=r['max_idle'],
|
max_idle=r['max_idle'],
|
||||||
os=r['os']
|
os=types.ActorOsConfigurationType(
|
||||||
|
action=os['action'],
|
||||||
|
name=os['name'],
|
||||||
|
username=os.get('username'),
|
||||||
|
password=os.get('password'),
|
||||||
|
new_password=os.get('new_password'),
|
||||||
|
ad=os.get('ad'),
|
||||||
|
ou=os.get('ou')
|
||||||
|
)
|
||||||
)
|
)
|
||||||
except requests.ConnectionError as e:
|
except requests.ConnectionError as e:
|
||||||
raise RESTConnectionError(str(e))
|
raise RESTConnectionError(str(e))
|
||||||
@ -206,3 +215,7 @@ class REST:
|
|||||||
def ready(self, own_token: str, interfaces: typing.Iterable[types.InterfaceInfoType]) -> None:
|
def ready(self, own_token: str, interfaces: typing.Iterable[types.InterfaceInfoType]) -> None:
|
||||||
# TODO: implement ready
|
# TODO: implement ready
|
||||||
return
|
return
|
||||||
|
|
||||||
|
def notifyIpChange(self, own_token: str, ip: str) -> None:
|
||||||
|
# TODO: implement notifyIpChange
|
||||||
|
return
|
@ -32,19 +32,16 @@
|
|||||||
|
|
||||||
import socket
|
import socket
|
||||||
import time
|
import time
|
||||||
import random
|
|
||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
import shlex
|
import shlex
|
||||||
import stat
|
import stat
|
||||||
import json
|
|
||||||
import typing
|
import typing
|
||||||
|
|
||||||
from . import platform
|
from . import platform
|
||||||
from . import rest
|
from . import rest
|
||||||
from . import types
|
from . import types
|
||||||
from .script_thread import ScriptExecutorThread
|
# from .script_thread import ScriptExecutorThread
|
||||||
from .utils import exceptionToMessage
|
|
||||||
from .log import logger
|
from .log import logger
|
||||||
|
|
||||||
|
|
||||||
@ -101,6 +98,36 @@ class CommonService:
|
|||||||
def setReady(self) -> None:
|
def setReady(self) -> None:
|
||||||
if self._cfg.own_token and self._interfaces:
|
if self._cfg.own_token and self._interfaces:
|
||||||
self._api.ready(self._cfg.own_token, self._interfaces)
|
self._api.ready(self._cfg.own_token, self._interfaces)
|
||||||
|
# Cleans sensible data
|
||||||
|
if self._cfg.config:
|
||||||
|
self._cfg._replace(config=self._cfg.config._replace(os=None), data=None)
|
||||||
|
platform.store.writeConfig(self._cfg)
|
||||||
|
|
||||||
|
def configureMachine(self) -> bool:
|
||||||
|
# Retry configurations, config in case of error 10 times
|
||||||
|
counter = 1
|
||||||
|
while counter < 10 and self._isAlive:
|
||||||
|
counter += 1
|
||||||
|
try:
|
||||||
|
if self._cfg.config and self._cfg.config.os:
|
||||||
|
osData = self._cfg.config.os
|
||||||
|
if osData.action == 'rename':
|
||||||
|
self.rename(osData.name, osData.username, osData.password, osData.new_password)
|
||||||
|
elif osData.action == 'rename_ad':
|
||||||
|
self.joinDomain(osData.name, osData.ad or '', osData.ou or '', osData.username or '', osData.password or '')
|
||||||
|
|
||||||
|
if self._rebootRequested:
|
||||||
|
try:
|
||||||
|
platform.operations.reboot()
|
||||||
|
except Exception as e:
|
||||||
|
logger.error('Exception on reboot: {}'.format(e))
|
||||||
|
return False # Stops service
|
||||||
|
break
|
||||||
|
except Exception as e:
|
||||||
|
logger.error('Got exception operationg machine: {}'.format(e))
|
||||||
|
self.doWait(5000)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
def initialize(self) -> bool:
|
def initialize(self) -> bool:
|
||||||
if not self._cfg.host: # Not configured
|
if not self._cfg.host: # Not configured
|
||||||
@ -110,203 +137,76 @@ class CommonService:
|
|||||||
while self._isAlive:
|
while self._isAlive:
|
||||||
if not self._interfaces:
|
if not self._interfaces:
|
||||||
self._interfaces = list(platform.operations.getNetworkInfo())
|
self._interfaces = list(platform.operations.getNetworkInfo())
|
||||||
continue
|
if not self._interfaces: # Wait a bit for interfaces to get initialized...
|
||||||
|
self.doWait(5000)
|
||||||
|
continue
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# If master token is present, initialize and get configuration data
|
# If master token is present, initialize and get configuration data
|
||||||
if self._cfg.master_token:
|
if self._cfg.master_token:
|
||||||
initResult: types.InitializationResultType = self._api.initialize(self._cfg.master_token, self._interfaces)
|
initResult: types.InitializationResultType = self._api.initialize(self._cfg.master_token, self._interfaces)
|
||||||
if not initResult.own_token: # Not managed
|
if not initResult.own_token: # Not managed
|
||||||
logger.fatal('This host is not managed by UDS Broker (ids: {})'.format(ids))
|
logger.debug('This host is not managed by UDS Broker (ids: {})'.format(self._interfaces))
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
self._cfg = self._cfg._replace(
|
||||||
|
master_token=None,
|
||||||
|
own_token=initResult.own_token,
|
||||||
|
config=types.ActorDataConfigurationType(
|
||||||
|
unique_id=initResult.unique_id,
|
||||||
|
max_idle=initResult.max_idle,
|
||||||
|
os=initResult.os
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
# On first successfull initialization request, master token will dissapear so it will be no more available (not needed anyway)
|
||||||
|
platform.store.writeConfig(self._cfg)
|
||||||
|
|
||||||
break # Initial configuration done..
|
break # Initial configuration done..
|
||||||
except rest.RESTConnectionError:
|
except rest.RESTConnectionError as e:
|
||||||
logger.info('Trying to inititialize connection with broker (last error: {})'.format(exceptionToMessage(e)))
|
logger.info('Trying to inititialize connection with broker (last error: {})'.format(e))
|
||||||
self.doWait(5000) # Wait a bit and retry
|
self.doWait(5000) # Wait a bit and retry
|
||||||
except rest.RESTError as e: # Invalid key?
|
except rest.RESTError as e: # Invalid key?
|
||||||
logger.error('Error validating with broker. (Invalid token?): {}'.format(e))
|
logger.error('Error validating with broker. (Invalid token?): {}'.format(e))
|
||||||
|
|
||||||
self._cfg.own_token = initResult.own_token
|
self.configureMachine()
|
||||||
self._cfg.master_token = None
|
|
||||||
|
|
||||||
# Now try to run the "runonce" element
|
|
||||||
if self._cfg.runonce_command:
|
|
||||||
logger.info('Executing runOnce app: {}'.format(runOnce))
|
|
||||||
if self.execute(self._cfg.runonce_command, 'RunOnce'):
|
|
||||||
self._cfg.runonce_command = None
|
|
||||||
platform.store.writeConfig(self._cfg)
|
|
||||||
# operations.reboot()
|
|
||||||
return False
|
|
||||||
|
|
||||||
# Broker connection is initialized, now get information about what to
|
|
||||||
# do
|
|
||||||
counter = 0
|
|
||||||
while self.isAlive:
|
|
||||||
try:
|
|
||||||
logger.debug('Requesting information of what to do now')
|
|
||||||
info = self.api.information()
|
|
||||||
data = info.split('\r')
|
|
||||||
if len(data) != 2:
|
|
||||||
logger.error('The format of the information message is not correct (got {})'.format(info))
|
|
||||||
raise Exception
|
|
||||||
params = data[1].split('\t')
|
|
||||||
if data[0] == 'rename':
|
|
||||||
try:
|
|
||||||
if len(params) == 1: # Simple rename
|
|
||||||
logger.debug('Renaming computer to {}'.format(params[0]))
|
|
||||||
self.rename(params[0])
|
|
||||||
# Rename with change password for an user
|
|
||||||
elif len(params) == 4:
|
|
||||||
logger.debug('Renaming computer to {}'.format(params))
|
|
||||||
self.rename(params[0], params[1], params[2], params[3])
|
|
||||||
else:
|
|
||||||
logger.error('Got invalid parameter for rename operation: {}'.format(params))
|
|
||||||
return False
|
|
||||||
break
|
|
||||||
except Exception as e:
|
|
||||||
logger.error('Error at computer renaming stage: {}'.format(e.message))
|
|
||||||
return None # Will retry complete broker connection if this point is reached
|
|
||||||
elif data[0] == 'domain':
|
|
||||||
if len(params) != 5:
|
|
||||||
logger.error('Got invalid parameters for domain message: {}'.format(params))
|
|
||||||
return False # Stop running service
|
|
||||||
self.joinDomain(params[0], params[1], params[2], params[3], params[4])
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
logger.error('Unrecognized action sent from broker: {}'.format(data[0]))
|
|
||||||
return False # Stop running service
|
|
||||||
except REST.UserServiceNotFoundError:
|
|
||||||
logger.error('The host has lost the sync state with broker! (host uuid changed?)')
|
|
||||||
return False
|
|
||||||
except Exception as err:
|
|
||||||
if counter % 60 == 0:
|
|
||||||
logger.warn('Too many retries in progress, though still trying (last error: {})'.format(exceptionToMessage(err)))
|
|
||||||
counter += 1
|
|
||||||
# Any other error is expectable and recoverable, so let's wait
|
|
||||||
# a bit and retry again
|
|
||||||
# Wait a bit before next check
|
|
||||||
self.doWait(5000)
|
|
||||||
|
|
||||||
if self.rebootRequested:
|
|
||||||
try:
|
|
||||||
operations.reboot()
|
|
||||||
except Exception as e:
|
|
||||||
logger.error('Exception on reboot: {}'.format(e.message))
|
|
||||||
return False # Stops service
|
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def checkIpsChanged(self):
|
def checkIpsChanged(self):
|
||||||
if self.api is None or self.api.uuid is None:
|
if not self._cfg.own_token or not self._cfg.config or not self._cfg.config.unique_id:
|
||||||
return # Not connected
|
# Not enouth data do check
|
||||||
netInfo = tuple(operations.getNetworkInfo())
|
|
||||||
for i in netInfo:
|
|
||||||
# If at least one ip has changed
|
|
||||||
if i.mac in self.knownIps and self.knownIps[i.mac] != i.ip:
|
|
||||||
logger.info('Notifying ip change to broker (mac {}, from {} to {})'.format(i.mac, self.knownIps[i.mac], i.ip))
|
|
||||||
try:
|
|
||||||
# Notifies all interfaces IPs
|
|
||||||
self.api.notifyIpChanges(((v.mac, v.ip) for v in netInfo))
|
|
||||||
|
|
||||||
# Regenerates Known ips
|
|
||||||
self.knownIps = dict(((v.mac, v.ip) for v in netInfo))
|
|
||||||
|
|
||||||
# And notify new listening address to broker
|
|
||||||
address = (self.knownIps[self.api.mac], self.httpServer.getPort())
|
|
||||||
# And new listening address
|
|
||||||
self.httpServer.restart(address)
|
|
||||||
# sends notification
|
|
||||||
self.api.notifyComm(self.httpServer.getServerUrl())
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
logger.warn('Got an error notifiying IPs to broker: {} (will retry in a bit)'.format(e.message.decode('windows-1250', 'ignore')))
|
|
||||||
|
|
||||||
def clientMessageProcessor(self, msg, data):
|
|
||||||
logger.debug('Got message {}'.format(msg))
|
|
||||||
if self.api is None:
|
|
||||||
logger.info('Rest api not ready')
|
|
||||||
return
|
return
|
||||||
|
|
||||||
if msg == ipc.REQ_LOGIN:
|
def locateMac(interfaces: typing.Iterable[types.InterfaceInfoType]) -> typing.Optional[types.InterfaceInfoType]:
|
||||||
self.loggedIn = True
|
|
||||||
res = self.api.login(data).split('\t')
|
|
||||||
# third parameter, if exists, sets maxSession duration to this.
|
|
||||||
# First & second parameters are ip & hostname of connection source
|
|
||||||
if len(res) >= 3:
|
|
||||||
self.api.maxSession = int(res[2]) # Third parameter is max session duration
|
|
||||||
msg = ipc.REQ_INFORMATION # Senf information, requested or not, to client on login notification
|
|
||||||
if msg == ipc.REQ_LOGOUT and self.loggedIn is True:
|
|
||||||
self.loggedIn = False
|
|
||||||
self.api.logout(data)
|
|
||||||
self.onLogout(data)
|
|
||||||
if msg == ipc.REQ_INFORMATION:
|
|
||||||
info = {}
|
|
||||||
if self.api.idle is not None:
|
|
||||||
info['idle'] = self.api.idle
|
|
||||||
if self.api.maxSession is not None:
|
|
||||||
info['maxSession'] = self.api.maxSession
|
|
||||||
self.ipc.sendInformationMessage(info)
|
|
||||||
if msg == ipc.REQ_TICKET:
|
|
||||||
d = json.loads(data)
|
|
||||||
try:
|
try:
|
||||||
result = self.api.getTicket(d['ticketId'], d['secure'])
|
return next(x for x in interfaces if x.mac.lower() == self._cfg.config.unique_id.lower())
|
||||||
self.ipc.sendTicketMessage(result)
|
except StopIteration:
|
||||||
except Exception:
|
return None
|
||||||
logger.exception('Getting ticket')
|
|
||||||
self.ipc.sendTicketMessage({'error': 'invalid ticket'})
|
|
||||||
|
|
||||||
def initIPC(self):
|
try:
|
||||||
# ******************************************
|
oldIp = locateMac(self._interfaces)
|
||||||
# * Initialize listener IPC & REST threads *
|
newIp = locateMac(platform.operations.getNetworkInfo())
|
||||||
# ******************************************
|
if not newIp:
|
||||||
logger.debug('Starting IPC listener at {}'.format(IPC_PORT))
|
raise Exception('No ip currently available for {}'.format(self._cfg.config.unique_id))
|
||||||
self.ipc = ipc.ServerIPC(IPC_PORT, clientMessageProcessor=self.clientMessageProcessor)
|
if oldIp != newIp:
|
||||||
self.ipc.start()
|
self._api.notifyIpChange(self._cfg.own_token, newIp)
|
||||||
|
logger.info('Ip changed from {} to {}. Notified to UDS'.format(oldIp, newIp))
|
||||||
if self.api.mac in self.knownIps:
|
except Exception as e:
|
||||||
address = (self.knownIps[self.api.mac], random.randrange(43900, 44000))
|
# No ip changed, log exception for info
|
||||||
logger.info('Starting REST listener at {}'.format(address))
|
logger.warn('Checking ips faield: {}'.format(e))
|
||||||
self.httpServer = httpserver.HTTPServerThread(address, self)
|
|
||||||
self.httpServer.start()
|
|
||||||
# And notify it to broker
|
|
||||||
self.api.notifyComm(self.httpServer.getServerUrl())
|
|
||||||
|
|
||||||
def endIPC(self):
|
|
||||||
# Remove IPC threads
|
|
||||||
if self.ipc is not None:
|
|
||||||
try:
|
|
||||||
self.ipc.stop()
|
|
||||||
except Exception:
|
|
||||||
logger.error('Couln\'t stop ipc server')
|
|
||||||
if self.httpServer is not None:
|
|
||||||
try:
|
|
||||||
self.httpServer.stop()
|
|
||||||
except Exception:
|
|
||||||
logger.error('Couln\'t stop REST server')
|
|
||||||
|
|
||||||
def endAPI(self):
|
|
||||||
if self.api is not None:
|
|
||||||
try:
|
|
||||||
if self.loggedIn:
|
|
||||||
self.loggedIn = False
|
|
||||||
self.api.logout('service_stopped')
|
|
||||||
self.api.notifyComm(None)
|
|
||||||
except Exception as e:
|
|
||||||
logger.error('Couln\'t remove comms url from broker: {}'.format(e))
|
|
||||||
|
|
||||||
# self.notifyStop()
|
|
||||||
|
|
||||||
# ***************************************************
|
# ***************************************************
|
||||||
# Methods that ARE overriden by linux & windows Actor
|
# Methods that ARE overriden by linux & windows Actor
|
||||||
# ***************************************************
|
# ***************************************************
|
||||||
def rename(self, name, user=None, oldPassword=None, newPassword=None):
|
def rename(self, name: str, user: typing.Optional[str] = None, oldPassword: typing.Optional[str] = None, newPassword: typing.Optional[str] = None):
|
||||||
'''
|
'''
|
||||||
Invoked when broker requests a rename action
|
Invoked when broker requests a rename action
|
||||||
MUST BE OVERRIDEN
|
MUST BE OVERRIDEN
|
||||||
'''
|
'''
|
||||||
raise NotImplementedError('Method renamed has not been implemented!')
|
raise NotImplementedError('Method renamed has not been implemented!')
|
||||||
|
|
||||||
def joinDomain(self, name, domain, ou, account, password):
|
def joinDomain(self, name: str, domain: str, ou: str, account: str, password: str):
|
||||||
'''
|
'''
|
||||||
Invoked when broker requests a "domain" action
|
Invoked when broker requests a "domain" action
|
||||||
MUST BE OVERRIDEN
|
MUST BE OVERRIDEN
|
||||||
@ -317,7 +217,7 @@ class CommonService:
|
|||||||
# Methods that CAN BE overriden by actors
|
# Methods that CAN BE overriden by actors
|
||||||
# ****************************************
|
# ****************************************
|
||||||
def notifyLocal(self):
|
def notifyLocal(self):
|
||||||
self.setReady(operations.getComputerName())
|
self.setReady()
|
||||||
|
|
||||||
def doWait(self, miliseconds):
|
def doWait(self, miliseconds):
|
||||||
'''
|
'''
|
||||||
@ -332,12 +232,12 @@ class CommonService:
|
|||||||
'''
|
'''
|
||||||
logger.info('Service is being stopped')
|
logger.info('Service is being stopped')
|
||||||
|
|
||||||
def preConnect(self, user, protocol):
|
def preConnect(self, user: str, protocol: str):
|
||||||
'''
|
'''
|
||||||
Invoked when received a PRE Connection request via REST
|
Invoked when received a PRE Connection request via REST
|
||||||
'''
|
'''
|
||||||
logger.debug('Pre-connect does nothing')
|
logger.debug('Pre-connect does nothing')
|
||||||
return 'ok'
|
return 'ok'
|
||||||
|
|
||||||
def onLogout(self, user):
|
def onLogout(self, user: str):
|
||||||
logger.debug('On logout invoked for {}'.format(user))
|
logger.debug('On logout invoked for {}'.format(user))
|
||||||
|
@ -2,8 +2,8 @@ import typing
|
|||||||
|
|
||||||
class InterfaceInfoType(typing.NamedTuple):
|
class InterfaceInfoType(typing.NamedTuple):
|
||||||
name: str
|
name: str
|
||||||
mac: typing.Optional[str]
|
mac: str
|
||||||
ip: typing.Optional[str]
|
ip: str
|
||||||
|
|
||||||
class AuthenticatorType(typing.NamedTuple):
|
class AuthenticatorType(typing.NamedTuple):
|
||||||
authId: str
|
authId: str
|
||||||
@ -43,5 +43,8 @@ class ActorConfigurationType(typing.NamedTuple):
|
|||||||
|
|
||||||
data: typing.Optional[typing.Dict[str, typing.Any]] = None
|
data: typing.Optional[typing.Dict[str, typing.Any]] = None
|
||||||
|
|
||||||
class InitializationResultType(ActorDataConfigurationType):
|
class InitializationResultType(typing.NamedTuple):
|
||||||
own_token: typing.Optional[str] = None
|
own_token: typing.Optional[str] = None
|
||||||
|
unique_id: typing.Optional[str] = None
|
||||||
|
max_idle: typing.Optional[int] = None
|
||||||
|
os: typing.Optional[ActorOsConfigurationType] = None
|
||||||
|
@ -1,72 +0,0 @@
|
|||||||
# -*- 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
|
|
||||||
'''
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import six
|
|
||||||
|
|
||||||
if sys.platform == 'win32':
|
|
||||||
_fromEncoding = 'windows-1250'
|
|
||||||
else:
|
|
||||||
_fromEncoding = 'utf-8'
|
|
||||||
|
|
||||||
|
|
||||||
def toUnicode(msg):
|
|
||||||
try:
|
|
||||||
if not isinstance(msg, six.text_type):
|
|
||||||
if isinstance(msg, six.binary_type):
|
|
||||||
return msg.decode(_fromEncoding, 'ignore')
|
|
||||||
return six.text_type(msg)
|
|
||||||
else:
|
|
||||||
return msg
|
|
||||||
except Exception:
|
|
||||||
try:
|
|
||||||
return six.text_type(msg)
|
|
||||||
except Exception:
|
|
||||||
return ''
|
|
||||||
|
|
||||||
|
|
||||||
def exceptionToMessage(e):
|
|
||||||
msg = ''
|
|
||||||
for arg in e.args:
|
|
||||||
if isinstance(arg, Exception):
|
|
||||||
msg = msg + exceptionToMessage(arg)
|
|
||||||
else:
|
|
||||||
msg = msg + toUnicode(arg) + '. '
|
|
||||||
return msg
|
|
||||||
|
|
||||||
|
|
||||||
class Bunch(dict):
|
|
||||||
def __init__(self, **kw):
|
|
||||||
dict.__init__(self, kw)
|
|
||||||
self.__dict__ = self
|
|
||||||
|
|
@ -35,7 +35,7 @@
|
|||||||
import logging
|
import logging
|
||||||
import typing
|
import typing
|
||||||
|
|
||||||
import dns
|
import dns.resolver
|
||||||
|
|
||||||
from django.utils.translation import ugettext_noop as _
|
from django.utils.translation import ugettext_noop as _
|
||||||
from uds.core import auths
|
from uds.core import auths
|
||||||
@ -126,6 +126,8 @@ class InternalDBAuth(auths.Authenticator):
|
|||||||
|
|
||||||
groupsManager.validate([g.name for g in user.groups.all()])
|
groupsManager.validate([g.name for g in user.groups.all()])
|
||||||
|
|
||||||
|
def createUser(self, usrData):
|
||||||
|
pass
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def test(env, data):
|
def test(env, data):
|
||||||
|
@ -111,7 +111,7 @@ class OSManager(Module):
|
|||||||
def actorData(self, userService: 'UserService') -> typing.MutableMapping[str, typing.Any]:
|
def actorData(self, userService: 'UserService') -> typing.MutableMapping[str, typing.Any]:
|
||||||
"""
|
"""
|
||||||
This method provides information to actor, so actor can complete os configuration.
|
This method provides information to actor, so actor can complete os configuration.
|
||||||
Currently exists 3 types of os managers
|
Currently exists 3 types of os managers actions
|
||||||
* rename vm and do NOT ADD to AD
|
* rename vm and do NOT ADD to AD
|
||||||
{
|
{
|
||||||
'action': 'rename',
|
'action': 'rename',
|
||||||
@ -119,7 +119,7 @@ class OSManager(Module):
|
|||||||
}
|
}
|
||||||
* rename vm and ADD to AD
|
* rename vm and ADD to AD
|
||||||
{
|
{
|
||||||
'action': 'renameAD',
|
'action': 'rename_ad',
|
||||||
'name': 'xxxxxxx',
|
'name': 'xxxxxxx',
|
||||||
'ad': 'domain.xxx'
|
'ad': 'domain.xxx'
|
||||||
'ou': 'ou' # or '' if default ou
|
'ou': 'ou' # or '' if default ou
|
||||||
@ -128,7 +128,7 @@ class OSManager(Module):
|
|||||||
}
|
}
|
||||||
* rename vm, do NOT ADD to AD, and change password for an user
|
* rename vm, do NOT ADD to AD, and change password for an user
|
||||||
{
|
{
|
||||||
'action': 'rename_and_pw'
|
'action': 'rename'
|
||||||
'name': 'xxxxx'
|
'name': 'xxxxx'
|
||||||
'username': 'username to change pass'
|
'username': 'username to change pass'
|
||||||
'password': 'current password for username to change password'
|
'password': 'current password for username to change password'
|
||||||
|
@ -92,7 +92,7 @@ class LinuxRandomPassManager(LinuxOsManager):
|
|||||||
|
|
||||||
def actorData(self, userService: 'UserService') -> typing.MutableMapping[str, typing.Any]:
|
def actorData(self, userService: 'UserService') -> typing.MutableMapping[str, typing.Any]:
|
||||||
return {
|
return {
|
||||||
'action': 'rename_and_pw',
|
'action': 'rename',
|
||||||
'name': userService.getName(),
|
'name': userService.getName(),
|
||||||
'username': self._userAccount,
|
'username': self._userAccount,
|
||||||
'password': '', # On linux, user password is not needed so we provide an empty one
|
'password': '', # On linux, user password is not needed so we provide an empty one
|
||||||
|
@ -321,7 +321,7 @@ class WinDomainOsManager(WindowsOsManager):
|
|||||||
|
|
||||||
def actorData(self, userService: 'UserService') -> typing.MutableMapping[str, typing.Any]:
|
def actorData(self, userService: 'UserService') -> typing.MutableMapping[str, typing.Any]:
|
||||||
return {
|
return {
|
||||||
'action': 'rename_and_pw',
|
'action': 'rename_ad',
|
||||||
'name': userService.getName(),
|
'name': userService.getName(),
|
||||||
'ad': self._domain,
|
'ad': self._domain,
|
||||||
'ou': self._ou,
|
'ou': self._ou,
|
||||||
|
@ -98,7 +98,7 @@ class WinRandomPassManager(WindowsOsManager):
|
|||||||
|
|
||||||
def actorData(self, userService: 'UserService') -> typing.MutableMapping[str, typing.Any]:
|
def actorData(self, userService: 'UserService') -> typing.MutableMapping[str, typing.Any]:
|
||||||
return {
|
return {
|
||||||
'action': 'rename_and_pw',
|
'action': 'rename',
|
||||||
'name': userService.getName(),
|
'name': userService.getName(),
|
||||||
'username': self._userAccount,
|
'username': self._userAccount,
|
||||||
'password': self._password,
|
'password': self._password,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user