2929PROJECT_ID = "00000000-0000-1000-8000-000000000001"
3030USER_ID = "00000000-0000-1000-8000-000000000002"
3131BRANCH_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"
3239
3340
3441def test_lookup_strategies ():
@@ -40,65 +47,63 @@ def test_lookup_strategies():
4047
4148
4249def new_signed_claims (
43- sub : str = "fake:fake:fake:fake" ,
50+ sub : str = SUBJECT ,
4451 organization_id : str = ORG_ID ,
4552 org_url_name : str = "fakeorg" ,
4653 project_id : str = PROJECT_ID ,
4754 project_name : str = "fakeproject" ,
4855 project_path : str = "fakeorg/fakeproject" ,
49- user_id : str = "00000000-0000-1000-8000-000000000002" ,
56+ user_id : str = USER_ID ,
5057 project_visibility : str = "public" ,
5158 branch_id : str | None = None ,
5259) -> SignedClaims :
5360 project_name = "fakeproject"
5461 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+ )
6574 if branch_id :
6675 claims ["branch_id" ] = branch_id
6776 return claims
6877
6978
7079class TestActiveStatePublisher :
7180 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 ()
7882
7983 assert publisher .publisher_name == "ActiveState"
8084
8185 def test_publisher_url (self ):
86+ org_name = "fakeorg"
87+ project_name = "fakeproject"
8288 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
8790 )
8891
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+ )
9096
91- def test_stringifies_as_email (self ):
97+ def test_stringifies_as_project_url (self ):
98+ org_name = "fakeorg"
99+ project_name = "fakeproject"
92100 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
97102 )
98103
99104 assert (
100105 str (publisher )
101- == f"https://platform.activestate.com/{ publisher . project_path } "
106+ == f"https://platform.activestate.com/{ org_name } / { project_name } "
102107 )
103108
104109 def test_activestate_publisher_all_known_claims (self ):
@@ -107,7 +112,6 @@ def test_activestate_publisher_all_known_claims(self):
107112 "organization_id" ,
108113 "project_id" ,
109114 "user_id" ,
110- "project_visibility" ,
111115 "sub" ,
112116 # optional verifiable claims
113117 "branch_id" ,
@@ -118,18 +122,15 @@ def test_activestate_publisher_all_known_claims(self):
118122 "exp" ,
119123 "aud" ,
120124 # unchecked claims
125+ "project_visibility" ,
121126 "project_name" ,
122127 "project_path" ,
123128 "organization_url_name" ,
124129 }
125130
126131 def test_activestate_publisher_unaccounted_claims (self , monkeypatch ):
127132 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 ,
133134 )
134135
135136 scope = pretend .stub ()
@@ -143,7 +144,6 @@ def test_activestate_publisher_unaccounted_claims(self, monkeypatch):
143144 )
144145 monkeypatch .setattr (_core , "sentry_sdk" , sentry_sdk )
145146
146- # We don't care if these actually verify, only that they're present.
147147 signed_claims = {
148148 claim_name : "fake" for claim_name in ActiveStatePublisher .all_known_claims ()
149149 }
@@ -158,13 +158,27 @@ def test_activestate_publisher_unaccounted_claims(self, monkeypatch):
158158 ]
159159 assert scope .fingerprint == ["another-fake-claim" , "fake-claim" ]
160160
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+ ):
162177 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 ,
168182 )
169183
170184 scope = pretend .stub ()
@@ -178,21 +192,21 @@ def test_activestate_publisher_missing_claims(self, monkeypatch):
178192 )
179193 monkeypatch .setattr (_core , "sentry_sdk" , sentry_sdk )
180194
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
188201 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 ]
196210
197211 @pytest .mark .parametrize (
198212 ("expect" , "actual" , "valid" ),
@@ -205,11 +219,10 @@ def test_activestate_publisher_org_id_verified(
205219 self , expect : str , actual : str , valid : bool
206220 ):
207221 publisher = ActiveStatePublisher (
208- sub = "fake:fake:fake:fake" ,
222+ sub = SUBJECT ,
209223 organization_id = actual ,
210224 project_id = PROJECT_ID ,
211225 user_id = USER_ID ,
212- project_visibility = "public" ,
213226 )
214227
215228 signed_claims = new_signed_claims (organization_id = expect )
@@ -218,66 +231,68 @@ def test_activestate_publisher_org_id_verified(
218231 @pytest .mark .parametrize (
219232 ("expect" , "actual" , "valid" ),
220233 [
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 ),
223242 ],
224243 )
225- def test_activestate_publisher_project_id_verified (
244+ def test_activestate_publisher_branch_id_verified (
226245 self , expect : str , actual : str , valid : bool
227246 ):
228247 publisher = ActiveStatePublisher (
229- sub = "fake:fake:fake:fake" ,
248+ sub = SUBJECT ,
230249 organization_id = ORG_ID ,
231- project_id = actual ,
250+ project_id = PROJECT_ID ,
232251 user_id = USER_ID ,
233- project_visibility = "public" ,
252+ branch_id = expect ,
234253 )
235254
236- signed_claims = new_signed_claims (project_id = expect )
255+ signed_claims = new_signed_claims (branch_id = actual )
237256 assert publisher .verify_claims (signed_claims = signed_claims ) is valid
238257
239258 @pytest .mark .parametrize (
240259 ("expect" , "actual" , "valid" ),
241260 [
242- (USER_ID , USER_ID , True ),
243- (USER_ID , ORG_ID , False ),
261+ (PROJECT_ID , PROJECT_ID , True ),
262+ (PROJECT_ID , ORG_ID , False ),
244263 ],
245264 )
246- def test_activestate_publisher_user_id_verified (
265+ def test_activestate_publisher_project_id_verified (
247266 self , expect : str , actual : str , valid : bool
248267 ):
249268 publisher = ActiveStatePublisher (
250- sub = "fake:fake:fake:fake" ,
269+ sub = SUBJECT ,
251270 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 ,
255273 )
256274
257- signed_claims = new_signed_claims (user_id = expect )
275+ signed_claims = new_signed_claims (project_id = expect )
258276 assert publisher .verify_claims (signed_claims = signed_claims ) is valid
259277
260278 @pytest .mark .parametrize (
261279 ("expect" , "actual" , "valid" ),
262280 [
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 ),
267283 ],
268284 )
269- def test_activestate_publisher_project_vis_verified (
285+ def test_activestate_publisher_user_id_verified (
270286 self , expect : str , actual : str , valid : bool
271287 ):
272288 publisher = ActiveStatePublisher (
273- sub = "fake:fake:fake:fake" ,
289+ sub = SUBJECT ,
274290 organization_id = ORG_ID ,
275291 project_id = PROJECT_ID ,
276- user_id = USER_ID ,
277- project_visibility = actual ,
292+ user_id = actual ,
278293 )
279294
280- signed_claims = new_signed_claims (project_visibility = expect )
295+ signed_claims = new_signed_claims (user_id = expect )
281296 assert publisher .verify_claims (signed_claims = signed_claims ) is valid
282297
283298 @pytest .mark .parametrize (
@@ -317,7 +332,6 @@ def test_activestate_publisher_project_vis_verified(
317332 )
318333 def test_activestate_publisher_sub (self , expected : str , actual : str , valid : bool ):
319334 check = ActiveStatePublisher .__required_verifiable_claims__ ["sub" ]
320- # claims: SignedClaims = new_signed_claims(sub=actual)
321335 assert check (expected , actual , pretend .stub ()) is valid
322336
323337
@@ -337,8 +351,6 @@ def test_reify_does_not_exist_yet(self, db_request):
337351 )
338352 publisher = pending_publisher .reify (db_request .db )
339353
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.
342354 assert isinstance (publisher , ActiveStatePublisher )
343355 assert pending_publisher in db_request .db .deleted
344356 assert publisher .organization_id == pending_publisher .organization_id
@@ -350,12 +362,9 @@ def test_reify_already_exists(self, db_request):
350362 organization_id = existing_publisher .organization_id ,
351363 project_id = existing_publisher .project_id ,
352364 branch_id = existing_publisher .branch_id ,
353- project_visibility = existing_publisher .project_visibility ,
354365 sub = existing_publisher .sub ,
355366 )
356367 publisher = pending_publisher .reify (db_request .db )
357368
358- # If an OIDC publisher for this pending publisher already exists,
359- # it is returned and the pending publisher is marked for deletion.
360369 assert existing_publisher == publisher
361370 assert pending_publisher in db_request .db .deleted
0 commit comments