def main(): """Parse arguments, load key from disk (prompts for password if key is encrypted) and call in_toto_run. """ parser = create_parser() args = parser.parse_args() LOG.setLevelVerboseOrQuiet(args.verbose, args.quiet) # Override defaults in settings.py with environment variables and RCfiles in_toto.user_settings.set_settings() # Regular signing and GPG signing are mutually exclusive if (args.key is None) == (args.gpg is None): parser.print_usage() parser.error("Specify either '--key <key path>' or '--gpg [<keyid>]'") password, prompt = parse_password_and_prompt_args(args) # If `--gpg` was set without argument it has the value `True` and # we will try to sign with the default key gpg_use_default = (args.gpg is True) # Otherwise we interpret it as actual keyid gpg_keyid = None if args.gpg is not True: gpg_keyid = args.gpg # If no_command is specified run in_toto_run without executing a command if args.no_command: args.link_cmd = [] elif not args.link_cmd: # pragma: no branch parser.print_usage() parser.error("No command specified." " Please specify (or use the --no-command option)") try: # We load the key here because it might prompt the user for a password in # case the key is encrypted. Something that should not happen in the lib. key = None if args.key: key = interface.import_privatekey_from_file( args.key, key_type=args.key_type, password=password, prompt=prompt) runlib.in_toto_run( args.step_name, args.materials, args.products, args.link_cmd, record_streams=args.record_streams, signing_key=key, gpg_keyid=gpg_keyid, gpg_use_default=gpg_use_default, gpg_home=args.gpg_home, exclude_patterns=args.exclude_patterns, base_path=args.base_path, lstrip_paths=args.lstrip_paths, metadata_directory=args.metadata_directory) except Exception as e: LOG.error("(in-toto-run) {0}: {1}".format(type(e).__name__, e)) sys.exit(1) sys.exit(0)
def test_import_privatekey_from_file(self): """Test generic private key import function. """ pw = "password" for idx, (path, key_type, key_schema) in enumerate([ (self.path_rsa, None, RSAKEY_SCHEMA), # default key type (self.path_rsa, KEY_TYPE_RSA, RSAKEY_SCHEMA), (self.path_ed25519, KEY_TYPE_ED25519, ED25519KEY_SCHEMA), (self.path_ecdsa, KEY_TYPE_ECDSA, ECDSAKEY_SCHEMA) ]): # Successfully import key per supported type, with ... # ... passed password key = import_privatekey_from_file(path, key_type=key_type, password=pw) self.assertTrue(key_schema.matches(key), "(row {})".format(idx)) # ... entered password on mock-prompt with mock.patch("securesystemslib.interface.get_password", return_value=pw): key = import_privatekey_from_file(path, key_type=key_type, prompt=True) self.assertTrue(key_schema.matches(key), "(row {})".format(idx)) # Error on wrong key for default key type with self.assertRaises(Error): import_privatekey_from_file(self.path_ed25519, password=pw) # Error on unsupported key type with self.assertRaises(FormatError): import_privatekey_from_file(self.path_rsa, key_type="KEY_TYPE_UNSUPPORTED", password=pw)
def main(): """Parse arguments, load key from disk (if passed) and call either runlib.in_toto_record_start or runlib.in_toto_record_stop depending on the specified subcommand. """ parser = create_parser() args = parser.parse_args() LOG.setLevelVerboseOrQuiet(args.verbose, args.quiet) # Override defaults in settings.py with environment variables and RCfiles in_toto.user_settings.set_settings() # Regular signing and GPG signing are mutually exclusive if (args.key is None) == (args.gpg is None): parser.print_usage() parser.error("Specify either '--key <key path>' or '--gpg [<keyid>]'") password, prompt = parse_password_and_prompt_args(args) # If `--gpg` was set without argument it has the value `True` and # we will try to sign with the default key gpg_use_default = (args.gpg is True) # Otherwise gpg_keyid stays either None or gets the passed argument assigned gpg_keyid = None if not gpg_use_default and args.gpg: gpg_keyid = args.gpg try: # We load the key here because it might prompt the user for a password in # case the key is encrypted. Something that should not happen in the lib. key = None if args.key: key = interface.import_privatekey_from_file(args.key, key_type=args.key_type, password=password, prompt=prompt) if args.command == "start": in_toto.runlib.in_toto_record_start( args.step_name, args.materials, signing_key=key, gpg_keyid=gpg_keyid, gpg_use_default=gpg_use_default, gpg_home=args.gpg_home, exclude_patterns=args.exclude_patterns, base_path=args.base_path, lstrip_paths=args.lstrip_paths) # Mutually exclusiveness is guaranteed by argparser else: # args.command == "stop": in_toto.runlib.in_toto_record_stop( args.step_name, args.products, signing_key=key, gpg_keyid=gpg_keyid, gpg_use_default=gpg_use_default, gpg_home=args.gpg_home, exclude_patterns=args.exclude_patterns, base_path=args.base_path, lstrip_paths=args.lstrip_paths, metadata_directory=args.metadata_directory) except Exception as e: LOG.error("(in-toto-record {0}) {1}: {2}".format( args.command, type(e).__name__, e)) sys.exit(1) sys.exit(0)
def _sign_and_dump_metadata(metadata, args): """ <Purpose> Internal method to sign link or layout metadata and dump it to disk. <Arguments> metadata: Metablock object (contains Link or Layout object) args: see argparser <Exceptions> SystemExit(0) if signing is successful SystemExit(2) if any exception occurs """ try: if not args.append: metadata.signatures = [] signature = None # If the cli tool was called with `--gpg [KEYID ...]` `args.gpg` is # a list (not None) and we will try to sign with gpg. # If `--gpg-home` was not set, args.gpg_home is None and the signer tries # to use the default gpg keyring. if args.gpg is not None: # If `--gpg` was passed without argument we sign with the default key # Excluded so that coverage does not vary in different test environments if len(args.gpg) == 0: # pragma: no cover signature = metadata.sign_gpg(gpg_keyid=None, gpg_home=args.gpg_home) # Otherwise we sign with each passed keyid for keyid in args.gpg: securesystemslib.formats.KEYID_SCHEMA.check_match(keyid) signature = metadata.sign_gpg(gpg_keyid=keyid, gpg_home=args.gpg_home) # Alternatively we iterate over passed private key paths `--key KEYPATH # ...` load the corresponding key from disk and sign with it elif args.key is not None: # pragma: no branch if args.key_type is None: args.key_type = [KEY_TYPE_RSA] * len(args.key) if len(args.key_type) != len(args.key): raise securesystemslib.exceptions.FormatError( "number of key_types should match with the number" " of keys specified") for idx, key_path in enumerate(args.key): key = interface.import_privatekey_from_file( key_path, key_type=args.key_type[idx], prompt=args.prompt) signature = metadata.sign(key) # If `--output` was specified we store the signed link or layout metadata # to that location no matter what if args.output: out_path = args.output # Otherwise, in case of links, we build the filename using the link/step # name and the keyid of the created signature (there is only one for links) elif metadata.type_ == "link": securesystemslib.formats.ANY_SIGNATURE_SCHEMA.check_match(signature) keyid = signature["keyid"] out_path = FILENAME_FORMAT.format(step_name=metadata.signed.name, keyid=keyid) # In case of layouts we just override the input file. elif metadata.type_ == "layout": # pragma: no branch out_path = args.file LOG.info("Dumping {0} to '{1}'...".format(metadata.type_, out_path)) metadata.dump(out_path) sys.exit(0) except Exception as e: LOG.error("The following error occurred while signing: " "{}".format(e)) sys.exit(2)