mirror of
https://github.com/theupdateframework/python-tuf
synced 2026-05-24 10:08:28 +00:00
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:
commit
d1ea040be3
4 changed files with 50 additions and 21 deletions
|
|
@ -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
|
||||
```
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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 = []
|
||||
|
|
|
|||
|
|
@ -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')
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue