Skip to content

Commit 74fdbfd

Browse files
committed
cli: Add --rekor-version to sign arguments
This should not be needed... but it could be handy if * SigningConfig already contains rekor v2 * user for some reason does not want rekor v2 entries in the bundle This option only does anything if there are multiple Rekor versions listed in SigningConfig. The test is changed since the "ANY" selector is now considered to not be an error if there are 0 services: * This is not a problem since for both TSAs and tlogs we have a check that there is at least one service * This improves the error message when --rekor-version is used with a version that is not found in signingconfig Signed-off-by: Jussi Kukkonen <[email protected]>
1 parent 3a26b7d commit 74fdbfd

File tree

3 files changed

+35
-12
lines changed

3 files changed

+35
-12
lines changed

sigstore/_cli.py

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,11 @@ def _parser() -> argparse.ArgumentParser:
288288
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
289289
parents=[parent_parser],
290290
)
291+
attest.add_argument(
292+
"--rekor-version",
293+
type=int,
294+
help="Force the rekor transparency log version (in case there are multiple in signing configuration)",
295+
)
291296
attest.add_argument(
292297
"files",
293298
metavar="FILE",
@@ -348,6 +353,11 @@ def _parser() -> argparse.ArgumentParser:
348353
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
349354
parents=[parent_parser],
350355
)
356+
sign.add_argument(
357+
"--rekor-version",
358+
type=int,
359+
help="Force the rekor transparency log version (in case there are multiple in signing configuration)",
360+
)
351361

352362
oidc_options = sign.add_argument_group("OpenID Connect options")
353363
oidc_options.add_argument(
@@ -1195,11 +1205,16 @@ def _get_trust_config(args: argparse.Namespace) -> ClientTrustConfig:
11951205
offline = getattr(args, "offline", False)
11961206

11971207
if args.trust_config:
1198-
return ClientTrustConfig.from_json(args.trust_config.read_text())
1208+
trust_config = ClientTrustConfig.from_json(args.trust_config.read_text())
11991209
elif args.staging:
1200-
return ClientTrustConfig.staging(offline=offline)
1210+
trust_config = ClientTrustConfig.staging(offline=offline)
12011211
else:
1202-
return ClientTrustConfig.production(offline=offline)
1212+
trust_config = ClientTrustConfig.production(offline=offline)
1213+
1214+
# Enforce rekor version if --rekor-version is used
1215+
trust_config.force_tlog_version = getattr(args, "rekor_version", None)
1216+
1217+
return trust_config
12031218

12041219

12051220
def _get_identity(

sigstore/_internal/trust.py

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -335,10 +335,13 @@ def __str__(self) -> str:
335335
"""Returns the variant's string value."""
336336
return self.value
337337

338-
def __init__(self, inner: _SigningConfig):
338+
def __init__(self, inner: _SigningConfig, tlog_version: int | None = None):
339339
"""
340340
Construct a new `SigningConfig`.
341341
342+
tlog_version is an optional argument that enforces that only specified
343+
versions of rekor are included in the transparency logs.
344+
342345
@api private
343346
"""
344347
self._inner = inner
@@ -351,8 +354,13 @@ def __init__(self, inner: _SigningConfig):
351354

352355
# Create lists of service protos that are valid, selected by the service
353356
# configuration & supported by this client
357+
if tlog_version is None:
358+
tlog_versions = REKOR_VERSIONS
359+
else:
360+
tlog_versions = [tlog_version]
361+
354362
self._tlogs = self._get_valid_services(
355-
self._inner.rekor_tlog_urls, REKOR_VERSIONS, self._inner.rekor_tlog_config
363+
self._inner.rekor_tlog_urls, tlog_versions, self._inner.rekor_tlog_config
356364
)
357365
if not self._tlogs:
358366
raise Error("No valid Rekor transparency log found in signing config")
@@ -415,7 +423,7 @@ def _get_valid_services(
415423

416424
# handle EXACT and ANY selectors
417425
count = config.count if config.selector == ServiceSelector.EXACT else 1
418-
if len(result) < count:
426+
if config.selector == ServiceSelector.EXACT and len(result) < count:
419427
raise ValueError(
420428
f"Expected {count} services in signing config, found {len(result)}"
421429
)
@@ -655,6 +663,9 @@ def __init__(self, inner: _ClientTrustConfig) -> None:
655663
self._inner = inner
656664
self._verify()
657665

666+
# This can be used to enforce a specific rekor major version in signingconfig
667+
self.force_tlog_version: int | None = None
668+
658669
def _verify(self) -> None:
659670
"""
660671
Performs various feats of heroism to ensure that the client trust config
@@ -681,4 +692,6 @@ def signing_config(self) -> SigningConfig:
681692
"""
682693
Return the interior root of trust, as a `SigningConfig`.
683694
"""
684-
return SigningConfig(self._inner.signing_config)
695+
return SigningConfig(
696+
self._inner.signing_config, tlog_version=self.force_tlog_version
697+
)

test/unit/internal/test_trust.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -188,11 +188,6 @@ def test_get_valid_services(self, services, versions, config, expected_result):
188188
@pytest.mark.parametrize(
189189
"services, versions, config",
190190
[
191-
( # ANY selector without services
192-
[],
193-
[1],
194-
ServiceConfiguration(ServiceSelector.ANY),
195-
),
196191
( # EXACT selector without enough services
197192
[_service_v1_op1],
198193
[1],

0 commit comments

Comments
 (0)