Merge pull request #640 from vladimir-v-diaz/support_remove_cli_option

CLI: Implement --remove command-line option
This commit is contained in:
Vladimir Diaz 2018-03-08 13:27:11 -05:00 committed by GitHub
commit d9b6d9846e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 110 additions and 5 deletions

View file

@ -51,10 +51,10 @@ $ repo.py --init --consistent_snapshot
## Add a target file ##
Copy a target file to the repo and add it to Targets metadata. More than one
target file, or directory, may be specified with --add. The --recursive option
may be selected to also include files in subdirectories of a specified
directory.
Copy a target file to the repo and add it to the Targets metadata (or the
Targets role specified in --role). More than one target file, or directory,
may be specified in --add. The --recursive option may be toggled to also
include files in subdirectories of a specified directory.
```Bash
$ repo.py --add <foo.tar.gz> <bar.tar.gz>
$ repo.py --add </path/to/dir> [--recursive]
@ -67,6 +67,30 @@ $ repo.py --add <foo.tar.gz> --path </path/to/my_repo>
## Remove a target file ##
Remove a target file from the Targets metadata (or the Targets role specified
in --role). More than one target file or glob pattern may be specified in
--remove.
```Bash
$ repo.py --remove <glob_pattern> ...
```
Examples:
Remove all target files, that match `foo*.tgz,` from the Targets metadata.
```Bash
$ repo.py --remove "foo*.tgz"
```
Remove all target files from the `my_role` Targets metadata.
```Bash
$ repo.py --remove "*" --role my_role --sign tufkeystore/my_role_key
```
## Generate key ##
Generate a cryptographic key. The generated key can later be used to sign
specific metadata with `--sign`. The supported key types are: `ecdsa`,
@ -105,7 +129,7 @@ Delegate trust of target files from the targets role (or the one specified
in --role) to some other role (--delegatee). --delegatee is trusted to
sign for target files that match the delegated glob patterns.
```Bash
$ repo.py --delegate <glob pattern>... --delegatee <rolename> --pubkeys
$ repo.py --delegate <glob pattern> ... --delegatee <rolename> --pubkeys
</path/to/pubkey.pub>... [--role <rolename> --terminating --threshold <X>
--sign </path/to/role_privkey>]
```

View file

@ -53,6 +53,7 @@
import errno
import getpass
import time
import fnmatch
import tuf
import tuf.log
@ -61,6 +62,8 @@
import securesystemslib
from colorama import Fore
import six
# See 'log.py' to learn how logging is handled in TUF.
logger = logging.getLogger('tuf.scripts.repo')
@ -122,6 +125,9 @@ def process_arguments(parsed_arguments):
if parsed_arguments.add:
add_targets(parsed_arguments)
if parsed_arguments.remove:
remove_targets(parsed_arguments)
if parsed_arguments.sign:
sign_role(parsed_arguments)
@ -453,6 +459,36 @@ def add_target_to_repo(target_path, repo_targets_path, repository):
def remove_target_files_from_metadata(repository):
if parsed_arguments.role in ['root', 'snapshot', 'timestamp']:
raise tuf.exceptions.Error(
'Invalid rolename specified: ' + repr(parsed_arguments.role) + '.'
' It must be "targets" or a delegated rolename.')
else:
# NOTE: The following approach of using tuf.roledb to update the target
# files will be modified in the future when the repository tool's API is
# refactored.
roleinfo = tuf.roledb.get_roleinfo(
parsed_arguments.role, repository._repository_name)
for glob_pattern in parsed_arguments.remove:
for path in list(six.iterkeys(roleinfo['paths'])):
if fnmatch.fnmatch(path, glob_pattern):
del roleinfo['paths'][path]
else:
logger.debug('Delegated path ' + repr(path) + ' does not match'
' given path/glob pattern ' + repr(glob_pattern))
continue
tuf.roledb.update_roleinfo(
parsed_arguments.role, roleinfo, mark_role_as_dirty=True,
repository_name=repository._repository_name)
def add_targets(parsed_arguments):
target_paths = os.path.join(parsed_arguments.add)
@ -502,6 +538,47 @@ def add_targets(parsed_arguments):
def remove_targets(parsed_arguments):
target_paths = os.path.join(parsed_arguments.remove)
repo_targets_path = os.path.join(parsed_arguments.path, REPO_DIR, 'targets')
repository = repo_tool.load_repository(
os.path.join(parsed_arguments.path, REPO_DIR))
# Remove target files from the Targets metadata (or the role specified in
# --role) that match the glob patterns specified in --remove.
remove_target_files_from_metadata(repository)
# Examples of how the --pw command-line option is interpreted:
# repo.py --init': parsed_arguments.pw = 'pw'
# repo.py --init --pw my_password: parsed_arguments.pw = 'my_password'
# repo.py --init --pw: The user is prompted for a password, as follows:
if not parsed_arguments.pw:
parsed_arguments.pw = securesystemslib.interface.get_password(
prompt='Enter a password for the top-level role keys: ', confirm=True)
# Load the top-level, non-root, keys to make a new release.
targets_private = import_privatekey_from_file(
os.path.join(parsed_arguments.path, KEYSTORE_DIR, TARGETS_KEY_NAME),
parsed_arguments.pw)
snapshot_private = import_privatekey_from_file(
os.path.join(parsed_arguments.path, KEYSTORE_DIR, SNAPSHOT_KEY_NAME),
parsed_arguments.pw)
timestamp_private = import_privatekey_from_file(
os.path.join(parsed_arguments.path, KEYSTORE_DIR,
TIMESTAMP_KEY_NAME), parsed_arguments.pw)
repository.targets.load_signing_key(targets_private)
repository.snapshot.load_signing_key(snapshot_private)
repository.timestamp.load_signing_key(timestamp_private)
repository.writeall()
# Move staged metadata directory to "live" metadata directory.
write_to_live_repo()
def init_repo(parsed_arguments):
"""
Create a repo at the specified location in --path (the current working
@ -667,6 +744,10 @@ def parse_arguments():
' "targets" role (or the role specified in --role). If a directory'
' is given, all files in the directory are added.')
parser.add_argument('--remove', type=str, nargs='+',
metavar='<glob pattern>', help='Remove one or more target files from the'
' "targets" role (or the role specified in --role).')
parser.add_argument('--role', nargs='?', type=str, const='targets',
default='targets', metavar='<rolename>', help='Specify a rolename.'
' The rolename "targets" is used by default.')