Skip to content

Commit c2edd30

Browse files
committed
Metadata API: Make sure Signed.expires is UTC
* Most importantly use strftime() to serialize the datetime * Force the timezone as UTC when deserializing Signed-off-by: Jussi Kukkonen <jkukkonen@google.com>
1 parent 048d3b3 commit c2edd30

4 files changed

Lines changed: 11 additions & 10 deletions

File tree

tests/generated_data/generate_md.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
import os
77
import sys
8-
from datetime import datetime
8+
from datetime import UTC, datetime
99
from typing import Dict, List, Optional
1010

1111
from securesystemslib.signer import SSlibKey, SSlibSigner
@@ -48,8 +48,7 @@
4848
}
4949
)
5050

51-
expires_str = "2050-01-01T00:00:00Z"
52-
EXPIRY = datetime.strptime(expires_str, "%Y-%m-%dT%H:%M:%SZ")
51+
EXPIRY = datetime(2050, 1, 1, tzinfo=UTC)
5352
OUT_DIR = "generated_data/ed25519_metadata"
5453
if not os.path.exists(OUT_DIR):
5554
os.mkdir(OUT_DIR)

tests/test_api.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,8 @@ def test_metadata_signed_is_expired(self) -> None:
313313
snapshot_path = os.path.join(self.repo_dir, "metadata", "snapshot.json")
314314
md = Metadata.from_file(snapshot_path)
315315

316-
self.assertEqual(md.signed.expires, datetime(2030, 1, 1, 0, 0))
316+
expected_expiry = datetime(2030, 1, 1, 0, 0, tzinfo=timezone.utc)
317+
self.assertEqual(md.signed.expires, expected_expiry)
317318

318319
# Test is_expired with reference_time provided
319320
is_expired = md.signed.is_expired(md.signed.expires)

tests/test_trusted_metadata_set.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import os
55
import sys
66
import unittest
7-
from datetime import datetime
7+
from datetime import UTC, datetime
88
from typing import Callable, ClassVar, Dict, List, Optional, Tuple
99

1010
from securesystemslib.interface import (
@@ -279,7 +279,7 @@ def test_update_root_new_root_ver_same_as_trusted_root_ver(self) -> None:
279279

280280
def test_root_expired_final_root(self) -> None:
281281
def root_expired_modifier(root: Root) -> None:
282-
root.expires = datetime(1970, 1, 1)
282+
root.expires = datetime(1970, 1, 1, tzinfo=UTC)
283283

284284
# intermediate root can be expired
285285
root = self.modify_metadata(Root.type, root_expired_modifier)
@@ -329,7 +329,7 @@ def bump_snapshot_version(timestamp: Timestamp) -> None:
329329
def test_update_timestamp_expired(self) -> None:
330330
# new_timestamp has expired
331331
def timestamp_expired_modifier(timestamp: Timestamp) -> None:
332-
timestamp.expires = datetime(1970, 1, 1)
332+
timestamp.expires = datetime(1970, 1, 1, tzinfo=UTC)
333333

334334
# expired intermediate timestamp is loaded but raises
335335
timestamp = self.modify_metadata(
@@ -406,7 +406,7 @@ def test_update_snapshot_expired_new_snapshot(self) -> None:
406406
self.trusted_set.update_timestamp(self.metadata[Timestamp.type])
407407

408408
def snapshot_expired_modifier(snapshot: Snapshot) -> None:
409-
snapshot.expires = datetime(1970, 1, 1)
409+
snapshot.expires = datetime(1970, 1, 1, tzinfo=UTC)
410410

411411
# expired intermediate snapshot is loaded but will raise
412412
snapshot = self.modify_metadata(
@@ -486,7 +486,7 @@ def test_update_targets_expired_new_target(self) -> None:
486486

487487
# new_delegated_target has expired
488488
def target_expired_modifier(target: Targets) -> None:
489-
target.expires = datetime(1970, 1, 1)
489+
target.expires = datetime(1970, 1, 1, tzinfo=UTC)
490490

491491
targets = self.modify_metadata(Targets.type, target_expired_modifier)
492492
with self.assertRaises(exceptions.ExpiredMetadataError):

tuf/api/_payload.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ def _common_fields_from_dict(
176176
# what the constructor expects and what we store. The inverse operation
177177
# is implemented in '_common_fields_to_dict'.
178178
expires = datetime.strptime(expires_str, "%Y-%m-%dT%H:%M:%SZ")
179+
expires = expires.replace(tzinfo=timezone.utc)
179180

180181
return version, spec_version, expires
181182

@@ -190,7 +191,7 @@ def _common_fields_to_dict(self) -> Dict[str, Any]:
190191
"_type": self._type,
191192
"version": self.version,
192193
"spec_version": self.spec_version,
193-
"expires": self.expires.isoformat() + "Z",
194+
"expires": self.expires.strftime("%Y-%m-%dT%H:%M:%SZ"),
194195
**self.unrecognized_fields,
195196
}
196197

0 commit comments

Comments
 (0)