47
47
SignedSerializer ,
48
48
)
49
49
50
- # Disable the "C0302: Too many lines in module" warning which warns for modules
51
- # with more 1000 lines, because all of the code here is logically connected
52
- # and currently, we are above 1000 lines by a small margin.
53
- # pylint: disable=C0302
50
+ # pylint: disable=too-many-lines
54
51
55
52
# We aim to support SPECIFICATION_VERSION and require the input metadata
56
53
# files to have the same major version (the first number) as ours.
@@ -66,7 +63,6 @@ class Metadata:
66
63
Attributes:
67
64
signed: A subclass of Signed, which has the actual metadata payload,
68
65
i.e. one of Targets, Snapshot, Timestamp or Root.
69
-
70
66
signatures: An ordered dictionary of keyids to Signature objects, each
71
67
signing the canonical serialized representation of 'signed'.
72
68
"""
@@ -93,8 +89,8 @@ def from_dict(cls, metadata: Dict[str, Any]) -> "Metadata":
93
89
94
90
Returns:
95
91
A TUF Metadata object.
96
-
97
92
"""
93
+
98
94
# Dispatch to contained metadata class on metadata _type field.
99
95
_type = metadata ["signed" ]["_type" ]
100
96
@@ -149,8 +145,8 @@ def from_file(
149
145
150
146
Returns:
151
147
A TUF Metadata object.
152
-
153
148
"""
149
+
154
150
if storage_backend is None :
155
151
storage_backend = FilesystemBackend ()
156
152
@@ -203,20 +199,18 @@ def to_file(
203
199
204
200
Arguments:
205
201
filename: The path to write the file to.
206
- serializer: A MetadataSerializer subclass instance that implements
207
- the desired wireline format serialization. Per default a
208
- JSONSerializer is used.
209
- storage_backend: An object that implements
210
- securesystemslib.storage.StorageBackendInterface. Per default
211
- a (local) FilesystemBackend is used.
202
+ serializer: A MetadataSerializer instance that implements the
203
+ desired serialization format. Default is JSONSerializer.
204
+ storage_backend: A StorageBackendInterface implementation. Default
205
+ is FilesystemBackend (i.e. a local file).
212
206
213
207
Raises:
214
208
tuf.api.serialization.SerializationError:
215
209
The metadata object cannot be serialized.
216
210
securesystemslib.exceptions.StorageError:
217
211
The file cannot be written.
218
-
219
212
"""
213
+
220
214
if serializer is None :
221
215
# Use local scope import to avoid circular import errors
222
216
# pylint: disable=import-outside-toplevel
@@ -238,14 +232,12 @@ def sign(
238
232
"""Creates signature over 'signed' and assigns it to 'signatures'.
239
233
240
234
Arguments:
241
- signer: An object implementing the securesystemslib.signer.Signer
242
- interface.
235
+ signer: A securesystemslib.signer.Signer implementation.
243
236
append: A boolean indicating if the signature should be appended to
244
237
the list of signatures or replace any existing signatures. The
245
238
default behavior is to replace signatures.
246
- signed_serializer: A SignedSerializer subclass instance that
247
- implements the desired canonicalization format. Per default a
248
- CanonicalJSONSerializer is used.
239
+ signed_serializer: A SignedSerializer that implements the desired
240
+ serialization format. Default is CanonicalJSONSerializer.
249
241
250
242
Raises:
251
243
tuf.api.serialization.SerializationError:
@@ -256,8 +248,8 @@ def sign(
256
248
257
249
Returns:
258
250
A securesystemslib-style signature object.
259
-
260
251
"""
252
+
261
253
if signed_serializer is None :
262
254
# Use local scope import to avoid circular import errors
263
255
# pylint: disable=import-outside-toplevel
@@ -408,8 +400,9 @@ def bump_version(self) -> None:
408
400
409
401
class Key :
410
402
"""A container class representing the public portion of a Key.
403
+
411
404
Please note that "Key" instances are not semanticly validated during
412
- initialization. We consider this as responsibility of securesystemslib .
405
+ initialization: this only happens at signature verification time .
413
406
414
407
Attributes:
415
408
keyid: An identifier string that must uniquely identify a key within
@@ -421,7 +414,6 @@ class Key:
421
414
"rsassa-pss-sha256", "ed25519", and "ecdsa-sha2-nistp256".
422
415
keyval: A dictionary containing the public portion of the key.
423
416
unrecognized_fields: Dictionary of all unrecognized fields.
424
-
425
417
"""
426
418
427
419
def __init__ (
@@ -521,15 +513,15 @@ def verify_signature(
521
513
522
514
523
515
class Role :
524
- """A container class containing the set of keyids and threshold associated
525
- with a particular role.
516
+ """Container that defines which keys are required to sign roles metadata.
517
+
518
+ Role defines how many keys are required to successfully sign the roles
519
+ metadata, and which keys are accepted.
526
520
527
521
Attributes:
528
- keyids: A set of strings each of which represents a given key.
529
- threshold: An integer representing the required number of keys for that
530
- particular role.
522
+ keyids: A set of strings representing signing keys for this role.
523
+ threshold: Number of keys required to sign this role's metadata.
531
524
unrecognized_fields: Dictionary of all unrecognized fields.
532
-
533
525
"""
534
526
535
527
def __init__ (
@@ -573,29 +565,14 @@ class Root(Signed):
573
565
Attributes:
574
566
consistent_snapshot: An optional boolean indicating whether the
575
567
repository supports consistent snapshots.
576
- keys: A dictionary that contains a public key store used to verify
577
- top level roles metadata signatures::
578
-
579
- {
580
- '<KEYID>': <Key instance>,
581
- ...
582
- },
583
-
584
- roles: A dictionary that contains a list of signing keyids and
585
- a signature threshold for each top level role::
586
-
587
- {
588
- '<ROLE>': <Role istance>,
589
- ...
590
- }
591
-
568
+ keys: Dictionary of keyids to Keys. Defines the keys used in 'roles'.
569
+ roles: Dictionary of role names to Roles. Defines which keys are
570
+ required to sign the metadata for a specific role.
592
571
"""
593
572
594
573
_signed_type = "root"
595
574
596
- # TODO: determine an appropriate value for max-args and fix places where
597
- # we violate that. This __init__ function takes 7 arguments, whereas the
598
- # default max-args value for pylint is 5
575
+ # TODO: determine an appropriate value for max-args
599
576
# pylint: disable=too-many-arguments
600
577
def __init__ (
601
578
self ,
@@ -739,18 +716,8 @@ class MetaFile(BaseFile):
739
716
Attributes:
740
717
version: An integer indicating the version of the metadata file.
741
718
length: An optional integer indicating the length of the metadata file.
742
- hashes: An optional dictionary mapping hash algorithms to the
743
- hashes resulting from applying them over the metadata file
744
- contents.::
745
-
746
- 'hashes': {
747
- '<HASH ALGO 1>': '<METADATA FILE HASH 1>',
748
- '<HASH ALGO 2>': '<METADATA FILE HASH 2>',
749
- ...
750
- }
751
-
719
+ hashes: An optional dictionary of hash algorithm names to hash values.
752
720
unrecognized_fields: Dictionary of all unrecognized fields.
753
-
754
721
"""
755
722
756
723
def __init__ (
@@ -799,10 +766,11 @@ def to_dict(self) -> Dict[str, Any]:
799
766
return res_dict
800
767
801
768
def verify_length_and_hashes (self , data : Union [bytes , BinaryIO ]):
802
- """Verifies that the length and hashes of "data" match expected
803
- values.
769
+ """Verifies that the length and hashes of "data" match expected values.
770
+
804
771
Args:
805
772
data: File object or its content in bytes.
773
+
806
774
Raises:
807
775
LengthOrHashMismatchError: Calculated length or hashes do not
808
776
match expected values or hash algorithm is not supported.
@@ -817,13 +785,11 @@ def verify_length_and_hashes(self, data: Union[bytes, BinaryIO]):
817
785
class Timestamp (Signed ):
818
786
"""A container for the signed part of timestamp metadata.
819
787
820
- Attributes:
821
- meta: A dictionary that contains information about snapshot metadata::
822
-
823
- {
824
- 'snapshot.json': <MetaFile INSTANCE>
825
- }
788
+ Timestamp contains information about the snapshot Metadata file.
826
789
790
+ Attributes:
791
+ meta: A dictionary of filenames to MetaFiles. The only valid key value
792
+ is the snapshot filename, as defined by the specification.
827
793
"""
828
794
829
795
_signed_type = "timestamp"
@@ -865,15 +831,10 @@ def update(self, snapshot_meta: MetaFile) -> None:
865
831
class Snapshot (Signed ):
866
832
"""A container for the signed part of snapshot metadata.
867
833
868
- Attributes:
869
- meta: A dictionary that contains information about targets metadata::
870
-
871
- {
872
- 'targets.json': <MetaFile INSTANCE>,
873
- '<DELEGATED TARGETS ROLE 1>.json': <MetaFile INSTANCE>,
874
- '<DELEGATED TARGETS ROLE 2>.json': <MetaFile INSTANCE>,
875
- }
834
+ Snapshot contains information about all target Metadata files.
876
835
836
+ Attributes:
837
+ meta: A dictionary of target metadata filenames to MetaFile objects.
877
838
"""
878
839
879
840
_signed_type = "snapshot"
@@ -918,22 +879,22 @@ def update(self, rolename: str, role_info: MetaFile) -> None:
918
879
919
880
920
881
class DelegatedRole (Role ):
921
- """A container with information about particular delegated role.
882
+ """A container with information about a delegated role.
883
+
884
+ A delegation can happen in three ways:
885
+ - paths is None and path_hash_prefixes is None: delegates all targets
886
+ - paths is set: delegates targets matching any path pattern in paths
887
+ - path_hash_prefixes is set: delegates targets whose target path hash
888
+ starts with any of the prefixes in path_hash_prefixes
889
+ paths and path_hash_prefixes are mutually exclusive: both cannot be set.
922
890
923
891
Attributes:
924
892
name: A string giving the name of the delegated role.
925
- keyids: A set of strings each of which represents a given key.
926
- threshold: An integer representing the required number of keys for that
927
- particular role.
928
893
terminating: A boolean indicating whether subsequent delegations
929
- should be considered.
930
- paths: An optional list of strings, where each string describes
931
- a path that the role is trusted to provide.
932
- path_hash_prefixes: An optional list of HEX_DIGESTs used to succinctly
933
- describe a set of target paths. Only one of the attributes "paths"
934
- and "path_hash_prefixes" is allowed to be set.
894
+ should be considered during a target lookup.
895
+ paths: An optional list of path pattern strings. See note above.
896
+ path_hash_prefixes: An optional list of hash prefixes. See note above.
935
897
unrecognized_fields: Dictionary of all unrecognized fields.
936
-
937
898
"""
938
899
939
900
def __init__ (
@@ -996,12 +957,11 @@ class Delegations:
996
957
"""A container object storing information about all delegations.
997
958
998
959
Attributes:
999
- keys: A dictionary of keyids and key objects containing information
1000
- about the corresponding key.
1001
- roles: A list of DelegatedRole instances containing information about
1002
- all delegated roles .
960
+ keys: Dictionary of keyids to Keys. Defines the keys used in 'roles'.
961
+ roles: List of DelegatedRoles that define which keys are required to
962
+ sign the metadata for a specific role. The roles order also
963
+ defines the order that role delegations are considered in .
1003
964
unrecognized_fields: Dictionary of all unrecognized fields.
1004
-
1005
965
"""
1006
966
1007
967
def __init__ (
@@ -1045,17 +1005,8 @@ class TargetFile(BaseFile):
1045
1005
1046
1006
Attributes:
1047
1007
length: An integer indicating the length of the target file.
1048
- hashes: A dictionary mapping hash algorithms to the
1049
- hashes resulting from applying them over the metadata file
1050
- contents::
1051
-
1052
- 'hashes': {
1053
- '<HASH ALGO 1>': '<TARGET FILE HASH 1>',
1054
- '<HASH ALGO 2>': '<TARGET FILE HASH 2>',
1055
- ...
1056
- }
1008
+ hashes: A dictionary of hash algorithm names to hash values.
1057
1009
unrecognized_fields: Dictionary of all unrecognized fields.
1058
-
1059
1010
"""
1060
1011
1061
1012
def __init__ (
@@ -1096,10 +1047,11 @@ def to_dict(self) -> Dict[str, Any]:
1096
1047
}
1097
1048
1098
1049
def verify_length_and_hashes (self , data : Union [bytes , BinaryIO ]):
1099
- """Verifies that the length and hashes of "data" match expected
1100
- values.
1050
+ """Verifies that length and hashes of "data" match expected values.
1051
+
1101
1052
Args:
1102
1053
data: File object or its content in bytes.
1054
+
1103
1055
Raises:
1104
1056
LengthOrHashMismatchError: Calculated length or hashes do not
1105
1057
match expected values or hash algorithm is not supported.
@@ -1111,25 +1063,18 @@ def verify_length_and_hashes(self, data: Union[bytes, BinaryIO]):
1111
1063
class Targets (Signed ):
1112
1064
"""A container for the signed part of targets metadata.
1113
1065
1114
- Attributes:
1115
- targets: A dictionary that contains information about target files::
1116
-
1117
- {
1118
- '<TARGET FILE NAME>': <TargetFile INSTANCE>,
1119
- ...
1120
- }
1121
-
1122
- delegations: An optional object containing a list of delegated target
1123
- roles and public key store used to verify their metadata
1124
- signatures.
1066
+ Targets contains verifying information about target files and also
1067
+ delegates responsibility to other Targets roles.
1125
1068
1069
+ Attributes:
1070
+ targets: A dictionary of target filenames to TargetFiles
1071
+ delegations: An optional Delegations that defines how this Targets
1072
+ further delegates responsibility to other Targets Metadata files.
1126
1073
"""
1127
1074
1128
1075
_signed_type = "targets"
1129
1076
1130
- # TODO: determine an appropriate value for max-args and fix places where
1131
- # we violate that. This __init__ function takes 7 arguments, whereas the
1132
- # default max-args value for pylint is 5
1077
+ # TODO: determine an appropriate value for max-args
1133
1078
# pylint: disable=too-many-arguments
1134
1079
def __init__ (
1135
1080
self ,
0 commit comments