def main(): key_owner = interface.import_rsa_privatekey_from_file("./keys/owner") key_clone = interface.import_rsa_publickey_from_file("./keys/clone.pub") key_build = interface.import_rsa_publickey_from_file("./keys/build.pub") key_build_image = interface.import_rsa_publickey_from_file( "./keys/build-image.pub") layout = Layout.read({ "_type": "layout", "keys": { key_clone["keyid"]: key_clone, key_build["keyid"]: key_build, key_build_image["keyid"]: key_build_image, }, "steps": [{ "name": "clone", "expected_materials": [["DISALLOW", "*"]], "expected_products": [["CREATE", "*"]], "pubkeys": [key_clone["keyid"]], "expected_command": [ "git", "clone", "https://gitlab.com/boxboat/demos/intoto-spire/go-hello-world" ], "threshold": 1, }, { "name": "build", "expected_materials": [["MATCH", "*", "WITH", "PRODUCTS", "FROM", "clone"], ["DISALLOW", "*"]], "expected_products": [["CREATE", "go-hello-world"], ["DISALLOW", "*"]], "pubkeys": [key_build["keyid"]], "expected_command": ["go", "build", "./..."], "threshold": 1, }, { "name": "build-image", "expected_materials": [["MATCH", "*", "WITH", "PRODUCTS", "FROM", "clone"], ["DISALLOW", "*"]], "expected_products": [["CREATE", "image-id"], ["CREATE", "go-hello-world.tar"], ["DISALLOW", "*"]], "pubkeys": [key_build_image["keyid"]], "threshold": 1, }], "inspect": [] }) metadata = Metablock(signed=layout) # Sign and dump layout to "root.layout" metadata.sign(key_owner) metadata.dump("root.layout")
def test_import_rsa_publickey_from_file(self): # Test normal case. temporary_directory = tempfile.mkdtemp(dir=self.temporary_directory) # Load one of the pre-generated key files from 'securesystemslib/tests/data'. key_filepath = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'data', 'keystore', 'rsa_key.pub') self.assertTrue(os.path.exists(key_filepath)) imported_rsa_key = interface.import_rsa_publickey_from_file(key_filepath) self.assertTrue(securesystemslib.formats.RSAKEY_SCHEMA.matches(imported_rsa_key)) # Test improperly formatted argument. self.assertRaises(securesystemslib.exceptions.FormatError, interface.import_rsa_privatekey_from_file, 3) # Test invalid argument. # Non-existent key file. nonexistent_keypath = os.path.join(temporary_directory, 'nonexistent_keypath') self.assertRaises(IOError, interface.import_rsa_publickey_from_file, nonexistent_keypath) # Invalid key file argument. invalid_keyfile = os.path.join(temporary_directory, 'invalid_keyfile') with open(invalid_keyfile, 'wb') as file_object: file_object.write(b'bad keyfile') self.assertRaises(securesystemslib.exceptions.Error, interface.import_rsa_publickey_from_file, invalid_keyfile)
def test_generate_and_write_rsa_keypair(self): # Test normal case. temporary_directory = tempfile.mkdtemp(dir=self.temporary_directory) test_keypath = os.path.join(temporary_directory, 'rsa_key') test_keypath_unencrypted = os.path.join(temporary_directory, 'rsa_key_unencrypted') interface.generate_and_write_rsa_keypair(test_keypath, password='******') self.assertTrue(os.path.exists(test_keypath)) self.assertTrue(os.path.exists(test_keypath + '.pub')) # If an empty string is given for 'password', the private key file # is written to disk unencrypted. interface.generate_and_write_rsa_keypair(test_keypath_unencrypted, password='') self.assertTrue(os.path.exists(test_keypath_unencrypted)) self.assertTrue(os.path.exists(test_keypath_unencrypted + '.pub')) # Ensure the generated key files are importable. scheme = 'rsassa-pss-sha256' imported_pubkey = \ interface.import_rsa_publickey_from_file(test_keypath + '.pub') self.assertTrue(securesystemslib.formats.RSAKEY_SCHEMA.matches(imported_pubkey)) imported_privkey = interface.import_rsa_privatekey_from_file(test_keypath, 'pw') self.assertTrue(securesystemslib.formats.RSAKEY_SCHEMA.matches(imported_privkey)) # Try to import the unencrypted key file. imported_privkey = interface.import_rsa_privatekey_from_file(test_keypath_unencrypted, '') self.assertTrue(securesystemslib.formats.RSAKEY_SCHEMA.matches(imported_privkey)) # Custom 'bits' argument. os.remove(test_keypath) os.remove(test_keypath + '.pub') interface.generate_and_write_rsa_keypair(test_keypath, bits=2048, password='******') self.assertTrue(os.path.exists(test_keypath)) self.assertTrue(os.path.exists(test_keypath + '.pub')) # Test improperly formatted arguments. self.assertRaises(securesystemslib.exceptions.FormatError, interface.generate_and_write_rsa_keypair, 3, bits=2048, password='******') self.assertRaises(securesystemslib.exceptions.FormatError, interface.generate_and_write_rsa_keypair, test_keypath, bits='bad', password='******') self.assertRaises(securesystemslib.exceptions.FormatError, interface.generate_and_write_rsa_keypair, test_keypath, bits=2048, password=3) # Test invalid 'bits' argument. self.assertRaises(securesystemslib.exceptions.FormatError, interface.generate_and_write_rsa_keypair, test_keypath, bits=1024, password='******')
def setUpClass(self): """Create and change into temporary directory, generate key pair and dummy material, read key pair. """ self.set_up_test_dir() self.step_name = "test_step" self.key_path = "test_key" generate_and_write_unencrypted_rsa_keypair(self.key_path) self.key = import_rsa_privatekey_from_file(self.key_path) self.key_pub = import_rsa_publickey_from_file(self.key_path + ".pub") self.test_artifact = "test_artifact" open(self.test_artifact, "w").close()
def import_publickey_from_file(keypath): try: key_metadata = sslib_util.load_json_file(keypath) # An RSA public key is saved to disk in PEM format (not JSON), so the # load_json_file() call above can fail for this reason. Try to potentially # load the PEM string in keypath if an exception is raised. except sslib_exceptions.Error: key_metadata = sslib_interface.import_rsa_publickey_from_file(keypath) key_object, junk = sslib_keys.format_metadata_to_key(key_metadata) if key_object['keytype'] not in SUPPORTED_KEY_TYPES: raise exceptions.Error('Trying to import an unsupported key' ' type: ' + repr(key_object['keytype'] + '.' ' Supported key types: ' + repr(SUPPORTED_KEY_TYPES))) else: return key_object
def test_rsa(self): """Test RSA key _generation and import interface functions. """ # TEST: Generate default keys and import # Assert location and format fn_default = "default" fn_default_ret = _generate_and_write_rsa_keypair(filepath=fn_default) pub = import_rsa_publickey_from_file(fn_default + ".pub") priv = import_rsa_privatekey_from_file(fn_default) self.assertEqual(fn_default, fn_default_ret) self.assertTrue(RSAKEY_SCHEMA.matches(pub)) self.assertTrue(PUBLIC_KEY_SCHEMA.matches(pub)) self.assertTrue(RSAKEY_SCHEMA.matches(priv)) # NOTE: There is no private key schema, at least check it has a value self.assertTrue(priv["keyval"]["private"]) # TEST: Generate unencrypted keys with empty prompt # Assert importable without password fn_empty_prompt = "empty_prompt" with mock.patch("securesystemslib.interface.get_password", return_value=""): _generate_and_write_rsa_keypair(filepath=fn_empty_prompt, prompt=True) import_rsa_privatekey_from_file(fn_empty_prompt) # TEST: Generate keys with auto-filename, i.e. keyid # Assert filename is keyid fn_keyid = _generate_and_write_rsa_keypair() pub = import_rsa_publickey_from_file(fn_keyid + ".pub") priv = import_rsa_privatekey_from_file(fn_keyid) self.assertTrue( os.path.basename(fn_keyid) == pub["keyid"] == priv["keyid"]) # TEST: Generate keys with custom bits # Assert length bits = 4096 fn_bits = "bits" _generate_and_write_rsa_keypair(filepath=fn_bits, bits=bits) priv = import_rsa_privatekey_from_file(fn_bits) # NOTE: Parse PEM with pyca/cryptography to get the key size property obj_bits = load_pem_private_key( priv["keyval"]["private"].encode("utf-8"), password=None, backend=default_backend()) self.assertEqual(obj_bits.key_size, bits) # TEST: Generate two keypairs with encrypted private keys using ... pw = "pw" fn_encrypted = "encrypted" fn_prompt = "prompt" # ... a passed pw ... _generate_and_write_rsa_keypair(filepath=fn_encrypted, password=pw) with mock.patch("securesystemslib.interface.get_password", return_value=pw): # ... and a prompted pw. _generate_and_write_rsa_keypair(filepath=fn_prompt, prompt=True) # Assert that both private keys are importable using the prompted pw ... import_rsa_privatekey_from_file(fn_prompt, prompt=True) import_rsa_privatekey_from_file(fn_encrypted, prompt=True) # ... and the passed pw. import_rsa_privatekey_from_file(fn_prompt, password=pw) import_rsa_privatekey_from_file(fn_encrypted, password=pw) # TEST: Import existing keys with encrypted private key (test regression) # Assert format pub = import_rsa_publickey_from_file(self.path_rsa + ".pub") priv = import_rsa_privatekey_from_file(self.path_rsa, "password") self.assertTrue(RSAKEY_SCHEMA.matches(pub)) self.assertTrue(PUBLIC_KEY_SCHEMA.matches(pub)) self.assertTrue(RSAKEY_SCHEMA.matches(priv)) # NOTE: There is no private key schema, at least check it has a value self.assertTrue(priv["keyval"]["private"]) # TEST: Generation errors for idx, (kwargs, err_msg) in enumerate([ # Error on empty password ({ "password": "" }, "encryption password must be 1 or more characters long"), # Error on 'password' and 'prompt=True' ({ "password": pw, "prompt": True }, "passing 'password' and 'prompt=True' is not allowed") ]): with self.assertRaises(ValueError, msg="(row {})".format(idx)) as ctx: _generate_and_write_rsa_keypair(**kwargs) self.assertEqual( err_msg, str(ctx.exception), "expected: '{}' got: '{}' (row {})".format( err_msg, ctx.exception, idx)) # Error on bad argument format for idx, kwargs in enumerate([ { "bits": 1024 }, # Too low { "bits": "not-an-int" }, { "filepath": 123456 }, # Not a string { "password": 123456 }, # Not a string { "prompt": "not-a-bool" } ]): with self.assertRaises(FormatError, msg="(row {})".format(idx)): _generate_and_write_rsa_keypair(**kwargs) # TEST: Import errors # Error public key import err_msg = "Invalid public pem" with self.assertRaises(Error) as ctx: import_rsa_publickey_from_file(fn_default) self.assertTrue( err_msg in str(ctx.exception), "expected: '{}' got: '{}'".format(err_msg, ctx.exception)) # Error on private key import... for idx, (args, kwargs, err, err_msg) in enumerate([ # Error on not a private key ([fn_default + ".pub"], {}, CryptoError, "Could not deserialize key data"), # Error on not encrypted ([fn_default], { "password": pw }, CryptoError, "Password was given but private key is not encrypted"), # Error on encrypted but no pw ([fn_encrypted], {}, CryptoError, "Password was not given but private key is encrypted"), # Error on encrypted but empty pw passed ([fn_encrypted], { "password": "" }, CryptoError, "Password was not given but private key is encrypted"), # Error on encrypted but bad pw passed ([fn_encrypted], { "password": "******" }, CryptoError, "Bad decrypt. Incorrect password?"), # Error on pw and prompt ([fn_default], { "password": pw, "prompt": True }, ValueError, "passing 'password' and 'prompt=True' is not allowed") ]): with self.assertRaises(err, msg="(row {})".format(idx)) as ctx: import_rsa_privatekey_from_file(*args, **kwargs) self.assertTrue( err_msg in str(ctx.exception), "expected: '{}' got: '{}' (row {})".format( err_msg, ctx.exception, idx)) # Error on encrypted but bad pw prompted err_msg = "Password was not given but private key is encrypted" with self.assertRaises(CryptoError) as ctx, mock.patch( "securesystemslib.interface.get_password", return_value="bad_pw"): import_rsa_privatekey_from_file(fn_encrypted) self.assertTrue( err_msg in str(ctx.exception), "expected: '{}' got: '{}'".format(err_msg, ctx.exception)) # Error on bad argument format for idx, (args, kwargs) in enumerate([ ([123456], {}), # bad path ([fn_default], { "scheme": 123456 }), # bad scheme ([fn_default], { "scheme": "bad scheme" }) # bad scheme ]): with self.assertRaises(FormatError, msg="(row {})".format(idx)): import_rsa_publickey_from_file(*args, **kwargs) with self.assertRaises(FormatError, msg="(row {})".format(idx)): import_rsa_privatekey_from_file(*args, **kwargs) # bad password with self.assertRaises(FormatError): import_rsa_privatekey_from_file(fn_default, password=123456) # bad prompt with self.assertRaises(FormatError): import_rsa_privatekey_from_file(fn_default, prompt="not-a-bool")
def test_generate_and_write_rsa_keypair(self): # Test normal case. temporary_directory = tempfile.mkdtemp(dir=self.temporary_directory) test_keypath = os.path.join(temporary_directory, 'rsa_key') test_keypath_unencrypted = os.path.join(temporary_directory, 'rsa_key_unencrypted') returned_path = interface.generate_and_write_rsa_keypair(test_keypath, password='******') self.assertTrue(os.path.exists(test_keypath)) self.assertTrue(os.path.exists(test_keypath + '.pub')) self.assertEqual(returned_path, test_keypath) # If an empty string is given for 'password', the private key file # is written to disk unencrypted. interface.generate_and_write_rsa_keypair(test_keypath_unencrypted, password='') self.assertTrue(os.path.exists(test_keypath_unencrypted)) self.assertTrue(os.path.exists(test_keypath_unencrypted + '.pub')) # Ensure the generated key files are importable. scheme = 'rsassa-pss-sha256' imported_pubkey = \ interface.import_rsa_publickey_from_file(test_keypath + '.pub') self.assertTrue(securesystemslib.formats.RSAKEY_SCHEMA.matches(imported_pubkey)) imported_privkey = interface.import_rsa_privatekey_from_file(test_keypath, 'pw') self.assertTrue(securesystemslib.formats.RSAKEY_SCHEMA.matches(imported_privkey)) # Try to import the unencrypted key file, by not passing a password imported_privkey = interface.import_rsa_privatekey_from_file(test_keypath_unencrypted) self.assertTrue(securesystemslib.formats.RSAKEY_SCHEMA.matches(imported_privkey)) # Try to import the unencrypted key file, by entering an empty password with mock.patch('securesystemslib.interface.get_password', return_value=''): imported_privkey = \ interface.import_rsa_privatekey_from_file(test_keypath_unencrypted, prompt=True) self.assertTrue( securesystemslib.formats.RSAKEY_SCHEMA.matches(imported_privkey)) # Fail importing unencrypted key passing a password with self.assertRaises(securesystemslib.exceptions.CryptoError): interface.import_rsa_privatekey_from_file(test_keypath_unencrypted, 'pw') # Fail importing encrypted key passing no password with self.assertRaises(securesystemslib.exceptions.CryptoError): interface.import_rsa_privatekey_from_file(test_keypath) # Custom 'bits' argument. os.remove(test_keypath) os.remove(test_keypath + '.pub') interface.generate_and_write_rsa_keypair(test_keypath, bits=2048, password='******') self.assertTrue(os.path.exists(test_keypath)) self.assertTrue(os.path.exists(test_keypath + '.pub')) # Test for a default filepath. If 'filepath' is not given, the key's # KEYID is used as the filename. The key is saved to the current working # directory. default_keypath = interface.generate_and_write_rsa_keypair(password='******') self.assertTrue(os.path.exists(default_keypath)) self.assertTrue(os.path.exists(default_keypath + '.pub')) written_key = interface.import_rsa_publickey_from_file(default_keypath + '.pub') self.assertEqual(written_key['keyid'], os.path.basename(default_keypath)) os.remove(default_keypath) os.remove(default_keypath + '.pub') # Test improperly formatted arguments. self.assertRaises(securesystemslib.exceptions.FormatError, interface.generate_and_write_rsa_keypair, 3, bits=2048, password='******') self.assertRaises(securesystemslib.exceptions.FormatError, interface.generate_and_write_rsa_keypair, test_keypath, bits='bad', password='******') self.assertRaises(securesystemslib.exceptions.FormatError, interface.generate_and_write_rsa_keypair, test_keypath, bits=2048, password=3) # Test invalid 'bits' argument. self.assertRaises(securesystemslib.exceptions.FormatError, interface.generate_and_write_rsa_keypair, test_keypath, bits=1024, password='******')
def main(): # Load Alice's private key to later sign the layout key_alice = interface.import_rsa_privatekey_from_file("alice") # Fetch and load Bob's and Carl's public keys # to specify that they are authorized to perform certain step in the layout key_bob = interface.import_rsa_publickey_from_file( "../functionary_bob/bob.pub") key_carl = interface.import_rsa_publickey_from_file( "../functionary_carl/carl.pub") layout = Layout.read({ "_type": "layout", "keys": { key_bob["keyid"]: key_bob, key_carl["keyid"]: key_carl, }, "steps": [{ "name": "clone", "expected_materials": [], "expected_products": [["CREATE", "demo-project/foo.py"], ["DISALLOW", "*"]], "pubkeys": [key_bob["keyid"]], "expected_command": ["git", "clone", "https://github.com/in-toto/demo-project.git"], "threshold": 1, }, { "name": "update-version", "expected_materials": [["MATCH", "demo-project/*", "WITH", "PRODUCTS", "FROM", "clone"], ["DISALLOW", "*"]], "expected_products": [["ALLOW", "demo-project/foo.py"], ["DISALLOW", "*"]], "pubkeys": [key_bob["keyid"]], "expected_command": [], "threshold": 1, }, { "name": "package", "expected_materials": [ [ "MATCH", "demo-project/*", "WITH", "PRODUCTS", "FROM", "update-version" ], ["DISALLOW", "*"], ], "expected_products": [ ["CREATE", "demo-project.tar.gz"], ["DISALLOW", "*"], ], "pubkeys": [key_carl["keyid"]], "expected_command": [ "tar", "--exclude", ".git", "-zcvf", "demo-project.tar.gz", "demo-project", ], "threshold": 1, }], "inspect": [{ "name": "untar", "expected_materials": [ [ "MATCH", "demo-project.tar.gz", "WITH", "PRODUCTS", "FROM", "package" ], # FIXME: If the routine running inspections would gather the # materials/products to record from the rules we wouldn't have to # ALLOW other files that we aren't interested in. ["ALLOW", ".keep"], ["ALLOW", "alice.pub"], ["ALLOW", "root.layout"], ["DISALLOW", "*"] ], "expected_products": [ [ "MATCH", "demo-project/foo.py", "WITH", "PRODUCTS", "FROM", "update-version" ], # FIXME: See expected_materials above ["ALLOW", "demo-project/.git/*"], ["ALLOW", "demo-project.tar.gz"], ["ALLOW", ".keep"], ["ALLOW", "alice.pub"], ["ALLOW", "root.layout"], ["DISALLOW", "*"] ], "run": [ "tar", "xzf", "demo-project.tar.gz", ] }], }) metadata = DbomMetablock(signed=layout) # Sign and dump layout to "root.layout" metadata.sign(key_alice) metadata.save_owner_key(key_alice, assetID) metadata.dump("root.layout") metadata.save_layout("root.layout", assetID)
def main(): # Load Jerry's private key to later sign the layout key_jerry = interface.import_rsa_privatekey_from_file("jerry") # Fetch and load Bob's and Alice's public keys # to specify that they are authorized to perform certain step in the layout key_alice = interface.import_rsa_publickey_from_file( "../functionary_alice/alice.pub") key_bob = interface.import_rsa_publickey_from_file( "../functionary_bob/bob.pub") layout = Layout.read({ "_type": "layout", "keys": { key_bob["keyid"]: key_bob, key_alice["keyid"]: key_alice, }, "steps": [{ "name": "clone", "expected_materials": [], "expected_products": [["CREATE", "inclavare-containers/rbi/kernel/Dockerfile"], [ "CREATE", "inclavare-containers/rbi/kernel/build-docker-image.sh" ], ["CREATE", "inclavare-containers/rbi/kernel/build-kernel.sh"], ["CREATE", "inclavare-containers/rbi/kernel/check-integrity.sh"], [ "CREATE", "inclavare-containers/rbi/kernel/patch/build-kernel.sh" ], ["CREATE", "inclavare-containers/rbi/kernel/scripts/start.sh"], ["CREATE", "inclavare-containers/rbi/misc/check-integrity.sh"]], "pubkeys": [key_alice["keyid"]], "expected_command": [ "git", "clone", "https://github.com/alibaba/inclavare-containers.git" ], "threshold": 1, }, { "name": "build", "expected_materials": [[ "MATCH", "inclavare-containers/rbi/kernel/Dockerfile", "WITH", "PRODUCTS", "FROM", "clone" ], [ "MATCH", "inclavare-containers/rbi/kernel/build-docker-image.sh", "WITH", "PRODUCTS", "FROM", "clone" ], [ "MATCH", "inclavare-containers/rbi/kernel/build-kernel.sh", "WITH", "PRODUCTS", "FROM", "clone" ], [ "MATCH", "inclavare-containers/rbi/kernel/check-integrity.sh", "WITH", "PRODUCTS", "FROM", "clone" ], [ "MATCH", "inclavare-containers/rbi/kernel/patch/build-kernel.sh", "WITH", "PRODUCTS", "FROM", "clone" ], [ "MATCH", "inclavare-containers/rbi/kernel/readme.md", "WITH", "PRODUCTS", "FROM", "clone" ], [ "MATCH", "inclavare-containers/rbi/kernel/scripts/start.sh", "WITH", "PRODUCTS", "FROM", "clone" ]], "expected_products": [ ["CREATE", "inclavare-containers/rbi/result/kernel/vmlinux"], ], "pubkeys": [key_bob["keyid"]], "expected_command": [ "bash", "inclavare-containers/rbi/rbi.sh", "kernel", ], "threshold": 1, }], "inspect": [{ "name": "integrity", "expected_materials": [ [ "MATCH", "inclavare-containers/rbi/result/kernel/vmlinux", "WITH", "PRODUCTS", "FROM", "build" ], [ "MATCH", "inclavare-containers/rbi/misc/check-integrity.sh", "WITH", "PRODUCTS", "FROM", "clone" ], ["ALLOW", "jerry.pub"], ["ALLOW", "root.layout"], ["ALLOW", ".keep"] ], "expected_products": [ [ "CREATE", "inclavare-containers/rbi/result/kernel/.check_done" ], # FIXME: See expected_materials above ["ALLOW", "jerry.pub"], ["ALLOW", "root.layout"], ["ALLOW", ".keep"] ], "run": [ "bash", "inclavare-containers/rbi/misc/check-integrity.sh", "inclavare-containers/rbi/result/kernel/vmlinux", SHA256_VALUE ] }], }) metadata = Metablock(signed=layout) # Sign and dump layout to "root.layout" metadata.sign(key_jerry) metadata.dump("root.layout")
def main(): # Load Jerry's private key to later sign the layout key_jerry = interface.import_rsa_privatekey_from_file("jerry") # Fetch and load Bob's and Alice's public keys # to specify that they are authorized to perform certain step in the layout key_alice = interface.import_rsa_publickey_from_file( "../functionary_alice/alice.pub") key_bob = interface.import_rsa_publickey_from_file( "../functionary_bob/bob.pub") layout = Layout.read({ "_type": "layout", "keys": { key_bob["keyid"]: key_bob, key_alice["keyid"]: key_alice, }, "steps": [{ "name": "clone", "expected_materials": [], "expected_products": [["CREATE", "inclavare-containers/rbi/kata-agent/Dockerfile"], [ "CREATE", "inclavare-containers/rbi/kata-agent/kata-build-docker.sh" ], [ "CREATE", "inclavare-containers/rbi/kata-agent/kata-source-code.sh" ], ["CREATE", "inclavare-containers/rbi/kata-agent/kata-test.sh"], [ "CREATE", "inclavare-containers/rbi/kata-agent/patch/Cargo.lock" ], ["CREATE", "inclavare-containers/rbi/kata-agent/patch/Makefile"], ["CREATE", "inclavare-containers/rbi/kata-agent/patch/protocols"], [ "CREATE", "inclavare-containers/rbi/kata-agent/patch/protocols/Cargo.toml" ], ["CREATE", "inclavare-containers/rbi/kata-agent/readme.md"], ["CREATE", "inclavare-containers/rbi/kata-agent/readme_cn.md"], [ "CREATE", "inclavare-containers/rbi/kata-agent/scripts/start.sh" ], ["CREATE", "inclavare-containers/rbi/misc/check-integrity.sh"]], "pubkeys": [key_alice["keyid"]], "expected_command": [ "git", "clone", "https://github.com/alibaba/inclavare-containers.git" ], "threshold": 1, }, { "name": "build", "expected_materials": [ [ "MATCH", "inclavare-containers/rbi/kata-agent/Dockerfile", "WITH", "PRODUCTS", "FROM", "clone" ], [ "MATCH", "inclavare-containers/rbi/kata-agent/kata-build-docker.sh", "WITH", "PRODUCTS", "FROM", "clone" ], [ "MATCH", "inclavare-containers/rbi/kata-agent/kata-source-code.sh", "WITH", "PRODUCTS", "FROM", "clone" ], [ "MATCH", "inclavare-containers/rbi/kata-agent/kata-test.sh", "WITH", "PRODUCTS", "FROM", "clone" ], [ "MATCH", "inclavare-containers/rbi/kata-agent/patch/Cargo.lock", "WITH", "PRODUCTS", "FROM", "clone" ], [ "MATCH", "inclavare-containers/rbi/kata-agent/patch/Makefile", "WITH", "PRODUCTS", "FROM", "clone" ], [ "MATCH", "inclavare-containers/rbi/kata-agent/patch/protocols", "WITH", "PRODUCTS", "FROM", "clone" ], [ "MATCH", "inclavare-containers/rbi/kata-agent/patch/protocols/Cargo.toml", "WITH", "PRODUCTS", "FROM", "clone" ], [ "MATCH", "inclavare-containers/rbi/kata-agent/readme.md", "WITH", "PRODUCTS", "FROM", "clone" ], [ "MATCH", "inclavare-containers/rbi/kata-agent/readme_cn.md", "WITH", "PRODUCTS", "FROM", "clone" ], [ "MATCH", "inclavare-containers/rbi/kata-agent/scripts/start.sh", "WITH", "PRODUCTS", "FROM", "clone" ] ], "expected_products": [ [ "CREATE", "inclavare-containers/rbi/result/kata-agent/kata-agent" ], ], "pubkeys": [key_bob["keyid"]], "expected_command": [ "bash", "inclavare-containers/rbi/rbi.sh", "agent", ], "threshold": 1, }], "inspect": [{ "name": "integrity", "expected_materials": [ [ "MATCH", "inclavare-containers/rbi/result/kata-agent/kata-agent", "WITH", "PRODUCTS", "FROM", "build" ], [ "MATCH", "inclavare-containers/rbi/misc/check-integrity.sh", "WITH", "PRODUCTS", "FROM", "clone" ], # FIXME: If the routine running inspections would gather the # materials/products to record from the rules we wouldn't have to # ALLOW other files that we aren't interested in. ["ALLOW", "jerry.pub"], ["ALLOW", "root.layout"], ["ALLOW", ".keep"] ], "expected_products": [ [ "CREATE", "inclavare-containers/rbi/result/kata-agent/.check_done" ], # FIXME: See expected_materials above ["ALLOW", "jerry.pub"], ["ALLOW", "root.layout"], ["ALLOW", ".keep"] ], "run": [ "bash", "inclavare-containers/rbi/misc/check-integrity.sh", "inclavare-containers/rbi/result/kata-agent/kata-agent", SHA256_VALUE ] }], }) metadata = Metablock(signed=layout) # Sign and dump layout to "root.layout" metadata.sign(key_jerry) metadata.dump("root.layout")
def main(): # Load Niels's private key to later sign the layout key_niels = interface.import_rsa_privatekey_from_file("niels") # Fetch and load aimee's and noud's public keys # to specify that they are authorized to perform certain step in the layout key_aimee = interface.import_rsa_publickey_from_file( "../functionary_aimee/aimee.pub") key_noud = interface.import_rsa_publickey_from_file( "../functionary_noud/noud.pub") layout = Layout.read({ "_type": "layout", "keys": { key_aimee["keyid"]: key_aimee, key_noud["keyid"]: key_noud, }, "steps": [{ "name": "create", "expected_materials": [], "expected_products": [["CREATE", "app/Program.cs"], ["DISALLOW", "*"]], "pubkeys": [key_aimee["keyid"]], "expected_command": ["dotnet", "new", "console", "-n", "app"], "threshold": 1, }, { "name": "publish", "expected_materials": [ [ "MATCH", "app/Program.cs", "WITH", "PRODUCTS", "FROM", "create" ], ["DISALLOW", "*"], ], "expected_products": [["CREATE", "published/app"], ["CREATE", "published/app.*"], ["DISALLOW", "*"]], "pubkeys": [key_noud["keyid"]], "expected_command": ["dotnet", "publish", "-o", "published", "app"], "threshold": 1, }, { "name": "package", "expected_materials": [ [ "MATCH", "published/*", "WITH", "PRODUCTS", "FROM", "publish" ], ["DISALLOW", "*"], ], "expected_products": [ ["CREATE", "published.tar.gz"], ["DISALLOW", "*"], ], "pubkeys": [key_noud["keyid"]], "expected_command": [ "tar", "-zcvf", "published.tar.gz", "published", ], "threshold": 1, }], "inspect": [{ "name": "untar", "expected_materials": [ [ "MATCH", "published.tar.gz", "WITH", "PRODUCTS", "FROM", "package" ], # FIXME: If the routine running inspections would gather the # materials/products to record from the rules we wouldn't have to # ALLOW other files that we aren't interested in. ["ALLOW", ".keep"], ["ALLOW", "niels.pub"], ["ALLOW", "root.layout"], ["DISALLOW", "*"] ], "expected_products": [ [ "MATCH", "published/*", "WITH", "PRODUCTS", "FROM", "publish" ], # FIXME: See expected_materials above ["ALLOW", "published/app.*"], ["ALLOW", "published.tar.gz"], ["ALLOW", ".keep"], ["ALLOW", "niels.pub"], ["ALLOW", "root.layout"], ["DISALLOW", "*"] ], "run": [ "tar", "xzf", "published.tar.gz", ] }], }) metadata = Metablock(signed=layout) # Sign and dump layout to "root.layout" metadata.sign(key_niels) metadata.dump("root.layout")
def setUp(self): """Imports keys, generates layout and layout_key_dict for the clone, update-version, and package step.""" self.key_alice = interface.import_rsa_privatekey_from_file( "keys/alice") # Fetch and load Bob's and Carl's public keys # to specify that they are authorized to perform certain step in the layout self.key_bob = interface.import_rsa_publickey_from_file("keys/bob.pub") self.key_carl = interface.import_rsa_publickey_from_file( "keys/carl.pub") # Create layout self.layout = Layout.read({ "_type": "layout", "keys": { self.key_bob["keyid"]: self.key_bob, self.key_carl["keyid"]: self.key_carl, }, "steps": [{ "name": "clone", "expected_materials": [], "expected_products": [["CREATE", "demo-project/foo.py"], ["DISALLOW", "*"]], "pubkeys": [self.key_bob["keyid"]], "expected_command": [ "git", "clone", "https://github.com/in-toto/demo-project.git" ], "threshold": 1, }, { "name": "update-version", "expected_materials": [[ "MATCH", "demo-project/*", "WITH", "PRODUCTS", "FROM", "clone" ], ["DISALLOW", "*"]], "expected_products": [["ALLOW", "demo-project/foo.py"], ["DISALLOW", "*"]], "pubkeys": [self.key_bob["keyid"]], "expected_command": [], "threshold": 1, }, { "name": "package", "expected_materials": [ [ "MATCH", "demo-project/*", "WITH", "PRODUCTS", "FROM", "update-version" ], ["DISALLOW", "*"], ], "expected_products": [ ["CREATE", "demo-project.tar.gz"], ["DISALLOW", "*"], ], "pubkeys": [self.key_carl["keyid"]], "expected_command": [ "tar", "--exclude", ".git", "-zcvf", "demo-project.tar.gz", "demo-project", ], "threshold": 1, }], "inspect": [], }) self.metadata = Metablock(signed=self.layout) self.metadata.sign(self.key_alice) # Create the public key dict self.layout_key_dict = {} self.layout_key_dict.update( interface.import_publickeys_from_file(["keys/alice.pub"]))