diff --git a/archivist/archivistpublic.py b/archivist/archivistpublic.py index cf6d530e..61671843 100644 --- a/archivist/archivistpublic.py +++ b/archivist/archivistpublic.py @@ -228,7 +228,7 @@ def get_file( Args: url (str): e.g. assets/xxxxxxxxxxxxxxxxxxxxxx - identity (str): e.g. attachments/xxxxxxxxxxxxxxxxxxxxxxxxxxxx` + identity (str): e.g. blobs/xxxxxxxxxxxxxxxxxxxxxxxxxxxx` fd (file): an iterable representing a file (usually from open()) the file must be opened in binary mode headers (dict): optional REST headers diff --git a/archivist/asset.py b/archivist/asset.py index df803fad..07e6e85f 100644 --- a/archivist/asset.py +++ b/archivist/asset.py @@ -21,6 +21,14 @@ def primary_image(self) -> str | None: :class:`Attachment` instance """ + + # try latest API + try: + return self["attributes"]["arc_primary_image"] + except (KeyError, TypeError): + pass + + # try old API try: attachments = self["attributes"]["arc_attachments"] except (KeyError, TypeError): diff --git a/archivist/assets.py b/archivist/assets.py index 09e7b671..2f2ccacc 100644 --- a/archivist/assets.py +++ b/archivist/assets.py @@ -204,6 +204,7 @@ def create_if_not_exists( attachments: - filename: functests/test_resources/doors/assets/entry-terminal.jpg content_type: image/jpg + attachment: terminal entry The 'selector' value is required and will usually specify the 'arc_display_name' as a secondary key. The keys in 'selector' must exist in the attributes of the asset. @@ -250,9 +251,15 @@ def create_if_not_exists( # any attachments ? if attachments is not None: - data["attributes"]["arc_attachments"] = [ - self._archivist.attachments.create(a) for a in attachments - ] + for a in attachments: + # attempt to get attachment to use as a key + attachment_key = a.get("attachment", None) + if attachment_key is None: + # failing that create a key from filename or url + attachment_key = self._archivist.attachments.get_default_key(a) + data["attributes"][attachment_key] = self._archivist.attachments.create( + a + ) asset = self.create_from_data( data=data, diff --git a/archivist/attachments.py b/archivist/attachments.py index 3865fe3c..48acdde5 100644 --- a/archivist/attachments.py +++ b/archivist/attachments.py @@ -28,6 +28,7 @@ from copy import deepcopy from io import BytesIO from logging import getLogger +from os import path from typing import BinaryIO, Optional, Any from requests.models import Response @@ -72,6 +73,18 @@ def __init__(self, archivist_instance: archivist.Archivist): def __str__(self) -> str: return f"AttachmentsClient({self._archivist.url})" + def get_default_key(self, data: dict[str, str]) -> str: + """ + Return a key to use if no key was provided + either use filename or url as one of them is required + """ + attachment_key = ( + data.get("filename", "") + if data.get("filename", "") + else data.get("url", "") + ) + return attachment_key.replace(".", "_") + def create(self, data: dict[str, Any]) -> dict[str, Any]: # pragma: no cover """ Create an attachment and return struct suitable for use in an asset @@ -108,14 +121,17 @@ def create(self, data: dict[str, Any]) -> dict[str, Any]: # pragma: no cover .. code-block:: yaml arc_display_name: Telephone - arc_attachment_identity: blobs/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - arc_hash_alg: SHA256 - arc_hash_value: xxxxxxxxxxxxxxxxxxxxxxx + arc_blob_identity: blobs/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + arc_blob_hash_alg: SHA256 + arc_blob_hash_value: xxxxxxxxxxxxxxxxxxxxxxx + arc_file_name: gdn_front.jpg """ result = None + file_part = None filename = data.get("filename") if filename is not None: + _, file_part = path.split(filename) with open(filename, "rb") as fd: attachment = self.upload(fd, mtype=data.get("content_type")) @@ -126,11 +142,15 @@ def create(self, data: dict[str, Any]) -> dict[str, Any]: # pragma: no cover attachment = self.upload(fd, mtype=data.get("content_type")) result = { - "arc_attachment_identity": attachment["identity"], - "arc_hash_alg": attachment["hash"]["alg"], - "arc_hash_value": attachment["hash"]["value"], + "arc_attribute_type": "arc_attachment", + "arc_blob_identity": attachment["identity"], + "arc_blob_hash_alg": attachment["hash"]["alg"], + "arc_blob_hash_value": attachment["hash"]["value"], } + if file_part: + result["arc_file_name"] = file_part + display_name = data.get("display_name") if display_name is not None: result["arc_display_name"] = display_name @@ -179,7 +199,7 @@ def download( fd iterator Args: - identity (str): attachment identity e.g. attachments/xxxxxxxxxxxxxxxxxxxxxxx + identity (str): attachment identity e.g. blobs/xxxxxxxxxxxxxxxxxxxxxxx fd (file): opened file descriptor or other file-type sink.. params (dict): e.g. {"allow_insecure": "true"} OR {"strict": "true" } @@ -202,7 +222,7 @@ def info( Reads attachment info Args: - identity (str): attachment identity e.g. attachments/xxxxxxxxxxxxxxxxxxxxxxx + identity (str): attachment identity e.g. blobs/xxxxxxxxxxxxxxxxxxxxxxx Returns: REST response diff --git a/archivist/events.py b/archivist/events.py index 0a8ba7b0..31edb5a2 100644 --- a/archivist/events.py +++ b/archivist/events.py @@ -360,19 +360,20 @@ def create_from_data( attachments = data.pop("attachments", None) if attachments is not None: - result = [self._archivist.attachments.create(a) for a in attachments] - for i, a in enumerate(attachments): + for a in attachments: + result = self._archivist.attachments.create(a) if a.get("type") == SBOM_RELEASE: sbom_result = self._archivist.sboms.parse(a) for k, v in sbom_result.items(): event_attributes[f"sbom_{k}"] = v - event_attributes["sbom_identity"] = result[i][ - "arc_attachment_identity" - ] - break + event_attributes["sbom_identity"] = result["arc_blob_identity"] - event_attributes["arc_attachments"] = result + attachment_key = a.get("attachment", None) + if attachment_key is None: + # failing that create a key from filename or url + attachment_key = self._archivist.attachments.get_default_key(a) + event_attributes[attachment_key] = result data["event_attributes"] = event_attributes diff --git a/archivist/notebooks/Find Asset and Create Attachment.ipynb b/archivist/notebooks/Find Asset and Create Attachment.ipynb index 23a7872d..74c99a1f 100644 --- a/archivist/notebooks/Find Asset and Create Attachment.ipynb +++ b/archivist/notebooks/Find Asset and Create Attachment.ipynb @@ -132,9 +132,9 @@ " blob = arch.attachments.upload(fd)\n", " attachment = {\n", " \"arc_display_name\": name,\n", - " \"arc_attachment_identity\": blob[\"identity\"],\n", - " \"arc_hash_value\": blob[\"hash\"][\"value\"],\n", - " \"arc_hash_alg\": blob[\"hash\"][\"alg\"],\n", + " \"arc_blob_identity\": blob[\"identity\"],\n", + " \"arc_blob_hash_value\": blob[\"hash\"][\"value\"],\n", + " \"arc_blob_hash_alg\": blob[\"hash\"][\"alg\"],\n", " }\n", " return attachment" ] @@ -173,7 +173,6 @@ " attachments = upload_attachment(\n", " arch, \"pexels-andrea-turner-707697.jpeg\", \"arc_primary_image\"\n", " )\n", - " attachment_list = [attachments]\n", "\n", " props = {\"operation\": \"Record\", \"behaviour\": \"RecordEvidence\"}\n", " attrs = {\n", @@ -181,7 +180,7 @@ " \"arc_display_type\": \"Primary image\",\n", " }\n", "\n", - " asset_attrs = {\"arc_attachments\": attachment_list}\n", + " asset_attrs = {\"pexels-andrea-turner-707697\": attachments}\n", "\n", " return arch.events.create(\n", " asset[\"identity\"], props=props, attrs=attrs, asset_attrs=asset_attrs\n", diff --git a/archivist/sboms.py b/archivist/sboms.py index 687526de..6a045325 100644 --- a/archivist/sboms.py +++ b/archivist/sboms.py @@ -174,7 +174,7 @@ def create(self, data: dict[str, Any]) -> dict[str, Any]: # pragma: no cover .. code-block:: yaml arc_display_name: Acme Generation1 SBOM - arc_attachment_identity: sboms/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + arc_blob_identity: sboms/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx ..... """ diff --git a/examples/scan_test.py b/examples/scan_test.py index a28b37fc..073ff201 100644 --- a/examples/scan_test.py +++ b/examples/scan_test.py @@ -67,10 +67,12 @@ def scan_test(arch, datestring, scanned_expected=False): "main/functests/test_resources/telephone.jpg" ), "content_type": "image/jpg", + "attachment": "telephone1", }, { "url": "https://secure.eicar.org/eicarcom2.zip", "content_type": "application/zip", + "attachment": "zipfile", }, ], }, @@ -82,7 +84,7 @@ def scan_test(arch, datestring, scanned_expected=False): fails = [] # first attachment should be clean.... - attachment_id = asset["attributes"]["arc_attachments"][0]["arc_attachment_identity"] + attachment_id = asset["attributes"]["telephone1"]["arc_blob_identity"] info = arch.attachments.info( attachment_id, asset_or_event_id=asset["identity"], @@ -100,7 +102,7 @@ def scan_test(arch, datestring, scanned_expected=False): fails.append("Yesterday's first attachment has not been scanned.") # second attachment should be bad when scanned.... - attachment_id = asset["attributes"]["arc_attachments"][1]["arc_attachment_identity"] + attachment_id = asset["attributes"]["zipfile"]["arc_blob_identity"] info = arch.attachments.info( attachment_id, asset_or_event_id=asset["identity"], diff --git a/functests/execassets.py b/functests/execassets.py index 8da67b3e..a7f4cebd 100644 --- a/functests/execassets.py +++ b/functests/execassets.py @@ -59,10 +59,12 @@ { "filename": "functests/test_resources/telephone.jpg", "content_type": "image/jpg", + "attachment": "telephone", }, { "url": "https://secure.eicar.org/eicarcom2.zip", "content_type": "application/zip", + "attachment": "zipfile", }, ], } @@ -271,9 +273,7 @@ def test_asset_create_if_not_exists_with_bad_attachment(self): LOGGER.debug("existed %s", existed) # first attachment is ok.... - attachment_id = asset["attributes"]["arc_attachments"][0][ - "arc_attachment_identity" - ] + attachment_id = asset["attributes"]["telephone"]["arc_blob_identity"] info = self.arch.attachments.info( attachment_id, ) @@ -290,9 +290,7 @@ def test_asset_create_if_not_exists_with_bad_attachment(self): ) # second attachment is bad when scanned.... - attachment_id = asset["attributes"]["arc_attachments"][1][ - "arc_attachment_identity" - ] + attachment_id = asset["attributes"]["zipfile"]["arc_blob_identity"] info = self.arch.attachments.info( attachment_id, ) @@ -327,9 +325,7 @@ def test_asset_create_if_not_exists_with_bad_attachment_assetattachment(self): LOGGER.debug("existed %s", existed) # first attachment is ok.... - attachment_id = asset["attributes"]["arc_attachments"][0][ - "arc_attachment_identity" - ] + attachment_id = asset["attributes"]["telephone"]["arc_blob_identity"] info = self.arch.assetattachments.info( asset["identity"], attachment_id, @@ -347,9 +343,7 @@ def test_asset_create_if_not_exists_with_bad_attachment_assetattachment(self): ) # second attachment is bad when scanned.... - attachment_id = asset["attributes"]["arc_attachments"][1][ - "arc_attachment_identity" - ] + attachment_id = asset["attributes"]["zipfile"]["arc_blob_identity"] info = self.arch.assetattachments.info( asset["identity"], attachment_id, diff --git a/functests/execpublicassets.py b/functests/execpublicassets.py index 49fe6858..d01b08f8 100644 --- a/functests/execpublicassets.py +++ b/functests/execpublicassets.py @@ -59,10 +59,12 @@ { "filename": "functests/test_resources/telephone.jpg", "content_type": "image/jpg", + "attachment": "telephone", }, { "url": "https://secure.eicar.org/eicarcom2.zip", "content_type": "application/zip", + "attachment": "zipfile", }, ], "public": True, @@ -231,9 +233,7 @@ def test_asset_create_if_not_exists_with_bad_attachment_assetattachment(self): asset_id = asset["identity"] # first attachment is ok.... - attachment_id = asset["attributes"]["arc_attachments"][0][ - "arc_attachment_identity" - ] + attachment_id = asset["attributes"]["telephone"]["arc_blob_identity"] public_asset_id = self.arch.assets.publicurl(asset_id) LOGGER.debug("public asset id %s", public_asset_id) public = self.arch.Public @@ -252,9 +252,7 @@ def test_asset_create_if_not_exists_with_bad_attachment_assetattachment(self): ) # second attachment is bad when scanned.... - attachment_id = asset["attributes"]["arc_attachments"][1][ - "arc_attachment_identity" - ] + attachment_id = asset["attributes"]["zipfile"]["arc_blob_identity"] info = public.assetattachments.info(public_asset_id, attachment_id) LOGGER.debug("info attachment1 %s", json_dumps(info, indent=4)) timestamp = info["scanned_timestamp"] diff --git a/unittests/testassets.py b/unittests/testassets.py index a14f52b9..de1a3611 100644 --- a/unittests/testassets.py +++ b/unittests/testassets.py @@ -360,8 +360,8 @@ def common_assets_create_if_not_exists_nonexistent_asset( ) if attachments_resp is not None: - mock_attachments.assert_called_once() - args, kwargs = mock_attachments.call_args + mock_attachments.assert_called() + args, kwargs = mock_attachments.call_args_list[0] self.assertEqual( args, (req.get("attachments")[0],), diff --git a/unittests/testassetsconstants.py b/unittests/testassetsconstants.py index d4cb7744..d25ed7a5 100644 --- a/unittests/testassetsconstants.py +++ b/unittests/testassetsconstants.py @@ -19,21 +19,24 @@ # pylint: disable=unused-variable PRIMARY_IMAGE = { + "arc_attribute_type": "arc_attachment", "arc_display_name": "arc_primary_image", - "arc_attachment_identity": "blobs/87b1a84c-1c6f-442b-923e-a97516f4d275", - "arc_hash_alg": "SHA256", - "arc_hash_value": "246c316e2cd6971ce5c83a3e61f9880fa6e2f14ae2976ee03500eb282fd03a60", + "arc_blob_identity": "blobs/87b1a84c-1c6f-442b-923e-a97516f4d275", + "arc_blob_hash_alg": "SHA256", + "arc_blob_hash_value": "246c316e2cd6971ce5c83a3e61f9880fa6e2f14ae2976ee03500eb282fd03a60", } SECONDARY_IMAGE = { + "arc_attribute_type": "arc_attachment", "arc_display_name": "arc_secondary_image", - "arc_attachment_identity": "blobs/87b1a84c-1c6f-442b-923e-a97516f4d275", - "arc_hash_alg": "SHA256", - "arc_hash_value": "246c316e2cd6971ce5c83a3e61f9880fa6e2f14ae2976ee03500eb282fd03a60", + "arc_blob_identity": "blobs/87b1a84c-1c6f-442b-923e-a97516f4d275", + "arc_blob_hash_alg": "SHA256", + "arc_blob_hash_value": "246c316e2cd6971ce5c83a3e61f9880fa6e2f14ae2976ee03500eb282fd03a60", } TERTIARY_IMAGE = { - "arc_attachment_identity": "blobs/87b1a84c-1c6f-442b-923e-a97516f4d275", - "arc_hash_alg": "SHA256", - "arc_hash_value": "246c316e2cd6971ce5c83a3e61f9880fa6e2f14ae2976ee03500eb282fd03a60", + "arc_attribute_type": "arc_attachment", + "arc_blob_identity": "blobs/87b1a84c-1c6f-442b-923e-a97516f4d275", + "arc_blob_hash_alg": "SHA256", + "arc_blob_hash_value": "246c316e2cd6971ce5c83a3e61f9880fa6e2f14ae2976ee03500eb282fd03a60", } ASSET_NAME = "tcl.ppj.003" # also has no arc_display_name @@ -232,6 +235,11 @@ "filename": "test_filename1", "content_type": "image/jpg", }, + { + "attachment": "test_filename2", + "filename": "test_filename1", + "content_type": "image/jpg", + }, ], } REQUEST_EXISTS_KWARGS_ATTACHMENTS = { @@ -246,17 +254,26 @@ "arc_description": "Traffic flow control light at A603 North East", "arc_display_type": "Traffic light with violation camera", "some_custom_attribute": "value", - "arc_attachments": [ - { - "arc_attachment_identity": f"{ATTACHMENTS_LABEL}/xxxxxxxx", - "arc_display_name": "arc_primary_image", - "arc_hash_alg": "SHA256", - "arc_hash_value": ( - "246c316e2cd6971ce5c83a3e61f9" - "880fa6e2f14ae2976ee03500eb282fd03a60" - ), - }, - ], + "test_filename1": { + "arc_attribute_type": "arc_attachment", + "arc_blob_identity": f"{ATTACHMENTS_LABEL}/xxxxxxxx", + "arc_display_name": "arc_primary_image", + "arc_blob_hash_alg": "SHA256", + "arc_blob_hash_value": ( + "246c316e2cd6971ce5c83a3e61f9" + "880fa6e2f14ae2976ee03500eb282fd03a60" + ), + }, + "test_filename2": { + "arc_attribute_type": "arc_attachment", + "arc_blob_identity": f"{ATTACHMENTS_LABEL}/xxxxxxxx", + "arc_display_name": "arc_primary_image", + "arc_blob_hash_alg": "SHA256", + "arc_blob_hash_value": ( + "246c316e2cd6971ce5c83a3e61f9" + "880fa6e2f14ae2976ee03500eb282fd03a60" + ), + }, }, }, "headers": { @@ -265,10 +282,11 @@ "verify": True, } RESPONSE_ATTACHMENTS = { - "arc_attachment_identity": f"{ATTACHMENTS_LABEL}/xxxxxxxx", + "arc_attribute_type": "arc_attachment", + "arc_blob_identity": f"{ATTACHMENTS_LABEL}/xxxxxxxx", "arc_display_name": "arc_primary_image", - "arc_hash_alg": "SHA256", - "arc_hash_value": "246c316e2cd6971ce5c83a3e61f9880fa6e2f14ae2976ee03500eb282fd03a60", + "arc_blob_hash_alg": "SHA256", + "arc_blob_hash_value": "246c316e2cd6971ce5c83a3e61f9880fa6e2f14ae2976ee03500eb282fd03a60", } RESPONSE_EXISTS_ATTACHMENTS = { "identity": IDENTITY, @@ -281,12 +299,13 @@ "arc_display_type": "Traffic light with violation camera", "some_custom_attribute": "value", "arc_display_name": ASSET_NAME, - "arc_attachments": [ + "test_filename1": [ { - "arc_attachment_identity": "blobs/87b1a84c-1c6f-442b-923e-a97516f4d275", + "arc_attribute_type": "arc_attachment", + "arc_blob_identity": "blobs/87b1a84c-1c6f-442b-923e-a97516f4d275", "arc_display_name": "arc_primary_image", - "arc_hash_alg": "SHA256", - "arc_hash_value": ( + "arc_blob_hash_alg": "SHA256", + "arc_blob_hash_value": ( "246c316e2cd6971ce5c83a3e61f988" "0fa6e2f14ae2976ee03500eb282fd03a60" ), diff --git a/unittests/testattachments.py b/unittests/testattachments.py index 327d97c1..7eebfc90 100644 --- a/unittests/testattachments.py +++ b/unittests/testattachments.py @@ -31,9 +31,9 @@ "identity": IDENTITY, } CREATE_RESULT = { - "arc_attachment_identity": IDENTITY, - "arc_hash_alg": "SHA256", - "arc_hash_value": "xxxxxxxxxxxxxxxxxxxxxxx", + "arc_blob_identity": IDENTITY, + "arc_blob_hash_alg": "SHA256", + "arc_blob_hash_value": "xxxxxxxxxxxxxxxxxxxxxxx", } INFO = { @@ -53,6 +53,8 @@ "scanned_timestamp": "", } +ATTACHMENT_DATA = {"filename": "/a/b/c/d.x"} + class TestAttachmentsBase(TestCase): """ @@ -77,6 +79,16 @@ def test_attachments_str(self): msg="Incorrect str", ) + def test_get_default_key(self): + """ + Test get_default_key + """ + self.assertEqual( + self.arch.attachments.get_default_key(ATTACHMENT_DATA), + "/a/b/c/d_x", + msg="Incorrect default key from filename", + ) + # NB: Also applies to sboms.create() which has pragma no cover set as well... # diff --git a/unittests/testeventsconstants.py b/unittests/testeventsconstants.py index 26a4f794..29f3f532 100644 --- a/unittests/testeventsconstants.py +++ b/unittests/testeventsconstants.py @@ -20,16 +20,16 @@ ASSET_ID = f"{ASSETS_LABEL}/xxxxxxxxxxxxxxxxxxxx" PRIMARY_IMAGE = { - "arc_attachment_identity": f"{ATTACHMENTS_LABEL}/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", + "arc_blob_identity": f"{ATTACHMENTS_LABEL}/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "arc_display_name": "an attachment 2", - "arc_hash_value": "042aea10a0f14f2d391373599be69d53a75dde9951fc3d3cd10b6100aa7a9f24", - "arc_hash_alg": "sha256", + "arc_blob_hash_value": "042aea10a0f14f2d391373599be69d53a75dde9951fc3d3cd10b6100aa7a9f24", + "arc_blob_hash_alg": "sha256", } SECONDARY_IMAGE = { - "arc_attachment_identity": f"{ATTACHMENTS_LABEL}/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", + "arc_blob_identity": f"{ATTACHMENTS_LABEL}/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "arc_display_name": "an attachment 1", - "arc_hash_value": "jnwpjocoqsssnundwlqalsqiiqsqp;lpiwpldkndwwlskqaalijopjkokkkojijl", - "arc_hash_alg": "sha256", + "arc_blob_hash_value": "jnwpjocoqsssnundwlqalsqiiqsqp;lpiwpldkndwwlskqaalijopjkokkkojijl", + "arc_blob_hash_alg": "sha256", } PRINCIPAL_DECLARED = { "issuer": "idp.synsation.io/1234", @@ -94,9 +94,11 @@ IDENTITY = f"{ASSET_ID}/{EVENTS_LABEL}/xxxxxxxxxxxxxxxxxxxx" ATTACHMENTS = { - "arc_attachment_identity": f"{ATTACHMENTS_LABEL}/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", - "arc_hash_value": "jnwpjocoqsssnundwlqalsqiiqsqp;lpiwpldkndwwlskqaalijopjkokkkojijl", - "arc_hash_alg": "sha256", + "arc_attribute_type": "arc_attachment", + "arc_blob_identity": f"{ATTACHMENTS_LABEL}/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", + "arc_blob_hash_value": "jnwpjocoqsssnundwlqalsqiiqsqp;lpiwpldkndwwlskqaalijopjkokkkojijl", + "arc_blob_hash_alg": "sha256", + "arc_file_name": "", } EVENT_ATTRS_ATTACHMENTS = { @@ -109,9 +111,14 @@ }, "attachments": [ { + "attachment": "door open", "filename": "door_open.png", "content_type": "image/jpg", }, + { + "filename": "door_closed.png", + "content_type": "image/jpg", + }, ], } REQUEST_WITH_ATTACHMENTS = { @@ -121,9 +128,8 @@ "principal_declared": PRINCIPAL_DECLARED, "event_attributes": { "arc_description": "event description", - "arc_attachments": [ - ATTACHMENTS, - ], + "door open": ATTACHMENTS, + "door_closed_png": ATTACHMENTS, }, } RESPONSE_WITH_ATTACHMENTS = { @@ -134,9 +140,8 @@ "principal_declared": PRINCIPAL_DECLARED, "event_attributes": { "arc_description": "event description", - "arc_attachments": [ - ATTACHMENTS, - ], + "door open": ATTACHMENTS, + "door_closed_png": ATTACHMENTS, }, } @@ -233,6 +238,7 @@ }, "attachments": [ { + "attachment": "sbom_document", "filename": "gen1.xml", "content_type": "text/xml", "type": SBOM_RELEASE, @@ -254,9 +260,7 @@ "sbom_supplier": "CycloneDx 1.3 XML Default Supplier", "sbom_uuid": "urn:uuid:a24426e6-f122-4339-8b03-758a96a42e3b", "sbom_version": "CycloneDx 1.3 XML Default Version", - "arc_attachments": [ - ATTACHMENTS, - ], + "sbom_document": ATTACHMENTS, }, } RESPONSE_WITH_SBOMATTACHMENT = { @@ -275,9 +279,7 @@ "sbom_supplier": "CycloneDx 1.3 XML Default Supplier", "sbom_uuid": "urn:uuid:a24426e6-f122-4339-8b03-758a96a42e3b", "sbom_version": "CycloneDx 1.3 XML Default Version", - "arc_attachments": [ - ATTACHMENTS, - ], + "sbom_document": ATTACHMENTS, }, } diff --git a/unittests/testrunnerassets.py b/unittests/testrunnerassets.py index dc0af376..c71292a9 100644 --- a/unittests/testrunnerassets.py +++ b/unittests/testrunnerassets.py @@ -103,20 +103,24 @@ "behaviour": "RecordEvidence", "event_attributes": { "arc_display_type": "open", - "arc_attachments": [ - { - "arc_attachment_identity": "blobs/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", - "arc_display_name": "an attachment 1", - "arc_hash_value": "jnwpjocoqsssnundwlqalsqiiqsqp;lpiwpldkndwwlskqaalijopjkokkkijl", - "arc_hash_alg": "sha256", - }, - { - "arc_attachment_identity": "blobs/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", - "arc_display_name": "an attachment 2", - "arc_hash_value": "042aea10a0f14f2d391373599be69d53a75dde9951fc3d3cd10b6100aa7f24", - "arc_hash_alg": "sha256", - }, - ], + "an attachment 1": { + "arc_attribute_type": "arc_attachment", + "arc_blob_identity": "blobs/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", + "arc_display_name": "an attachment 1", + "arc_blob_hash_value": ( + "jnwpjocoqsssnundwlqalsqiiqsqp;lpiwpldkndwwlskqaalijopjkokkkijl" + ), + "arc_blob_hash_alg": "sha256", + }, + "an attachment 2": { + "arc_attribute_type": "arc_attachment", + "arc_blob_identity": "blobs/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", + "arc_display_name": "an attachment 2", + "arc_blob_hash_value": ( + "042aea10a0f14f2d391373599be69d53a75dde9951fc3d3cd10b6100aa7f24" + ), + "arc_blob_hash_alg": "sha256", + }, }, "location": {"identity": "locations/add30235-1424-4fda-840a-d5ef82c4c96f"}, } @@ -130,20 +134,24 @@ "behaviour": "RecordEvidence", "event_attributes": { "arc_display_type": "open", - "arc_attachments": [ - { - "arc_attachment_identity": "blobs/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", - "arc_display_name": "an attachment 1", - "arc_hash_value": "jnwpjocoqsssnundwlqalsqiiqsqp;lpiwpldkndwwlskqaalijopjkokkkijl", - "arc_hash_alg": "sha256", - }, - { - "arc_attachment_identity": "blobs/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", - "arc_display_name": "an attachment 2", - "arc_hash_value": "042aea10a0f14f2d391373599be69d53a75dde9951fc3d3cd10b6100aa7f24", - "arc_hash_alg": "sha256", - }, - ], + "an attachment 1": { + "arc_attribute_type": "arc_attachment", + "arc_blob_identity": "blobs/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", + "arc_display_name": "an attachment 1", + "arc_blob_hash_value": ( + "jnwpjocoqsssnundwlqalsqiiqsqp;lpiwpldkndwwlskqaalijopjkokkkijl" + ), + "arc_blob_hash_alg": "sha256", + }, + "an attachment 2": { + "arc_attribute_type": "arc_attachment", + "arc_blob_identity": "blobs/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", + "arc_display_name": "an attachment 2", + "arc_blob_hash_value": ( + "042aea10a0f14f2d391373599be69d53a75dde9951fc3d3cd10b6100aa7f24" + ), + "arc_blob_hash_alg": "sha256", + }, }, "asset_attributes": { "arc_display_type": "door",