Example #1
0
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)
Example #3
0
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)
Example #4
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)