Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove deprecated CLI/API arguments and legacy securesystemslib integration #739

Merged
merged 17 commits into from
May 9, 2024
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 13 additions & 51 deletions doc/source/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,19 @@ can use to generate, consume, modify and verify in-toto metadata, as a more
feature-rich, programmable alternative to the :doc:`command line tools
<command-line-tools/index>`.

.. note::
adityasaky marked this conversation as resolved.
Show resolved Hide resolved

**Cryptographic Signatures**

in-toto metadata is signed with cryptographic keys using the in-house crypto
adityasaky marked this conversation as resolved.
Show resolved Hide resolved
library `securesystemslib <https://github.com/secure-systems-lab/securesystemslib>`_
Please refer to its `documentation <https://python-securesystemslib.readthedocs.io/en/latest/signer.html>`_
for details about loading a `Signer` for "Evidence Generation".

Loading verification keys for "Supply Chain Verification" is
documented `in-toto#663 <https://github.com/in-toto/in-toto/issues/663>`_.



Evidence Generation
-------------------
Expand All @@ -20,54 +33,3 @@ Supply Chain Verification
-------------------------

.. autofunction:: in_toto.verifylib.in_toto_verify

Key Utilities
-------------

in-toto uses the in-house crypto library `securesystemslib
<https://github.com/secure-systems-lab/securesystemslib>`_ to generate and
verify cryptographic signatures. Useful securesystemslib API functions, e.g. to
generate asymmetric key pairs and import them into a format that aligns with
the `in-toto metadata specification
<https://github.com/in-toto/docs/blob/v0.9/in-toto-spec.md#4-document-formats>`_,
are documented below.

Generate Key Pairs
^^^^^^^^^^^^^^^^^^
.. autofunction:: securesystemslib.interface.generate_and_write_rsa_keypair
.. autofunction:: securesystemslib.interface.generate_and_write_rsa_keypair_with_prompt
.. autofunction:: securesystemslib.interface.generate_and_write_unencrypted_rsa_keypair
.. autofunction:: securesystemslib.interface.generate_and_write_ed25519_keypair
.. autofunction:: securesystemslib.interface.generate_and_write_ed25519_keypair_with_prompt
.. autofunction:: securesystemslib.interface.generate_and_write_unencrypted_ed25519_keypair

.. note::

``securesystemslib`` does not provide functions to generate OpenPGP key
pairs. You can use `GnuPG <https://gnupg.org/>`_ for that.

Load Signing Keys
^^^^^^^^^^^^^^^^^
.. autofunction:: securesystemslib.interface.import_privatekey_from_file
.. autofunction:: securesystemslib.interface.import_rsa_privatekey_from_file
.. autofunction:: securesystemslib.interface.import_ed25519_privatekey_from_file

.. note::

OpenPGP private keys do not need to be imported for signing. They remain in
the `GnuPG <https://gnupg.org/>`_ keyring and can be addressed by keyid
(see the :py:func:`in_toto.models.metadata.Metablock.sign_gpg` method).

Load Verification Keys
^^^^^^^^^^^^^^^^^^^^^^
.. autofunction:: securesystemslib.interface.import_publickeys_from_file
.. autofunction:: securesystemslib.interface.import_ed25519_publickey_from_file
.. autofunction:: securesystemslib.interface.import_rsa_publickey_from_file
.. autofunction:: securesystemslib.gpg.functions.export_pubkey
.. autofunction:: securesystemslib.gpg.functions.export_pubkeys

.. seealso::

The :py:func:`in_toto.models.layout.Layout` class also provides shortcuts to
load public functionary keys and directly assign them to an in-toto layout
(see ``add_functionary_key*`` methods).
8 changes: 8 additions & 0 deletions doc/source/command-line-tools/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@ consume, modify and verify in-toto metadata. Detailed usage instructions for
each tool, along with examples, are provided below.


.. note::

**Cryptographic Signatures**

