python-tuf: Reading some attributes of a delegated targets role after loading a repository throws a KeyError

Description of issue or feature request:

After loading a repository, reading the threshold of a delegated targets role throws a KeyError.

Current behavior:

  1. Create a new repository with a delegated targets role.
  2. Load the repository.
  3. Try to read the threshold of this delegated targets role:
(Pdb) delegated_targets_role.threshold
*** KeyError: 'threshold'
  1. Try to read the keys of this delegated targets role:
  File "/usr/lib/python3.6/site-packages/tuf/repository_tool.py", line 1008, in keys
    keyids = roleinfo['keyids']
KeyError: 'keyids'

Expected behavior:

Should return the threshold / keys of the delegated targets role. I suspect this is due to missing assignments [1].

Ideally, the fix should include checking the schema of the delegated targets role after assignments.

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Comments: 16 (16 by maintainers)

Most upvoted comments

As a workaround, I am forced to use a kludge (e.g., manually reading from tuf.roledb.get_roleinfo(‘targets’, ‘default’) to get the keyids and threshold for a delegated targets role off the top-level targets role).

Should we add a wrapper for this? repository.get_roleinfo("rolename")? The returned dict should contain all of the metadata fields you’d want.

Asking about the threshold and keyids of a delegated role (e.g., my_role.threshold) is complicated by the fact that my_role can be a delegation of more than one role. For instance, foo can delegate to my_role some paths with a threshold of X and keyids A, B, C. The bar role can also delegate to my_role some different paths with a threshold of Y and keyids D, E.

So when you give the my_role.threshold query, which value do you expect?

my_role.threshold was actually a thing in the past, back when delegations resembled a tree rather than a graph. I suppose it’s clear which value is meant via repository.targets.foo.my_role.threshold. Unfortunately, it was decided that this command was unweildy, so it was replaced by, for example, repository.targets("my_role").delegate() and repository.targets("foo").version = 2).

What should the interface be to modify a delegation?

Is this good?

repository.targets("foo").revoke("my_role")
repository.targets("foo").delegate("my_role", new_threshold, new_keyids...)

Hopefully we can settle on a design that doesn’t negatively impact code maintainability and my well being 😃

FYI: I think you can still give a repository.targets.threshold. It is allowed because there is a definitive value.