Skip to content

Commit 52faf6e

Browse files
committed
Refactor: logs didn't need to generate full header
Fix: extracts domain from node url instead of sending url Fix: using vmclient sessions in get_logs instead of creating new one
1 parent 6860015 commit 52faf6e

File tree

1 file changed

+41
-23
lines changed

1 file changed

+41
-23
lines changed

src/aleph/sdk/client/vmclient.py

Lines changed: 41 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import datetime
22
import json
33
import logging
4-
from typing import Any, Dict, Tuple, Optional
4+
from typing import Any, Dict, Optional, Tuple
5+
from urllib.parse import urlparse
56

67
import aiohttp
78
from eth_account.messages import encode_defunct
@@ -39,7 +40,7 @@ def _generate_pubkey_payload(self) -> Dict[str, Any]:
3940
return {
4041
"pubkey": json.loads(self.ephemeral_key.export_public()),
4142
"alg": "ECDSA",
42-
"domain": self.node_url,
43+
"domain": urlparse(self.node_url).netloc,
4344
"address": self.account.get_address(),
4445
"expires": (
4546
datetime.datetime.utcnow() + datetime.timedelta(days=1)
@@ -60,36 +61,51 @@ async def _generate_pubkey_signature_header(self) -> str:
6061
"sender": self.account.get_address(),
6162
"payload": pubkey_payload,
6263
"signature": pubkey_signature,
63-
"content": {"domain": self.node_url},
64+
"content": {"domain": urlparse(self.node_url).netloc},
6465
}
6566
)
6667

67-
async def _generate_header(
68-
self, vm_id: str, operation: str
69-
) -> Tuple[str, Dict[str, str]]:
68+
def create_payload(self, vm_id: str, operation: str) -> Dict[str, str]:
7069
path = (
7170
f"/logs/{vm_id}"
7271
if operation == "logs"
7372
else f"/control/machine/{vm_id}/{operation}"
7473
)
75-
7674
payload = {
7775
"time": datetime.datetime.utcnow().isoformat() + "Z",
7876
"method": "POST",
7977
"path": path,
8078
}
79+
return payload
80+
81+
def sign_payload(self, payload: Dict[str, str], ephemeral_key) -> str:
8182
payload_as_bytes = json.dumps(payload).encode("utf-8")
82-
headers = {"X-SignedPubKey": self.pubkey_signature_header}
8383
payload_signature = JWA.signing_alg("ES256").sign(
84-
self.ephemeral_key, payload_as_bytes
84+
ephemeral_key, payload_as_bytes
8585
)
86-
headers["X-SignedOperation"] = json.dumps(
86+
signed_operation = json.dumps(
8787
{
8888
"payload": payload_as_bytes.hex(),
8989
"signature": payload_signature.hex(),
9090
}
9191
)
92+
return signed_operation
9293

94+
async def _generate_header(
95+
self, vm_id: str, operation: str
96+
) -> Tuple[str, Dict[str, str]]:
97+
payload = self.create_payload(vm_id, operation)
98+
signed_operation = self.sign_payload(payload, self.ephemeral_key)
99+
100+
if not self.pubkey_signature_header:
101+
self.pubkey_signature_header = await self.generate_pubkey_signature_header()
102+
103+
headers = {
104+
"X-SignedPubKey": self.pubkey_signature_header,
105+
"X-SignedOperation": signed_operation,
106+
}
107+
108+
path = payload["path"]
93109
return f"{self.node_url}{path}", headers
94110

95111
async def perform_operation(self, vm_id, operation):
@@ -114,22 +130,24 @@ async def get_logs(self, vm_id):
114130
await self._generate_pubkey_signature_header()
115131
)
116132

133+
payload = self.create_payload(vm_id, "logs")
134+
signed_operation = self.sign_payload(payload, self.ephemeral_key)
135+
117136
ws_url, header = await self._generate_header(vm_id=vm_id, operation="logs")
118137

119-
async with aiohttp.ClientSession() as session:
120-
async with session.ws_connect(ws_url) as ws:
121-
auth_message = {
122-
"auth": {
123-
"X-SignedPubKey": header["X-SignedPubKey"],
124-
"X-SignedOperation": header["X-SignedOperation"],
125-
}
138+
async with self.session.ws_connect(ws_url) as ws:
139+
auth_message = {
140+
"auth": {
141+
"X-SignedPubKey": self.pubkey_signature_header,
142+
"X-SignedOperation": signed_operation,
126143
}
127-
await ws.send_json(auth_message)
128-
async for msg in ws: # msg is of type aiohttp.WSMessage
129-
if msg.type == aiohttp.WSMsgType.TEXT:
130-
yield msg.data
131-
elif msg.type == aiohttp.WSMsgType.ERROR:
132-
break
144+
}
145+
await ws.send_json(auth_message)
146+
async for msg in ws: # msg is of type aiohttp.WSMessage
147+
if msg.type == aiohttp.WSMsgType.TEXT:
148+
yield msg.data
149+
elif msg.type == aiohttp.WSMsgType.ERROR:
150+
break
133151

134152
async def start_instance(self, vm_id):
135153
return await self.notify_allocation(vm_id)

0 commit comments

Comments
 (0)