Metadata API: Use OrderedDict for signatures

Dict ordering is part of regular Dict from Python 3.7: Use OrderedDict
for signatures to make sure signatures are serialized in a reproducible
order even on 3.6.

The added benefit is that reader will immediately understand that the
order has some significance.

The actual type annotations are a bit convoluted because:
* typing does not include OrderedDict before 3.7 so can't use that
* Annotating inner types does not work for collections.OrderedDict
  in older pythons (so have to use the "stringified annotations")

Signed-off-by: Jussi Kukkonen <jkukkonen@vmware.com>
This commit is contained in:
Jussi Kukkonen 2021-06-03 10:09:43 +03:00
parent e3190fca9d
commit 1ce36d0cd6

View file

@ -17,6 +17,7 @@
"""
import abc
import tempfile
from collections import OrderedDict
from datetime import datetime, timedelta
from typing import Any, ClassVar, Dict, List, Mapping, Optional, Tuple, Type
@ -48,11 +49,13 @@ class Metadata:
signed: A subclass of Signed, which has the actual metadata payload,
i.e. one of Targets, Snapshot, Timestamp or Root.
signatures: A dict of keyids to Securesystemslib Signature objects,
each signing the canonical serialized representation of 'signed'.
signatures: An ordered dictionary of keyids to Signature objects, each
signing the canonical serialized representation of 'signed'.
"""
def __init__(self, signed: "Signed", signatures: Dict[str, Signature]):
def __init__(
self, signed: "Signed", signatures: "OrderedDict[str, Signature]"
):
self.signed = signed
self.signatures = signatures
@ -89,7 +92,7 @@ def from_dict(cls, metadata: Dict[str, Any]) -> "Metadata":
raise ValueError(f'unrecognized metadata type "{_type}"')
# Make sure signatures are unique
signatures: Dict[str, Signature] = {}
signatures: "OrderedDict[str, Signature]" = OrderedDict()
for sig_dict in metadata.pop("signatures"):
sig = Signature.from_dict(sig_dict)
if sig.keyid in signatures:
@ -249,7 +252,7 @@ def sign(
if append:
self.signatures[signature.keyid] = signature
else:
self.signatures = {signature.keyid: signature}
self.signatures = OrderedDict({signature.keyid: signature})
return signature