Skip to content

cli: Add --rekor-version to sign arguments #1471

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 13 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,8 @@ optional arguments:

<!-- @begin-sigstore-sign-help@ -->
```
usage: sigstore sign [-h] [-v] [--identity-token TOKEN] [--oidc-client-id ID]
usage: sigstore sign [-h] [-v] [--rekor-version VERSION]
[--identity-token TOKEN] [--oidc-client-id ID]
[--oidc-client-secret SECRET]
[--oidc-disable-ambient-providers] [--oidc-issuer URL]
[--oauth-force-oob] [--no-default-files]
Expand All @@ -109,6 +110,10 @@ optional arguments:
-h, --help show this help message and exit
-v, --verbose run with additional debug logging; supply multiple
times to increase verbosity (default: 0)
--rekor-version VERSION
Force the rekor transparency log version. Valid values
are [1, 2]. By default the highest available version
is used

OpenID Connect options:
--identity-token TOKEN
Expand Down Expand Up @@ -151,9 +156,9 @@ Output options:

<!-- @begin-sigstore-attest-help@ -->
```
usage: sigstore attest [-h] [-v] --predicate FILE --predicate-type TYPE
[--identity-token TOKEN] [--oidc-client-id ID]
[--oidc-client-secret SECRET]
usage: sigstore attest [-h] [-v] [--rekor-version VERSION] --predicate FILE
--predicate-type TYPE [--identity-token TOKEN]
[--oidc-client-id ID] [--oidc-client-secret SECRET]
[--oidc-disable-ambient-providers] [--oidc-issuer URL]
[--oauth-force-oob] [--bundle FILE] [--overwrite]
FILE [FILE ...]
Expand All @@ -165,6 +170,10 @@ optional arguments:
-h, --help show this help message and exit
-v, --verbose run with additional debug logging; supply multiple
times to increase verbosity (default: 0)
--rekor-version VERSION
Force the rekor transparency log version. Valid values
are [1, 2]. By default the highest available version
is used

DSSE options:
--predicate FILE Path to the predicate file (default: None)
Expand Down
25 changes: 22 additions & 3 deletions sigstore/_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,13 @@ def _parser() -> argparse.ArgumentParser:
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
parents=[parent_parser],
)
attest.add_argument(
"--rekor-version",
type=int,
metavar="VERSION",
default=argparse.SUPPRESS,
help="Force the rekor transparency log version. Valid values are [1, 2]. By default the highest available version is used",
)
attest.add_argument(
"files",
metavar="FILE",
Expand Down Expand Up @@ -348,6 +355,13 @@ def _parser() -> argparse.ArgumentParser:
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
parents=[parent_parser],
)
sign.add_argument(
"--rekor-version",
type=int,
metavar="VERSION",
default=argparse.SUPPRESS,
help="Force the rekor transparency log version. Valid values are [1, 2]. By default the highest available version is used",
)

oidc_options = sign.add_argument_group("OpenID Connect options")
oidc_options.add_argument(
Expand Down Expand Up @@ -1195,11 +1209,16 @@ def _get_trust_config(args: argparse.Namespace) -> ClientTrustConfig:
offline = getattr(args, "offline", False)

if args.trust_config:
return ClientTrustConfig.from_json(args.trust_config.read_text())
trust_config = ClientTrustConfig.from_json(args.trust_config.read_text())
elif args.staging:
return ClientTrustConfig.staging(offline=offline)
trust_config = ClientTrustConfig.staging(offline=offline)
else:
return ClientTrustConfig.production(offline=offline)
trust_config = ClientTrustConfig.production(offline=offline)

# Enforce rekor version if --rekor-version is used
trust_config.force_tlog_version = getattr(args, "rekor_version", None)

return trust_config


def _get_identity(
Expand Down
21 changes: 17 additions & 4 deletions sigstore/_internal/trust.py
Original file line number Diff line number Diff line change
Expand Up @@ -335,10 +335,13 @@ def __str__(self) -> str:
"""Returns the variant's string value."""
return self.value

def __init__(self, inner: _SigningConfig):
def __init__(self, inner: _SigningConfig, tlog_version: int | None = None):
"""
Construct a new `SigningConfig`.

tlog_version is an optional argument that enforces that only specified
versions of rekor are included in the transparency logs.

@api private
"""
self._inner = inner
Expand All @@ -351,8 +354,13 @@ def __init__(self, inner: _SigningConfig):

# Create lists of service protos that are valid, selected by the service
# configuration & supported by this client
if tlog_version is None:
tlog_versions = REKOR_VERSIONS
else:
tlog_versions = [tlog_version]

self._tlogs = self._get_valid_services(
self._inner.rekor_tlog_urls, REKOR_VERSIONS, self._inner.rekor_tlog_config
self._inner.rekor_tlog_urls, tlog_versions, self._inner.rekor_tlog_config
)
if not self._tlogs:
raise Error("No valid Rekor transparency log found in signing config")
Expand Down Expand Up @@ -415,7 +423,7 @@ def _get_valid_services(

# handle EXACT and ANY selectors
count = config.count if config.selector == ServiceSelector.EXACT else 1
if len(result) < count:
if config.selector == ServiceSelector.EXACT and len(result) < count:
raise ValueError(
f"Expected {count} services in signing config, found {len(result)}"
)
Expand Down Expand Up @@ -655,6 +663,9 @@ def __init__(self, inner: _ClientTrustConfig) -> None:
self._inner = inner
self._verify()

# This can be used to enforce a specific rekor major version in signingconfig
self.force_tlog_version: int | None = None

def _verify(self) -> None:
"""
Performs various feats of heroism to ensure that the client trust config
Expand All @@ -681,4 +692,6 @@ def signing_config(self) -> SigningConfig:
"""
Return the interior root of trust, as a `SigningConfig`.
"""
return SigningConfig(self._inner.signing_config)
return SigningConfig(
self._inner.signing_config, tlog_version=self.force_tlog_version
)
5 changes: 0 additions & 5 deletions test/unit/internal/test_trust.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,11 +188,6 @@ def test_get_valid_services(self, services, versions, config, expected_result):
@pytest.mark.parametrize(
"services, versions, config",
[
( # ANY selector without services
[],
[1],
ServiceConfiguration(ServiceSelector.ANY),
),
( # EXACT selector without enough services
[_service_v1_op1],
[1],
Expand Down
Loading