Merge remote-tracking branch 'origin/v3.6'

This commit is contained in:
Adolfo Gómez García 2022-08-06 19:30:01 +02:00
commit e51e13b821
6 changed files with 55 additions and 28 deletions

View File

@ -198,7 +198,7 @@ class UDSActorClient(threading.Thread): # pylint: disable=too-many-instance-att
time.sleep(1.3) # Sleeps between loop iterations
self._loginInfo = None
self.api.logout(platform.operations.getCurrentUser() + self._extraLogoff)
self.api.logout(platform.operations.getCurrentUser() + self._extraLogoff, platform.operations.getSessionType())
except Exception as e:
logger.error('Error on client loop: %s', e)

View File

@ -329,11 +329,7 @@ class UDSServerApi(UDSApi):
) -> types.LoginResultInfoType:
if not token:
return types.LoginResultInfoType(
ip='0.0.0.0', # nosec: this is not a binding
hostname=UNKNOWN,
dead_line=None,
max_idle=None,
session_id=None,
ip='0.0.0.0', hostname=UNKNOWN, dead_line=None, max_idle=None, session_id=None
)
payload = {
'type': actor_type or types.MANAGED,
@ -344,7 +340,7 @@ class UDSServerApi(UDSApi):
'secret': secret or '',
}
result = self._doPost('login', payload)
return types.LoginResultInfoType( # nosec: this is not a binding
return types.LoginResultInfoType(
ip=result['ip'],
hostname=result['hostname'],
dead_line=result['dead_line'],
@ -358,20 +354,22 @@ class UDSServerApi(UDSApi):
token: str,
username: str,
session_id: typing.Optional[str],
session_type: str,
interfaces: typing.Iterable[types.InterfaceInfoType],
secret: typing.Optional[str],
) -> None:
) -> typing.Optional[str]:
if not token:
return
return None
payload = {
'type': actor_type or types.MANAGED,
'id': [{'mac': i.mac, 'ip': i.ip} for i in interfaces],
'token': token,
'username': username,
'session_type': session_type,
'session_id': session_id or '',
'secret': secret or '',
}
self._doPost('logout', payload)
return self._doPost('logout', payload) # Can be 'ok' or 'notified'
def log(self, own_token: str, level: int, message: str) -> None:
if not own_token:
@ -427,8 +425,11 @@ class UDSClientApi(UDSApi):
session_id=result['session_id'],
)
def logout(self, username: str) -> None:
payLoad = {'username': username}
def logout(self, username: str, sessionType: typing.Optional[str]) -> None:
payLoad = {
'username': username,
'session_type': sessionType or UNKNOWN
}
self.post('logout', payLoad)
def ping(self) -> bool:

View File

@ -379,6 +379,7 @@ class CommonService: # pylint: disable=too-many-instance-attributes
self._cfg.actorType,
self._cfg.own_token,
'',
'',
self._interfaces,
self._secret,
)
@ -496,9 +497,12 @@ class CommonService: # pylint: disable=too-many-instance-attributes
# If unmanaged, do initialization now, because we don't know before this
# Also, even if not initialized, get a "login" notification token
if not self.isManaged():
self.initialize()
master_token = self._cfg.master_token
secret = self._secret
self._initialized = (
self.initialize()
) # Maybe it's a local login by an unmanaged host.... On real login, will execute initilize again
if self._initialized:
master_token = self._cfg.master_token
secret = self._secret
# Own token will not be set if UDS did not assigned the initialized VM to an user
# In that case, take master token (if machine is Unamanaged version)
@ -520,7 +524,7 @@ class CommonService: # pylint: disable=too-many-instance-attributes
return result
def logout(self, username: str) -> None:
def logout(self, username: str, sessionType: typing.Optional[str] = None) -> None:
self._loggedIn = False
master_token = self._cfg.master_token
@ -529,9 +533,20 @@ class CommonService: # pylint: disable=too-many-instance-attributes
# In that case, take master token (if machine is Unamanaged version)
token = self._cfg.own_token or master_token
if token:
self._api.logout(
self._cfg.actorType, token, username, self._interfaces, self._secret
)
# If logout is not processed (that is, not ok result), the logout has not been processed
if (
self._api.logout(
self._cfg.actorType,
token,
username,
sessionType or '',
self._interfaces,
self._secret,
)
!= 'ok'
):
logger.info('Logout from %s ignored as required by uds broker', username)
return
self.onLogout(username)

