|
20 | 20 | import os |
21 | 21 | import sys |
22 | 22 | import time |
23 | | -import random |
24 | 23 | import hashlib |
| 24 | +import secrets |
| 25 | +import asyncio |
25 | 26 |
|
26 | 27 | import avalon_enclave_manager.sgx_work_order_request as work_order_request |
27 | 28 | import avalon_enclave_manager.avalon_enclave_helper as enclave_helper |
@@ -54,12 +55,9 @@ def __init__(self, config, signup_data, measurements): |
54 | 55 | self.verifying_key = signup_data.verifying_key |
55 | 56 | self.encryption_key = signup_data.encryption_key |
56 | 57 |
|
57 | | - # TODO: EncryptionKeyNonce and EncryptionKeySignature are hardcoded |
58 | | - # to dummy values. |
59 | | - # Need to come up with a scheme to generate both for every unique |
60 | | - # encryption key. |
61 | | - self.encryption_key_nonce = "" |
62 | | - self.encryption_key_signature = "" |
| 58 | + self.encryption_key_signature = signup_data.encryption_key_signature |
| 59 | + # Generate random 32 byte nonce in hex format |
| 60 | + self.encryption_key_nonce = secrets.token_hex(32) |
63 | 61 | self.enclave_id = signup_data.enclave_id |
64 | 62 | self.extended_measurements = measurements |
65 | 63 |
|
@@ -92,11 +90,8 @@ def manager_on_boot(self, kv_helper): |
92 | 90 |
|
93 | 91 | worker_info = create_json_worker(self, self.config) |
94 | 92 | logger.info("Adding enclave workers to workers table") |
95 | | - worker_id = crypto_utils.strip_begin_end_public_key(self.enclave_id) \ |
96 | | - .encode("UTF-8") |
97 | | - # Calculate sha256 of worker id to get 32 bytes. The TC spec proxy |
98 | | - # model contracts expect byte32. Then take a hexdigest for hex str. |
99 | | - worker_id = hashlib.sha256(worker_id).hexdigest() |
| 93 | + worker_id = crypto_utils.calculate_worker_id_from_public_key( |
| 94 | + self.enclave_id) |
100 | 95 |
|
101 | 96 | kv_helper.set("workers", worker_id, worker_info) |
102 | 97 |
|
@@ -159,7 +154,6 @@ def manager_on_boot(self, kv_helper): |
159 | 154 |
|
160 | 155 | # End of for-loop |
161 | 156 |
|
162 | | - # ----------------------------------------------------------------- |
163 | 157 | def process_work_orders(self, kv_helper): |
164 | 158 | """ |
165 | 159 | Executes Run time flow of enclave manager |
@@ -255,7 +249,6 @@ def process_work_orders(self, kv_helper): |
255 | 249 | # end of for loop |
256 | 250 |
|
257 | 251 | # ----------------------------------------------------------------- |
258 | | - |
259 | 252 | def __update_receipt(self, kv_helper, wo_id, wo_json_resp): |
260 | 253 | """ |
261 | 254 | Update the existing work order receipt with the status as in wo_json_ |
@@ -330,6 +323,71 @@ def create_enclave_signup_data(): |
330 | 323 | return enclave_signup_data |
331 | 324 |
|
332 | 325 |
|
| 326 | +# ----------------------------------------------------------------- |
| 327 | +async def wo_process(config, kv_helper, enclave_manager): |
| 328 | + """ |
| 329 | + Process work order requests in TEE and persist result in KvStorage |
| 330 | +
|
| 331 | + @param enclave_manager - instance of the EnclaveManager class |
| 332 | + @param kv_helper - instance of KvStorage |
| 333 | + @param config - instance of the configuration parsed while bringing up |
| 334 | + enclave manager service |
| 335 | + """ |
| 336 | + try: |
| 337 | + sleep_interval = int(config["EnclaveManager"]["sleep_interval"]) |
| 338 | + except Exception as err: |
| 339 | + logger.error("Failed to get sleep interval from config file. " + |
| 340 | + "Setting sleep interval to 10 seconds: %s", str(err)) |
| 341 | + sleep_interval = 10 |
| 342 | + |
| 343 | + while True: |
| 344 | + try: |
| 345 | + enclave_manager.process_work_orders(kv_helper) |
| 346 | + except Exception as e: |
| 347 | + logger.error("Error while processing work-order") |
| 348 | + logger.error("Exception: {} args {} details {}".format(type(e), |
| 349 | + e.args, e)) |
| 350 | + await asyncio.sleep(sleep_interval) |
| 351 | + |
| 352 | + |
| 353 | +# ----------------------------------------------------------------- |
| 354 | +async def initiate_key_refresh(config, kv_helper, enclave_manager): |
| 355 | + |
| 356 | + """ |
| 357 | + Initiate worker encryption key refresh and update worker details |
| 358 | + and updates worker details to kv storage |
| 359 | + @param lock - ayncio lock instance |
| 360 | + @param config - instance of configuration parsed to enclave manager process |
| 361 | + @param kv_helper - instance of KvStorage |
| 362 | + @param enclave_manager - instance of enclave manager |
| 363 | + """ |
| 364 | + try: |
| 365 | + key_refresh_interval = \ |
| 366 | + int(config["WorkerKeyRefresh"]["key_refresh_interval"]) |
| 367 | + if key_refresh_interval <= 0: |
| 368 | + return |
| 369 | + except Exception as err: |
| 370 | + logger.error("Failed to get key refresh interval from config file", |
| 371 | + str(err)) |
| 372 | + return |
| 373 | + asyncio.sleep(key_refresh_interval) |
| 374 | + while True: |
| 375 | + try: |
| 376 | + enclave_data = enclave_manager.enclave_data |
| 377 | + enclave_signup_data = \ |
| 378 | + enclave_data.initiate_refresh_worker_encryption_key() |
| 379 | + # Update Enclave Manager with updated signup data after key refresh |
| 380 | + enclave_manager = EnclaveManager( |
| 381 | + config, enclave_signup_data, |
| 382 | + enclave_manager.extended_measurements) |
| 383 | + # Persist updated worker to KV storage |
| 384 | + persist_worker(enclave_manager, kv_helper) |
| 385 | + except Exception as e: |
| 386 | + logger.error("failed to get signup data after key refresh: %s", |
| 387 | + str(e)) |
| 388 | + await asyncio.sleep(key_refresh_interval) |
| 389 | + |
| 390 | + |
333 | 391 | # ----------------------------------------------------------------- |
334 | 392 | def execute_work_order(enclave_data, input_json_str, indent=4): |
335 | 393 | """ |
@@ -385,6 +443,8 @@ def create_json_worker(enclave_data, config): |
385 | 443 | worker_type_data["encryptionKey"] = enclave_data.encryption_key |
386 | 444 | worker_type_data["encryptionKeySignature"] = \ |
387 | 445 | enclave_data.encryption_key_signature |
| 446 | + worker_type_data["encryptionKeyNonce"] = \ |
| 447 | + enclave_data.encryption_key_nonce |
388 | 448 |
|
389 | 449 | worker_info = dict() |
390 | 450 | worker_info["workerType"] = WorkerType.TEE_SGX.value |
@@ -430,6 +490,37 @@ def create_json_worker(enclave_data, config): |
430 | 490 | return json_worker_info |
431 | 491 |
|
432 | 492 |
|
| 493 | +# ----------------------------------------------------------------- |
| 494 | +def persist_worker(enclave_manager, kv_helper): |
| 495 | + """ |
| 496 | + Persists worker to KvStorage |
| 497 | +
|
| 498 | + @param enclave_manager - instance of EnclaveManager class |
| 499 | + @param kv_helper - instance of KvStorage |
| 500 | + """ |
| 501 | + worker_info = create_json_worker(enclave_manager, enclave_manager.config) |
| 502 | + worker_id = crypto_utils.calculate_worker_id_from_public_key( |
| 503 | + enclave_manager.enclave_id) |
| 504 | + logger.info("Persisting worker to workers table") |
| 505 | + kv_helper.set("workers", worker_id, worker_info) |
| 506 | + |
| 507 | + |
| 508 | +async def execute_tasks(enclave_manager, kv_helper, config): |
| 509 | + """ |
| 510 | + Executes worker encryption key refresh task and work order execution |
| 511 | + inside TEE asynchronously. |
| 512 | +
|
| 513 | + @param enclave_manager - instance of the EnclaveManager class |
| 514 | + @param kv_helper - instance of KvStorage |
| 515 | + @param config - instance of the configuration parsed while bringing up |
| 516 | + enclave manager service |
| 517 | + """ |
| 518 | + await asyncio.wait([ |
| 519 | + wo_process(config, kv_helper, enclave_manager), |
| 520 | + initiate_key_refresh(config, kv_helper, enclave_manager) |
| 521 | + ]) |
| 522 | + |
| 523 | + |
433 | 524 | # ----------------------------------------------------------------- |
434 | 525 | def start_enclave_manager(config): |
435 | 526 | """ |
@@ -475,23 +566,19 @@ def start_enclave_manager(config): |
475 | 566 |
|
476 | 567 | try: |
477 | 568 | sleep_interval = int(config["EnclaveManager"]["sleep_interval"]) |
| 569 | + key_refresh_interval = \ |
| 570 | + int(config["WorkerKeyRefresh"]["key_refresh_interval"]) |
478 | 571 | except Exception as err: |
479 | 572 | logger.error("Failed to get sleep interval from config file. " + |
480 | 573 | "Setting sleep interval to 10 seconds: %s", str(err)) |
481 | 574 | sleep_interval = 10 |
482 | 575 |
|
| 576 | + event_loop = asyncio.get_event_loop() |
483 | 577 | try: |
484 | | - while True: |
485 | | - # Poll KV storage for new work-order requests and process |
486 | | - enclave_manager.process_work_orders(kv_helper) |
487 | | - logger.info("Enclave manager sleeping for %d secs", sleep_interval) |
488 | | - time.sleep(sleep_interval) |
489 | | - except Exception as inst: |
490 | | - logger.error("Error while processing work-order; " + |
491 | | - "shutting down enclave manager") |
492 | | - logger.error("Exception: {} args {} details {}".format(type(inst), |
493 | | - inst.args, inst)) |
494 | | - exit(1) |
| 578 | + event_loop.run_until_complete( |
| 579 | + execute_tasks(enclave_manager, kv_helper, config)) |
| 580 | + finally: |
| 581 | + event_loop.close() |
495 | 582 |
|
496 | 583 |
|
497 | 584 | TCFHOME = os.environ.get("TCF_HOME", "../../../../") |
|
0 commit comments