1111# limitations under the License.
1212
1313import pretend
14+ import pytest
1415
1516from warehouse .oidc import models
1617
1718
19+ def test_check_claim_binary ():
20+ wrapped = models ._check_claim_binary (str .__eq__ )
21+
22+ assert wrapped ("foo" , "bar" , pretend .stub ()) is False
23+ assert wrapped ("foo" , "foo" , pretend .stub ()) is True
24+
25+
1826class TestOIDCProvider :
1927 def test_oidc_provider_not_default_verifiable (self ):
2028 provider = models .OIDCProvider (projects = [])
@@ -27,9 +35,9 @@ def test_github_provider_all_known_claims(self):
2735 assert models .GitHubProvider .all_known_claims () == {
2836 # verifiable claims
2937 "repository" ,
30- "workflow" ,
3138 "repository_owner" ,
3239 "repository_owner_id" ,
40+ "job_workflow_ref" ,
3341 # preverified claims
3442 "iss" ,
3543 "iat" ,
@@ -51,7 +59,7 @@ def test_github_provider_all_known_claims(self):
5159 "event_name" ,
5260 "ref_type" ,
5361 "repository_id" ,
54- "job_workflow_ref " ,
62+ "workflow " ,
5563 }
5664
5765 def test_github_provider_computed_properties (self ):
@@ -120,7 +128,7 @@ def test_github_provider_verifies(self, monkeypatch):
120128 workflow_filename = "fakeworkflow.yml" ,
121129 )
122130
123- noop_check = pretend .call_recorder (lambda l , r : True )
131+ noop_check = pretend .call_recorder (lambda gt , sc , ac : True )
124132 verifiable_claims = {
125133 claim_name : noop_check for claim_name in provider .__verifiable_claims__
126134 }
@@ -132,3 +140,62 @@ def test_github_provider_verifies(self, monkeypatch):
132140 }
133141 assert provider .verify_claims (signed_claims = signed_claims )
134142 assert len (noop_check .calls ) == len (verifiable_claims )
143+
144+ @pytest .mark .parametrize (
145+ ("claim" , "ref" , "valid" ),
146+ [
147+ # okay: workflow name, followed by a nonempty ref
148+ (
149+ "foo/bar/.github/workflows/baz.yml@refs/tags/v0.0.1" ,
150+ "refs/tags/v0.0.1" ,
151+ True ,
152+ ),
153+ ("foo/bar/.github/workflows/baz.yml@refs/pulls/6" , "refs/pulls/6" , True ),
154+ (
155+ "foo/bar/.github/workflows/baz.yml@refs/heads/main" ,
156+ "refs/heads/main" ,
157+ True ,
158+ ),
159+ (
160+ "foo/bar/.github/workflows/baz.yml@notrailingslash" ,
161+ "notrailingslash" ,
162+ True ,
163+ ),
164+ # bad: workflow name, empty or missing ref
165+ ("foo/bar/.github/workflows/baz.yml@emptyref" , "" , False ),
166+ ("foo/bar/.github/workflows/baz.yml@missingref" , None , False ),
167+ # bad: workflow name with various attempted impersonations
168+ (
169+ "foo/bar/.github/workflows/[email protected] @notrailingslash" , 170+ "notrailingslash" ,
171+ False ,
172+ ),
173+ (
174+ "foo/bar/.github/workflows/[email protected] @refs/pulls/6" , 175+ "refs/pulls/6" ,
176+ False ,
177+ ),
178+ # bad: missing tail or workflow name or otherwise partial
179+ ("foo/bar/.github/workflows/baz.yml@" , "notrailingslash" , False ),
180+ ("foo/bar/.github/workflows/@" , "notrailingslash" , False ),
181+ ("foo/bar/.github/workflows/" , "notrailingslash" , False ),
182+ ("baz.yml" , "notrailingslash" , False ),
183+ (
184+ "foo/bar/.github/workflows/[email protected] @" , 185+ "notrailingslash" ,
186+ False ,
187+ ),
188+ ("foo/bar/.github/workflows/baz.yml@@" , "notrailingslash" , False ),
189+ ("" , "notrailingslash" , False ),
190+ ],
191+ )
192+ def test_github_provider_job_workflow_ref (self , claim , ref , valid ):
193+ provider = models .GitHubProvider (
194+ repository_name = "bar" ,
195+ repository_owner = "foo" ,
196+ repository_owner_id = pretend .stub (),
197+ workflow_filename = "baz.yml" ,
198+ )
199+
200+ check = models .GitHubProvider .__verifiable_claims__ ["job_workflow_ref" ]
201+ assert check (provider .job_workflow_ref , claim , {"ref" : ref }) is valid
0 commit comments