View File

@ -435,7 +435,7 @@ class Version(ActorV3Action):
class LoginLogout(ActorV3Action):
name = 'notused' # Not really important, this is not a "leaf" class and will not be directly available
def notifyService(self, isLogin: bool):
def notifyService(self, isLogin: bool) -> None:
try:
# If unmanaged, use Service locator
service: 'services.Service' = Service.objects.get(
@ -462,12 +462,12 @@ class LoginLogout(ActorV3Action):
# idInfo = service.recoverIdInfo(validId)
# Notify Service that someone logged in/out
is_remote = self._params.get('session_type', '')[:4] in ('xrdp', 'RDP-')
if isLogin:
# Try to guess if this is a remote session
is_remote = self._params.get('session_type', '')[:4] in ('xrdp', 'RDP-')
service.processLogin(validId, remote_login=is_remote)
else:
service.processLogout(validId)
service.processLogout(validId, remote_login=is_remote)
# All right, service notified...
except Exception:
@ -578,6 +578,7 @@ class Logout(LoginLogout):
if isManaged:
raise
self.notifyService(isLogin=False) # Logout notification
return ActorV3Action.actorResult('notified') # Result is that we have not processed the logout in fact, but notified the service
return ActorV3Action.actorResult('ok')

View File

@ -344,7 +344,7 @@ class Service(Module):
"""
return
def processLogout(self, id: str) -> None:
def processLogout(self, id: str, remote_login: bool) -> None:
"""
In the case that a logout is invoked directly on an actor controlled machine with
an service token, this method will be called with provided info by uds actor (parameters)

View File

@ -230,10 +230,13 @@ class IPMachinesService(IPServiceBase):
# Sets maximum services for this
self.maxDeployed = len(self._ips)
def canBeUsed(self, locked: typing.Optional[int], now: int) -> int:
def canBeUsed(self, locked: typing.Optional[typing.Union[str, int]], now: int) -> int:
# If _maxSessionForMachine is 0, it can be used only if not locked
# (that is locked is None)
locked = locked or 0
if isinstance(locked, str) and not '.' in locked: # Convert to int and treat it as a "locked" element
locked = int(locked)
if self._maxSessionForMachine <= 0:
return not bool(locked) # If locked is None, it can be used
@ -341,19 +344,26 @@ class IPMachinesService(IPServiceBase):
Process login for a machine not assigned to any user.
'''
logger.debug('Processing login for %s: %s', self, id)
# Locate the IP on the storage
theIP = IPServiceBase.getIp(id)
now = getSqlDatetimeAsUnix()
locked = self.storage.getPickle(theIP)
locked: typing.Union[None, str, int] = self.storage.getPickle(theIP)
if self.canBeUsed(locked, now):
self.storage.putPickle(theIP, now) # Lock it
self.storage.putPickle(theIP, str(now)) # Lock it
def processLogout(self, id: str) -> None:
def processLogout(self, id: str, remote_login: bool) -> None:
'''
Process logout for a machine not assigned to any user.
'''
logger.debug('Processing logout for %s: %s', self, id)
self.unassignMachine(id)
# Locate the IP on the storage
theIP = IPServiceBase.getIp(id)
locked: typing.Union[None, str, int] = self.storage.getPickle(theIP)
# If locked is str, has been locked by processLogin so we can unlock it
if isinstance(locked, str):
self.unassignMachine(id)
# If not proccesed by login, we cannot release it
def notifyInitialization(self, id: str) -> None:
'''