1 package integration
2
3 import (
4 "fmt"
5 "testing"
6
7 "github.com/stretchr/testify/assert"
8
9 "edge-infra.dev/pkg/edge/api/graph/model"
10 "edge-infra.dev/pkg/edge/api/services"
11 "edge-infra.dev/pkg/edge/api/sql/plugin"
12 "edge-infra.dev/test/f2"
13 "edge-infra.dev/test/f2/x/postgres"
14 )
15
16
17 var oiSeedData []plugin.Seed = func() []plugin.Seed {
18 type rule struct {
19 CommandName string
20 PrivilegeName string
21 }
22 type command struct {
23 CommandName string
24 }
25 type privilege struct {
26 PrivilegeName string
27 }
28 type roleMapping struct {
29 BslRole string
30 EaPrivilege string
31 }
32
33 return []plugin.Seed{
34 {
35 Name: "seed-ea-default-rules.tmpl",
36 Priority: 5,
37 Data: []rule{
38 {CommandName: "ls", PrivilegeName: "ea-read"},
39 {CommandName: "hostname", PrivilegeName: "ea-read"},
40 {CommandName: "cat", PrivilegeName: "ea-read"},
41 {CommandName: "dmesg", PrivilegeName: "ea-read"},
42 {CommandName: "base64", PrivilegeName: "ea-read"},
43 {CommandName: "echo", PrivilegeName: "ea-read"},
44 {CommandName: "head", PrivilegeName: "ea-read"},
45 {CommandName: "tail", PrivilegeName: "ea-read"},
46 {CommandName: "df", PrivilegeName: "ea-read"},
47 {CommandName: "du", PrivilegeName: "ea-read"},
48 {CommandName: "free", PrivilegeName: "ea-read"},
49 {CommandName: "ps", PrivilegeName: "ea-read"},
50 {CommandName: "pwd", PrivilegeName: "ea-read"},
51 {CommandName: "ping", PrivilegeName: "ea-read"},
52 {CommandName: "date", PrivilegeName: "ea-read"},
53 {CommandName: "stat", PrivilegeName: "ea-read"},
54 {CommandName: "grep", PrivilegeName: "ea-read"},
55 {CommandName: "kubectl", PrivilegeName: "ea-write"},
56 {CommandName: "systemctl", PrivilegeName: "ea-dev"},
57 {CommandName: "journalctl", PrivilegeName: "ea-dev"},
58 {CommandName: "rm", PrivilegeName: "ea-dev"},
59 {CommandName: "mv", PrivilegeName: "ea-dev"},
60 {CommandName: "kill", PrivilegeName: "ea-dev"},
61 {CommandName: "wget", PrivilegeName: "ea-dev"},
62 {CommandName: "curl", PrivilegeName: "ea-dev"},
63 {CommandName: "cp", PrivilegeName: "ea-dev"},
64 {CommandName: "tar", PrivilegeName: "ea-dev"},
65 {CommandName: "timedatectl", PrivilegeName: "ea-dev"},
66 },
67 },
68 {
69 Name: "seed-ea-commands.tmpl",
70 Priority: 4,
71 Data: []command{
72 {CommandName: "ls"},
73 {CommandName: "hostname"},
74 {CommandName: "cat"},
75 {CommandName: "dmesg"},
76 {CommandName: "base64"},
77 {CommandName: "echo"},
78 {CommandName: "head"},
79 {CommandName: "tail"},
80 {CommandName: "df"},
81 {CommandName: "du"},
82 {CommandName: "free"},
83 {CommandName: "ps"},
84 {CommandName: "pwd"},
85 {CommandName: "ping"},
86 {CommandName: "curl"},
87 {CommandName: "kubectl"},
88 {CommandName: "systemctl"},
89 {CommandName: "journalctl"},
90 {CommandName: "cp"},
91 {CommandName: "tar"},
92 {CommandName: "rm"},
93 {CommandName: "mv"},
94 {CommandName: "kill"},
95 {CommandName: "wget"},
96 {CommandName: "date"},
97 {CommandName: "timedatectl"},
98 {CommandName: "stat"},
99 {CommandName: "grep"},
100 },
101 },
102 {
103 Name: "seed-ea-privileges.tmpl",
104 Priority: 4,
105 Data: []privilege{
106 {PrivilegeName: "ea-read"},
107 {PrivilegeName: "ea-write"},
108 {PrivilegeName: "ea-dev"},
109 },
110 },
111 {
112 Name: "seed-ea-oi-role-privileges.tmpl",
113 Priority: 5,
114 Data: []roleMapping{
115 {BslRole: "EDGE_L1", EaPrivilege: "ea-read"},
116 {BslRole: "EDGE_L2", EaPrivilege: "ea-write"},
117 {BslRole: "EDGE_L2", EaPrivilege: "ea-read"},
118 {BslRole: "EDGE_L3", EaPrivilege: "ea-write"},
119 {BslRole: "EDGE_L3", EaPrivilege: "ea-read"},
120 {BslRole: "EDGE_L4", EaPrivilege: "ea-read"},
121 {BslRole: "EDGE_L4", EaPrivilege: "ea-write"},
122 {BslRole: "EDGE_L4", EaPrivilege: "ea-dev"},
123 },
124 },
125 }
126 }()
127
128 func TestOiRoleMappings(t *testing.T) {
129 var oiService services.OperatorInterventionService
130
131 feat := f2.NewFeature("Oi Role Mappings").
132 Setup("Load Data", postgres.WithData(oiSeedData)).
133 Setup("Create service", func(ctx f2.Context, t *testing.T) f2.Context {
134 db := postgres.FromContextT(ctx, t).DB()
135 oiService = services.NewOperatorInterventionService(db)
136
137 return ctx
138 }).
139 Test("Get All Role Mappings", func(ctx f2.Context, t *testing.T) f2.Context {
140 roleMappings, err := oiService.RoleMappings(ctx, nil)
141 assert.NoError(t, err)
142
143 var expectedRoleMappings = []*model.OiRoleMapping{
144 {Role: model.RoleEdgeL1, Privileges: []*model.Privilege{
145 {Name: "ea-read"},
146 }},
147 {Role: model.RoleEdgeL2, Privileges: []*model.Privilege{
148 {Name: "ea-write"},
149 {Name: "ea-read"},
150 }},
151 {Role: model.RoleEdgeL3, Privileges: []*model.Privilege{
152 {Name: "ea-write"},
153 {Name: "ea-read"},
154 }},
155 {Role: model.RoleEdgeL4, Privileges: []*model.Privilege{
156 {Name: "ea-read"},
157 {Name: "ea-write"},
158 {Name: "ea-dev"},
159 }},
160 }
161
162 assert.Equal(t, expectedRoleMappings, roleMappings)
163
164 return ctx
165 }).
166 Test("Get 1 Role Mapping", func(ctx f2.Context, t *testing.T) f2.Context {
167 roleMappings, err := oiService.RoleMappings(ctx, []string{"EDGE_L2"})
168 assert.NoError(t, err)
169
170 var expectedRoleMappings = []*model.OiRoleMapping{
171 {Role: model.RoleEdgeL2, Privileges: []*model.Privilege{
172 {Name: "ea-read"},
173 {Name: "ea-write"},
174 }},
175 }
176
177 assert.Equal(t, expectedRoleMappings, roleMappings)
178
179 return ctx
180 }).
181 Feature()
182
183 f.Test(t, feat)
184 }
185
186 func TestDeleteOperatorInterventionRoleMapping(t *testing.T) {
187 var oiService services.OperatorInterventionService
188
189
190 var invalidEdgeRole = "INVALID_EDGE_ROLE"
191 var invalidPrivilege = "unknownprivilege"
192 var eaRead = "ea-read"
193 var edgeOrgAdmin = "EDGE_L4"
194
195
196 var tests = []struct {
197 oirole string
198 privName string
199 resp *model.DeleteOperatorInterventionResponse
200 }{
201 {
202
203 oirole: edgeOrgAdmin,
204 privName: eaRead,
205 resp: &model.DeleteOperatorInterventionResponse{},
206 },
207 {
208
209 oirole: edgeOrgAdmin,
210 privName: eaRead,
211 resp: &model.DeleteOperatorInterventionResponse{Errors: []*model.OperatorInterventionErrorResponse{
212 {
213 Type: model.OperatorInterventionErrorTypeUnknownRoleMapping,
214 Privilege: &eaRead,
215 Role: &edgeOrgAdmin,
216 },
217 }},
218 },
219 {
220
221
222
223 oirole: "INVALID_EDGE_ROLE",
224 privName: "unknownprivilege",
225 resp: &model.DeleteOperatorInterventionResponse{Errors: []*model.OperatorInterventionErrorResponse{
226 {
227 Type: model.OperatorInterventionErrorTypeUnknownRoleMapping,
228 Privilege: &invalidPrivilege,
229 Role: &invalidEdgeRole,
230 },
231 }},
232 },
233 }
234
235 featureBuilder := f2.NewFeature("DeleteOIRoleMapping").
236 Setup("Load Data", postgres.WithData(oiSeedData)).
237 Setup("Create Service", func(ctx f2.Context, t *testing.T) f2.Context {
238 db := postgres.FromContextT(ctx, t).DB()
239 oiService = services.NewOperatorInterventionService(db)
240 return ctx
241 })
242
243 for idx, tc := range tests {
244 featureBuilder.
245 Test(fmt.Sprintf("Test %d", idx), func(ctx f2.Context, t *testing.T) f2.Context {
246 out, err := oiService.DeleteRoleMapping(ctx, model.DeleteOperatorInterventionMappingInput{
247 Privilege: &model.OperatorInterventionPrivilegeInput{Name: tc.privName},
248 Role: tc.oirole,
249 })
250
251 assert.NoError(t, err)
252
253 assert.Equal(t, tc.resp, out)
254
255 return ctx
256 })
257 }
258
259 f.Test(t, featureBuilder.Feature())
260 }
261
262 func TestAddOiRoleMappings(t *testing.T) {
263 var oiService services.OperatorInterventionService
264
265 roleMappingInput := []*model.UpdateOperatorInterventionRoleMappingInput{
266 {
267 Role: "EDGE_L3",
268 Privileges: []*model.OperatorInterventionPrivilegeInput{
269 {Name: "ea-read"},
270 {Name: "ea-write"},
271 },
272 },
273 {
274 Role: "EDGE_L4",
275 Privileges: []*model.OperatorInterventionPrivilegeInput{
276 {Name: "ea-read"},
277 },
278 },
279 }
280
281 verifyRoles := func(ctx f2.Context, t *testing.T) f2.Context {
282 out, err := oiService.RoleMappings(ctx, nil)
283 assert.NoError(t, err)
284
285 exp := []*model.OiRoleMapping{
286 {Role: model.RoleEdgeL3, Privileges: []*model.Privilege{
287 {Name: "ea-read"},
288 {Name: "ea-write"},
289 }},
290 {Role: model.RoleEdgeL4, Privileges: []*model.Privilege{
291 {Name: "ea-read"},
292 }},
293 }
294 assert.Equal(t, exp, out)
295
296 return ctx
297 }
298
299 feat := f2.NewFeature("Add Oi Role Mappings").
300 Setup("Add Privileges", func(ctx f2.Context, t *testing.T) f2.Context {
301 db := postgres.FromContextT(ctx, t).DB()
302 privs := []any{"ea-read", "ea-write", "ea-dev"}
303 _, err := db.ExecContext(ctx, `INSERT INTO ea_rules_privileges (name) VALUES ($1), ($2), ($3)`, privs...)
304 assert.NoError(t, err)
305
306 return ctx
307 }).
308 Setup("Create Service", func(ctx f2.Context, t *testing.T) f2.Context {
309 db := postgres.FromContextT(ctx, t).DB()
310 oiService = services.NewOperatorInterventionService(db)
311 return ctx
312 }).
313 Test("Add new Role Mappings", func(ctx f2.Context, t *testing.T) f2.Context {
314 roleMappings, err := oiService.UpdateRoleMappings(ctx, roleMappingInput)
315 assert.NoError(t, err)
316
317 assert.Empty(t, roleMappings.Errors)
318 for _, errResp := range roleMappings.Errors {
319
320
321
322 assert.Zero(t, errResp)
323 }
324
325 return ctx
326 }).
327 Test("Verify DB Contents", verifyRoles).
328 Test("Insert Duplicates", func(ctx f2.Context, t *testing.T) f2.Context {
329 roleMappings, err := oiService.UpdateRoleMappings(ctx, roleMappingInput)
330 assert.NoError(t, err)
331
332 assert.Empty(t, roleMappings.Errors)
333 for _, errResp := range roleMappings.Errors {
334
335
336
337 assert.Zero(t, errResp)
338 }
339
340 return ctx
341 }).
342 Test("Verify DB Contents on duplicates", verifyRoles).
343 Test("Insert empty", func(ctx f2.Context, t *testing.T) f2.Context {
344 db := postgres.FromContextT(ctx, t).DB()
345 oiService := services.NewOperatorInterventionService(db)
346
347 roleMappings, err := oiService.UpdateRoleMappings(ctx, []*model.UpdateOperatorInterventionRoleMappingInput{})
348 assert.NoError(t, err)
349
350 assert.Empty(t, roleMappings.Errors)
351 for _, errResp := range roleMappings.Errors {
352
353
354
355 assert.Zero(t, errResp)
356 }
357
358 return ctx
359 }).
360 Test("Verify DB Contents on Empty insert", verifyRoles).
361 Test("Insert invalid values", func(ctx f2.Context, t *testing.T) f2.Context {
362 roleMappings, err := oiService.UpdateRoleMappings(ctx,
363 []*model.UpdateOperatorInterventionRoleMappingInput{
364 {
365 Role: "Invalid_Role",
366 Privileges: []*model.OperatorInterventionPrivilegeInput{{Name: "ea-read"}},
367 },
368 {
369 Role: "EDGE_L4",
370 Privileges: []*model.OperatorInterventionPrivilegeInput{{Name: "invalid_privilege"}},
371 },
372 },
373 )
374 assert.NoError(t, err)
375
376 var invalidRole = "Invalid_Role"
377 var invalidPrivilege = "invalid_privilege"
378
379 expRoleMappings := model.UpdateOperatorInterventionRoleMappingResponse{
380 Errors: []*model.OperatorInterventionErrorResponse{
381 {Type: model.OperatorInterventionErrorTypeUnknownRole, Role: &invalidRole},
382 {Type: model.OperatorInterventionErrorTypeUnknownPrivilege, Privilege: &invalidPrivilege},
383 },
384 }
385
386 assert.Equal(t, expRoleMappings.Errors, roleMappings.Errors)
387
388 return ctx
389 }).
390 Feature()
391
392 f.Test(t, feat)
393 }
394
395 func TestReadOperatorInterventionCommands(t *testing.T) {
396 feat := f2.NewFeature("Read OI Commands").
397 Setup("Load Data", postgres.WithData(oiSeedData)).
398 Test("Read a Command", func(ctx f2.Context, t *testing.T) f2.Context {
399 db := postgres.FromContextT(ctx, t).DB()
400 oiService := services.NewOperatorInterventionService(db)
401
402 payload := []*model.OperatorInterventionCommandInput{{Name: "ls"}}
403 result, err := oiService.ReadCommands(ctx, payload)
404 assert.NoError(t, err)
405
406 assert.Len(t, result, 1)
407 assert.Equal(t, "ls", result[0].Name)
408
409 return ctx
410 }).
411 Test("Read Multiple Commands", func(ctx f2.Context, t *testing.T) f2.Context {
412 db := postgres.FromContextT(ctx, t).DB()
413 oiService := services.NewOperatorInterventionService(db)
414
415 payload := []*model.OperatorInterventionCommandInput{{Name: "ls"}, {Name: "echo"}, {Name: "cat"}}
416 result, err := oiService.ReadCommands(ctx, payload)
417 assert.NoError(t, err)
418
419 assert.Len(t, result, 3)
420 for _, command := range payload {
421 assert.Contains(t, result, &model.Command{Name: command.Name})
422 }
423
424 return ctx
425 }).
426 Test("Read All Commands", func(ctx f2.Context, t *testing.T) f2.Context {
427 db := postgres.FromContextT(ctx, t).DB()
428 oiService := services.NewOperatorInterventionService(db)
429
430 result, err := oiService.ReadCommands(ctx, nil)
431 assert.NoError(t, err)
432
433 assert.Greater(t, len(result), 0)
434
435 return ctx
436 }).
437 Test("No Command Found", func(ctx f2.Context, t *testing.T) f2.Context {
438 db := postgres.FromContextT(ctx, t).DB()
439 oiService := services.NewOperatorInterventionService(db)
440
441 payload := []*model.OperatorInterventionCommandInput{{Name: "nonexistant-command"}}
442 result, err := oiService.ReadCommands(ctx, payload)
443 assert.NoError(t, err)
444
445 assert.Len(t, result, 0)
446
447 return ctx
448 }).
449 Test("Some Commands Found", func(ctx f2.Context, t *testing.T) f2.Context {
450 db := postgres.FromContextT(ctx, t).DB()
451 oiService := services.NewOperatorInterventionService(db)
452
453
454 payload := []*model.OperatorInterventionCommandInput{
455 {Name: "ls"},
456 {Name: "nonexistant-command"},
457 {Name: "echo"},
458 }
459 result, err := oiService.ReadCommands(ctx, payload)
460 assert.NoError(t, err)
461
462 assert.Len(t, result, 2)
463 assert.Contains(t, result, &model.Command{Name: payload[0].Name})
464 assert.Contains(t, result, &model.Command{Name: payload[2].Name})
465 assert.NotContains(t, result, &model.Command{Name: payload[1].Name})
466
467 return ctx
468 }).
469 Feature()
470
471 f.Test(t, feat)
472 }
473
474
475 func TestOperatorInterventionCreateCommands(t *testing.T) {
476 feat := f2.NewFeature("Create OI Commands").
477 Setup("Load Data", postgres.WithData(oiSeedData)).
478 Test("Add One Command", func(ctx f2.Context, t *testing.T) f2.Context {
479 db := postgres.FromContextT(ctx, t).DB()
480 oiService := services.NewOperatorInterventionService(db)
481
482 payload := []*model.OperatorInterventionCommandInput{
483 {Name: "a-command-that-is-not-in-yet"},
484 }
485 response, err := oiService.CreateCommands(ctx, payload)
486 assert.NoError(t, err)
487 assert.Empty(t, response)
488 return ctx
489 }).
490 Test("Add Multiple Commands", func(ctx f2.Context, t *testing.T) f2.Context {
491 db := postgres.FromContextT(ctx, t).DB()
492 oiService := services.NewOperatorInterventionService(db)
493
494 payload := []*model.OperatorInterventionCommandInput{
495 {Name: "a-command-that-is-not-in-yet-1"},
496 {Name: "a-command-that-is-not-in-yet-2"},
497 {Name: "a-command-that-is-not-in-yet-3"},
498 }
499 response, err := oiService.CreateCommands(ctx, payload)
500 assert.NoError(t, err)
501 assert.Empty(t, response)
502 return ctx
503 }).
504 Test("Conflicts", func(ctx f2.Context, t *testing.T) f2.Context {
505 db := postgres.FromContextT(ctx, t).DB()
506 oiService := services.NewOperatorInterventionService(db)
507
508 conflictCommand1 := "ls"
509 conflictCommand2 := "echo"
510 payload := []*model.OperatorInterventionCommandInput{
511 {Name: conflictCommand1},
512 {Name: "a-command-that-is-definitely-not-in-yet"},
513 {Name: conflictCommand2},
514 }
515 response, err := oiService.CreateCommands(ctx, payload)
516 assert.NoError(t, err)
517 assert.Empty(t, response)
518 return ctx
519 }).
520 Feature()
521
522 f.Test(t, feat)
523 }
524
525
526 func TestDeleteOperatorInterventionCommand(t *testing.T) {
527 feat := f2.NewFeature("Create OI Commands").
528 Setup("Load Data", postgres.WithData(oiSeedData)).
529 Setup("Add Command To Be Deleted In Test", func(ctx f2.Context, t *testing.T) f2.Context {
530 db := postgres.FromContextT(ctx, t).DB()
531 oiService := services.NewOperatorInterventionService(db)
532
533 payload := []*model.OperatorInterventionCommandInput{
534 {Name: "a-command-that-is-not-in-yet"},
535 }
536 response, err := oiService.CreateCommands(ctx, payload)
537 assert.NoError(t, err)
538
539 assert.Empty(t, response)
540
541 return ctx
542 }).
543 Test("Delete Command", func(ctx f2.Context, t *testing.T) f2.Context {
544 db := postgres.FromContextT(ctx, t).DB()
545 oiService := services.NewOperatorInterventionService(db)
546
547 payload := model.OperatorInterventionCommandInput{
548 Name: "a-command-that-is-not-in-yet",
549 }
550 response, err := oiService.DeleteCommand(ctx, payload)
551 assert.NoError(t, err)
552
553 assert.Empty(t, response)
554
555 return ctx
556 }).
557 Test("Fail to Delete Non-Existing Command", func(ctx f2.Context, t *testing.T) f2.Context {
558 db := postgres.FromContextT(ctx, t).DB()
559 oiService := services.NewOperatorInterventionService(db)
560
561 command := "a-command-that-was-never-there"
562 payload := model.OperatorInterventionCommandInput{
563 Name: command,
564 }
565 response, err := oiService.DeleteCommand(ctx, payload)
566 assert.NoError(t, err)
567
568 assert.NotEmpty(t, response)
569 assert.Equal(t, command, *response.Errors[0].Command)
570 assert.Equal(t, model.OperatorInterventionErrorTypeUnknownCommand, response.Errors[0].Type)
571
572 return ctx
573 }).
574 Test("Fail to Delete Command with an active rule", func(ctx f2.Context, t *testing.T) f2.Context {
575 db := postgres.FromContextT(ctx, t).DB()
576 oiService := services.NewOperatorInterventionService(db)
577
578 command := "ls"
579 payload := model.OperatorInterventionCommandInput{
580 Name: command,
581 }
582 response, err := oiService.DeleteCommand(ctx, payload)
583 assert.NoError(t, err)
584
585 assert.NotEmpty(t, response)
586 assert.Equal(t, command, *response.Errors[0].Command)
587 assert.Equal(t, model.OperatorInterventionErrorTypeConflict, response.Errors[0].Type)
588
589 return ctx
590 }).
591 Feature()
592
593 f.Test(t, feat)
594 }
595
596
597 func TestDeleteOperatorInterventionPrivilege(t *testing.T) {
598 feat := f2.NewFeature("Delete OI Privileges").
599 Setup("Load Data", postgres.WithData(oiSeedData)).
600 Setup("Add Privilege to be used in delete tests", func(ctx f2.Context, t *testing.T) f2.Context {
601 db := postgres.FromContextT(ctx, t).DB()
602 oiService := services.NewOperatorInterventionService(db)
603 payload := []*model.OperatorInterventionPrivilegeInput{
604 {Name: "test-priv"},
605 }
606 response, err := oiService.CreatePrivileges(ctx, payload)
607 assert.NoError(t, err)
608
609 assert.Empty(t, response)
610 return ctx
611 }).
612 Test("Delete Privilege", func(ctx f2.Context, t *testing.T) f2.Context {
613 db := postgres.FromContextT(ctx, t).DB()
614 oiService := services.NewOperatorInterventionService(db)
615
616 payload := model.OperatorInterventionPrivilegeInput{
617 Name: "test-priv",
618 }
619 response, err := oiService.DeletePrivilege(ctx, payload)
620 assert.NoError(t, err)
621
622 assert.Empty(t, response)
623
624 return ctx
625 }).
626 Test("Fail to Delete Non-Existing Privilege", func(ctx f2.Context, t *testing.T) f2.Context {
627 db := postgres.FromContextT(ctx, t).DB()
628 oiService := services.NewOperatorInterventionService(db)
629
630 privilege := "a-privilege-that-was-never-there"
631 payload := model.OperatorInterventionPrivilegeInput{
632 Name: privilege,
633 }
634 response, err := oiService.DeletePrivilege(ctx, payload)
635 assert.NoError(t, err)
636
637 assert.NotEmpty(t, response)
638 assert.Equal(t, privilege, *response.Errors[0].Privilege)
639 assert.Equal(t, model.OperatorInterventionErrorTypeUnknownPrivilege, response.Errors[0].Type)
640
641 return ctx
642 }).
643 Test("Fail to Delete Privilege with an active rule", func(ctx f2.Context, t *testing.T) f2.Context {
644 db := postgres.FromContextT(ctx, t).DB()
645 oiService := services.NewOperatorInterventionService(db)
646
647 privilege := "ea-read"
648 payload := model.OperatorInterventionPrivilegeInput{
649 Name: privilege,
650 }
651 response, err := oiService.DeletePrivilege(ctx, payload)
652 assert.NoError(t, err)
653
654 assert.NotEmpty(t, response)
655 assert.Equal(t, privilege, *response.Errors[0].Privilege)
656 assert.Equal(t, model.OperatorInterventionErrorTypeConflict, response.Errors[0].Type)
657
658 return ctx
659 }).
660 Feature()
661 f.Test(t, feat)
662 }
663
664 func TestOperatorInterventionReadPrivilege(t *testing.T) {
665 const (
666 privilegeName = "ea-read"
667 )
668 feat := f2.NewFeature("Read Privilege").
669 Setup("Load Data", postgres.WithData(oiSeedData)).
670 Test("Read one privilege", func(ctx f2.Context, t *testing.T) f2.Context {
671 db := postgres.FromContextT(ctx, t).DB()
672 oiService := services.NewOperatorInterventionService(db)
673 privileges, err := oiService.ReadPrivileges(ctx, []*model.OperatorInterventionPrivilegeInput{
674 {Name: privilegeName},
675 })
676 assert.NoError(t, err)
677 assert.Len(t, privileges, 1)
678 assert.Equal(t, privilegeName, privileges[0].Name)
679
680 return ctx
681 }).
682 Test("Read multiple privileges", func(ctx f2.Context, t *testing.T) f2.Context {
683 db := postgres.FromContextT(ctx, t).DB()
684 oiService := services.NewOperatorInterventionService(db)
685
686
687 privileges, err := oiService.ReadPrivileges(ctx, []*model.OperatorInterventionPrivilegeInput{
688 {Name: "ea-read"},
689 {Name: "ea-write"},
690 })
691 assert.NoError(t, err)
692 assert.Len(t, privileges, 2)
693 returnedPrivileges := []string{privileges[0].Name, privileges[1].Name}
694 assert.EqualValues(t, []string{privilegeName, "ea-write"}, returnedPrivileges)
695 return ctx
696 }).
697 Feature()
698 f.Test(t, feat)
699 }
700
701
702 func TestOperatorInterventionCreatePrivileges(t *testing.T) {
703 feat := f2.NewFeature("Create Privileges").
704 Setup("Load Data", postgres.WithData(oiSeedData)).
705 Test("Create single privilege", func(ctx f2.Context, t *testing.T) f2.Context {
706 db := postgres.FromContextT(ctx, t).DB()
707 oiService := services.NewOperatorInterventionService(db)
708
709 payload := []*model.OperatorInterventionPrivilegeInput{
710 {Name: "test-priv"},
711 }
712 response, err := oiService.CreatePrivileges(ctx, payload)
713 assert.NoError(t, err)
714
715 assert.Empty(t, response)
716 return ctx
717 }).
718 Test("Create multiple privileges", func(ctx f2.Context, t *testing.T) f2.Context {
719 db := postgres.FromContextT(ctx, t).DB()
720 oiService := services.NewOperatorInterventionService(db)
721
722 payload := []*model.OperatorInterventionPrivilegeInput{
723 {Name: "test-priv-1"},
724 {Name: "test-priv-2"},
725 {Name: "test-priv-3"},
726 }
727 response, err := oiService.CreatePrivileges(ctx, payload)
728 assert.NoError(t, err)
729 assert.Empty(t, response)
730 return ctx
731 }).
732 Test("Create conflicting privileges", func(ctx f2.Context, t *testing.T) f2.Context {
733 db := postgres.FromContextT(ctx, t).DB()
734 oiService := services.NewOperatorInterventionService(db)
735
736 payload := []*model.OperatorInterventionPrivilegeInput{
737 {Name: "ea-read"},
738 {Name: "ea-write"},
739 }
740 response, err := oiService.CreatePrivileges(ctx, payload)
741 assert.NoError(t, err)
742
743 assert.Empty(t, response)
744
745 return ctx
746 }).
747 Feature()
748 f.Test(t, feat)
749 }
750
751 func TestDeleteOperatorInterventionRules(t *testing.T) {
752 feat := f2.NewFeature("Delete OI Rules").
753 Setup("Load Data", postgres.WithData(oiSeedData)).
754 Test("Delete Rule", func(ctx f2.Context, t *testing.T) f2.Context {
755 db := postgres.FromContextT(ctx, t).DB()
756 oiService := services.NewOperatorInterventionService(db)
757
758 payload := model.DeleteOperatorInterventionRuleInput{
759 Privilege: "ea-read",
760 Command: "ls",
761 }
762 response, err := oiService.DeleteRule(ctx, payload)
763 assert.NoError(t, err)
764
765 assert.Empty(t, response)
766
767 return ctx
768 }).
769 Test("Fail to Delete Rule with non-existing command", func(ctx f2.Context, t *testing.T) f2.Context {
770 db := postgres.FromContextT(ctx, t).DB()
771 oiService := services.NewOperatorInterventionService(db)
772 command := "non-existent-command"
773 payload := model.DeleteOperatorInterventionRuleInput{
774 Command: command,
775 Privilege: "ea-read",
776 }
777 response, err := oiService.DeleteRule(ctx, payload)
778 assert.NoError(t, err)
779
780 assert.NotEmpty(t, response)
781 assert.Equal(t, []*model.OperatorInterventionErrorResponse{
782 {
783 Type: model.OperatorInterventionErrorTypeUnknownCommand,
784 Command: &command,
785 },
786 }, response.Errors)
787
788 return ctx
789 }).
790 Test("Fail to Delete Rule with non-existing privilege", func(ctx f2.Context, t *testing.T) f2.Context {
791 db := postgres.FromContextT(ctx, t).DB()
792 oiService := services.NewOperatorInterventionService(db)
793 privilege := "non-existent-privilege"
794 payload := model.DeleteOperatorInterventionRuleInput{
795 Command: "ls",
796 Privilege: privilege,
797 }
798 response, err := oiService.DeleteRule(ctx, payload)
799 assert.NoError(t, err)
800
801 assert.NotEmpty(t, response)
802 assert.Equal(t, []*model.OperatorInterventionErrorResponse{
803 {
804 Type: model.OperatorInterventionErrorTypeUnknownPrivilege,
805 Privilege: &privilege,
806 },
807 }, response.Errors)
808
809 return ctx
810 }).
811 Test("Fail to Delete Rule with non-existing command and privilege", func(ctx f2.Context, t *testing.T) f2.Context {
812 db := postgres.FromContextT(ctx, t).DB()
813 oiService := services.NewOperatorInterventionService(db)
814 command := "a-non-existent-command"
815 privilege := "a-non-existent-privilege"
816 payload := model.DeleteOperatorInterventionRuleInput{
817 Command: command,
818 Privilege: privilege,
819 }
820 response, err := oiService.DeleteRule(ctx, payload)
821 assert.NoError(t, err)
822
823 assert.NotEmpty(t, response)
824 assert.Equal(t, []*model.OperatorInterventionErrorResponse{
825 {
826 Type: model.OperatorInterventionErrorTypeUnknownCommand,
827 Command: &command,
828 },
829 {
830 Type: model.OperatorInterventionErrorTypeUnknownPrivilege,
831 Privilege: &privilege,
832 },
833 }, response.Errors)
834
835 return ctx
836 }).
837 Test("Fail to delete non-existing rule", func(ctx f2.Context, t *testing.T) f2.Context {
838 db := postgres.FromContextT(ctx, t).DB()
839 oiService := services.NewOperatorInterventionService(db)
840 payload := model.DeleteOperatorInterventionRuleInput{
841 Command: "ls",
842 Privilege: "ea-read",
843 }
844 response, err := oiService.DeleteRule(ctx, payload)
845 assert.NoError(t, err)
846
847 assert.NotEmpty(t, response)
848 assert.Equal(t, []*model.OperatorInterventionErrorResponse{
849 {
850 Type: model.OperatorInterventionErrorTypeUnknownRule,
851 Privilege: func() *string { s := "ea-read"; return &s }(),
852 Command: func() *string { s := "ls"; return &s }(),
853 },
854 }, response.Errors)
855
856 return ctx
857 }).
858 Feature()
859 f.Test(t, feat)
860 }
861
862 func TestUpdateOperatorInterventionRules(t *testing.T) {
863 feat := f2.NewFeature("Create OI Rules").
864 Setup("Add Commands", func(ctx f2.Context, t *testing.T) f2.Context {
865 db := postgres.FromContextT(ctx, t).DB()
866 oiService := services.NewOperatorInterventionService(db)
867 payload := []*model.OperatorInterventionCommandInput{
868 {Name: "testCommand1"},
869 {Name: "testCommand2"},
870 {Name: "testCommand3"},
871 }
872 response, err := oiService.CreateCommands(ctx, payload)
873 assert.NoError(t, err)
874
875 assert.Empty(t, response)
876 return ctx
877 }).
878 Setup("Add Privileges", func(ctx f2.Context, t *testing.T) f2.Context {
879 db := postgres.FromContextT(ctx, t).DB()
880 oiService := services.NewOperatorInterventionService(db)
881 payload := []*model.OperatorInterventionPrivilegeInput{
882 {Name: "testPriv1"},
883 {Name: "testPriv2"},
884 {Name: "testPriv3"},
885 }
886 response, err := oiService.CreatePrivileges(ctx, payload)
887 assert.NoError(t, err)
888
889 assert.Empty(t, response)
890 return ctx
891 }).
892 Test("Create Rule", func(ctx f2.Context, t *testing.T) f2.Context {
893 payload := []*model.UpdateOperatorInterventionRuleInput{{
894
895 Privilege: &model.OperatorInterventionPrivilegeInput{Name: "testPriv1"},
896 Commands: []*model.OperatorInterventionCommandInput{
897 {Name: "testCommand1"},
898 },
899 },
900 }
901 db := postgres.FromContextT(ctx, t).DB()
902 oiService := services.NewOperatorInterventionService(db)
903 response, err := oiService.UpdateRules(ctx, payload)
904 assert.NoError(t, err)
905
906 assert.Empty(t, response)
907
908 assertRulesInDB(ctx, t, []*model.Rule{
909 {
910 Commands: []*model.Command{
911 {Name: "testCommand1"}},
912 Privilege: &model.Privilege{
913 Name: "testPriv1",
914 },
915 },
916 })
917 return ctx
918 }).
919 Test("Conflicting Rule", func(ctx f2.Context, t *testing.T) f2.Context {
920 payload := []*model.UpdateOperatorInterventionRuleInput{
921 {
922 Privilege: &model.OperatorInterventionPrivilegeInput{Name: "testPriv1"},
923 Commands: []*model.OperatorInterventionCommandInput{
924 {Name: "testCommand1"},
925 },
926 },
927 }
928 db := postgres.FromContextT(ctx, t).DB()
929 oiService := services.NewOperatorInterventionService(db)
930 response, err := oiService.UpdateRules(ctx, payload)
931 assert.NoError(t, err)
932
933 assert.Empty(t, response)
934 assertRulesInDB(ctx, t, []*model.Rule{
935 {
936 Commands: []*model.Command{
937 {Name: "testCommand1"}},
938 Privilege: &model.Privilege{
939 Name: "testPriv1",
940 },
941 },
942 })
943 return ctx
944 }).
945 Test("Create Rule with multiple commands", func(ctx f2.Context, t *testing.T) f2.Context {
946 payload := []*model.UpdateOperatorInterventionRuleInput{
947 {
948
949
950
951
952
953 Privilege: &model.OperatorInterventionPrivilegeInput{Name: "testPriv1"},
954 Commands: []*model.OperatorInterventionCommandInput{
955 {Name: "testCommand2"},
956 {Name: "testCommand3"},
957 },
958 },
959 }
960 db := postgres.FromContextT(ctx, t).DB()
961 oiService := services.NewOperatorInterventionService(db)
962 response, err := oiService.UpdateRules(ctx, payload)
963 assert.NoError(t, err)
964
965 assert.Empty(t, response)
966 assertRulesInDB(ctx, t, []*model.Rule{
967 {
968 Commands: []*model.Command{
969 {Name: "testCommand1"},
970 {Name: "testCommand2"},
971 {Name: "testCommand3"},
972 },
973 Privilege: &model.Privilege{
974 Name: "testPriv1",
975 },
976 },
977 })
978 return ctx
979 }).
980 Test("Create Rule with multiple privileges", func(ctx f2.Context, t *testing.T) f2.Context {
981 payload := []*model.UpdateOperatorInterventionRuleInput{
982 {
983 Privilege: &model.OperatorInterventionPrivilegeInput{Name: "testPriv2"},
984 Commands: []*model.OperatorInterventionCommandInput{
985 {Name: "testCommand1"},
986 },
987 },
988 {
989 Privilege: &model.OperatorInterventionPrivilegeInput{Name: "testPriv3"},
990 Commands: []*model.OperatorInterventionCommandInput{
991 {Name: "testCommand1"},
992 },
993 },
994 }
995 db := postgres.FromContextT(ctx, t).DB()
996 oiService := services.NewOperatorInterventionService(db)
997 response, err := oiService.UpdateRules(ctx, payload)
998 assert.NoError(t, err)
999
1000 assert.Empty(t, response)
1001 assertRulesInDB(ctx, t, []*model.Rule{
1002 {
1003 Commands: []*model.Command{
1004 {Name: "testCommand1"},
1005 {Name: "testCommand2"},
1006 {Name: "testCommand3"},
1007 },
1008 Privilege: &model.Privilege{
1009 Name: "testPriv1",
1010 },
1011 },
1012 {
1013 Commands: []*model.Command{
1014 {Name: "testCommand1"},
1015 },
1016 Privilege: &model.Privilege{
1017 Name: "testPriv2",
1018 },
1019 },
1020 {
1021 Commands: []*model.Command{
1022 {Name: "testCommand1"},
1023 },
1024 Privilege: &model.Privilege{
1025 Name: "testPriv3",
1026 },
1027 },
1028 })
1029 return ctx
1030 }).
1031 Test("Fail to create rule with non-existing command", func(ctx f2.Context, t *testing.T) f2.Context {
1032 payload := []*model.UpdateOperatorInterventionRuleInput{
1033 {
1034 Privilege: &model.OperatorInterventionPrivilegeInput{Name: "testPriv1"},
1035 Commands: []*model.OperatorInterventionCommandInput{
1036 {Name: "non-existent-command"},
1037 },
1038 },
1039 }
1040 db := postgres.FromContextT(ctx, t).DB()
1041 oiService := services.NewOperatorInterventionService(db)
1042 response, err := oiService.UpdateRules(ctx, payload)
1043 assert.NoError(t, err)
1044
1045 assert.NotEmpty(t, response)
1046 assert.Equal(t, []*model.OperatorInterventionErrorResponse{
1047 {
1048 Type: model.OperatorInterventionErrorTypeUnknownCommand,
1049 Command: func() *string { s := "non-existent-command"; return &s }(),
1050 },
1051 }, response.Errors)
1052 return ctx
1053 }).
1054 Test("Fail to create rule with non-existing privilege", func(ctx f2.Context, t *testing.T) f2.Context {
1055 payload := []*model.UpdateOperatorInterventionRuleInput{
1056 {
1057 Privilege: &model.OperatorInterventionPrivilegeInput{Name: "non-existent-privilege"},
1058 Commands: []*model.OperatorInterventionCommandInput{
1059 {Name: "testCommand1"},
1060 },
1061 },
1062 }
1063 db := postgres.FromContextT(ctx, t).DB()
1064 oiService := services.NewOperatorInterventionService(db)
1065 response, err := oiService.UpdateRules(ctx, payload)
1066 assert.NoError(t, err)
1067
1068 assert.NotEmpty(t, response)
1069 assert.Equal(t, []*model.OperatorInterventionErrorResponse{
1070 {
1071 Type: model.OperatorInterventionErrorTypeUnknownPrivilege,
1072 Privilege: func() *string { s := "non-existent-privilege"; return &s }(),
1073 },
1074 }, response.Errors)
1075 return ctx
1076 }).
1077 Test("Create rule despite conflicting rule", func(ctx f2.Context, t *testing.T) f2.Context {
1078 payload := []*model.UpdateOperatorInterventionRuleInput{
1079
1080
1081 {
1082 Privilege: &model.OperatorInterventionPrivilegeInput{Name: "testPriv1"},
1083 Commands: []*model.OperatorInterventionCommandInput{
1084 {Name: "testCommand1"},
1085 },
1086 },
1087 {
1088 Privilege: &model.OperatorInterventionPrivilegeInput{Name: "testPriv2"},
1089 Commands: []*model.OperatorInterventionCommandInput{
1090 {Name: "testCommand2"},
1091 },
1092 },
1093 }
1094 db := postgres.FromContextT(ctx, t).DB()
1095 oiService := services.NewOperatorInterventionService(db)
1096 response, err := oiService.UpdateRules(ctx, payload)
1097 assert.NoError(t, err)
1098
1099 assert.Empty(t, response)
1100 assertRulesInDB(ctx, t, []*model.Rule{
1101 {
1102 Commands: []*model.Command{
1103 {Name: "testCommand1"},
1104 {Name: "testCommand2"},
1105 {Name: "testCommand3"},
1106 },
1107 Privilege: &model.Privilege{
1108 Name: "testPriv1",
1109 },
1110 },
1111 {
1112 Commands: []*model.Command{
1113 {Name: "testCommand1"},
1114 {Name: "testCommand2"},
1115 },
1116 Privilege: &model.Privilege{
1117 Name: "testPriv2",
1118 },
1119 },
1120 {
1121 Commands: []*model.Command{
1122 {Name: "testCommand1"},
1123 },
1124 Privilege: &model.Privilege{
1125 Name: "testPriv3",
1126 },
1127 },
1128 })
1129 return ctx
1130 }).
1131 Feature()
1132 f.Test(t, feat)
1133 }
1134
1135 func assertRulesInDB(ctx f2.Context, t *testing.T, expectedRules []*model.Rule) {
1136 db := postgres.FromContextT(ctx, t).DB()
1137 oiService := services.NewOperatorInterventionService(db)
1138
1139 rules, err := oiService.ReadRules(ctx, nil)
1140 assert.NoError(t, err)
1141 assert.ElementsMatch(t, expectedRules, rules)
1142 }
1143
1144 func TestReadOperatorInterventionRules(t *testing.T) {
1145 feat := f2.NewFeature("Read OI Rules").
1146 Setup("Load Data", postgres.WithData(oiSeedData)).
1147 Test("Read all rules", func(ctx f2.Context, t *testing.T) f2.Context {
1148 db := postgres.FromContextT(ctx, t).DB()
1149 oiService := services.NewOperatorInterventionService(db)
1150 rules, err := oiService.ReadRules(ctx, nil)
1151 assert.NoError(t, err)
1152 assert.Greater(t, len(rules), 0)
1153 return ctx
1154 }).
1155 Test("Read one rule", func(ctx f2.Context, t *testing.T) f2.Context {
1156 db := postgres.FromContextT(ctx, t).DB()
1157 oiService := services.NewOperatorInterventionService(db)
1158 rules, err := oiService.ReadRules(ctx, []*model.OperatorInterventionPrivilegeInput{
1159 {Name: "ea-read"},
1160 })
1161 assert.NoError(t, err)
1162 assert.Len(t, rules, 1)
1163 assert.Equal(t, "ea-read", rules[0].Privilege.Name)
1164 return ctx
1165 }).
1166 Test("Read multiple rules", func(ctx f2.Context, t *testing.T) f2.Context {
1167 db := postgres.FromContextT(ctx, t).DB()
1168 oiService := services.NewOperatorInterventionService(db)
1169 rules, err := oiService.ReadRules(ctx, []*model.OperatorInterventionPrivilegeInput{
1170 {Name: "ea-read"},
1171 {Name: "ea-write"},
1172 })
1173 assert.NoError(t, err)
1174 assert.Len(t, rules, 2)
1175 return ctx
1176 }).
1177 Feature()
1178 f.Test(t, feat)
1179 }
1180
View as plain text