From 71cc898933d899d8e0d59f41ba532267f75ce8d7 Mon Sep 17 00:00:00 2001 From: John Andersen Date: Tue, 12 Sep 2023 14:53:56 +0000 Subject: [PATCH] Add /service-parameters route to enable discovery via client CLI Related: https://github.com/ietf-wg-scitt/draft-ietf-scitt-architecture/issues/96 Signed-off-by: John Andersen --- scitt_emulator/client.py | 24 ++++++++++++++++++++++++ scitt_emulator/scitt.py | 3 +++ scitt_emulator/server.py | 8 +++++++- tests/test_cli.py | 16 ++++++++++++++++ 4 files changed, 50 insertions(+), 1 deletion(-) diff --git a/scitt_emulator/client.py b/scitt_emulator/client.py index 40645bda..3b0a1884 100644 --- a/scitt_emulator/client.py +++ b/scitt_emulator/client.py @@ -151,6 +151,16 @@ def retrieve_receipt(url: str, entry_id: Path, receipt_path: Path, client: HttpC print(f"Receipt written to {receipt_path}") +def retrieve_service_parameters(url: str, service_parameters_path: Path, client: HttpClient): + response = client.get(f"{url}/service-parameters") + service_parameters = response.content + + with open(service_parameters_path, "wb") as f: + f.write(service_parameters) + + print(f"Service parameters written to {service_parameters_path}") + + def verify_receipt(cose_path: Path, receipt_path: Path, service_parameters_path: Path): with open(service_parameters_path) as f: service_parameters = json.load(f) @@ -227,6 +237,20 @@ def cli(fn): ) ) + p = sub.add_parser("retrieve-service-parameters", description="Retrieve SCITT service parameters") + p.add_argument( + "--out", required=True, type=Path, help="Path to write the service parameters to" + ) + p.add_argument("--url", required=False, default=DEFAULT_URL) + p.add_argument("--token", help="Bearer token to authenticate with") + p.add_argument("--cacert", type=Path, help="CA certificate to verify host against") + p.set_defaults( + func=lambda args: retrieve_service_parameters( + args.url, args.out, + HttpClient(args.token, args.cacert) + ) + ) + p = sub.add_parser("verify-receipt", description="Verify a SCITT receipt") p.add_argument("--claim", required=True, type=Path) p.add_argument("--receipt", required=True, type=Path) diff --git a/scitt_emulator/scitt.py b/scitt_emulator/scitt.py index f33ca89f..bfac6162 100644 --- a/scitt_emulator/scitt.py +++ b/scitt_emulator/scitt.py @@ -71,6 +71,9 @@ def create_receipt_contents(self, countersign_tbi: bytes, entry_id: str): def verify_receipt_contents(receipt_contents: list, countersign_tbi: bytes): raise NotImplementedError + def get_service_parameters(self) -> dict: + return self.service_parameters + def get_operation(self, operation_id: str) -> dict: operation_path = self.operations_path / f"{operation_id}.json" try: diff --git a/scitt_emulator/server.py b/scitt_emulator/server.py index 094d0b6a..729713e0 100644 --- a/scitt_emulator/server.py +++ b/scitt_emulator/server.py @@ -6,7 +6,7 @@ from io import BytesIO import random -from flask import Flask, request, send_file, make_response +from flask import Flask, request, send_file, make_response, jsonify from scitt_emulator.tree_algs import TREE_ALGS from scitt_emulator.scitt import EntryNotFoundError, ClaimInvalidError, OperationNotFoundError @@ -52,6 +52,12 @@ def create_flask_app(config): def is_unavailable(): return random.random() <= error_rate + @app.route("/service-parameters", methods=["GET"]) + def get_service_parameters(): + if is_unavailable(): + return make_unavailable_error() + return jsonify(app.scitt_service.get_service_parameters()) + @app.route("/entries//receipt", methods=["GET"]) def get_receipt(entry_id: str): if is_unavailable(): diff --git a/tests/test_cli.py b/tests/test_cli.py index f04f2cf5..690e371a 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -1,6 +1,7 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT License. import os +import json import threading import pytest from werkzeug.serving import make_server @@ -86,6 +87,21 @@ def test_client_cli(use_lro: bool, tmp_path): assert os.path.exists(receipt_path) assert os.path.exists(entry_id_path) + # retrieve service parameters + original_service_parameters = json.loads(service.service_parameters_path.read_text()) + service.service_parameters_path.unlink() + assert not service.service_parameters_path.exists() + command = [ + "client", + "retrieve-service-parameters", + "--out", + service.service_parameters_path, + "--url", + service.url + ] + execute_cli(command) + assert original_service_parameters == json.loads(service.service_parameters_path.read_text()) + # verify receipt command = [ "client",