def setUp(self): self.item_name = "item" self.sha256_1 = \ "d65165279105ca6773180500688df4bdc69a2c7b771752f0a46ef120b7fd8ec3" self.sha256_2 = \ "cfdaaf1ab2e4661952a9dec5e8fa3c360c1b06b1a073e8493a7c46d2af8c504b" self.links = { "item": Metablock(signed=Link(name="item", materials={ "foo": { "sha256": self.sha256_1 }, "foobar": { "sha256": self.sha256_1 }, "bar": { "sha256": self.sha256_1 } }, products={ "baz": { "sha256": self.sha256_1 }, "foo": { "sha256": self.sha256_1 }, "bar": { "sha256": self.sha256_2 } })) }
def load(path): """Loads the JSON string representation of in-toto metadata from disk. Arguments: path: The path to read the file from. Raises: IOError: The file cannot be written. securesystemslib.exceptions.FormatError: Metadata format is invalid. Returns: A Metablock object whose signable attribute is either a Link or a Layout object. """ with open(path, "r") as fp: data = json.load(fp) signatures = data.get("signatures", []) signed_data = data.get("signed", {}) signed_type = signed_data.get("_type") if signed_type == "link": signed = Link.read(signed_data) elif signed_type == "layout": signed = Layout.read(signed_data) else: raise securesystemslib.exceptions.FormatError( "Invalid Metadata format") return Metablock(signatures=signatures, signed=signed)
def test_validate_byproducts(self): """Test `byproducts` field. Must be a `dict` """ test_link = Link() # Good byproducts test_link.byproducts = {} test_link.validate() # Bad byproducts test_link.byproducts = "not a dict" with self.assertRaises(FormatError): test_link.validate()
def test_validate_command(self): """Test `command` field. Must be either a `list` """ test_link = Link() # Good command test_link.command = ["echo", "'good command'"] test_link.validate() # Bad command test_link.command = "echo 'bad command'" with self.assertRaises(FormatError): test_link.validate()
def test_validate_type(self): """Test `_type` field. Must be "link" """ test_link = Link() # Good type test_link._type = "link" test_link.validate() # Bad type test_link._type = "bad link" with self.assertRaises(FormatError): test_link.validate()
def test_validate_environment(self): """Test `environment` field. Must be a `dict` """ test_link = Link() # good env per default test_link.validate() # Bad env test_link.environment = "not a dict" with self.assertRaises(FormatError): test_link.validate()
def setUp(self): """Setup artifact queues, artifacts dictionary and Link dictionary. """ # Dummy artifact hashes self.sha256_foo = \ "d65165279105ca6773180500688df4bdc69a2c7b771752f0a46ef120b7fd8ec3" self.sha256_foobar = \ "155c693a6b7481f48626ebfc545f05236df679f0099225d6d0bc472e6dd21155" self.sha256_bar = \ "cfdaaf1ab2e4661952a9dec5e8fa3c360c1b06b1a073e8493a7c46d2af8c504b" self.sha256_barfoo = \ "2036784917e49b7685c7c17e03ddcae4a063979aa296ee5090b5bb8f8aeafc5d" # Link dictionary containing dummy artifacts related to Steps the rule is # matched with (match destination). materials = { "foo": { "sha256": self.sha256_foo }, "foobar": { "sha256": self.sha256_foobar }, "dev/foo": { "sha256": self.sha256_foo }, "dev/foobar": { "sha256": self.sha256_foobar } } products = { "bar": { "sha256": self.sha256_bar }, "barfoo": { "sha256": self.sha256_barfoo }, "dev/bar": { "sha256": self.sha256_bar }, "dev/barfoo": { "sha256": self.sha256_barfoo }, } # Note: For simplicity the Links don't have all usually required fields set self.links = { "link-1": Metablock(signed=Link( name="link-1", materials=materials, products=products)), }
def to_link(self, step_name): """Returns an in-toto link Metablock class from a GrafeasInTotoOccurrence class. """ materials = {} products = {} command = [] byproducts = {} environment = {} for item in self.intoto["signed"]["materials"]: materials[item["resource_uri"]] = item["hashes"] for item in self.intoto["signed"]["products"]: products[item["resource_uri"]] = item["hashes"] command = self.intoto["signed"]["command"] for key, value in self.intoto["signed"]["byproducts"].items(): if key != "custom_values": byproducts[key] = value if "custom_values" in self.intoto["signed"]["byproducts"]: for key, value in \ self.intoto["signed"]["byproducts"]["custom_values"].items(): if key == "return-value": # This highlights a special case - in-toto's reference implementations # store return value as an integer while Grafeas allows only strings byproducts[key] = int(value) else: byproducts[key] = value for key, value in self.intoto["signed"]["environment"].items(): if key != "custom_values": environment[key] = value if "custom_values" in self.intoto["signed"]["environment"]: for key, value in \ self.intoto["signed"]["environment"]["custom_values"].items(): environment[key] = value return Metablock(signed=Link(name=step_name, materials=materials, products=products, command=command, byproducts=byproducts, environment=environment), signatures=self.intoto["signatures"])
def test_validate_signed(self): """Test validate Metablock's 'signed' property. """ # Valid Layout Metablock metablock = Metablock(signed=Layout()) metablock._validate_signed() # Valid Link Metablock Metablock(signed=Link()) metablock._validate_signed() # Fail instantiation with empty or invalid signed property # Metablock is validated on instantiation with self.assertRaises(FormatError): Metablock() with self.assertRaises(FormatError): Metablock(signed="not-a-layout-or-link") # Fail with invalid signed property metablock = Metablock(signed=Layout()) metablock.signed._type = "bogus type" with self.assertRaises(FormatError): metablock._validate_signed()
def load(path): """ <Purpose> Loads the JSON string representation of signed metadata from disk and creates a Metablock object. The `signed` attribute of the Metablock object is assigned a Link or Layout object, depending on the `_type` field in the loaded metadata file. <Arguments> path: The path to write the file to. <Side Effects> Reading metadata file from disk <Returns> None. """ with open(path, "r") as fp: data = json.load(fp) signatures = data.get("signatures", []) signed_data = data.get("signed", {}) signed_type = signed_data.get("_type") if signed_type == "link": signed = Link.read(signed_data) elif signed_type == "layout": signed = Layout.read(signed_data) else: raise securesystemslib.exceptions.FormatError( "Invalid Metadata format") return Metablock(signatures=signatures, signed=signed)
def test_validate_products(self): """Test `products` field. Must be a `dict` of HASH_DICTs """ test_link = Link() # Good products sha = "cfdaaf1ab2e4661952a9dec5e8fa3c360c1b06b1a073e8493a7c46d2af8c504b" test_link.products = {"bar": {"sha256": sha}} test_link.validate() # Bad products 1 test_link = Link() test_link.products = "not a dict" with self.assertRaises(FormatError): test_link.validate() # Bad products 2 test_link.products = {"not": "a product dict"} with self.assertRaises(FormatError): test_link.validate()
def test_validate_materials(self): """Test `materials` field. Must be a `dict` of HASH_DICTs """ test_link = Link() # Good materials sha = "d65165279105ca6773180500688df4bdc69a2c7b771752f0a46ef120b7fd8ec3" test_link.materials = {"foo": {"sha256": sha}} test_link.validate() # Bad materials 1 test_link.materials = "not a dict" with self.assertRaises(FormatError): test_link.validate() # Bad materials 1 test_link.materials = {"not": "a material dict"} with self.assertRaises(FormatError): test_link.validate()
def setUp(self): """Create a dummy supply chain with two steps one inspection and the according link metadata: write-code (Step) -> package (step) -> untar (Inspection) 'write-code' creates an artifact foo 'package' creates foo.tar.gz and deletes foo 'untar' untars foo.tar.gz which results in foo.tar.gz and foo """ self.sha256_foo = \ "d65165279105ca6773180500688df4bdc69a2c7b771752f0a46ef120b7fd8ec3" self.sha256_foo_tar = \ "93c3c35a039a6a3d53e81c5dbee4ebb684de57b7c8be11b8739fd35804a0e918" self.steps = [ Step( name="write-code", expected_products=[["CREATE", "foo"]], ), Step( name="package", expected_materials=[[ "MATCH", "foo", "WITH", "PRODUCTS", "FROM", "write-code" ]], expected_products=[["CREATE", "foo.tar.gz"], ["DELETE", "foo"]], ) ] self.inspections = [ Inspection(name="untar", expected_materials=[[ "MATCH", "foo.tar.gz", "WITH", "PRODUCTS", "FROM", "package" ]], expected_products=[[ "MATCH", "foo", "IN", "dir", "WITH", "PRODUCTS", "FROM", "write-code" ]]) ] self.links = { "write-code": Metablock( signed=Link(name="write-code", products={"foo": { "sha256": self.sha256_foo }})), "package": Metablock(signed=Link( name="package", materials={"foo": { "sha256": self.sha256_foo }}, products={"foo.tar.gz": { "sha256": self.sha256_foo_tar }})), "untar": Metablock(signed=Link( name="untar", materials={"foo.tar.gz": { "sha256": self.sha256_foo_tar }}, products={ "dir/foo": { "sha256": self.sha256_foo }, })) }