29
29
PROJECT_ID = "00000000-0000-1000-8000-000000000001"
30
30
USER_ID = "00000000-0000-1000-8000-000000000002"
31
31
BRANCH_ID = "00000000-0000-1000-8000-000000000003"
32
+ # This follows the format of the subject that ActiveState sends us. We don't
33
+ # validate the format when verifying the JWT. That should happen when the
34
+ # Publisher is configured. We just need to make sure that the subject matches
35
+ #
36
+ # Technically, the branch should only be present if a branch was provided in the JWT
37
+ # claims
38
+ SUBJECT = "org:fake_org_id:project:fake_project_id:branch_id:fake_branch_id"
32
39
33
40
34
41
def test_lookup_strategies ():
@@ -40,65 +47,63 @@ def test_lookup_strategies():
40
47
41
48
42
49
def new_signed_claims (
43
- sub : str = "fake:fake:fake:fake" ,
50
+ sub : str = SUBJECT ,
44
51
organization_id : str = ORG_ID ,
45
52
org_url_name : str = "fakeorg" ,
46
53
project_id : str = PROJECT_ID ,
47
54
project_name : str = "fakeproject" ,
48
55
project_path : str = "fakeorg/fakeproject" ,
49
- user_id : str = "00000000-0000-1000-8000-000000000002" ,
56
+ user_id : str = USER_ID ,
50
57
project_visibility : str = "public" ,
51
58
branch_id : str | None = None ,
52
59
) -> SignedClaims :
53
60
project_name = "fakeproject"
54
61
org_url_name = "fakeorg"
55
- claims : SignedClaims = {
56
- "sub" : sub ,
57
- "organization_id" : organization_id ,
58
- "organization_url_name" : org_url_name ,
59
- "project_id" : project_id ,
60
- "project_name" : project_name ,
61
- "project_path" : project_path ,
62
- "user_id" : user_id ,
63
- "project_visibility" : project_visibility ,
64
- }
62
+ claims = SignedClaims (
63
+ {
64
+ "sub" : sub ,
65
+ "organization_id" : organization_id ,
66
+ "organization_url_name" : org_url_name ,
67
+ "project_id" : project_id ,
68
+ "project_name" : project_name ,
69
+ "project_path" : project_path ,
70
+ "user_id" : user_id ,
71
+ "project_visibility" : project_visibility ,
72
+ }
73
+ )
65
74
if branch_id :
66
75
claims ["branch_id" ] = branch_id
67
76
return claims
68
77
69
78
70
79
class TestActiveStatePublisher :
71
80
def test_publisher_name (self ):
72
- publisher = ActiveStatePublisher (
73
- organization_id = ORG_ID ,
74
- project_id = PROJECT_ID ,
75
- user_id = USER_ID ,
76
- project_visibility = "public" ,
77
- )
81
+ publisher = ActiveStatePublisher ()
78
82
79
83
assert publisher .publisher_name == "ActiveState"
80
84
81
85
def test_publisher_url (self ):
86
+ org_name = "fakeorg"
87
+ project_name = "fakeproject"
82
88
publisher = ActiveStatePublisher (
83
- organization_id = ORG_ID ,
84
- project_id = PROJECT_ID ,
85
- user_id = USER_ID ,
86
- project_visibility = "public" ,
89
+ organization_url_name = org_name , activestate_project_name = project_name
87
90
)
88
91
89
- assert publisher .publisher_url == "https://platform.activestate.com/oauth/oidc"
92
+ assert (
93
+ publisher .publisher_url ()
94
+ == f"https://platform.activestate.com/{ org_name } /{ project_name } "
95
+ )
90
96
91
- def test_stringifies_as_email (self ):
97
+ def test_stringifies_as_project_url (self ):
98
+ org_name = "fakeorg"
99
+ project_name = "fakeproject"
92
100
publisher = ActiveStatePublisher (
93
- organization_id = ORG_ID ,
94
- project_id = PROJECT_ID ,
95
- user_id = USER_ID ,
96
- project_visibility = "public" ,
101
+ organization_url_name = org_name , activestate_project_name = project_name
97
102
)
98
103
99
104
assert (
100
105
str (publisher )
101
- == f"https://platform.activestate.com/{ publisher . project_path } "
106
+ == f"https://platform.activestate.com/{ org_name } / { project_name } "
102
107
)
103
108
104
109
def test_activestate_publisher_all_known_claims (self ):
@@ -107,7 +112,6 @@ def test_activestate_publisher_all_known_claims(self):
107
112
"organization_id" ,
108
113
"project_id" ,
109
114
"user_id" ,
110
- "project_visibility" ,
111
115
"sub" ,
112
116
# optional verifiable claims
113
117
"branch_id" ,
@@ -118,18 +122,15 @@ def test_activestate_publisher_all_known_claims(self):
118
122
"exp" ,
119
123
"aud" ,
120
124
# unchecked claims
125
+ "project_visibility" ,
121
126
"project_name" ,
122
127
"project_path" ,
123
128
"organization_url_name" ,
124
129
}
125
130
126
131
def test_activestate_publisher_unaccounted_claims (self , monkeypatch ):
127
132
publisher = ActiveStatePublisher (
128
- sub = "fake:fake:fake:fake:fake:fake" ,
129
- organization_id = ORG_ID ,
130
- project_id = PROJECT_ID ,
131
- user_id = USER_ID ,
132
- project_visibility = "public" ,
133
+ sub = SUBJECT ,
133
134
)
134
135
135
136
scope = pretend .stub ()
@@ -143,7 +144,6 @@ def test_activestate_publisher_unaccounted_claims(self, monkeypatch):
143
144
)
144
145
monkeypatch .setattr (_core , "sentry_sdk" , sentry_sdk )
145
146
146
- # We don't care if these actually verify, only that they're present.
147
147
signed_claims = {
148
148
claim_name : "fake" for claim_name in ActiveStatePublisher .all_known_claims ()
149
149
}
@@ -158,13 +158,27 @@ def test_activestate_publisher_unaccounted_claims(self, monkeypatch):
158
158
]
159
159
assert scope .fingerprint == ["another-fake-claim" , "fake-claim" ]
160
160
161
- def test_activestate_publisher_missing_claims (self , monkeypatch ):
161
+ @pytest .mark .parametrize (
162
+ ("claim_to_drop" , "valid" ),
163
+ [
164
+ ("organization_id" , False ),
165
+ ("project_id" , False ),
166
+ ("user_id" , False ),
167
+ ("branch_id" , True ),
168
+ ("organization_url_name" , True ),
169
+ ("project_visibility" , True ),
170
+ ("project_name" , True ),
171
+ ("project_path" , True ),
172
+ ],
173
+ )
174
+ def test_activestate_publisher_missing_claims (
175
+ self , monkeypatch , claim_to_drop : str , valid : bool
176
+ ):
162
177
publisher = ActiveStatePublisher (
163
- sub = "fake:fake:fake:fake:fake:fake" ,
164
- organization_id = "fake" ,
165
- project_id = "fake" ,
166
- user_id = "fake" ,
167
- project_visibility = "fake" ,
178
+ sub = SUBJECT ,
179
+ organization_id = ORG_ID ,
180
+ project_id = PROJECT_ID ,
181
+ user_id = USER_ID ,
168
182
)
169
183
170
184
scope = pretend .stub ()
@@ -178,21 +192,21 @@ def test_activestate_publisher_missing_claims(self, monkeypatch):
178
192
)
179
193
monkeypatch .setattr (_core , "sentry_sdk" , sentry_sdk )
180
194
181
- signed_claims = {
182
- claim_name : "fake" for claim_name in ActiveStatePublisher .all_known_claims ()
183
- }
184
- signed_claims ["sub" ] = "fake:fake:fake:fake:fake:fake"
185
- # Pop the first signed claim, so that it's the first one to fail.
186
- signed_claims .pop ("organization_id" )
187
- assert "organization_id" not in signed_claims
195
+ signed_claims = new_signed_claims ()
196
+ # I don't set branch_id in the claims by default, so no need to remove it
197
+ if claim_to_drop != "branch_id" :
198
+ # Remove a required claim to test that the code detects it's missing
199
+ signed_claims .pop (claim_to_drop )
200
+ assert claim_to_drop not in signed_claims
188
201
assert publisher .__required_verifiable_claims__
189
- assert not publisher .verify_claims (signed_claims = signed_claims )
190
- assert sentry_sdk .capture_message .calls == [
191
- pretend .call (
192
- "JWT for ActiveStatePublisher is missing claim: organization_id"
193
- )
194
- ]
195
- assert scope .fingerprint == ["organization_id" ]
202
+ assert publisher .verify_claims (signed_claims = signed_claims ) is valid
203
+ if not valid :
204
+ assert sentry_sdk .capture_message .calls == [
205
+ pretend .call (
206
+ "JWT for ActiveStatePublisher is missing claim: " + claim_to_drop
207
+ )
208
+ ]
209
+ assert scope .fingerprint == [claim_to_drop ]
196
210
197
211
@pytest .mark .parametrize (
198
212
("expect" , "actual" , "valid" ),
@@ -205,11 +219,10 @@ def test_activestate_publisher_org_id_verified(
205
219
self , expect : str , actual : str , valid : bool
206
220
):
207
221
publisher = ActiveStatePublisher (
208
- sub = "fake:fake:fake:fake" ,
222
+ sub = SUBJECT ,
209
223
organization_id = actual ,
210
224
project_id = PROJECT_ID ,
211
225
user_id = USER_ID ,
212
- project_visibility = "public" ,
213
226
)
214
227
215
228
signed_claims = new_signed_claims (organization_id = expect )
@@ -218,66 +231,68 @@ def test_activestate_publisher_org_id_verified(
218
231
@pytest .mark .parametrize (
219
232
("expect" , "actual" , "valid" ),
220
233
[
221
- (PROJECT_ID , PROJECT_ID , True ),
222
- (PROJECT_ID , ORG_ID , False ),
234
+ (BRANCH_ID , BRANCH_ID , True ),
235
+ (BRANCH_ID , PROJECT_ID , False ),
236
+ # If it's configured in the publisher, it must be present in the claim
237
+ (BRANCH_ID , None , False ),
238
+ # If it's not configured in the publisher, we don't care what it is
239
+ # in the claim
240
+ (None , None , True ),
241
+ (None , PROJECT_ID , True ),
223
242
],
224
243
)
225
- def test_activestate_publisher_project_id_verified (
244
+ def test_activestate_publisher_branch_id_verified (
226
245
self , expect : str , actual : str , valid : bool
227
246
):
228
247
publisher = ActiveStatePublisher (
229
- sub = "fake:fake:fake:fake" ,
248
+ sub = SUBJECT ,
230
249
organization_id = ORG_ID ,
231
- project_id = actual ,
250
+ project_id = PROJECT_ID ,
232
251
user_id = USER_ID ,
233
- project_visibility = "public" ,
252
+ branch_id = expect ,
234
253
)
235
254
236
- signed_claims = new_signed_claims (project_id = expect )
255
+ signed_claims = new_signed_claims (branch_id = actual )
237
256
assert publisher .verify_claims (signed_claims = signed_claims ) is valid
238
257
239
258
@pytest .mark .parametrize (
240
259
("expect" , "actual" , "valid" ),
241
260
[
242
- (USER_ID , USER_ID , True ),
243
- (USER_ID , ORG_ID , False ),
261
+ (PROJECT_ID , PROJECT_ID , True ),
262
+ (PROJECT_ID , ORG_ID , False ),
244
263
],
245
264
)
246
- def test_activestate_publisher_user_id_verified (
265
+ def test_activestate_publisher_project_id_verified (
247
266
self , expect : str , actual : str , valid : bool
248
267
):
249
268
publisher = ActiveStatePublisher (
250
- sub = "fake:fake:fake:fake" ,
269
+ sub = SUBJECT ,
251
270
organization_id = ORG_ID ,
252
- project_id = PROJECT_ID ,
253
- user_id = actual ,
254
- project_visibility = "public" ,
271
+ project_id = actual ,
272
+ user_id = USER_ID ,
255
273
)
256
274
257
- signed_claims = new_signed_claims (user_id = expect )
275
+ signed_claims = new_signed_claims (project_id = expect )
258
276
assert publisher .verify_claims (signed_claims = signed_claims ) is valid
259
277
260
278
@pytest .mark .parametrize (
261
279
("expect" , "actual" , "valid" ),
262
280
[
263
- ("public" , "public" , True ),
264
- ("private" , "private" , True ),
265
- ("public" , "private" , False ),
266
- ("private" , "public" , False ),
281
+ (USER_ID , USER_ID , True ),
282
+ (USER_ID , ORG_ID , False ),
267
283
],
268
284
)
269
- def test_activestate_publisher_project_vis_verified (
285
+ def test_activestate_publisher_user_id_verified (
270
286
self , expect : str , actual : str , valid : bool
271
287
):
272
288
publisher = ActiveStatePublisher (
273
- sub = "fake:fake:fake:fake" ,
289
+ sub = SUBJECT ,
274
290
organization_id = ORG_ID ,
275
291
project_id = PROJECT_ID ,
276
- user_id = USER_ID ,
277
- project_visibility = actual ,
292
+ user_id = actual ,
278
293
)
279
294
280
- signed_claims = new_signed_claims (project_visibility = expect )
295
+ signed_claims = new_signed_claims (user_id = expect )
281
296
assert publisher .verify_claims (signed_claims = signed_claims ) is valid
282
297
283
298
@pytest .mark .parametrize (
@@ -317,7 +332,6 @@ def test_activestate_publisher_project_vis_verified(
317
332
)
318
333
def test_activestate_publisher_sub (self , expected : str , actual : str , valid : bool ):
319
334
check = ActiveStatePublisher .__required_verifiable_claims__ ["sub" ]
320
- # claims: SignedClaims = new_signed_claims(sub=actual)
321
335
assert check (expected , actual , pretend .stub ()) is valid
322
336
323
337
@@ -337,8 +351,6 @@ def test_reify_does_not_exist_yet(self, db_request):
337
351
)
338
352
publisher = pending_publisher .reify (db_request .db )
339
353
340
- # If an OIDC publisher for this pending publisher does not already exist,
341
- # a new one is created and the pending publisher is marked for deletion.
342
354
assert isinstance (publisher , ActiveStatePublisher )
343
355
assert pending_publisher in db_request .db .deleted
344
356
assert publisher .organization_id == pending_publisher .organization_id
@@ -350,12 +362,9 @@ def test_reify_already_exists(self, db_request):
350
362
organization_id = existing_publisher .organization_id ,
351
363
project_id = existing_publisher .project_id ,
352
364
branch_id = existing_publisher .branch_id ,
353
- project_visibility = existing_publisher .project_visibility ,
354
365
sub = existing_publisher .sub ,
355
366
)
356
367
publisher = pending_publisher .reify (db_request .db )
357
368
358
- # If an OIDC publisher for this pending publisher already exists,
359
- # it is returned and the pending publisher is marked for deletion.
360
369
assert existing_publisher == publisher
361
370
assert pending_publisher in db_request .db .deleted
0 commit comments