in-toto metadata is signed with cryptographic keys. The CLI accepts key files
in standard PEM format. See `in-toto#662 <https://github.com/in-toto/in-toto/issues/662>`_
for details about key generation.

Evidence Generation
-------------------

Expand Down
5 changes: 0 additions & 5 deletions in_toto/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,7 @@
Configure base logger for in_toto (see in_toto.log for details).

"""
from securesystemslib import KEY_TYPE_ECDSA, KEY_TYPE_ED25519, KEY_TYPE_RSA

import in_toto.log

SUPPORTED_KEY_TYPES = [KEY_TYPE_RSA, KEY_TYPE_ED25519, KEY_TYPE_ECDSA]


# in-toto version
__version__ = "2.3.0"
45 changes: 5 additions & 40 deletions in_toto/common_args.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,6 @@
"""
import sys

from in_toto import (
KEY_TYPE_ECDSA,
KEY_TYPE_ED25519,
KEY_TYPE_RSA,
SUPPORTED_KEY_TYPES,
)
from in_toto.settings import LINK_CMD_EXEC_TIMEOUT

EXCLUDE_ARGS = ["--exclude"]
Expand Down Expand Up @@ -80,41 +74,13 @@
),
}

KEY_ARGS = ["-k", "--key"]
KEY_KWARGS = {
"type": str,
"metavar": "<path>",
"help": (
"path to a private key file to sign the resulting link metadata."
" The keyid prefix is used as an infix for the link metadata"
" filename, i.e. '<name>.<keyid prefix>.link'. See '--key-type' for"
" available formats. Passing one of '--key' or '--gpg' is required."
),
}

KEY_TYPE_ARGS = ["-t", "--key-type"]
KEY_TYPE_KWARGS = {
"dest": "key_type",
"type": str,
"choices": SUPPORTED_KEY_TYPES,
"default": KEY_TYPE_RSA,
"help": (
"type of key specified by the '--key' option. '{rsa}' keys are"
" expected in a 'PEM' format. '{ed25519}' and '{ecdsa}' are"
" expected to be in a custom 'securesystemslib/json' format."
" Default is '{rsa}'.".format(
rsa=KEY_TYPE_RSA, ed25519=KEY_TYPE_ED25519, ecdsa=KEY_TYPE_ECDSA
)
),
}

KEY_PASSWORD_ARGS = ["-P", "--password"]
KEY_PASSWORD_KWARGS = {
"nargs": "?",
"const": True,
"metavar": "<password>",
"help": (
"password for encrypted key specified with '--key'. Passing '-P'"
"password for encrypted key specified with '--signing-key'. Passing '-P'"
" without <password> opens a prompt. If no password is passed, or"
" entered on the prompt, the key is treated as unencrypted. (Do "
" not confuse with '-p/--products'!)"
Expand Down Expand Up @@ -146,7 +112,7 @@ def parse_password_and_prompt_args(args):
"GPG keyid to sign the resulting link metadata. When '--gpg' is"
" passed without the keyid, the default GPG key is used. The keyid"
" prefix is used as an infix for the link metadata filename, i.e."
" '<name>.<keyid prefix>.link'. Passing one of '--key' or '--gpg'"
" '<name>.<keyid prefix>.link'. Passing one of '--signing-key' or '--gpg'"
" is required."
),
}
Expand All @@ -169,10 +135,9 @@ def parse_password_and_prompt_args(args):
"metavar": "<path>",
"dest": "signing_key",
"help": (
"replacement for '--key' using a standard PKCS8/PEM format. Key type is"
" detected automatically and need not be specified with '--key-type'."
" Use '--password [<password>]' to pass a decryption password"
" or toggle a prompt, if the key es encrypted."
"signing key in a standard PKCS8/PEM format. Supported keytypes are"
" rsa, ed25519, ecdsa (nistp256). Use '--password [<password>]' to pass"
" a decryption password or toggle a prompt, if the key es encrypted."
lukpueh marked this conversation as resolved.
Show resolved Hide resolved
),
}

