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

This commit is contained in:
Adolfo Gómez García 2022-08-04 21:56:39 +02:00
commit e79753748e
6 changed files with 54 additions and 23 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

@ -131,7 +131,7 @@ class UDSApi: # pylint: disable=too-few-public-methods
headers=headers,
verify=self._validateCert,
timeout=TIMEOUT,
proxies=NO_PROXY # type: ignore
proxies=NO_PROXY # type: ignore
if disableProxy
else None, # if not proxies wanted, enforce it
)
@ -351,19 +351,21 @@ class UDSServerApi(UDSApi):
actor_type: typing.Optional[str],
token: str,
username: str,
sessionType: 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': sessionType,
'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:
@ -418,8 +420,11 @@ class UDSClientApi(UDSApi):
max_idle=result['max_idle'],
)
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

@ -377,6 +377,7 @@ class CommonService: # pylint: disable=too-many-instance-attributes
self._cfg.actorType,
self._cfg.own_token,
'',
'',
self._interfaces,
self._secret,
)
@ -494,9 +495,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)
@ -518,7 +522,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
@ -527,9 +531,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

@ -419,7 +419,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(
@ -446,12 +446,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:
@ -562,6 +562,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

@ -335,7 +335,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

@ -231,10 +231,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
@ -342,19 +345,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:
'''