|
|
@@ -320,7 +320,7 @@ def get_authorized_board_parms(board_id, token: str = Depends(oauth2_scheme), |
|
|
|
return dict(board_id=board_id, token=token, data=data, brdmgr=brdmgr) |
|
|
|
|
|
|
|
@contextlib.asynccontextmanager |
|
|
|
async def validate_board_params(board_id, token, data, brdmgr): |
|
|
|
async def validate_board_params(board_id, data, brdmgr, user=None, token=None): |
|
|
|
'''This context manager checks to see if the request is authorized |
|
|
|
for the board_id. This requires that the board is reserved by |
|
|
|
the user, or the connection came from the board's jail (TBI). |
|
|
@@ -329,7 +329,8 @@ async def validate_board_params(board_id, token, data, brdmgr): |
|
|
|
brd = brdmgr.boards[board_id] |
|
|
|
|
|
|
|
async with brd.lock: |
|
|
|
user = await lookup_user(token, data) |
|
|
|
if user is None: |
|
|
|
user = await lookup_user(token, data) |
|
|
|
|
|
|
|
try: |
|
|
|
brduser = await data.BoardStatus.objects.get(board=board_id) |
|
|
@@ -448,11 +449,12 @@ async def reserve_board(board_id_or_class, |
|
|
|
return brd |
|
|
|
|
|
|
|
class HandleExec(WSFWDServer): |
|
|
|
def __init__(self, *args, board_id, data, **kwargs): |
|
|
|
def __init__(self, *args, board_id, data, brdmgr, **kwargs): |
|
|
|
super().__init__(*args, **kwargs) |
|
|
|
|
|
|
|
self._board_id = board_id |
|
|
|
self._data = data |
|
|
|
self._brdmgr = brdmgr |
|
|
|
self._auth_user = None |
|
|
|
self._did_exec = False |
|
|
|
|
|
|
@@ -514,9 +516,16 @@ class HandleExec(WSFWDServer): |
|
|
|
if self._auth_user is None: |
|
|
|
raise RuntimeError('not authenticated') |
|
|
|
|
|
|
|
self._proc = await asyncio.create_subprocess_exec( |
|
|
|
'jexec', self._board_id, *msg['args'], |
|
|
|
stdin=subprocess.PIPE, stdout=subprocess.PIPE) |
|
|
|
try: |
|
|
|
async with validate_board_params(self._board_id, self._data, |
|
|
|
self._brdmgr, user=self._auth_user) as brd: |
|
|
|
self._proc = await \ |
|
|
|
asyncio.create_subprocess_exec('jexec', |
|
|
|
self._board_id, *msg['args'], |
|
|
|
stdin=subprocess.PIPE, |
|
|
|
stdout=subprocess.PIPE) |
|
|
|
except BITEError as e: |
|
|
|
raise RuntimeError(e.errobj.error) |
|
|
|
|
|
|
|
self._did_exec = True |
|
|
|
|
|
|
@@ -547,7 +556,7 @@ async def board_exec_ws( |
|
|
|
try: |
|
|
|
async with HandleExec(websocket.receive_bytes, |
|
|
|
websocket.send_bytes, data=data, |
|
|
|
board_id=board_id) as server: |
|
|
|
board_id=board_id, brdmgr=brdmgr) as server: |
|
|
|
await server.get_finish_handler() |
|
|
|
finally: |
|
|
|
await websocket.close() |
|
|
@@ -773,7 +782,29 @@ class TestWebSocket(TestCommon): |
|
|
|
# that a valid auth token works |
|
|
|
await client.auth(dict(bearer='thisisanapikey')) |
|
|
|
|
|
|
|
# XXX - enforce board reservation and correct user |
|
|
|
# That since the board isn't reserved, it fails |
|
|
|
with self.assertRaisesRegex(RuntimeError, |
|
|
|
'Board not reserved.'): |
|
|
|
await client.exec([ 'sshd', '-i' ], stdin=1, |
|
|
|
stdout=2) |
|
|
|
|
|
|
|
# that when the board is reserved by the wrong user |
|
|
|
brd = self.brdmgr.boards['cora-1'] |
|
|
|
obrdreq = await self.data.BoardStatus.objects.create( |
|
|
|
board='cora-1', user='bar') |
|
|
|
async with brd.lock: |
|
|
|
await brd.reserve() |
|
|
|
|
|
|
|
# that it fails |
|
|
|
with self.assertRaisesRegex(RuntimeError, 'Board reserved by \'bar\'.'): |
|
|
|
await client.exec([ 'sshd', '-i' ], stdin=1, stdout=2) |
|
|
|
|
|
|
|
brduser = await self.data.BoardStatus.objects.get(board='cora-1') |
|
|
|
obrdreq = await self.data.BoardStatus.delete(brduser) |
|
|
|
|
|
|
|
# that when the board is reserved by the correct user |
|
|
|
obrdreq = await self.data.BoardStatus.objects.create( |
|
|
|
board='cora-1', user='foo') |
|
|
|
|
|
|
|
echodata = b'somedata' |
|
|
|
wrap_subprocess_exec(cse, stdout=echodata, retcode=0) |
|
|
|