@@ -16,7 +16,7 @@ defmodule Livebook.ZTA.LivebookTeamsTest do
16
16
% { hub_id: ^ hub_id , org_id: ^ org_id , deployment_group_id: ^ deployment_group_id } }
17
17
18
18
start_supervised! ( { LivebookTeams , name: test , identity_key: team . id } )
19
- { :ok , deployment_group: deployment_group , team: team }
19
+ { :ok , deployment_group: deployment_group , org: org , team: team }
20
20
end
21
21
22
22
describe "authenticate/3" do
@@ -58,6 +58,171 @@ defmodule Livebook.ZTA.LivebookTeamsTest do
58
58
assert { % { halted: false } , ^ metadata } = LivebookTeams . authenticate ( test , conn , [ ] )
59
59
end
60
60
61
+ test "authorizes user to access admin page with full access permission" ,
62
+ % { conn: conn , node: node , deployment_group: deployment_group , org: org , test: test } do
63
+ erpc_call ( node , :toggle_groups_authorization , [ deployment_group ] )
64
+ oidc_provider = erpc_call ( node , :create_oidc_provider , [ org ] )
65
+
66
+ authorization_group =
67
+ erpc_call ( node , :create_authorization_group , [
68
+ % {
69
+ group_name: "developers" ,
70
+ access_type: :app_server ,
71
+ oidc_provider: oidc_provider ,
72
+ deployment_group: deployment_group
73
+ }
74
+ ] )
75
+
76
+ { conn , code , % { groups: [ ] } } = authenticate_user ( conn , node , test )
77
+ session = get_session ( conn )
78
+
79
+ conn =
80
+ build_conn ( :get , ~p" /" )
81
+ |> init_test_session ( session )
82
+
83
+ group = % {
84
+ "oidc_provider_id" => to_string ( oidc_provider . id ) ,
85
+ "group_name" => authorization_group . group_name
86
+ }
87
+
88
+ # Get the user with updated groups
89
+ erpc_call ( node , :update_user_info_groups , [ code , [ group ] ] )
90
+ assert { % { halted: false } , % { groups: [ ^ group ] } } = LivebookTeams . authenticate ( test , conn , [ ] )
91
+ end
92
+
93
+ @ tag :tmp_dir
94
+ test "renders unauthorized user to access app with prefix the user don't have access" ,
95
+ % {
96
+ conn: conn ,
97
+ node: node ,
98
+ deployment_group: deployment_group ,
99
+ org: org ,
100
+ tmp_dir: tmp_dir ,
101
+ team: team ,
102
+ test: test
103
+ } do
104
+ erpc_call ( node , :toggle_groups_authorization , [ deployment_group ] )
105
+ oidc_provider = erpc_call ( node , :create_oidc_provider , [ org ] )
106
+
107
+ authorization_group =
108
+ erpc_call ( node , :create_authorization_group , [
109
+ % {
110
+ group_name: "marketing" ,
111
+ access_type: :apps ,
112
+ prefixes: [ "mkt-" ] ,
113
+ oidc_provider: oidc_provider ,
114
+ deployment_group: deployment_group
115
+ }
116
+ ] )
117
+
118
+ Livebook.Apps . subscribe ( )
119
+ slug = "marketing-app"
120
+
121
+ notebook = % {
122
+ Livebook.Notebook . new ( )
123
+ | app_settings: % { Livebook.Notebook.AppSettings . new ( ) | slug: slug } ,
124
+ file_entries: [ ] ,
125
+ name: slug ,
126
+ hub_id: team . id ,
127
+ deployment_group_id: to_string ( deployment_group . id )
128
+ }
129
+
130
+ files_dir = Livebook.FileSystem.File . local ( tmp_dir )
131
+
132
+ { :ok , % Livebook.Teams.AppDeployment { file: zip_content } = app_deployment } =
133
+ Livebook.Teams.AppDeployment . new ( notebook , files_dir )
134
+
135
+ secret_key = Livebook.Teams . derive_key ( team . teams_key )
136
+ encrypted_content = Livebook.Teams . encrypt ( zip_content , secret_key )
137
+
138
+ Livebook.Teams.Broadcasts . subscribe ( :app_deployments )
139
+
140
+ app_deployment_id =
141
+ erpc_call ( node , :upload_app_deployment , [
142
+ org ,
143
+ deployment_group ,
144
+ app_deployment ,
145
+ encrypted_content ,
146
+ # broadcast?
147
+ true
148
+ ] ) . id
149
+
150
+ app_deployment_id = to_string ( app_deployment_id )
151
+ assert_receive { :app_deployment_started , % { id: ^ app_deployment_id } }
152
+
153
+ Livebook.Apps.Manager . sync_permanent_apps ( )
154
+ Livebook.Apps . subscribe ( )
155
+
156
+ assert_receive { :app_created , % { pid: pid , slug: ^ slug } }
157
+
158
+ assert_receive { :app_updated ,
159
+ % {
160
+ slug: ^ slug ,
161
+ sessions: [ % { app_status: % { execution: :executed , lifecycle: :active } } ]
162
+ } }
163
+
164
+ # Now we need to check if the current user has access to this app
165
+ { conn , code , % { groups: [ ] } } = authenticate_user ( conn , node , test )
166
+ session = get_session ( conn )
167
+
168
+ conn =
169
+ build_conn ( :get , ~p" /apps/#{ slug } " )
170
+ |> init_test_session ( session )
171
+
172
+ group = % {
173
+ "oidc_provider_id" => to_string ( oidc_provider . id ) ,
174
+ "group_name" => authorization_group . group_name
175
+ }
176
+
177
+ # Get the user with updated groups
178
+ erpc_call ( node , :update_user_info_groups , [ code , [ group ] ] )
179
+ assert { % { halted: true } = conn , nil } = LivebookTeams . authenticate ( test , conn , [ ] )
180
+ assert html_response ( conn , 200 ) =~ "You don't have permission to access this app"
181
+
182
+ # Guarantee we don't list the app for this user
183
+ conn = build_conn ( :get , ~p" /" ) |> init_test_session ( session )
184
+ { % { halted: false } , metadata } = LivebookTeams . authenticate ( test , conn , [ ] )
185
+ { :ok , user } = Livebook.Users . update_user ( Livebook.Users.User . new ( metadata . id ) , metadata )
186
+ assert Livebook.Apps . list_authorized_apps ( user ) == [ ]
187
+
188
+ Livebook.App . close ( pid )
189
+ end
190
+
191
+ test "renders unauthorized user to access admin page with slug prefix access permission" ,
192
+ % { conn: conn , node: node , deployment_group: deployment_group , org: org , test: test } do
193
+ erpc_call ( node , :toggle_groups_authorization , [ deployment_group ] )
194
+ oidc_provider = erpc_call ( node , :create_oidc_provider , [ org ] )
195
+
196
+ authorization_group =
197
+ erpc_call ( node , :create_authorization_group , [
198
+ % {
199
+ group_name: "marketing" ,
200
+ access_type: :apps ,
201
+ prefixes: [ "mkt-" ] ,
202
+ oidc_provider: oidc_provider ,
203
+ deployment_group: deployment_group
204
+ }
205
+ ] )
206
+
207
+ { conn , code , % { groups: [ ] } } = authenticate_user ( conn , node , test )
208
+
209
+ group = % {
210
+ "oidc_provider_id" => to_string ( oidc_provider . id ) ,
211
+ "group_name" => authorization_group . group_name
212
+ }
213
+
214
+ erpc_call ( node , :update_user_info_groups , [ code , [ group ] ] )
215
+
216
+ for page <- [ "/settings" , "/learn" , "/hub" , "/apps-dashboard" ] do
217
+ conn =
218
+ build_conn ( :get , page )
219
+ |> init_test_session ( get_session ( conn ) )
220
+
221
+ assert { % { halted: true } = conn , nil } = LivebookTeams . authenticate ( test , conn , [ ] )
222
+ assert html_response ( conn , 200 ) =~ "You don't have permission to access this server"
223
+ end
224
+ end
225
+
61
226
test "redirects to Livebook Teams with invalid access token" ,
62
227
% { conn: conn , test: test } do
63
228
conn = init_test_session ( conn , % { livebook_teams_access_token: "1234567890" } )
@@ -78,13 +243,12 @@ defmodule Livebook.ZTA.LivebookTeamsTest do
78
243
conn = % Plug.Conn { conn | params: params_from_teams }
79
244
80
245
{ conn , nil } = LivebookTeams . authenticate ( test , conn , [ ] )
81
- session = Plug.Conn . get_session ( conn )
82
-
83
246
assert conn . status == 302
84
247
85
248
# Step 2: follow the redirect keeping the session set in previous request
86
- conn = build_conn ( :get , redirected_to ( conn ) )
87
- conn = init_test_session ( conn , session )
249
+ conn =
250
+ build_conn ( :get , redirected_to ( conn ) )
251
+ |> init_test_session ( get_session ( conn ) )
88
252
89
253
{ conn , nil } = LivebookTeams . authenticate ( test , conn , [ ] )
90
254
@@ -95,51 +259,44 @@ defmodule Livebook.ZTA.LivebookTeamsTest do
95
259
96
260
describe "logout/2" do
97
261
test "revoke access token from Livebook Teams" , % { conn: conn , node: node , test: test } do
98
- # Step 1: Get redirected to Livebook Teams
99
- conn = init_test_session ( conn , % { } )
100
- { conn , nil } = LivebookTeams . authenticate ( test , conn , [ ] )
101
-
102
- [ _ , location ] = Regex . run ( ~r/ URL\( "(.*?)"\) / , html_response ( conn , 200 ) )
103
- uri = URI . parse ( location )
104
- assert uri . path == "/identity/authorize"
105
- assert % { "code" => code } = URI . decode_query ( uri . query )
106
-
107
- erpc_call ( node , :allow_auth_request , [ code ] )
108
-
109
- # Step 2: Emulate the redirect back with the code for validation
110
- conn =
111
- build_conn ( :get , "/" , % { teams_identity: "" , code: code } )
112
- |> init_test_session ( Plug.Conn . get_session ( conn ) )
113
-
114
- assert { conn , % { id: _id , name: _ , email: _ , payload: % { } } = metadata } =
115
- LivebookTeams . authenticate ( test , conn , [ ] )
116
-
117
- assert redirected_to ( conn , 302 ) == "/"
118
-
119
- # Step 3: Confirm the token is valid for future requests
120
- conn =
121
- build_conn ( :get , "/" )
122
- |> init_test_session ( Plug.Conn . get_session ( conn ) )
123
-
262
+ { conn , _code , metadata } = authenticate_user ( conn , node , test )
124
263
assert { % { halted: false } , ^ metadata } = LivebookTeams . authenticate ( test , conn , [ ] )
125
264
126
- # Step 4: Revoke the token and the metadata will be invalid for future requests
127
- conn =
128
- build_conn ( :get , "/" )
129
- |> init_test_session ( Plug.Conn . get_session ( conn ) )
130
-
265
+ # Revoke the token and the metadata will be invalid for future requests
131
266
assert % { status: 302 } = conn = LivebookTeams . logout ( test , conn )
132
267
[ url ] = get_resp_header ( conn , "location" )
133
268
assert % { status: 200 } = Req . get! ( url )
134
269
135
- # Step 5: It we try to authenticate again, it should redirect to Teams
270
+ # If we try to authenticate again, it should redirect to Teams
136
271
conn =
137
- build_conn ( :get , "/" )
138
- |> init_test_session ( Plug.Conn . get_session ( conn ) )
272
+ build_conn ( :get , ~p " /" )
273
+ |> init_test_session ( get_session ( conn ) )
139
274
140
275
{ conn , nil } = LivebookTeams . authenticate ( test , conn , [ ] )
141
276
assert conn . halted
142
277
assert html_response ( conn , 200 ) =~ "window.location.href = "
143
278
end
144
279
end
280
+
281
+ defp authenticate_user ( conn , node , test ) do
282
+ conn = init_test_session ( conn , % { } )
283
+ { conn , nil } = LivebookTeams . authenticate ( test , conn , [ ] )
284
+
285
+ [ _ , location ] = Regex . run ( ~r/ URL\( "(.*?)"\) / , html_response ( conn , 200 ) )
286
+ uri = URI . parse ( location )
287
+ % { "code" => code } = URI . decode_query ( uri . query )
288
+
289
+ erpc_call ( node , :allow_auth_request , [ code ] )
290
+
291
+ session = get_session ( conn )
292
+
293
+ conn =
294
+ build_conn ( :get , ~p" /" , % { teams_identity: "" , code: code } )
295
+ |> init_test_session ( session )
296
+
297
+ { conn , % { id: _id } = metadata } = LivebookTeams . authenticate ( test , conn , [ ] )
298
+ session = get_session ( conn )
299
+
300
+ { init_test_session ( build_conn ( ) , session ) , code , metadata }
301
+ end
145
302
end
0 commit comments