Skip to content

Commit

Permalink
Merge pull request #528 from GrahamDumpleton/lookup-service-hardening
Browse files Browse the repository at this point in the history
Lookup service hardening.
  • Loading branch information
GrahamDumpleton authored Aug 7, 2024
2 parents af3eacf + 20bc86a commit ba04553
Show file tree
Hide file tree
Showing 2 changed files with 250 additions and 215 deletions.
274 changes: 146 additions & 128 deletions lookup-service/service/caches/portals.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

import logging
from dataclasses import dataclass
from typing import TYPE_CHECKING, Any, Dict, List, Tuple, Union
from typing import TYPE_CHECKING, Dict, List, Tuple, Union

from aiohttp import BasicAuth, ClientSession
from aiohttp import BasicAuth, ClientSession, ClientConnectorError

from .clusters import ClusterConfig

Expand Down Expand Up @@ -179,76 +179,73 @@ def connected(self):
async def login(self) -> bool:
"""Login to the portal service ."""

async with self.session.post(
f"{self.portal.url}/oauth2/token/",
data={
"grant_type": "password",
"username": self.portal.credentials.username,
"password": self.portal.credentials.password,
},
auth=BasicAuth(
self.portal.credentials.client_id, self.portal.credentials.client_secret
),
) as response:
if response.status != 200:
logger.error(
"Failed to login to portal %s of cluster %s.",
self.portal.name,
self.portal.cluster.name,
)
try:
async with self.session.post(
f"{self.portal.url}/oauth2/token/",
data={
"grant_type": "password",
"username": self.portal.credentials.username,
"password": self.portal.credentials.password,
},
auth=BasicAuth(
self.portal.credentials.client_id,
self.portal.credentials.client_secret,
),
) as response:
if response.status != 200:
logger.error(
"Failed to login to portal %s of cluster %s.",
self.portal.name,
self.portal.cluster.name,
)

return False

data = await response.json()

self.access_token = data.get("access_token")

return False

data = await response.json()
return True

self.access_token = data.get("access_token")
except ClientConnectorError as exc:
logger.error(
"Failed to connect to portal %s of cluster %s when attempting to login: %s",
self.portal.name,
self.portal.cluster.name,
exc,
)

return True
return False

async def logout(self) -> None:
"""Logout from the portal service."""

if not self.connected:
return

async with self.session.post(
f"{self.portal.url}/oauth2/revoke-token/",
data={
"client_id": self.portal.credentials.client_id,
"client_secret": self.portal.credentials.client_secret,
"token": self.access_token,
},
) as response:
if response.status != 200:
logger.error(
"Failed to logout from portal %s of cluster %s.",
self.portal.name,
self.portal.cluster.name,
)

async def user_sessions(self, user_id: str) -> List[Dict[str, Any]]:
"""Fetches the list of active sessions for a user."""

if not self.connected:
return {}

headers = {"Authorization": f"Bearer {self.access_token}"}

async with self.session.get(
f"{self.portal.url}/workshops/user/{user_id}/sessions/",
headers=headers,
) as response:
if response.status != 200:
logger.error(
"Failed to get sessions from portal %s of cluster %s for user %s.",
self.portal.name,
self.portal.cluster.name,
user_id,
)

return {}

return await response.json()
try:
async with self.session.post(
f"{self.portal.url}/oauth2/revoke-token/",
data={
"client_id": self.portal.credentials.client_id,
"client_secret": self.portal.credentials.client_secret,
"token": self.access_token,
},
) as response:
if response.status != 200:
logger.error(
"Failed to logout from portal %s of cluster %s.",
self.portal.name,
self.portal.cluster.name,
)

except ClientConnectorError as exc:
logger.error(
"Failed to connect to portal %s of cluster %s when attempting to logout: %s",
self.portal.name,
self.portal.cluster.name,
exc,
)

async def reacquire_workshop_session(
self, user_id: str, environment_name: str, session_name: str, index_url: str
Expand All @@ -263,39 +260,50 @@ async def reacquire_workshop_session(

headers = {"Authorization": f"Bearer {self.access_token}"}

async with self.session.get(
f"{self.portal.url}/workshops/environment/{environment_name}/request/",
headers=headers,
params={
"index_url": index_url,
"user": user_id,
"session": session_name,
},
) as response:
if response.status != 200:
logger.error(
"Failed to reacquire session %s from portal %s of cluster %s for user %s.",
session_name,
self.portal.name,
self.portal.cluster.name,
user_id,
)

return

data = await response.json()

url = data.get("url")

if url:
return {
"clusterName": self.portal.cluster.name,
"portalName": self.portal.name,
"environmentName": environment_name,
"sessionName": session_name,
"clientUserId": user_id,
"sessionActionvationUrl": f"{self.portal.url}{url}",
}
try:
async with self.session.get(
f"{self.portal.url}/workshops/environment/{environment_name}/request/",
headers=headers,
params={
"index_url": index_url,
"user": user_id,
"session": session_name,
},
) as response:
if response.status != 200:
logger.error(
"Failed to reacquire session %s from portal %s of cluster %s for user %s.",
session_name,
self.portal.name,
self.portal.cluster.name,
user_id,
)

return

data = await response.json()

url = data.get("url")

if url:
return {
"clusterName": self.portal.cluster.name,
"portalName": self.portal.name,
"environmentName": environment_name,
"sessionName": session_name,
"clientUserId": user_id,
"sessionActionvationUrl": f"{self.portal.url}{url}",
}

except ClientConnectorError as exc:
logger.error(
"Failed to connect to portal %s of cluster %s when attempting to reacquire session %s for user %s: %s", # pylint: disable=line-too-long
self.portal.name,
self.portal.cluster.name,
session_name,
user_id,
exc,
)

async def request_workshop_session(
self,
Expand All @@ -311,36 +319,46 @@ async def request_workshop_session(

headers = {"Authorization": f"Bearer {self.access_token}"}

async with self.session.get(
f"{self.portal.url}/workshops/environment/{environment_name}/request/",
headers=headers,
params={
"user": user_id,
"parameters": parameters,
"index_url": index_url,
},
) as response:
if response.status != 200:
logger.error(
"Failed to request session from portal %s of cluster %s for user %s.",
self.portal.name,
self.portal.cluster.name,
user_id,
)

return

data = await response.json()

url = data.get("url")
session_name = data.get("name")

if url:
return {
"clusterName": self.portal.cluster.name,
"portalName": self.portal.name,
"environmentName": environment_name,
"sessionName": session_name,
"clientUserId": user_id,
"sessionActionvationUrl": f"{self.portal.url}{url}",
}
try:
async with self.session.get(
f"{self.portal.url}/workshops/environment/{environment_name}/request/",
headers=headers,
params={
"user": user_id,
"parameters": parameters,
"index_url": index_url,
},
) as response:
if response.status != 200:
logger.error(
"Failed to request session from portal %s of cluster %s for user %s.",
self.portal.name,
self.portal.cluster.name,
user_id,
)

return

data = await response.json()

url = data.get("url")
session_name = data.get("name")

if url:
return {
"clusterName": self.portal.cluster.name,
"portalName": self.portal.name,
"environmentName": environment_name,
"sessionName": session_name,
"clientUserId": user_id,
"sessionActionvationUrl": f"{self.portal.url}{url}",
}

except ClientConnectorError as exc:
logger.error(
"Failed to connect to portal %s of cluster %s when attempting to request session for user %s: %s", # pylint: disable=line-too-long
self.portal.name,
self.portal.cluster.name,
user_id,
exc,
)
Loading

0 comments on commit ba04553

Please sign in to comment.