11
11
# limitations under the License.
12
12
13
13
import pretend
14
+ import pytest
14
15
15
16
from warehouse .oidc import models
16
17
17
18
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
+
18
26
class TestOIDCProvider :
19
27
def test_oidc_provider_not_default_verifiable (self ):
20
28
provider = models .OIDCProvider (projects = [])
@@ -27,9 +35,9 @@ def test_github_provider_all_known_claims(self):
27
35
assert models .GitHubProvider .all_known_claims () == {
28
36
# verifiable claims
29
37
"repository" ,
30
- "workflow" ,
31
38
"repository_owner" ,
32
39
"repository_owner_id" ,
40
+ "job_workflow_ref" ,
33
41
# preverified claims
34
42
"iss" ,
35
43
"iat" ,
@@ -51,7 +59,7 @@ def test_github_provider_all_known_claims(self):
51
59
"event_name" ,
52
60
"ref_type" ,
53
61
"repository_id" ,
54
- "job_workflow_ref " ,
62
+ "workflow " ,
55
63
}
56
64
57
65
def test_github_provider_computed_properties (self ):
@@ -120,7 +128,7 @@ def test_github_provider_verifies(self, monkeypatch):
120
128
workflow_filename = "fakeworkflow.yml" ,
121
129
)
122
130
123
- noop_check = pretend .call_recorder (lambda l , r : True )
131
+ noop_check = pretend .call_recorder (lambda gt , sc , ac : True )
124
132
verifiable_claims = {
125
133
claim_name : noop_check for claim_name in provider .__verifiable_claims__
126
134
}
@@ -132,3 +140,62 @@ def test_github_provider_verifies(self, monkeypatch):
132
140
}
133
141
assert provider .verify_claims (signed_claims = signed_claims )
134
142
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/baz.yml@fake.yml@notrailingslash" ,
170
+ "notrailingslash" ,
171
+ False ,
172
+ ),
173
+ (
174
+ "foo/bar/.github/workflows/baz.yml@fake.yml@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/baz.yml@malicious.yml@" ,
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