From 0f37f0b802b6999abe8b07f7751abd35ec5d9d2c Mon Sep 17 00:00:00 2001 From: laurentsimon Date: Fri, 2 Jun 2023 17:21:55 +0000 Subject: [PATCH 01/10] update Signed-off-by: laurentsimon --- sigstore/_cli.py | 10 +++++++++- sigstore/oidc.py | 8 ++++---- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/sigstore/_cli.py b/sigstore/_cli.py index 5827ce4ce..0f2f634cb 100644 --- a/sigstore/_cli.py +++ b/sigstore/_cli.py @@ -221,6 +221,12 @@ def _add_shared_oidc_options( default=os.getenv("SIGSTORE_OIDC_ISSUER", DEFAULT_OAUTH_ISSUER_URL), help="The OpenID Connect issuer to use (conflicts with --staging)", ) + group.add_argument( + "--oidc-disable-default-browser", + action="store_true", + default=_boolify_env("SIGSTORE_OIDC_DISABLE_DEFAULT_BROWSER"), + help="Do not start the default web browser to complete the OAuth flow. Instead display a web link to the user.", + ) def _parser() -> argparse.ArgumentParser: @@ -964,7 +970,9 @@ def _get_identity(args: argparse.Namespace) -> Optional[IdentityToken]: args.oidc_client_secret = "" # nosec: B105 token = issuer.identity_token( - client_id=args.oidc_client_id, client_secret=args.oidc_client_secret + client_id=args.oidc_client_id, + client_secret=args.oidc_client_secret, + force_oob=args.oidc_disable_default_browser, ) return token diff --git a/sigstore/oidc.py b/sigstore/oidc.py index 8a03a1c83..b5960434f 100644 --- a/sigstore/oidc.py +++ b/sigstore/oidc.py @@ -19,7 +19,6 @@ from __future__ import annotations import logging -import os import sys import time import urllib.parse @@ -247,7 +246,10 @@ def staging(cls) -> Issuer: return cls(STAGING_OAUTH_ISSUER_URL) def identity_token( # nosec: B107 - self, client_id: str = "sigstore", client_secret: str = "" + self, + client_id: str = "sigstore", + client_secret: str = "", + force_oob: bool = False, ) -> IdentityToken: """ Retrieves and returns an `IdentityToken` from the current `Issuer`, via OAuth. @@ -261,8 +263,6 @@ def identity_token( # nosec: B107 from sigstore._internal.oidc.oauth import _OAuthFlow - force_oob = os.getenv("SIGSTORE_OAUTH_FORCE_OOB") is not None - code: str with _OAuthFlow(client_id, client_secret, self) as server: # Launch web browser From dd9e0b8a6e5ecea77b29c355ddd1e3e1093044ab Mon Sep 17 00:00:00 2001 From: laurentsimon Date: Fri, 2 Jun 2023 17:22:59 +0000 Subject: [PATCH 02/10] update Signed-off-by: laurentsimon --- sigstore/_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sigstore/_utils.py b/sigstore/_utils.py index bfac19903..ae5378d12 100644 --- a/sigstore/_utils.py +++ b/sigstore/_utils.py @@ -178,7 +178,7 @@ def read_embedded(name: str, prefix: str) -> bytes: Read a resource embedded in this distribution of sigstore-python, returning its contents as bytes. """ - return resources.files("sigstore._store").joinpath(prefix, name).read_bytes() # type: ignore + return resources.files("sigstore._store").joinpath(prefix, name).read_bytes() def cert_is_ca(cert: Certificate) -> bool: From a60c7598b1eb0788d97ecac66a47cd08b1d450a5 Mon Sep 17 00:00:00 2001 From: laurentsimon Date: Fri, 2 Jun 2023 17:34:59 +0000 Subject: [PATCH 03/10] update Signed-off-by: laurentsimon --- sigstore/_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sigstore/_utils.py b/sigstore/_utils.py index ae5378d12..bfac19903 100644 --- a/sigstore/_utils.py +++ b/sigstore/_utils.py @@ -178,7 +178,7 @@ def read_embedded(name: str, prefix: str) -> bytes: Read a resource embedded in this distribution of sigstore-python, returning its contents as bytes. """ - return resources.files("sigstore._store").joinpath(prefix, name).read_bytes() + return resources.files("sigstore._store").joinpath(prefix, name).read_bytes() # type: ignore def cert_is_ca(cert: Certificate) -> bool: From 329bd063d446f837e97eaee18fc4edbd2f2374e0 Mon Sep 17 00:00:00 2001 From: laurentsimon Date: Fri, 2 Jun 2023 17:57:37 +0000 Subject: [PATCH 04/10] update Signed-off-by: laurentsimon --- CHANGELOG.md | 3 +++ README.md | 1 + sigstore/_cli.py | 8 ++++---- sigstore/oidc.py | 2 +- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 28d3f0076..346dc121f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,9 @@ All versions prior to 0.9.0 are untracked. ### Changed +* CLI now supports a `--oauth-force-oob` option. + ([#667](https://github.com/sigstore/sigstore-python/pull/667)) + * `sigstore verify` now performs additional verification of Rekor's inclusion proofs by cross-checking them against signed checkpoints ([#634](https://github.com/sigstore/sigstore-python/pull/634)) diff --git a/README.md b/README.md index a7e3952da..d149c8a22 100644 --- a/README.md +++ b/README.md @@ -160,6 +160,7 @@ OpenID Connect options: (e.g. on GitHub Actions) (default: False) --oidc-issuer URL The OpenID Connect issuer to use (conflicts with --staging) (default: https://oauth2.sigstore.dev/auth) + --oauth-force-oob Force an out-of-band OAuth flow and do not automatically start the default web browser (default: False) Output options: --no-default-files Don't emit the default output files ({input}.sigstore) diff --git a/sigstore/_cli.py b/sigstore/_cli.py index 0f2f634cb..a7405cabd 100644 --- a/sigstore/_cli.py +++ b/sigstore/_cli.py @@ -222,10 +222,10 @@ def _add_shared_oidc_options( help="The OpenID Connect issuer to use (conflicts with --staging)", ) group.add_argument( - "--oidc-disable-default-browser", + "--oauth-force-oob", action="store_true", - default=_boolify_env("SIGSTORE_OIDC_DISABLE_DEFAULT_BROWSER"), - help="Do not start the default web browser to complete the OAuth flow. Instead display a web link to the user.", + default=_boolify_env("SIGSTORE_OAUTH_FORCE_OOB"), + help="Force an out-of-band OAuth flow and do not automatically start the default web browser", ) @@ -972,7 +972,7 @@ def _get_identity(args: argparse.Namespace) -> Optional[IdentityToken]: token = issuer.identity_token( client_id=args.oidc_client_id, client_secret=args.oidc_client_secret, - force_oob=args.oidc_disable_default_browser, + force_oob=args.oath_force_oob, ) return token diff --git a/sigstore/oidc.py b/sigstore/oidc.py index b5960434f..9239418a9 100644 --- a/sigstore/oidc.py +++ b/sigstore/oidc.py @@ -255,7 +255,7 @@ def identity_token( # nosec: B107 Retrieves and returns an `IdentityToken` from the current `Issuer`, via OAuth. This function blocks on user interaction, either via a web browser or an out-of-band - OAuth flow. + OAuth flow. When force_oob, the out-of-band flow is always used. """ # This function and the components that it relies on are based off of: From 1819143ece74b2aa7637b4abc6cfb4c059e69406 Mon Sep 17 00:00:00 2001 From: laurentsimon Date: Fri, 2 Jun 2023 17:59:05 +0000 Subject: [PATCH 05/10] update Signed-off-by: laurentsimon --- sigstore/oidc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sigstore/oidc.py b/sigstore/oidc.py index 9239418a9..a34601f47 100644 --- a/sigstore/oidc.py +++ b/sigstore/oidc.py @@ -255,7 +255,7 @@ def identity_token( # nosec: B107 Retrieves and returns an `IdentityToken` from the current `Issuer`, via OAuth. This function blocks on user interaction, either via a web browser or an out-of-band - OAuth flow. When force_oob, the out-of-band flow is always used. + OAuth flow. When force_oob is true, the out-of-band flow is always used. """ # This function and the components that it relies on are based off of: From 195ec729d756b4849c9de84b3a9d80a4ef52070e Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Fri, 2 Jun 2023 14:12:13 -0400 Subject: [PATCH 06/10] _cli: typo Signed-off-by: William Woodruff --- sigstore/_cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sigstore/_cli.py b/sigstore/_cli.py index a7405cabd..cdaa3569d 100644 --- a/sigstore/_cli.py +++ b/sigstore/_cli.py @@ -972,7 +972,7 @@ def _get_identity(args: argparse.Namespace) -> Optional[IdentityToken]: token = issuer.identity_token( client_id=args.oidc_client_id, client_secret=args.oidc_client_secret, - force_oob=args.oath_force_oob, + force_oob=args.oauth_force_oob, ) return token From 86c882db8324d4493cb1c165a04f9817dbe1fd4e Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Fri, 2 Jun 2023 14:14:27 -0400 Subject: [PATCH 07/10] oidc: elaborate on behavior Signed-off-by: William Woodruff --- sigstore/oidc.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/sigstore/oidc.py b/sigstore/oidc.py index a34601f47..f96ddc604 100644 --- a/sigstore/oidc.py +++ b/sigstore/oidc.py @@ -254,8 +254,11 @@ def identity_token( # nosec: B107 """ Retrieves and returns an `IdentityToken` from the current `Issuer`, via OAuth. - This function blocks on user interaction, either via a web browser or an out-of-band - OAuth flow. When force_oob is true, the out-of-band flow is always used. + This function blocks on user interaction. + + The `force_oob` flag controls the kind of flow performed. When `False` (the default), + this function attempts to open the user's web browser before falling back to + an out-of-band flow. When `True`, the out-of-band flow is always used. """ # This function and the components that it relies on are based off of: From 41990487ab9ee6a09218eb2e3171e1170a1d720f Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Fri, 2 Jun 2023 14:15:36 -0400 Subject: [PATCH 08/10] README: update `--help` Signed-off-by: William Woodruff --- README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index d149c8a22..4dfe67d7f 100644 --- a/README.md +++ b/README.md @@ -134,8 +134,8 @@ Sigstore instance options: usage: sigstore sign [-h] [--identity-token TOKEN] [--oidc-client-id ID] [--oidc-client-secret SECRET] [--oidc-disable-ambient-providers] [--oidc-issuer URL] - [--no-default-files] [--signature FILE] - [--certificate FILE] [--bundle FILE] + [--oauth-force-oob] [--no-default-files] + [--signature FILE] [--certificate FILE] [--bundle FILE] [--output-directory DIR] [--overwrite] [--staging] [--rekor-url URL] [--rekor-root-pubkey FILE] [--fulcio-url URL] [--ctfe FILE] @@ -160,7 +160,9 @@ OpenID Connect options: (e.g. on GitHub Actions) (default: False) --oidc-issuer URL The OpenID Connect issuer to use (conflicts with --staging) (default: https://oauth2.sigstore.dev/auth) - --oauth-force-oob Force an out-of-band OAuth flow and do not automatically start the default web browser (default: False) + --oauth-force-oob Force an out-of-band OAuth flow and do not + automatically start the default web browser (default: + False) Output options: --no-default-files Don't emit the default output files ({input}.sigstore) From 7b6fc659c5f8f9da2f8521b2f33a4ff1d1e9ff11 Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Fri, 2 Jun 2023 14:17:23 -0400 Subject: [PATCH 09/10] CHANGELOG: reflow Signed-off-by: William Woodruff --- CHANGELOG.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 346dc121f..6cbb0ea44 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,11 +8,15 @@ All versions prior to 0.9.0 are untracked. ## [Unreleased] -### Changed +### Added -* CLI now supports a `--oauth-force-oob` option. +* CLI: `sigstore sign` and `sigstore get-identity-token` now support the + `--oauth-force-oob` option; which has the same behavior as the + preexisting `SIGSTORE_OAUTH_FORCE_OOB` environment variable ([#667](https://github.com/sigstore/sigstore-python/pull/667)) +### Changed + * `sigstore verify` now performs additional verification of Rekor's inclusion proofs by cross-checking them against signed checkpoints ([#634](https://github.com/sigstore/sigstore-python/pull/634)) From d6052c9b2aae384a8f8f0f0b54483099ee90c9df Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Thu, 8 Jun 2023 17:03:10 -0400 Subject: [PATCH 10/10] test: fix identity_token test Signed-off-by: William Woodruff --- test/unit/internal/oidc/test_issuer.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/unit/internal/oidc/test_issuer.py b/test/unit/internal/oidc/test_issuer.py index b3458b28c..77d4c4d38 100644 --- a/test/unit/internal/oidc/test_issuer.py +++ b/test/unit/internal/oidc/test_issuer.py @@ -30,8 +30,7 @@ def test_init_url(): @pytest.mark.online def test_get_identity_token_identity_error(monkeypatch): - monkeypatch.setenv("SIGSTORE_OAUTH_FORCE_OOB", "") monkeypatch.setattr("builtins.input", lambda _: "hunter2") with pytest.raises(IdentityError): - Issuer.staging().identity_token() + Issuer.staging().identity_token(force_oob=True)