Merge pull request #638 from vladimir-v-diaz/sign_fresh_metadata

CLI --sign: Support signing of delegated metadata and ability to import any public key type
This commit is contained in:
Vladimir Diaz 2018-03-06 11:32:19 -05:00 committed by GitHub
commit d1ea040be3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 50 additions and 21 deletions

View file

@ -86,14 +86,12 @@ the Targets role or its key is used. The Snapshot and Timestamp role are also
automatically signed, if possible.
```Bash
$ repo.py --sign
$ repo.py --sign </path/to/key>
$ repo.py --sign </path/to/key> [--role <rolename>]
$ repo.py --sign </path/to/key> [--role <rolename>, --path </path/to/repo>]
```
For example, to sign new Timestamp metadata:
```Bash
$ repo.py --sign /path/to/timestamp_key --role timestamp
$ repo.py --sign /path/to/foo_key --role foo
```
Note: In the future, the user might have the option of disabling automatic
@ -112,7 +110,8 @@ $ repo.py --delegate <glob pattern>... --delegatee <rolename> --pubkeys
--sign </path/to/role_privkey>]
```
Example:
For example, to delegate trust of `/foo*.gz` packages to the `foo` role:
```
$ repo.py --delegate "/foo*.tgz" --delegatee foo --pubkeys ./keystore/foo.pub
```

View file

@ -1189,12 +1189,6 @@ def test_delegate(self):
self.assertEqual(self.targets_object.get_delegated_rolenames(),
['tuf'])
# Try to delegate to a role that has already been delegated.
self.assertRaises(securesystemslib.exceptions.Error,
self.targets_object.delegate, rolename, public_keys, paths, threshold,
terminating=False, list_of_targets=list_of_targets,
path_hash_prefixes=path_hash_prefixes)
# Test for targets that do not exist under the targets directory.
self.targets_object.revoke(rolename)
self.assertRaises(securesystemslib.exceptions.Error,

View file

@ -2233,11 +2233,6 @@ def delegate(self, rolename, public_keys, paths, threshold=1,
if path_hash_prefixes is not None:
securesystemslib.formats.PATH_HASH_PREFIXES_SCHEMA.check_match(path_hash_prefixes)
# Check if 'rolename' is not already a delegation.
if tuf.roledb.role_exists(rolename, self._repository_name):
raise securesystemslib.exceptions.Error(repr(rolename) + ' already'
' delegated.')
# Keep track of the valid keyids (added to the new Targets object) and
# their keydicts (added to this Targets delegations).
keyids = []

View file

@ -52,6 +52,7 @@
import shutil
import errno
import getpass
import time
import tuf
import tuf.log
@ -147,7 +148,7 @@ def delegate(parsed_arguments):
public_keys = []
for public_key in parsed_arguments.pubkeys:
# In the future, any type of key can be imported...
imported_pubkey = repo_tool.import_ecdsa_publickey_from_file(
imported_pubkey = import_publickey_from_file(
public_key)
public_keys.append(imported_pubkey)
@ -329,6 +330,21 @@ def import_privatekey_from_file(keypath, password=None):
def import_publickey_from_file(keypath):
key_metadata = securesystemslib.util.load_json_file(keypath)
key_object, junk = securesystemslib.keys.format_metadata_to_key(key_metadata)
if key_object['keytype'] not in SUPPORTED_KEY_TYPES:
raise tuf.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 sign_role(parsed_arguments):
repository = repo_tool.load_repository(
@ -351,7 +367,32 @@ def sign_role(parsed_arguments):
pass
else:
repository.targets(parsed_arguments.role).load_signing_key(role_privatekey)
# TODO: The repository tool will be refactored to clean up the following
# approach, which adds and signs for a non-existent role.
if not tuf.roledb.role_exists(parsed_arguments.role):
# Load the private key keydb and set the roleinfo in roledb so that
# metadata can be written with repository.write().
tuf.keydb.remove_key(role_privatekey['keyid'],
repository_name = repository._repository_name)
tuf.keydb.add_key(
role_privatekey, repository_name = repository._repository_name)
expiration = tuf.formats.unix_timestamp_to_datetime(
int(time.time() + 7889230))
expiration = expiration.isoformat() + 'Z'
roleinfo = {'name': parsed_arguments.role, 'keyids': [role_privatekey['keyid']],
'signing_keyids': [role_privatekey['keyid']], 'partial_loaded': False, 'paths': {},
'signatures': [], 'version': 1, 'expires': expiration,
'delegations': {'keys': {}, 'roles': []}}
tuf.roledb.add_role(parsed_arguments.role, roleinfo,
repository_name=repository._repository_name)
repository.write(parsed_arguments.role, increment_version_number=False)
else:
repository.targets(parsed_arguments.role).load_signing_key(role_privatekey)
# Update the required top-level roles, Snapshot and Timestamp, to make a new
# release.
@ -523,16 +564,16 @@ def set_top_level_keys(repository):
# Import the public keys. They are needed so that metadata roles are
# assigned verification keys, which clients need in order to verify the
# signatures created by the corresponding private keys.
root_public = repo_tool.import_ecdsa_publickey_from_file(
root_public = import_publickey_from_file(
os.path.join(parsed_arguments.path, KEYSTORE_DIR,
ROOT_KEY_NAME) + '.pub')
targets_public = repo_tool.import_ecdsa_publickey_from_file(
targets_public = import_publickey_from_file(
os.path.join(parsed_arguments.path, KEYSTORE_DIR,
TARGETS_KEY_NAME) + '.pub')
snapshot_public = repo_tool.import_ecdsa_publickey_from_file(
snapshot_public = import_publickey_from_file(
os.path.join(parsed_arguments.path, KEYSTORE_DIR,
SNAPSHOT_KEY_NAME) + '.pub')
timestamp_public = repo_tool.import_ecdsa_publickey_from_file(
timestamp_public = import_publickey_from_file(
os.path.join(parsed_arguments.path, KEYSTORE_DIR,
TIMESTAMP_KEY_NAME) + '.pub')