Expand Down
10 changes: 0 additions & 10 deletions in_toto/formats.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,13 +127,3 @@ def _check_public_keys(arg):
for k, v in arg.items():
_check_hex(k)
_check_public_key(v)


def _check_signing_key(arg):
"""Check legacy signing key dict format.

NOTE: signing key dict is deprecated, this check will be removed with it
"""
_check_public_key(arg)
if not arg["keyval"].get("private"):
raise _err(arg, "private key data")
39 changes: 7 additions & 32 deletions in_toto/in_toto_record.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@
import sys
from getpass import getpass

from securesystemslib import interface

import in_toto.runlib
from in_toto import __version__
from in_toto.common_args import (
Expand All @@ -46,12 +44,8 @@
GPG_HOME_ARGS,
GPG_HOME_KWARGS,
GPG_KWARGS,
KEY_ARGS,
KEY_KWARGS,
KEY_PASSWORD_ARGS,
KEY_PASSWORD_KWARGS,
KEY_TYPE_ARGS,
KEY_TYPE_KWARGS,
LSTRIP_PATHS_ARGS,
LSTRIP_PATHS_KWARGS,
METADATA_DIRECTORY_ARGS,
Expand Down Expand Up @@ -91,8 +85,8 @@ def create_parser():
loaded from 'key_file', recording all files in the CWD as materials (on
start), and as products (on stop).

{prog} start -n edit-files -k path/to/key_file -m .
{prog} stop -n edit-files -k path/to/key_file -p .
{prog} start -n edit-files --signing-key path/to/key_file -m .
{prog} stop -n edit-files --signing-key path/to/key_file -p .


Create link metadata file signed with the default GPG key from the default
Expand All @@ -106,8 +100,8 @@ def create_parser():
record all files in the CWD as material and product, and dump finished link
file to the target directory (on stop).

{prog} start -n edit-files -k path/to/key_file -m .
{prog} stop -d path/to/target/dir -n edit-files -k path/to/key_file -p .
{prog} start -n edit-files --signing-key path/to/key_file -m .
{prog} stop -d path/to/target/dir -n edit-files --signing-key path/to/key_file -p .

""".format(
prog=parser.prog
Expand Down Expand Up @@ -138,8 +132,6 @@ def create_parser():
),
)

parent_named_args.add_argument(*KEY_ARGS, **KEY_KWARGS)
parent_parser.add_argument(*KEY_TYPE_ARGS, **KEY_TYPE_KWARGS)
parent_parser.add_argument(*KEY_PASSWORD_ARGS, **KEY_PASSWORD_KWARGS)

parent_named_args.add_argument(*GPG_ARGS, **GPG_KWARGS)
Expand Down Expand Up @@ -238,12 +230,11 @@ def main():

LOG.setLevelVerboseOrQuiet(args.verbose, args.quiet)

# Use exactly one of legacy key, gpg or pkcs8 signing key
if sum([bool(args.key), bool(args.gpg), bool(args.signing_key)]) != 1:
# Use exactly one of gpg or pkcs8 signing key
if sum([bool(args.gpg), bool(args.signing_key)]) != 1:
parser.print_usage()
parser.error(
"Specify exactly one of '--key <key path>', "
"--gpg [<keyid>]' or --signing-key <key path>"
"Specify either '--signing-key <path>' or '--gpg [<keyid>]'"
)

password, prompt = parse_password_and_prompt_args(args)
Expand All @@ -258,20 +249,6 @@ def main():
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:
LOG.warning(
"'-k', '--key' is deprecated, use '--signing-key' instead."
)
key = interface.import_privatekey_from_file(
args.key,
key_type=args.key_type,
password=password,
prompt=prompt,
)

signer = None
if args.signing_key:
if prompt:
Expand All @@ -288,7 +265,6 @@ def main():
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,
Expand All @@ -304,7 +280,6 @@ def main():
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,
Expand Down
Loading
Loading