Skip to content

Commit f8046d8

Browse files
author
Jussi Kukkonen
authored
Merge pull request #1470 from sechkova/ngclient-settings
ngclient constants and configuration
2 parents faeaf34 + 37defa9 commit f8046d8

File tree

4 files changed

+40
-22
lines changed

4 files changed

+40
-22
lines changed

tuf/ngclient/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,6 @@
44
"""TUF client public API
55
"""
66

7+
from tuf.ngclient.config import UpdaterConfig
78
from tuf.ngclient.fetcher import FetcherInterface
89
from tuf.ngclient.updater import Updater

tuf/ngclient/_internal/requests_fetcher.py

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,15 @@
77

88
import logging
99
import time
10+
from typing import Optional
1011
from urllib import parse
1112

1213
# Imports
1314
import requests
1415
import urllib3.exceptions
1516

1617
import tuf
17-
from tuf import exceptions, settings
18+
from tuf import exceptions
1819
from tuf.ngclient.fetcher import FetcherInterface
1920

2021
# Globals
@@ -47,6 +48,11 @@ def __init__(self):
4748
# Some cookies may not be HTTP-safe.
4849
self._sessions = {}
4950

51+
# Default settings
52+
self.socket_timeout: int = 4 # seconds
53+
self.chunk_size: int = 400000 # bytes
54+
self.sleep_before_round: Optional[int] = None
55+
5056
def fetch(self, url, required_length):
5157
"""Fetches the contents of HTTP/HTTPS url from a remote server.
5258
@@ -75,9 +81,7 @@ def fetch(self, url, required_length):
7581
# requests as:
7682
# - connect timeout (max delay before first byte is received)
7783
# - read (gap) timeout (max delay between bytes received)
78-
response = session.get(
79-
url, stream=True, timeout=settings.SOCKET_TIMEOUT
80-
)
84+
response = session.get(url, stream=True, timeout=self.socket_timeout)
8185
# Check response status.
8286
try:
8387
response.raise_for_status()
@@ -99,11 +103,11 @@ def chunks():
99103
# large file in one shot. Before beginning the round, sleep
100104
# (if set) for a short amount of time so that the CPU is not
101105
# hogged in the while loop.
102-
if settings.SLEEP_BEFORE_ROUND:
103-
time.sleep(settings.SLEEP_BEFORE_ROUND)
106+
if self.sleep_before_round:
107+
time.sleep(self.sleep_before_round)
104108

105109
read_amount = min(
106-
settings.CHUNK_SIZE,
110+
self.chunk_size,
107111
required_length - bytes_received,
108112
)
109113

tuf/ngclient/config.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Copyright 2021, New York University and the TUF contributors
2+
# SPDX-License-Identifier: MIT OR Apache-2.0
3+
4+
"""Configuration options for Updater class
5+
"""
6+
7+
from dataclasses import dataclass
8+
9+
10+
@dataclass
11+
class UpdaterConfig:
12+
max_root_rotations: int = 32
13+
max_delegations: int = 32
14+
root_max_length: int = 512000 # bytes
15+
timestamp_max_length: int = 16384 # bytes
16+
snapshot_max_length: int = 2000000 # bytes
17+
targets_max_length: int = 5000000 # bytes

tuf/ngclient/updater.py

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,9 @@
2020
requests_fetcher,
2121
trusted_metadata_set,
2222
)
23+
from tuf.ngclient.config import UpdaterConfig
2324
from tuf.ngclient.fetcher import FetcherInterface
2425

25-
# Globals
26-
MAX_ROOT_ROTATIONS = 32
27-
MAX_DELEGATIONS = 32
28-
DEFAULT_ROOT_MAX_LENGTH = 512000 # bytes
29-
DEFAULT_TIMESTAMP_MAX_LENGTH = 16384 # bytes
30-
DEFAULT_SNAPSHOT_MAX_LENGTH = 2000000 # bytes
31-
DEFAULT_TARGETS_MAX_LENGTH = 5000000 # bytes
32-
3326
logger = logging.getLogger(__name__)
3427

3528

@@ -45,6 +38,7 @@ def __init__(
4538
metadata_base_url: str,
4639
target_base_url: Optional[str] = None,
4740
fetcher: Optional[FetcherInterface] = None,
41+
config: Optional[UpdaterConfig] = None,
4842
):
4943
"""
5044
Args:
@@ -76,6 +70,8 @@ def __init__(
7670
else:
7771
self._fetcher = fetcher
7872

73+
self.config = config or UpdaterConfig()
74+
7975
def refresh(self) -> None:
8076
"""
8177
This method downloads, verifies, and loads metadata for the top-level
@@ -251,12 +247,12 @@ def _load_root(self) -> None:
251247

252248
# Update the root role
253249
lower_bound = self._trusted_set.root.signed.version + 1
254-
upper_bound = lower_bound + MAX_ROOT_ROTATIONS
250+
upper_bound = lower_bound + self.config.max_root_rotations
255251

256252
for next_version in range(lower_bound, upper_bound):
257253
try:
258254
data = self._download_metadata(
259-
"root", DEFAULT_ROOT_MAX_LENGTH, next_version
255+
"root", self.config.root_max_length, next_version
260256
)
261257
self._trusted_set.update_root(data)
262258
self._persist_metadata("root", data)
@@ -281,7 +277,7 @@ def _load_timestamp(self) -> None:
281277

282278
# Load from remote (whether local load succeeded or not)
283279
data = self._download_metadata(
284-
"timestamp", DEFAULT_TIMESTAMP_MAX_LENGTH
280+
"timestamp", self.config.timestamp_max_length
285281
)
286282
self._trusted_set.update_timestamp(data)
287283
self._persist_metadata("timestamp", data)
@@ -297,7 +293,7 @@ def _load_snapshot(self) -> None:
297293
logger.debug("Failed to load local snapshot %s", e)
298294

299295
metainfo = self._trusted_set.timestamp.signed.meta["snapshot.json"]
300-
length = metainfo.length or DEFAULT_SNAPSHOT_MAX_LENGTH
296+
length = metainfo.length or self.config.snapshot_max_length
301297
version = None
302298
if self._trusted_set.root.signed.consistent_snapshot:
303299
version = metainfo.version
@@ -317,7 +313,7 @@ def _load_targets(self, role: str, parent_role: str) -> None:
317313
logger.debug("Failed to load local %s: %s", role, e)
318314

319315
metainfo = self._trusted_set.snapshot.signed.meta[f"{role}.json"]
320-
length = metainfo.length or DEFAULT_TARGETS_MAX_LENGTH
316+
length = metainfo.length or self.config.targets_max_length
321317
version = None
322318
if self._trusted_set.root.signed.consistent_snapshot:
323319
version = metainfo.version
@@ -336,7 +332,7 @@ def _preorder_depth_first_walk(self, target_filepath) -> Dict:
336332
target = None
337333
role_names = [("targets", "root")]
338334
visited_role_names = set()
339-
number_of_delegations = MAX_DELEGATIONS
335+
number_of_delegations = self.config.max_delegations
340336

341337
# Preorder depth-first traversal of the graph of target delegations.
342338
while (
@@ -417,7 +413,7 @@ def _preorder_depth_first_walk(self, target_filepath) -> Dict:
417413
):
418414
msg = (
419415
f"{len(role_names)} roles left to visit, but allowed to ",
420-
f"visit at most {MAX_DELEGATIONS} delegations.",
416+
f"visit at most {self.config.max_delegations} delegations.",
421417
)
422418
logger.debug(msg)
423419

0 commit comments

Comments
 (0)