1
2
3
4 package securitypolicy
5
6 import (
7 "context"
8 _ "embed"
9 "encoding/json"
10 "fmt"
11 "math/rand"
12 "sort"
13 "strconv"
14 "strings"
15 "syscall"
16 "testing"
17 "testing/quick"
18
19 "github.com/Microsoft/hcsshim/internal/guestpath"
20 rpi "github.com/Microsoft/hcsshim/internal/regopolicyinterpreter"
21 "github.com/blang/semver/v4"
22 "github.com/open-policy-agent/opa/rego"
23 oci "github.com/opencontainers/runtime-spec/specs-go"
24 "github.com/pkg/errors"
25 )
26
27 const (
28
29 maxDiffLength = 64
30 maxExternalProcessesInGeneratedConstraints = 16
31 maxFragmentsInGeneratedConstraints = 4
32 maxGeneratedExternalProcesses = 12
33 maxGeneratedSandboxIDLength = 32
34 maxGeneratedEnforcementPointLength = 64
35 maxGeneratedPlan9Mounts = 8
36 maxGeneratedFragmentFeedLength = 256
37 maxGeneratedFragmentIssuerLength = 16
38 maxPlan9MountTargetLength = 64
39 maxPlan9MountIndex = 16
40 )
41
42 func Test_RegoTemplates(t *testing.T) {
43 query := rego.New(
44 rego.Query("data.api"),
45 rego.Module("api.rego", APICode))
46
47 ctx := context.Background()
48 resultSet, err := query.Eval(ctx)
49 if err != nil {
50 t.Fatalf("unable to query API enforcement points: %s", err)
51 }
52
53 apiRules := resultSet[0].Expressions[0].Value.(map[string]interface{})
54 enforcementPoints := apiRules["enforcement_points"].(map[string]interface{})
55
56 policyCode := strings.Replace(policyRegoTemplate, "@@OBJECTS@@", "", 1)
57 policyCode = strings.Replace(policyCode, "@@API_VERSION@@", apiVersion, 1)
58 policyCode = strings.Replace(policyCode, "@@FRAMEWORK_VERSION@@", frameworkVersion, 1)
59
60 err = verifyPolicyRules(apiVersion, enforcementPoints, policyCode)
61 if err != nil {
62 t.Errorf("Policy Rego Template is invalid: %s", err)
63 }
64
65 err = verifyPolicyRules(apiVersion, enforcementPoints, openDoorRego)
66 if err != nil {
67 t.Errorf("Open Door Rego Template is invalid: %s", err)
68 }
69 }
70
71 func Test_MarshalRego_Policy(t *testing.T) {
72 f := func(p *generatedConstraints) bool {
73 p.externalProcesses = generateExternalProcesses(testRand)
74 for _, process := range p.externalProcesses {
75
76
77 process.envRules = []EnvRuleConfig{{
78 Strategy: "string",
79 Rule: "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
80 Required: true,
81 }}
82 }
83
84 p.fragments = generateFragments(testRand, 1)
85
86 securityPolicy := p.toPolicy()
87 defaultMounts := toOCIMounts(generateMounts(testRand))
88 privilegedMounts := toOCIMounts(generateMounts(testRand))
89
90 expected := securityPolicy.marshalRego()
91
92 containers := make([]*Container, len(p.containers))
93 for i, container := range p.containers {
94 containers[i] = container.toContainer()
95 }
96
97 externalProcesses := make([]ExternalProcessConfig, len(p.externalProcesses))
98 for i, process := range p.externalProcesses {
99 externalProcesses[i] = process.toConfig()
100 }
101
102 fragments := make([]FragmentConfig, len(p.fragments))
103 for i, fragment := range p.fragments {
104 fragments[i] = fragment.toConfig()
105 }
106
107 actual, err := MarshalPolicy(
108 "rego",
109 false,
110 containers,
111 externalProcesses,
112 fragments,
113 p.allowGetProperties,
114 p.allowDumpStacks,
115 p.allowRuntimeLogging,
116 p.allowEnvironmentVariableDropping,
117 p.allowUnencryptedScratch,
118 p.allowCapabilityDropping,
119 )
120 if err != nil {
121 t.Error(err)
122 return false
123 }
124
125 if actual != expected {
126 start := -1
127 end := -1
128 for i := 0; i < len(actual) && i < len(expected); i++ {
129 if actual[i] != expected[i] {
130 if start == -1 {
131 start = i
132 } else if i-start >= maxDiffLength {
133 end = i
134 break
135 }
136 } else if start != -1 {
137 end = i
138 break
139 }
140 }
141 start = start - 512
142 if start < 0 {
143 start = 0
144 }
145 t.Errorf(`MarshalPolicy does not create the expected Rego policy [%d-%d]: "%s" != "%s"`, start, end, actual[start:end], expected[start:end])
146 return false
147 }
148
149 _, err = newRegoPolicy(expected, defaultMounts, privilegedMounts)
150 if err != nil {
151 t.Errorf("unable to convert policy to rego: %v", err)
152 return false
153 }
154
155 return true
156 }
157
158 if err := quick.Check(f, &quick.Config{MaxCount: 4, Rand: testRand}); err != nil {
159 t.Errorf("Test_MarshalRego_Policy failed: %v", err)
160 }
161 }
162
163 func Test_MarshalRego_Fragment(t *testing.T) {
164 f := func(p *generatedConstraints) bool {
165 p.externalProcesses = generateExternalProcesses(testRand)
166 for _, process := range p.externalProcesses {
167
168
169 process.envRules = []EnvRuleConfig{{
170 Strategy: "string",
171 Rule: "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
172 Required: true,
173 }}
174 }
175
176 p.fragments = generateFragments(testRand, 1)
177
178 fragment := p.toFragment()
179 expected := fragment.marshalRego()
180
181 containers := make([]*Container, len(p.containers))
182 for i, container := range p.containers {
183 containers[i] = container.toContainer()
184 }
185
186 externalProcesses := make([]ExternalProcessConfig, len(p.externalProcesses))
187 for i, process := range p.externalProcesses {
188 externalProcesses[i] = process.toConfig()
189 }
190
191 fragments := make([]FragmentConfig, len(p.fragments))
192 for i, fragment := range p.fragments {
193 fragments[i] = fragment.toConfig()
194 }
195
196 actual, err := MarshalFragment(p.namespace, p.svn, containers, externalProcesses, fragments)
197 if err != nil {
198 t.Error(err)
199 return false
200 }
201
202 if actual != expected {
203 start := -1
204 end := -1
205 for i := 0; i < len(actual) && i < len(expected); i++ {
206 if actual[i] != expected[i] {
207 if start == -1 {
208 start = i
209 } else if i-start >= maxDiffLength {
210 end = i
211 break
212 }
213 } else if start != -1 {
214 end = i
215 break
216 }
217 }
218 t.Errorf("MarshalFragment does not create the expected Rego fragment [%d-%d]: %s != %s", start, end, actual[start:end], expected[start:end])
219 return false
220 }
221
222 return true
223 }
224
225 if err := quick.Check(f, &quick.Config{MaxCount: 4, Rand: testRand}); err != nil {
226 t.Errorf("Test_MarshalRego_Fragment failed: %v", err)
227 }
228 }
229
230
231
232 func Test_Rego_EnforceDeviceMountPolicy_No_Matches(t *testing.T) {
233 f := func(p *generatedConstraints) bool {
234 securityPolicy := p.toPolicy()
235 policy, err := newRegoPolicy(securityPolicy.marshalRego(), []oci.Mount{}, []oci.Mount{})
236 if err != nil {
237 t.Errorf("unable to convert policy to rego: %v", err)
238 return false
239 }
240
241 target := testDataGenerator.uniqueMountTarget()
242 rootHash := generateInvalidRootHash(testRand)
243
244 err = policy.EnforceDeviceMountPolicy(p.ctx, target, rootHash)
245
246
247 return assertDecisionJSONContains(t, err, rootHash, "deviceHash not found")
248 }
249
250 if err := quick.Check(f, &quick.Config{MaxCount: 50, Rand: testRand}); err != nil {
251 t.Errorf("Test_Rego_EnforceDeviceMountPolicy_No_Matches failed: %v", err)
252 }
253 }
254
255
256
257 func Test_Rego_EnforceDeviceMountPolicy_Matches(t *testing.T) {
258 f := func(p *generatedConstraints) bool {
259 securityPolicy := p.toPolicy()
260 policy, err := newRegoPolicy(securityPolicy.marshalRego(), []oci.Mount{}, []oci.Mount{})
261 if err != nil {
262 t.Errorf("unable to convert policy to rego: %v", err)
263 return false
264 }
265
266 target := testDataGenerator.uniqueMountTarget()
267 rootHash := selectRootHashFromConstraints(p, testRand)
268
269 err = policy.EnforceDeviceMountPolicy(p.ctx, target, rootHash)
270
271
272 return err == nil
273 }
274
275 if err := quick.Check(f, &quick.Config{MaxCount: 50, Rand: testRand}); err != nil {
276 t.Errorf("Test_Rego_EnforceDeviceMountPolicy_Matches failed: %v", err)
277 }
278 }
279
280 func Test_Rego_EnforceDeviceUmountPolicy_Removes_Device_Entries(t *testing.T) {
281 f := func(p *generatedConstraints) bool {
282 securityPolicy := p.toPolicy()
283 policy, err := newRegoPolicy(securityPolicy.marshalRego(), []oci.Mount{}, []oci.Mount{})
284 if err != nil {
285 t.Error(err)
286 return false
287 }
288
289 target := testDataGenerator.uniqueMountTarget()
290 rootHash := selectRootHashFromConstraints(p, testRand)
291
292 err = policy.EnforceDeviceMountPolicy(p.ctx, target, rootHash)
293 if err != nil {
294 t.Errorf("unable to mount device: %v", err)
295 return false
296 }
297
298 err = policy.EnforceDeviceUnmountPolicy(p.ctx, target)
299 if err != nil {
300 t.Errorf("unable to unmount device: %v", err)
301 return false
302 }
303
304 err = policy.EnforceDeviceMountPolicy(p.ctx, target, rootHash)
305 if err != nil {
306 t.Errorf("unable to remount device: %v", err)
307 return false
308 }
309
310 return true
311 }
312
313 if err := quick.Check(f, &quick.Config{MaxCount: 50, Rand: testRand}); err != nil {
314 t.Errorf("Test_Rego_EnforceDeviceUmountPolicy_Removes_Device_Entries failed: %v", err)
315 }
316 }
317
318 func Test_Rego_EnforceDeviceMountPolicy_Duplicate_Device_Target(t *testing.T) {
319 f := func(p *generatedConstraints) bool {
320 securityPolicy := p.toPolicy()
321 policy, err := newRegoPolicy(securityPolicy.marshalRego(), []oci.Mount{}, []oci.Mount{})
322 if err != nil {
323 t.Errorf("unable to convert policy to rego: %v", err)
324 return false
325 }
326
327 target := testDataGenerator.uniqueMountTarget()
328 rootHash := selectRootHashFromConstraints(p, testRand)
329 err = policy.EnforceDeviceMountPolicy(p.ctx, target, rootHash)
330 if err != nil {
331 t.Error("Valid device mount failed. It shouldn't have.")
332 return false
333 }
334
335 rootHash = selectRootHashFromConstraints(p, testRand)
336 err = policy.EnforceDeviceMountPolicy(p.ctx, target, rootHash)
337 if err == nil {
338 t.Error("Duplicate device mount target was allowed. It shouldn't have been.")
339 return false
340 }
341
342 return assertDecisionJSONContains(t, err, "device already mounted at path")
343 }
344
345 if err := quick.Check(f, &quick.Config{MaxCount: 50, Rand: testRand}); err != nil {
346 t.Errorf("Test_Rego_EnforceDeviceMountPolicy_Duplicate_Device_Target failed: %v", err)
347 }
348 }
349
350
351
352 func Test_Rego_EnforceOverlayMountPolicy_No_Matches(t *testing.T) {
353 f := func(p *generatedConstraints) bool {
354 tc, err := setupRegoOverlayTest(p, false)
355 if err != nil {
356 t.Error(err)
357 return false
358 }
359
360 err = tc.policy.EnforceOverlayMountPolicy(p.ctx, tc.containerID, tc.layers, testDataGenerator.uniqueMountTarget())
361
362 if err == nil {
363 return false
364 }
365
366 toFind := []string{"no matching containers for overlay"}
367 if len(tc.layers) > 0 {
368 toFind = append(toFind, tc.layers[0])
369 }
370
371 return assertDecisionJSONContains(t, err, toFind...)
372 }
373
374 if err := quick.Check(f, &quick.Config{MaxCount: 50, Rand: testRand}); err != nil {
375 t.Errorf("Test_Rego_EnforceOverlayMountPolicy_No_Matches failed: %v", err)
376 }
377 }
378
379
380
381 func Test_Rego_EnforceOverlayMountPolicy_Matches(t *testing.T) {
382 f := func(p *generatedConstraints) bool {
383 tc, err := setupRegoOverlayTest(p, true)
384 if err != nil {
385 t.Error(err)
386 return false
387 }
388
389 err = tc.policy.EnforceOverlayMountPolicy(p.ctx, tc.containerID, tc.layers, testDataGenerator.uniqueMountTarget())
390
391
392 return err == nil
393 }
394
395 if err := quick.Check(f, &quick.Config{MaxCount: 50, Rand: testRand}); err != nil {
396 t.Errorf("Test_Rego_EnforceOverlayMountPolicy_Matches: %v", err)
397 }
398 }
399
400
401
402
403 func Test_Rego_EnforceOverlayMountPolicy_Layers_With_Same_Root_Hash(t *testing.T) {
404
405 container := generateConstraintsContainer(testRand, 2, maxLayersInGeneratedContainer)
406
407
408 numLayers := len(container.Layers)
409 container.Layers[numLayers-2] = container.Layers[numLayers-1]
410
411 constraints := new(generatedConstraints)
412 constraints.ctx = context.Background()
413 constraints.containers = []*securityPolicyContainer{container}
414 constraints.externalProcesses = generateExternalProcesses(testRand)
415 securityPolicy := constraints.toPolicy()
416 policy, err := newRegoPolicy(securityPolicy.marshalRego(), []oci.Mount{}, []oci.Mount{})
417 if err != nil {
418 t.Fatal("Unable to create security policy")
419 }
420
421 containerID := testDataGenerator.uniqueContainerID()
422
423 layers, err := testDataGenerator.createValidOverlayForContainer(policy, container)
424 if err != nil {
425 t.Fatalf("error creating valid overlay: %v", err)
426 }
427
428 err = policy.EnforceOverlayMountPolicy(constraints.ctx, containerID, layers, testDataGenerator.uniqueMountTarget())
429 if err != nil {
430 t.Fatalf("Unable to create an overlay where root hashes are the same")
431 }
432 }
433
434
435
436
437
438 func Test_Rego_EnforceOverlayMountPolicy_Layers_Shared_Layers(t *testing.T) {
439 containerOne := generateConstraintsContainer(testRand, 1, 2)
440 containerTwo := generateConstraintsContainer(testRand, 1, 10)
441
442 sharedLayerIndex := 0
443
444
445 containerTwo.Layers[sharedLayerIndex] = containerOne.Layers[sharedLayerIndex]
446 constraints := new(generatedConstraints)
447 constraints.ctx = context.Background()
448 constraints.containers = []*securityPolicyContainer{containerOne, containerTwo}
449 constraints.externalProcesses = generateExternalProcesses(testRand)
450
451 securityPolicy := constraints.toPolicy()
452 policy, err := newRegoPolicy(securityPolicy.marshalRego(), []oci.Mount{}, []oci.Mount{})
453 if err != nil {
454 t.Fatal("Unable to create security policy")
455 }
456
457
458
459
460 containerID := testDataGenerator.uniqueContainerID()
461
462
463 containerOneOverlay := make([]string, len(containerOne.Layers))
464
465 sharedMount := ""
466 for i := 0; i < len(containerOne.Layers); i++ {
467 mount := testDataGenerator.uniqueMountTarget()
468 err := policy.EnforceDeviceMountPolicy(constraints.ctx, mount, containerOne.Layers[i])
469 if err != nil {
470 t.Fatalf("Unexpected error mounting overlay device: %v", err)
471 }
472 if i == sharedLayerIndex {
473 sharedMount = mount
474 }
475
476 containerOneOverlay[len(containerOneOverlay)-i-1] = mount
477 }
478
479 err = policy.EnforceOverlayMountPolicy(constraints.ctx, containerID, containerOneOverlay, testDataGenerator.uniqueMountTarget())
480 if err != nil {
481 t.Fatalf("Unexpected error mounting overlay: %v", err)
482 }
483
484
485
486
487 containerID = testDataGenerator.uniqueContainerID()
488
489
490 containerTwoOverlay := make([]string, len(containerTwo.Layers))
491
492 for i := 0; i < len(containerTwo.Layers); i++ {
493 var mount string
494 if i != sharedLayerIndex {
495 mount = testDataGenerator.uniqueMountTarget()
496
497 err := policy.EnforceDeviceMountPolicy(constraints.ctx, mount, containerTwo.Layers[i])
498 if err != nil {
499 t.Fatalf("Unexpected error mounting overlay device: %v", err)
500 }
501 } else {
502 mount = sharedMount
503 }
504
505 containerTwoOverlay[len(containerTwoOverlay)-i-1] = mount
506 }
507
508 err = policy.EnforceOverlayMountPolicy(constraints.ctx, containerID, containerTwoOverlay, testDataGenerator.uniqueMountTarget())
509 if err != nil {
510 t.Fatalf("Unexpected error mounting overlay: %v", err)
511 }
512
513
514 if containerOneOverlay[len(containerOneOverlay)-1] != containerTwoOverlay[len(containerTwoOverlay)-1] {
515 t.Fatal("Ooops. Looks like we botched our test setup.")
516 }
517 }
518
519
520
521 func Test_Rego_EnforceOverlayMountPolicy_Overlay_Single_Container_Twice(t *testing.T) {
522 f := func(p *generatedConstraints) bool {
523 tc, err := setupRegoOverlayTest(p, true)
524 if err != nil {
525 t.Error(err)
526 return false
527 }
528
529 if err := tc.policy.EnforceOverlayMountPolicy(p.ctx, tc.containerID, tc.layers, testDataGenerator.uniqueMountTarget()); err != nil {
530 t.Errorf("expected nil error got: %v", err)
531 return false
532 }
533
534 if err := tc.policy.EnforceOverlayMountPolicy(p.ctx, tc.containerID, tc.layers, testDataGenerator.uniqueMountTarget()); err == nil {
535 t.Errorf("able to create overlay for the same container twice")
536 return false
537 } else {
538 return assertDecisionJSONContains(t, err, "overlay has already been mounted")
539 }
540 }
541
542 if err := quick.Check(f, &quick.Config{MaxCount: 50, Rand: testRand}); err != nil {
543 t.Errorf("Test_Rego_EnforceOverlayMountPolicy_Overlay_Single_Container_Twice: %v", err)
544 }
545 }
546
547 func Test_Rego_EnforceOverlayMountPolicy_Reusing_ID_Across_Overlays(t *testing.T) {
548 constraints := new(generatedConstraints)
549 constraints.ctx = context.Background()
550 for i := 0; i < 2; i++ {
551 constraints.containers = append(constraints.containers, generateConstraintsContainer(testRand, 1, maxLayersInGeneratedContainer))
552 }
553
554 constraints.externalProcesses = generateExternalProcesses(testRand)
555
556 securityPolicy := constraints.toPolicy()
557 defaultMounts := generateMounts(testRand)
558 privilegedMounts := generateMounts(testRand)
559
560 policy, err := newRegoPolicy(securityPolicy.marshalRego(),
561 toOCIMounts(defaultMounts),
562 toOCIMounts(privilegedMounts))
563 if err != nil {
564 t.Fatal(err)
565 }
566
567 containerID := testDataGenerator.uniqueContainerID()
568
569
570 layerPaths, err := testDataGenerator.createValidOverlayForContainer(policy, constraints.containers[0])
571 if err != nil {
572 t.Fatalf("Unexpected error creating valid overlay: %v", err)
573 }
574
575 err = policy.EnforceOverlayMountPolicy(constraints.ctx, containerID, layerPaths, testDataGenerator.uniqueMountTarget())
576 if err != nil {
577 t.Fatalf("Unexpected error mounting overlay filesystem: %v", err)
578 }
579
580
581 layerPaths, err = testDataGenerator.createValidOverlayForContainer(policy, constraints.containers[1])
582 if err != nil {
583 t.Fatalf("Unexpected error creating valid overlay: %v", err)
584 }
585
586 err = policy.EnforceOverlayMountPolicy(constraints.ctx, containerID, layerPaths, testDataGenerator.uniqueMountTarget())
587 if err == nil {
588 t.Fatalf("Unexpected success mounting overlay filesystem")
589 }
590 }
591
592
593
594
595
596
597 func Test_Rego_EnforceOverlayMountPolicy_Multiple_Instances_Same_Container(t *testing.T) {
598 for containersToCreate := 13; containersToCreate <= maxContainersInGeneratedConstraints; containersToCreate++ {
599 constraints := new(generatedConstraints)
600 constraints.ctx = context.Background()
601 constraints.externalProcesses = generateExternalProcesses(testRand)
602
603 for i := 1; i <= containersToCreate; i++ {
604 arg := "command " + strconv.Itoa(i)
605 c := &securityPolicyContainer{
606 Command: []string{arg},
607 Layers: []string{"1", "2"},
608 }
609
610 constraints.containers = append(constraints.containers, c)
611 }
612
613 securityPolicy := constraints.toPolicy()
614 policy, err := newRegoPolicy(securityPolicy.marshalRego(), []oci.Mount{}, []oci.Mount{})
615 if err != nil {
616 t.Fatalf("failed create enforcer")
617 }
618
619 for i := 0; i < len(constraints.containers); i++ {
620 layerPaths, err := testDataGenerator.createValidOverlayForContainer(policy, constraints.containers[i])
621 if err != nil {
622 t.Fatal("unexpected error on test setup")
623 }
624
625 id := testDataGenerator.uniqueContainerID()
626 err = policy.EnforceOverlayMountPolicy(constraints.ctx, id, layerPaths, testDataGenerator.uniqueMountTarget())
627 if err != nil {
628 t.Fatalf("failed with %d containers", containersToCreate)
629 }
630 }
631 }
632 }
633
634 func Test_Rego_EnforceOverlayUnmountPolicy(t *testing.T) {
635 f := func(p *generatedConstraints) bool {
636 tc, err := setupRegoOverlayTest(p, true)
637 if err != nil {
638 t.Error(err)
639 return false
640 }
641
642 target := testDataGenerator.uniqueMountTarget()
643 err = tc.policy.EnforceOverlayMountPolicy(p.ctx, tc.containerID, tc.layers, target)
644 if err != nil {
645 t.Errorf("Failure setting up overlay for testing: %v", err)
646 return false
647 }
648
649 err = tc.policy.EnforceOverlayUnmountPolicy(p.ctx, target)
650 if err != nil {
651 t.Errorf("Unexpected policy enforcement failure: %v", err)
652 return false
653 }
654
655 return true
656 }
657
658 if err := quick.Check(f, &quick.Config{MaxCount: 50, Rand: testRand}); err != nil {
659 t.Errorf("Test_Rego_EnforceOverlayUnmountPolicy: %v", err)
660 }
661 }
662
663 func Test_Rego_EnforceOverlayUnmountPolicy_No_Matches(t *testing.T) {
664 f := func(p *generatedConstraints) bool {
665 tc, err := setupRegoOverlayTest(p, true)
666 if err != nil {
667 t.Error(err)
668 return false
669 }
670
671 target := testDataGenerator.uniqueMountTarget()
672 err = tc.policy.EnforceOverlayMountPolicy(p.ctx, tc.containerID, tc.layers, target)
673 if err != nil {
674 t.Errorf("Failure setting up overlay for testing: %v", err)
675 return false
676 }
677
678 badTarget := testDataGenerator.uniqueMountTarget()
679 err = tc.policy.EnforceOverlayUnmountPolicy(p.ctx, badTarget)
680 if err == nil {
681 t.Errorf("Unexpected policy enforcement success: %v", err)
682 return false
683 }
684
685 return true
686 }
687
688 if err := quick.Check(f, &quick.Config{MaxCount: 50, Rand: testRand}); err != nil {
689 t.Errorf("Test_Rego_EnforceOverlayUnmountPolicy: %v", err)
690 }
691 }
692
693 func Test_Rego_EnforceCommandPolicy_NoMatches(t *testing.T) {
694 f := func(p *generatedConstraints) bool {
695 tc, err := setupSimpleRegoCreateContainerTest(p)
696 if err != nil {
697 t.Error(err)
698 return false
699 }
700
701 _, _, _, err = tc.policy.EnforceCreateContainerPolicy(p.ctx, tc.sandboxID, tc.containerID, generateCommand(testRand), tc.envList, tc.workingDir, tc.mounts, false, tc.noNewPrivileges, tc.user, tc.groups, tc.umask, tc.capabilities, tc.seccomp)
702
703 if err == nil {
704 return false
705 }
706
707 return assertDecisionJSONContains(t, err, "invalid command")
708 }
709
710 if err := quick.Check(f, &quick.Config{MaxCount: 50, Rand: testRand}); err != nil {
711 t.Errorf("Test_EnforceCommandPolicy_NoMatches: %v", err)
712 }
713 }
714
715 func Test_Rego_EnforceEnvironmentVariablePolicy_Re2Match(t *testing.T) {
716 testFunc := func(gc *generatedConstraints) bool {
717 container := selectContainerFromContainerList(gc.containers, testRand)
718
719 re2MatchRule := EnvRuleConfig{
720 Strategy: EnvVarRuleRegex,
721 Rule: "PREFIX_.+=.+",
722 }
723
724 container.EnvRules = append(container.EnvRules, re2MatchRule)
725
726 tc, err := setupRegoCreateContainerTest(gc, container, false)
727 if err != nil {
728 t.Error(err)
729 return false
730 }
731
732 envList := append(tc.envList, "PREFIX_FOO=BAR")
733 _, _, _, err = tc.policy.EnforceCreateContainerPolicy(gc.ctx, tc.sandboxID, tc.containerID, tc.argList, envList, tc.workingDir, tc.mounts, false, tc.noNewPrivileges, tc.user, tc.groups, tc.umask, tc.capabilities, tc.seccomp)
734
735
736 if err != nil {
737 t.Errorf("Expected container setup to be allowed. It wasn't: %v", err)
738 return false
739 }
740
741 return true
742 }
743
744 if err := quick.Check(testFunc, &quick.Config{MaxCount: 50, Rand: testRand}); err != nil {
745 t.Errorf("Test_Rego_EnforceEnvironmentVariablePolicy_Re2Match: %v", err)
746 }
747 }
748
749 func Test_Rego_EnforceEnvironmentVariablePolicy_NotAllMatches(t *testing.T) {
750 f := func(p *generatedConstraints) bool {
751 tc, err := setupSimpleRegoCreateContainerTest(p)
752 if err != nil {
753 t.Error(err)
754 return false
755 }
756
757 envList := append(tc.envList, generateNeverMatchingEnvironmentVariable(testRand))
758 _, _, _, err = tc.policy.EnforceCreateContainerPolicy(p.ctx, tc.sandboxID, tc.containerID, tc.argList, envList, tc.workingDir, tc.mounts, false, tc.noNewPrivileges, tc.user, tc.groups, tc.umask, tc.capabilities, tc.seccomp)
759
760
761 if err == nil {
762 return false
763 }
764
765 return assertDecisionJSONContains(t, err, "invalid env list", envList[0])
766 }
767
768 if err := quick.Check(f, &quick.Config{MaxCount: 50, Rand: testRand}); err != nil {
769 t.Errorf("Test_Rego_EnforceEnvironmentVariablePolicy_NotAllMatches: %v", err)
770 }
771 }
772
773 func Test_Rego_EnforceEnvironmentVariablePolicy_DropEnvs(t *testing.T) {
774 testFunc := func(gc *generatedConstraints) bool {
775 gc.allowEnvironmentVariableDropping = true
776 container := selectContainerFromContainerList(gc.containers, testRand)
777
778 tc, err := setupRegoCreateContainerTest(gc, container, false)
779 if err != nil {
780 t.Error(err)
781 return false
782 }
783
784 extraRules := generateEnvironmentVariableRules(testRand)
785 extraEnvs := buildEnvironmentVariablesFromEnvRules(extraRules, testRand)
786
787 envList := append(tc.envList, extraEnvs...)
788 actual, _, _, err := tc.policy.EnforceCreateContainerPolicy(gc.ctx, tc.sandboxID, tc.containerID, tc.argList, envList, tc.workingDir, tc.mounts, false, tc.noNewPrivileges, tc.user, tc.groups, tc.umask, tc.capabilities, tc.seccomp)
789
790
791 if err != nil {
792 t.Errorf("Expected container creation to be allowed. It wasn't: %v", err)
793 return false
794 }
795
796 if !areStringArraysEqual(actual, tc.envList) {
797 t.Errorf("environment variables were not dropped correctly.")
798 return false
799 }
800
801 return true
802 }
803
804 if err := quick.Check(testFunc, &quick.Config{MaxCount: 50, Rand: testRand}); err != nil {
805 t.Errorf("Test_Rego_EnforceEnvironmentVariablePolicy_DropEnvs: %v", err)
806 }
807 }
808
809 func Test_Rego_EnforceEnvironmentVariablePolicy_DropEnvs_Multiple(t *testing.T) {
810 tc, err := setupRegoDropEnvsTest(false)
811 if err != nil {
812 t.Fatalf("error setting up test: %v", err)
813 }
814
815 extraRules := generateEnvironmentVariableRules(testRand)
816 extraEnvs := buildEnvironmentVariablesFromEnvRules(extraRules, testRand)
817
818 envList := append(tc.envList, extraEnvs...)
819 actual, _, _, err := tc.policy.EnforceCreateContainerPolicy(tc.ctx, tc.sandboxID, tc.containerID, tc.argList, envList, tc.workingDir, tc.mounts, false, tc.noNewPrivileges, tc.user, tc.groups, tc.umask, tc.capabilities, tc.seccomp)
820
821
822 if err != nil {
823 t.Errorf("Expected container creation to be allowed. It wasn't: %v", err)
824 }
825
826 if !areStringArraysEqual(actual, tc.envList) {
827 t.Error("environment variables were not dropped correctly.")
828 }
829 }
830
831 func Test_Rego_EnforceEnvironmentVariablePolicy_DropEnvs_Multiple_NoMatch(t *testing.T) {
832 tc, err := setupRegoDropEnvsTest(true)
833 if err != nil {
834 t.Fatalf("error setting up test: %v", err)
835 }
836
837 extraRules := generateEnvironmentVariableRules(testRand)
838 extraEnvs := buildEnvironmentVariablesFromEnvRules(extraRules, testRand)
839
840 envList := append(tc.envList, extraEnvs...)
841 actual, _, _, err := tc.policy.EnforceCreateContainerPolicy(tc.ctx, tc.sandboxID, tc.containerID, tc.argList, envList, tc.workingDir, tc.mounts, false, tc.noNewPrivileges, tc.user, tc.groups, tc.umask, tc.capabilities, tc.seccomp)
842
843
844 if err == nil {
845 t.Error("expected container creation not to be allowed.")
846 }
847
848 if actual != nil {
849 t.Error("envList should be nil")
850 }
851 }
852
853 func Test_Rego_WorkingDirectoryPolicy_NoMatches(t *testing.T) {
854 testFunc := func(gc *generatedConstraints) bool {
855 tc, err := setupSimpleRegoCreateContainerTest(gc)
856 if err != nil {
857 t.Error(err)
858 return false
859 }
860
861 _, _, _, err = tc.policy.EnforceCreateContainerPolicy(tc.ctx, tc.sandboxID, tc.containerID, tc.argList, tc.envList, randString(testRand, 20), tc.mounts, false, tc.noNewPrivileges, tc.user, tc.groups, tc.umask, tc.capabilities, tc.seccomp)
862
863 if err == nil {
864 return false
865 }
866
867 return assertDecisionJSONContains(t, err, "invalid working directory")
868 }
869
870 if err := quick.Check(testFunc, &quick.Config{MaxCount: 50, Rand: testRand}); err != nil {
871 t.Errorf("Test_Rego_WorkingDirectoryPolicy_NoMatches: %v", err)
872 }
873 }
874
875 func Test_Rego_EnforceCreateContainer(t *testing.T) {
876 f := func(p *generatedConstraints) bool {
877 tc, err := setupSimpleRegoCreateContainerTest(p)
878 if err != nil {
879 t.Error(err)
880 return false
881 }
882
883 _, _, _, err = tc.policy.EnforceCreateContainerPolicy(p.ctx, tc.sandboxID, tc.containerID, tc.argList, tc.envList, tc.workingDir, tc.mounts, false, tc.noNewPrivileges, tc.user, tc.groups, tc.umask, tc.capabilities, tc.seccomp)
884
885
886 return err == nil
887 }
888
889 if err := quick.Check(f, &quick.Config{MaxCount: 50, Rand: testRand}); err != nil {
890 t.Errorf("Test_Rego_EnforceCreateContainer: %v", err)
891 }
892 }
893
894 func Test_Rego_EnforceCreateContainer_Start_All_Containers(t *testing.T) {
895 f := func(p *generatedConstraints) bool {
896 securityPolicy := p.toPolicy()
897 defaultMounts := generateMounts(testRand)
898 privilegedMounts := generateMounts(testRand)
899
900 policy, err := newRegoPolicy(securityPolicy.marshalRego(),
901 toOCIMounts(defaultMounts),
902 toOCIMounts(privilegedMounts))
903 if err != nil {
904 t.Error(err)
905 return false
906 }
907
908 for _, container := range p.containers {
909 containerID, err := mountImageForContainer(policy, container)
910 if err != nil {
911 t.Error(err)
912 return false
913 }
914
915 envList := buildEnvironmentVariablesFromEnvRules(container.EnvRules, testRand)
916 user := buildIDNameFromConfig(container.User.UserIDName, testRand)
917 groups := buildGroupIDNamesFromUser(container.User, testRand)
918
919 sandboxID := testDataGenerator.uniqueSandboxID()
920 mounts := container.Mounts
921 mounts = append(mounts, defaultMounts...)
922 if container.AllowElevated {
923 mounts = append(mounts, privilegedMounts...)
924 }
925 mountSpec := buildMountSpecFromMountArray(mounts, sandboxID, testRand)
926 capabilities := container.Capabilities.toExternal()
927 seccomp := container.SeccompProfileSHA256
928
929 _, _, _, err = policy.EnforceCreateContainerPolicy(p.ctx, sandboxID, containerID, container.Command, envList, container.WorkingDir, mountSpec.Mounts, false, container.NoNewPrivileges, user, groups, container.User.Umask, &capabilities, seccomp)
930
931
932 if err != nil {
933 t.Error(err)
934 return false
935 }
936 }
937
938 return true
939
940 }
941
942 if err := quick.Check(f, &quick.Config{MaxCount: 10, Rand: testRand}); err != nil {
943 t.Errorf("Test_Rego_EnforceCreateContainer_Start_All_Containers: %v", err)
944 }
945 }
946
947 func Test_Rego_EnforceCreateContainer_Invalid_ContainerID(t *testing.T) {
948 f := func(p *generatedConstraints) bool {
949 tc, err := setupSimpleRegoCreateContainerTest(p)
950 if err != nil {
951 t.Error(err)
952 return false
953 }
954
955 containerID := testDataGenerator.uniqueContainerID()
956 _, _, _, err = tc.policy.EnforceCreateContainerPolicy(p.ctx, tc.sandboxID, containerID, tc.argList, tc.envList, tc.workingDir, tc.mounts, false, tc.noNewPrivileges, tc.user, tc.groups, tc.umask, tc.capabilities, tc.seccomp)
957
958
959 return err != nil
960 }
961
962 if err := quick.Check(f, &quick.Config{MaxCount: 50, Rand: testRand}); err != nil {
963 t.Errorf("Test_Rego_EnforceCreateContainer_Invalid_ContainerID: %v", err)
964 }
965 }
966
967 func Test_Rego_EnforceCreateContainer_Same_Container_Twice(t *testing.T) {
968 f := func(p *generatedConstraints) bool {
969 tc, err := setupSimpleRegoCreateContainerTest(p)
970 if err != nil {
971 t.Error(err)
972 return false
973 }
974
975 _, _, _, err = tc.policy.EnforceCreateContainerPolicy(p.ctx, tc.sandboxID, tc.containerID, tc.argList, tc.envList, tc.workingDir, tc.mounts, false, tc.noNewPrivileges, tc.user, tc.groups, tc.umask, tc.capabilities, tc.seccomp)
976 if err != nil {
977 t.Error("Unable to start valid container.")
978 return false
979 }
980 _, _, _, err = tc.policy.EnforceCreateContainerPolicy(p.ctx, tc.sandboxID, tc.containerID, tc.argList, tc.envList, tc.workingDir, tc.mounts, false, tc.noNewPrivileges, tc.user, tc.groups, tc.umask, tc.capabilities, tc.seccomp)
981 if err == nil {
982 t.Error("Able to start a container with already used id.")
983 return false
984 }
985
986 return true
987 }
988
989 if err := quick.Check(f, &quick.Config{MaxCount: 50, Rand: testRand}); err != nil {
990 t.Errorf("Test_Rego_EnforceCreateContainer_Same_Container_Twice: %v", err)
991 }
992 }
993
994 func Test_Rego_EnforceCreateContainer_Capabilities_NoMatches(t *testing.T) {
995 f := func(p *generatedConstraints) bool {
996 tc, err := setupSimpleRegoCreateContainerTest(p)
997 if err != nil {
998 t.Error(err)
999 return false
1000 }
1001
1002 capabilities := tc.capabilities
1003 capabilities.Bounding = alterCapabilitySet(testRand, capabilities.Bounding)
1004 capabilities.Effective = alterCapabilitySet(testRand, capabilities.Effective)
1005 capabilities.Inheritable = alterCapabilitySet(testRand, capabilities.Inheritable)
1006 capabilities.Permitted = alterCapabilitySet(testRand, capabilities.Permitted)
1007 capabilities.Ambient = alterCapabilitySet(testRand, capabilities.Ambient)
1008
1009 _, _, _, err = tc.policy.EnforceCreateContainerPolicy(p.ctx, tc.sandboxID, tc.containerID, tc.argList, tc.envList, tc.workingDir, tc.mounts, false, tc.noNewPrivileges, tc.user, tc.groups, tc.umask, capabilities, tc.seccomp)
1010
1011 if err == nil {
1012 t.Error("Unexpected success with incorrect capabilities")
1013 return false
1014 }
1015
1016 return true
1017 }
1018
1019 if err := quick.Check(f, &quick.Config{MaxCount: 25, Rand: testRand}); err != nil {
1020 t.Errorf("Test_Rego_EnforceCreateContainer_Capabilities_NoMatches: %v", err)
1021 }
1022 }
1023
1024 func Test_Rego_EnforceCreateContainer_Capabilities_SubsetDoesntMatch(t *testing.T) {
1025 f := func(p *generatedConstraints) bool {
1026 tc, err := setupSimpleRegoCreateContainerTest(p)
1027 if err != nil {
1028 t.Error(err)
1029 return false
1030 }
1031
1032 if len(tc.capabilities.Bounding) > 0 {
1033 capabilities := copyLinuxCapabilities(*tc.capabilities)
1034 capabilities.Bounding = subsetCapabilitySet(testRand, copyStrings(capabilities.Bounding))
1035
1036 _, _, _, err = tc.policy.EnforceCreateContainerPolicy(p.ctx, tc.sandboxID, tc.containerID, tc.argList, tc.envList, tc.workingDir, tc.mounts, false, tc.noNewPrivileges, tc.user, tc.groups, tc.umask, &capabilities, tc.seccomp)
1037
1038 if err == nil {
1039 t.Error("Unexpected success with bounding as a subset of allowed capabilities")
1040 return false
1041 }
1042 }
1043
1044 if len(tc.capabilities.Effective) > 0 {
1045 capabilities := copyLinuxCapabilities(*tc.capabilities)
1046 capabilities.Effective = subsetCapabilitySet(testRand, copyStrings(capabilities.Effective))
1047
1048 _, _, _, err = tc.policy.EnforceCreateContainerPolicy(p.ctx, tc.sandboxID, tc.containerID, tc.argList, tc.envList, tc.workingDir, tc.mounts, false, tc.noNewPrivileges, tc.user, tc.groups, tc.umask, &capabilities, tc.seccomp)
1049
1050 if err == nil {
1051 t.Error("Unexpected success with effective as a subset of allowed capabilities")
1052 return false
1053 }
1054 }
1055
1056 if len(tc.capabilities.Inheritable) > 0 {
1057 capabilities := copyLinuxCapabilities(*tc.capabilities)
1058 capabilities.Inheritable = subsetCapabilitySet(testRand, copyStrings(capabilities.Inheritable))
1059
1060 _, _, _, err = tc.policy.EnforceCreateContainerPolicy(p.ctx, tc.sandboxID, tc.containerID, tc.argList, tc.envList, tc.workingDir, tc.mounts, false, tc.noNewPrivileges, tc.user, tc.groups, tc.umask, &capabilities, tc.seccomp)
1061
1062 if err == nil {
1063 t.Error("Unexpected success with inheritable as a subset of allowed capabilities")
1064 return false
1065 }
1066 }
1067
1068 if len(tc.capabilities.Permitted) > 0 {
1069 capabilities := copyLinuxCapabilities(*tc.capabilities)
1070 capabilities.Permitted = subsetCapabilitySet(testRand, copyStrings(capabilities.Permitted))
1071
1072 _, _, _, err = tc.policy.EnforceCreateContainerPolicy(p.ctx, tc.sandboxID, tc.containerID, tc.argList, tc.envList, tc.workingDir, tc.mounts, false, tc.noNewPrivileges, tc.user, tc.groups, tc.umask, &capabilities, tc.seccomp)
1073
1074 if err == nil {
1075 t.Error("Unexpected success with permitted as a subset of allowed capabilities")
1076 return false
1077 }
1078 }
1079
1080 if len(tc.capabilities.Ambient) > 0 {
1081 capabilities := copyLinuxCapabilities(*tc.capabilities)
1082 capabilities.Ambient = subsetCapabilitySet(testRand, copyStrings(capabilities.Ambient))
1083
1084 _, _, _, err = tc.policy.EnforceCreateContainerPolicy(p.ctx, tc.sandboxID, tc.containerID, tc.argList, tc.envList, tc.workingDir, tc.mounts, false, tc.noNewPrivileges, tc.user, tc.groups, tc.umask, &capabilities, tc.seccomp)
1085
1086 if err == nil {
1087 t.Error("Unexpected success with ambient as a subset of allowed capabilities")
1088 return false
1089 }
1090 }
1091
1092 return true
1093 }
1094
1095 if err := quick.Check(f, &quick.Config{MaxCount: 25, Rand: testRand}); err != nil {
1096 t.Errorf("Test_Rego_EnforceCreateContainer_Capabilities_SubsetDoesntMatch: %v", err)
1097 }
1098 }
1099
1100 func Test_Rego_EnforceCreateContainer_Capabilities_SupersetDoesntMatch(t *testing.T) {
1101 f := func(p *generatedConstraints) bool {
1102 tc, err := setupSimpleRegoCreateContainerTest(p)
1103 if err != nil {
1104 t.Error(err)
1105 return false
1106 }
1107
1108 capabilities := copyLinuxCapabilities(*tc.capabilities)
1109 capabilities.Bounding = superCapabilitySet(testRand, copyStrings(capabilities.Bounding))
1110
1111 _, _, _, err = tc.policy.EnforceCreateContainerPolicy(p.ctx, tc.sandboxID, tc.containerID, tc.argList, tc.envList, tc.workingDir, tc.mounts, false, tc.noNewPrivileges, tc.user, tc.groups, tc.umask, &capabilities, tc.seccomp)
1112
1113 if err == nil {
1114 t.Error("Unexpected success with bounding as a superset of allowed capabilities")
1115 return false
1116 }
1117
1118 capabilities = copyLinuxCapabilities(*tc.capabilities)
1119 capabilities.Effective = superCapabilitySet(testRand, copyStrings(capabilities.Effective))
1120
1121 _, _, _, err = tc.policy.EnforceCreateContainerPolicy(p.ctx, tc.sandboxID, tc.containerID, tc.argList, tc.envList, tc.workingDir, tc.mounts, false, tc.noNewPrivileges, tc.user, tc.groups, tc.umask, &capabilities, tc.seccomp)
1122
1123 if err == nil {
1124 t.Error("Unexpected success with effective as a superset of allowed capabilities")
1125 return false
1126 }
1127
1128 capabilities = copyLinuxCapabilities(*tc.capabilities)
1129 capabilities.Inheritable = superCapabilitySet(testRand, copyStrings(capabilities.Inheritable))
1130
1131 _, _, _, err = tc.policy.EnforceCreateContainerPolicy(p.ctx, tc.sandboxID, tc.containerID, tc.argList, tc.envList, tc.workingDir, tc.mounts, false, tc.noNewPrivileges, tc.user, tc.groups, tc.umask, &capabilities, tc.seccomp)
1132
1133 if err == nil {
1134 t.Error("Unexpected success with inheritable as a superset of allowed capabilities")
1135 return false
1136 }
1137
1138 capabilities = copyLinuxCapabilities(*tc.capabilities)
1139 capabilities.Permitted = superCapabilitySet(testRand, copyStrings(capabilities.Permitted))
1140
1141 _, _, _, err = tc.policy.EnforceCreateContainerPolicy(p.ctx, tc.sandboxID, tc.containerID, tc.argList, tc.envList, tc.workingDir, tc.mounts, false, tc.noNewPrivileges, tc.user, tc.groups, tc.umask, &capabilities, tc.seccomp)
1142
1143 if err == nil {
1144 t.Error("Unexpected success with permitted as a superset of allowed capabilities")
1145 return false
1146 }
1147
1148 capabilities = copyLinuxCapabilities(*tc.capabilities)
1149 capabilities.Ambient = superCapabilitySet(testRand, copyStrings(capabilities.Ambient))
1150
1151 _, _, _, err = tc.policy.EnforceCreateContainerPolicy(p.ctx, tc.sandboxID, tc.containerID, tc.argList, tc.envList, tc.workingDir, tc.mounts, false, tc.noNewPrivileges, tc.user, tc.groups, tc.umask, &capabilities, tc.seccomp)
1152
1153 if err == nil {
1154 t.Error("Unexpected success with ambient as a superset of allowed capabilities")
1155 return false
1156 }
1157
1158 return true
1159 }
1160
1161 if err := quick.Check(f, &quick.Config{MaxCount: 25, Rand: testRand}); err != nil {
1162 t.Errorf("Test_Rego_EnforceCreateContainer_Capabilities_SupersetDoesntMatch: %v", err)
1163 }
1164 }
1165
1166 func Test_Rego_EnforceCreateContainer_Capabilities_DenialHasErrorMessage(t *testing.T) {
1167 constraints := generateConstraints(testRand, 1)
1168 tc, err := setupSimpleRegoCreateContainerTest(constraints)
1169 if err != nil {
1170 t.Fatal(err)
1171 }
1172
1173 capabilities := tc.capabilities
1174 capabilities.Bounding = alterCapabilitySet(testRand, capabilities.Bounding)
1175 capabilities.Effective = alterCapabilitySet(testRand, capabilities.Effective)
1176 capabilities.Inheritable = alterCapabilitySet(testRand, capabilities.Inheritable)
1177 capabilities.Permitted = alterCapabilitySet(testRand, capabilities.Permitted)
1178 capabilities.Ambient = alterCapabilitySet(testRand, capabilities.Ambient)
1179
1180 _, _, _, err = tc.policy.EnforceCreateContainerPolicy(tc.ctx, tc.sandboxID, tc.containerID, tc.argList, tc.envList, tc.workingDir, tc.mounts, false, tc.noNewPrivileges, tc.user, tc.groups, tc.umask, capabilities, tc.seccomp)
1181
1182 if err == nil {
1183 t.Error("Unexpected success with incorrect capabilities")
1184 }
1185
1186 if !assertDecisionJSONContains(t, err, "capabilities don't match") {
1187 t.Fatal("No error message given for denial by capability mismatch")
1188 }
1189 }
1190
1191 func Test_Rego_EnforceCreateContainer_Capabilities_UndecidableHasErrorMessage(t *testing.T) {
1192 constraints := generateConstraints(testRand, 1)
1193
1194
1195 testCaps := []string{"one", "two", "three"}
1196 firstCaps := []string{"one", "three"}
1197 secondCaps := []string{"two", "three"}
1198
1199 incomingCapabilities := &oci.LinuxCapabilities{
1200 Bounding: testCaps,
1201 Effective: testCaps,
1202 Inheritable: testCaps,
1203 Permitted: testCaps,
1204 Ambient: testCaps,
1205 }
1206
1207 firstContainerCapabilities := &capabilitiesInternal{
1208 Bounding: firstCaps,
1209 Effective: firstCaps,
1210 Inheritable: firstCaps,
1211 Permitted: firstCaps,
1212 Ambient: firstCaps,
1213 }
1214
1215 secondContainerCapabilities := &capabilitiesInternal{
1216 Bounding: secondCaps,
1217 Effective: secondCaps,
1218 Inheritable: secondCaps,
1219 Permitted: secondCaps,
1220 Ambient: secondCaps,
1221 }
1222
1223
1224 constraints.containers[0].Capabilities = firstContainerCapabilities
1225
1226
1227
1228 duplicate := &securityPolicyContainer{
1229 Command: constraints.containers[0].Command,
1230 EnvRules: constraints.containers[0].EnvRules,
1231 WorkingDir: constraints.containers[0].WorkingDir,
1232 Mounts: constraints.containers[0].Mounts,
1233 Layers: constraints.containers[0].Layers,
1234 AllowElevated: constraints.containers[0].AllowElevated,
1235 AllowStdioAccess: constraints.containers[0].AllowStdioAccess,
1236 NoNewPrivileges: constraints.containers[0].NoNewPrivileges,
1237 User: constraints.containers[0].User,
1238 SeccompProfileSHA256: constraints.containers[0].SeccompProfileSHA256,
1239
1240 Capabilities: secondContainerCapabilities,
1241
1242 ExecProcesses: generateExecProcesses(testRand),
1243 Signals: generateListOfSignals(testRand, 0, maxSignalNumber),
1244 }
1245
1246 constraints.containers = append(constraints.containers, duplicate)
1247
1248
1249 constraints.allowCapabilityDropping = true
1250
1251 tc, err := setupSimpleRegoCreateContainerTest(constraints)
1252 if err != nil {
1253 t.Fatal(err)
1254 }
1255 _, _, _, err = tc.policy.EnforceCreateContainerPolicy(tc.ctx, tc.sandboxID, tc.containerID, tc.argList, tc.envList, tc.workingDir, tc.mounts, false, tc.noNewPrivileges, tc.user, tc.groups, tc.umask, incomingCapabilities, tc.seccomp)
1256
1257 if err == nil {
1258 t.Fatal("Unexpected success with undecidable capabilities")
1259 }
1260
1261 if !assertDecisionJSONContains(t, err, "containers only distinguishable by capabilties") {
1262 t.Fatal("No error message given for undecidable based on capabilities mismatch")
1263 }
1264 }
1265
1266 func Test_Rego_EnforceCreateContainer_CapabilitiesIsNil(t *testing.T) {
1267 constraints := generateConstraints(testRand, 1)
1268 tc, err := setupSimpleRegoCreateContainerTest(constraints)
1269 if err != nil {
1270 t.Fatal(err)
1271 }
1272
1273 _, _, _, err = tc.policy.EnforceCreateContainerPolicy(tc.ctx, tc.sandboxID, tc.containerID, tc.argList, tc.envList, tc.workingDir, tc.mounts, false, tc.noNewPrivileges, tc.user, tc.groups, tc.umask, nil, tc.seccomp)
1274
1275 if err == nil {
1276 t.Fatal("Unexpected success with nil capabilities")
1277 }
1278
1279 if err.Error() != capabilitiesNilError {
1280 t.Fatal("No error message given for denial by capability being nil")
1281 }
1282 }
1283
1284 func Test_Rego_EnforceCreateContainer_Capabilities_Null_Elevated(t *testing.T) {
1285 constraints := generateConstraints(testRand, 1)
1286 constraints.containers[0].AllowElevated = true
1287 constraints.containers[0].Capabilities = nil
1288 tc, err := setupSimpleRegoCreateContainerTest(constraints)
1289 if err != nil {
1290 t.Fatal(err)
1291 }
1292
1293 capabilities := capabilitiesInternal{
1294 Bounding: DefaultUnprivilegedCapabilities(),
1295 Effective: DefaultUnprivilegedCapabilities(),
1296 Inheritable: []string{},
1297 Permitted: DefaultUnprivilegedCapabilities(),
1298 Ambient: []string{},
1299 }.toExternal()
1300
1301 _, _, _, err = tc.policy.EnforceCreateContainerPolicy(tc.ctx, tc.sandboxID, tc.containerID, tc.argList, tc.envList, tc.workingDir, tc.mounts, false, tc.noNewPrivileges, tc.user, tc.groups, tc.umask, &capabilities, tc.seccomp)
1302
1303 if err != nil {
1304 t.Fatal("Unexpected failure with null capabilities and elevated: %w", err)
1305 }
1306 }
1307
1308 func Test_Rego_EnforceCreateContainer_Capabilities_Null(t *testing.T) {
1309 constraints := generateConstraints(testRand, 1)
1310 constraints.containers[0].AllowElevated = false
1311 constraints.containers[0].Capabilities = nil
1312 tc, err := setupSimpleRegoCreateContainerTest(constraints)
1313 if err != nil {
1314 t.Fatal(err)
1315 }
1316
1317 capabilities := capabilitiesInternal{
1318 Bounding: DefaultUnprivilegedCapabilities(),
1319 Effective: DefaultUnprivilegedCapabilities(),
1320 Inheritable: []string{},
1321 Permitted: DefaultUnprivilegedCapabilities(),
1322 Ambient: []string{},
1323 }.toExternal()
1324
1325 _, _, _, err = tc.policy.EnforceCreateContainerPolicy(tc.ctx, tc.sandboxID, tc.containerID, tc.argList, tc.envList, tc.workingDir, tc.mounts, false, tc.noNewPrivileges, tc.user, tc.groups, tc.umask, &capabilities, tc.seccomp)
1326
1327 if err != nil {
1328 t.Fatal("Unexpected failure with null capabilities: %w", err)
1329 }
1330 }
1331
1332 func Test_Rego_EnforceCreateContainer_Capabilities_Null_Elevated_Privileged(t *testing.T) {
1333 constraints := generateConstraints(testRand, 1)
1334 constraints.containers[0].AllowElevated = true
1335 constraints.containers[0].Capabilities = nil
1336 tc, err := setupSimpleRegoCreateContainerTest(constraints)
1337 if err != nil {
1338 t.Fatal(err)
1339 }
1340
1341 capabilities := capabilitiesInternal{
1342 Bounding: DefaultPrivilegedCapabilities(),
1343 Effective: DefaultPrivilegedCapabilities(),
1344 Inheritable: DefaultPrivilegedCapabilities(),
1345 Permitted: DefaultPrivilegedCapabilities(),
1346 Ambient: []string{},
1347 }.toExternal()
1348
1349 _, _, _, err = tc.policy.EnforceCreateContainerPolicy(tc.ctx, tc.sandboxID, tc.containerID, tc.argList, tc.envList, tc.workingDir, tc.mounts, true, tc.noNewPrivileges, tc.user, tc.groups, tc.umask, &capabilities, tc.seccomp)
1350
1351 if err != nil {
1352 t.Fatal("Unexpected failure with null capabilities when elevated and privileged: %w", err)
1353 }
1354 }
1355
1356 func Test_Rego_EnforceExecInContainer_Capabilities_Null_Elevated(t *testing.T) {
1357 constraints := generateConstraints(testRand, 1)
1358 constraints.containers[0].AllowElevated = true
1359 constraints.containers[0].Capabilities = nil
1360 tc, err := setupRegoRunningContainerTest(constraints, false)
1361 if err != nil {
1362 t.Fatal(err)
1363 }
1364
1365 capabilities := capabilitiesInternal{
1366 Bounding: DefaultUnprivilegedCapabilities(),
1367 Effective: DefaultUnprivilegedCapabilities(),
1368 Inheritable: []string{},
1369 Permitted: DefaultUnprivilegedCapabilities(),
1370 Ambient: []string{},
1371 }.toExternal()
1372
1373 container := selectContainerFromRunningContainers(tc.runningContainers, testRand)
1374
1375 process := selectExecProcess(container.container.ExecProcesses, testRand)
1376 envList := buildEnvironmentVariablesFromEnvRules(container.container.EnvRules, testRand)
1377 user := buildIDNameFromConfig(container.container.User.UserIDName, testRand)
1378 groups := buildGroupIDNamesFromUser(container.container.User, testRand)
1379 umask := container.container.User.Umask
1380
1381 _, _, _, err = tc.policy.EnforceExecInContainerPolicy(constraints.ctx, container.containerID, process.Command, envList, container.container.WorkingDir, container.container.NoNewPrivileges, user, groups, umask, &capabilities)
1382
1383 if err != nil {
1384 t.Fatal("Unexpected failure with null capabilities and elevated: %w", err)
1385 }
1386 }
1387
1388 func Test_Rego_EnforceExecInContainer_Capabilities_Null(t *testing.T) {
1389 constraints := generateConstraints(testRand, 1)
1390 constraints.containers[0].Capabilities = nil
1391 tc, err := setupRegoRunningContainerTest(constraints, false)
1392 if err != nil {
1393 t.Fatal(err)
1394 }
1395
1396 capabilities := capabilitiesInternal{
1397 Bounding: DefaultUnprivilegedCapabilities(),
1398 Effective: DefaultUnprivilegedCapabilities(),
1399 Inheritable: []string{},
1400 Permitted: DefaultUnprivilegedCapabilities(),
1401 Ambient: []string{},
1402 }.toExternal()
1403
1404 container := selectContainerFromRunningContainers(tc.runningContainers, testRand)
1405
1406 process := selectExecProcess(container.container.ExecProcesses, testRand)
1407 envList := buildEnvironmentVariablesFromEnvRules(container.container.EnvRules, testRand)
1408 user := buildIDNameFromConfig(container.container.User.UserIDName, testRand)
1409 groups := buildGroupIDNamesFromUser(container.container.User, testRand)
1410 umask := container.container.User.Umask
1411
1412 _, _, _, err = tc.policy.EnforceExecInContainerPolicy(constraints.ctx, container.containerID, process.Command, envList, container.container.WorkingDir, container.container.NoNewPrivileges, user, groups, umask, &capabilities)
1413
1414 if err != nil {
1415 t.Fatal("Unexpected failure with null capabilities: %w", err)
1416 }
1417 }
1418
1419 func Test_Rego_EnforceExecInContainer_Capabilities_Null_Elevated_Privileged(t *testing.T) {
1420 constraints := generateConstraints(testRand, 1)
1421 constraints.containers[0].AllowElevated = true
1422 constraints.containers[0].Capabilities = nil
1423 tc, err := setupRegoRunningContainerTest(constraints, true)
1424 if err != nil {
1425 t.Fatal(err)
1426 }
1427
1428 capabilities := capabilitiesInternal{
1429 Bounding: DefaultPrivilegedCapabilities(),
1430 Effective: DefaultPrivilegedCapabilities(),
1431 Inheritable: DefaultPrivilegedCapabilities(),
1432 Permitted: DefaultPrivilegedCapabilities(),
1433 Ambient: []string{},
1434 }.toExternal()
1435
1436 container := selectContainerFromRunningContainers(tc.runningContainers, testRand)
1437
1438 process := selectExecProcess(container.container.ExecProcesses, testRand)
1439 envList := buildEnvironmentVariablesFromEnvRules(container.container.EnvRules, testRand)
1440 user := buildIDNameFromConfig(container.container.User.UserIDName, testRand)
1441 groups := buildGroupIDNamesFromUser(container.container.User, testRand)
1442 umask := container.container.User.Umask
1443
1444 _, _, _, err = tc.policy.EnforceExecInContainerPolicy(constraints.ctx, container.containerID, process.Command, envList, container.container.WorkingDir, container.container.NoNewPrivileges, user, groups, umask, &capabilities)
1445
1446 if err != nil {
1447 t.Fatal("Unexpected failure with null capabilities when elevated and privileged: %w", err)
1448 }
1449 }
1450
1451 func Test_Rego_EnforceCreateContainer_CapabilitiesAreEmpty(t *testing.T) {
1452 constraints := generateConstraints(testRand, 1)
1453 constraints.containers[0].Capabilities.Bounding = make([]string, 0)
1454 constraints.containers[0].Capabilities.Effective = make([]string, 0)
1455 constraints.containers[0].Capabilities.Inheritable = make([]string, 0)
1456 constraints.containers[0].Capabilities.Permitted = make([]string, 0)
1457 constraints.containers[0].Capabilities.Ambient = make([]string, 0)
1458
1459 tc, err := setupSimpleRegoCreateContainerTest(constraints)
1460 if err != nil {
1461 t.Fatal(err)
1462 }
1463
1464 capabilities := oci.LinuxCapabilities{}
1465
1466 _, _, _, err = tc.policy.EnforceCreateContainerPolicy(tc.ctx, tc.sandboxID, tc.containerID, tc.argList, tc.envList, tc.workingDir, tc.mounts, false, tc.noNewPrivileges, tc.user, tc.groups, tc.umask, &capabilities, tc.seccomp)
1467
1468 if err != nil {
1469 t.Fatal("Unexpected failure")
1470 }
1471 }
1472
1473 func Test_Rego_EnforceCreateContainer_Capabilities_Drop(t *testing.T) {
1474 f := func(p *generatedConstraints) bool {
1475 p.allowCapabilityDropping = true
1476 tc, err := setupSimpleRegoCreateContainerTest(p)
1477 if err != nil {
1478 t.Error(err)
1479 return false
1480 }
1481
1482 capabilities := copyLinuxCapabilities(*tc.capabilities)
1483 extraCapabilities := generateCapabilities(testRand)
1484 capabilities.Bounding = append(capabilities.Bounding, extraCapabilities.Bounding...)
1485 capabilities.Effective = append(capabilities.Effective, extraCapabilities.Effective...)
1486 capabilities.Inheritable = append(capabilities.Inheritable, extraCapabilities.Inheritable...)
1487 capabilities.Permitted = append(capabilities.Permitted, extraCapabilities.Permitted...)
1488 capabilities.Ambient = append(capabilities.Ambient, extraCapabilities.Ambient...)
1489
1490 _, actual, _, err := tc.policy.EnforceCreateContainerPolicy(p.ctx, tc.sandboxID, tc.containerID, tc.argList, tc.envList, tc.workingDir, tc.mounts, false, tc.noNewPrivileges, tc.user, tc.groups, tc.umask, &capabilities, tc.seccomp)
1491
1492 if err != nil {
1493 t.Errorf("Expected container creation to be allowed. It wasn't for extra capabilities: %v", err)
1494 return false
1495 }
1496
1497 if !areStringArraysEqual(actual.Bounding, tc.capabilities.Bounding) {
1498 t.Errorf("bounding capabilities were not dropped correctly.")
1499 return false
1500 }
1501
1502 if !areStringArraysEqual(actual.Effective, tc.capabilities.Effective) {
1503 t.Errorf("effective capabilities were not dropped correctly.")
1504 return false
1505 }
1506
1507 if !areStringArraysEqual(actual.Inheritable, tc.capabilities.Inheritable) {
1508 t.Errorf("inheritable capabilities were not dropped correctly.")
1509 return false
1510 }
1511
1512 if !areStringArraysEqual(actual.Permitted, tc.capabilities.Permitted) {
1513 t.Errorf("permitted capabilities were not dropped correctly.")
1514 return false
1515 }
1516
1517 if !areStringArraysEqual(actual.Ambient, tc.capabilities.Ambient) {
1518 t.Errorf("ambient capabilities were not dropped correctly.")
1519 return false
1520 }
1521
1522 return true
1523 }
1524
1525 if err := quick.Check(f, &quick.Config{MaxCount: 25, Rand: testRand}); err != nil {
1526 t.Errorf("Test_Rego_EnforceCreateContainer_Capabilities_Drop: %v", err)
1527 }
1528 }
1529
1530 func Test_Rego_EnforceCreateContainer_Capabilities_Drop_NoMatches(t *testing.T) {
1531 f := func(p *generatedConstraints) bool {
1532 p.allowCapabilityDropping = true
1533 tc, err := setupSimpleRegoCreateContainerTest(p)
1534 if err != nil {
1535 t.Error(err)
1536 return false
1537 }
1538
1539 capabilities := generateCapabilities(testRand)
1540
1541 _, _, _, err = tc.policy.EnforceCreateContainerPolicy(p.ctx, tc.sandboxID, tc.containerID, tc.argList, tc.envList, tc.workingDir, tc.mounts, false, tc.noNewPrivileges, tc.user, tc.groups, tc.umask, capabilities, tc.seccomp)
1542
1543 if err == nil {
1544 t.Errorf("Unexpected success with non matching capabilities set and dropping")
1545 return false
1546 }
1547
1548 return true
1549 }
1550
1551 if err := quick.Check(f, &quick.Config{MaxCount: 25, Rand: testRand}); err != nil {
1552 t.Errorf("Test_Rego_EnforceCreateContainer_Capabilities_Drop_NoMatches: %v", err)
1553 }
1554 }
1555
1556 func Test_Rego_ExtendDefaultMounts(t *testing.T) {
1557 f := func(p *generatedConstraints) bool {
1558 tc, err := setupSimpleRegoCreateContainerTest(p)
1559 if err != nil {
1560 t.Error(err)
1561 return false
1562 }
1563
1564 defaultMounts := generateMounts(testRand)
1565 _ = tc.policy.ExtendDefaultMounts(toOCIMounts(defaultMounts))
1566
1567 additionalMounts := buildMountSpecFromMountArray(defaultMounts, tc.sandboxID, testRand)
1568 tc.mounts = append(tc.mounts, additionalMounts.Mounts...)
1569
1570 _, _, _, err = tc.policy.EnforceCreateContainerPolicy(p.ctx, tc.sandboxID, tc.containerID, tc.argList, tc.envList, tc.workingDir, tc.mounts, false, tc.noNewPrivileges, tc.user, tc.groups, tc.umask, tc.capabilities, tc.seccomp)
1571
1572 if err != nil {
1573 t.Error(err)
1574 return false
1575 } else {
1576 return true
1577 }
1578 }
1579
1580 if err := quick.Check(f, &quick.Config{MaxCount: 50, Rand: testRand}); err != nil {
1581 t.Errorf("Test_Rego_ExtendDefaultMounts: %v", err)
1582 }
1583 }
1584
1585 func Test_Rego_MountPolicy_NoMatches(t *testing.T) {
1586 f := func(p *generatedConstraints) bool {
1587 tc, err := setupSimpleRegoCreateContainerTest(p)
1588 if err != nil {
1589 t.Error(err)
1590 return false
1591 }
1592
1593 invalidMounts := generateMounts(testRand)
1594 additionalMounts := buildMountSpecFromMountArray(invalidMounts, tc.sandboxID, testRand)
1595 tc.mounts = append(tc.mounts, additionalMounts.Mounts...)
1596
1597 _, _, _, err = tc.policy.EnforceCreateContainerPolicy(p.ctx, tc.sandboxID, tc.containerID, tc.argList, tc.envList, tc.workingDir, tc.mounts, false, tc.noNewPrivileges, tc.user, tc.groups, tc.umask, tc.capabilities, tc.seccomp)
1598
1599
1600 if err == nil {
1601 t.Error("We added additional mounts not in policyS and it didn't result in an error")
1602 return false
1603 }
1604
1605 return assertDecisionJSONContains(t, err, "invalid mount list")
1606 }
1607
1608 if err := quick.Check(f, &quick.Config{MaxCount: 50, Rand: testRand}); err != nil {
1609 t.Errorf("Test_Rego_MountPolicy_NoMatches: %v", err)
1610 }
1611 }
1612
1613 func Test_Rego_MountPolicy_NotAllOptionsFromConstraints(t *testing.T) {
1614 f := func(p *generatedConstraints) bool {
1615 tc, err := setupSimpleRegoCreateContainerTest(p)
1616 if err != nil {
1617 t.Error(err)
1618 return false
1619 }
1620
1621 inputMounts := tc.mounts
1622 mindex := randMinMax(testRand, 0, int32(len(tc.mounts)-1))
1623 options := inputMounts[mindex].Options
1624 inputMounts[mindex].Options = options[:len(options)-1]
1625
1626 _, _, _, err = tc.policy.EnforceCreateContainerPolicy(p.ctx, tc.sandboxID, tc.containerID, tc.argList, tc.envList, tc.workingDir, tc.mounts, false, tc.noNewPrivileges, tc.user, tc.groups, tc.umask, tc.capabilities, tc.seccomp)
1627
1628
1629 if err == nil {
1630 return false
1631 }
1632
1633 return assertDecisionJSONContains(t, err, "invalid mount list")
1634 }
1635
1636 if err := quick.Check(f, &quick.Config{MaxCount: 50, Rand: testRand}); err != nil {
1637 t.Errorf("Test_Rego_MountPolicy_NotAllOptionsFromConstraints: %v", err)
1638 }
1639 }
1640
1641 func Test_Rego_MountPolicy_BadSource(t *testing.T) {
1642 f := func(p *generatedConstraints) bool {
1643 tc, err := setupSimpleRegoCreateContainerTest(p)
1644 if err != nil {
1645 t.Error(err)
1646 return false
1647 }
1648
1649 index := randMinMax(testRand, 0, int32(len(tc.mounts)-1))
1650 tc.mounts[index].Source = randString(testRand, maxGeneratedMountSourceLength)
1651
1652 _, _, _, err = tc.policy.EnforceCreateContainerPolicy(p.ctx, tc.sandboxID, tc.containerID, tc.argList, tc.envList, tc.workingDir, tc.mounts, false, tc.noNewPrivileges, tc.user, tc.groups, tc.umask, tc.capabilities, tc.seccomp)
1653
1654
1655 if err == nil {
1656 return false
1657 }
1658
1659 return assertDecisionJSONContains(t, err, "invalid mount list")
1660 }
1661
1662 if err := quick.Check(f, &quick.Config{MaxCount: 50, Rand: testRand}); err != nil {
1663 t.Errorf("Test_Rego_MountPolicy_BadSource: %v", err)
1664 }
1665 }
1666
1667 func Test_Rego_MountPolicy_BadDestination(t *testing.T) {
1668 f := func(p *generatedConstraints) bool {
1669 tc, err := setupSimpleRegoCreateContainerTest(p)
1670 if err != nil {
1671 t.Error(err)
1672 return false
1673 }
1674
1675 index := randMinMax(testRand, 0, int32(len(tc.mounts)-1))
1676 tc.mounts[index].Destination = randString(testRand, maxGeneratedMountDestinationLength)
1677
1678 _, _, _, err = tc.policy.EnforceCreateContainerPolicy(p.ctx, tc.sandboxID, tc.containerID, tc.argList, tc.envList, tc.workingDir, tc.mounts, false, tc.noNewPrivileges, tc.user, tc.groups, tc.umask, tc.capabilities, tc.seccomp)
1679
1680
1681 if err == nil {
1682 return false
1683 }
1684
1685 return assertDecisionJSONContains(t, err, "invalid mount list")
1686 }
1687
1688 if err := quick.Check(f, &quick.Config{MaxCount: 50, Rand: testRand}); err != nil {
1689 t.Errorf("Test_Rego_MountPolicy_BadDestination: %v", err)
1690 }
1691 }
1692
1693 func Test_Rego_MountPolicy_BadType(t *testing.T) {
1694 f := func(p *generatedConstraints) bool {
1695 tc, err := setupSimpleRegoCreateContainerTest(p)
1696 if err != nil {
1697 t.Error(err)
1698 return false
1699 }
1700
1701 index := randMinMax(testRand, 0, int32(len(tc.mounts)-1))
1702 tc.mounts[index].Type = randString(testRand, 4)
1703
1704 _, _, _, err = tc.policy.EnforceCreateContainerPolicy(p.ctx, tc.sandboxID, tc.containerID, tc.argList, tc.envList, tc.workingDir, tc.mounts, false, tc.noNewPrivileges, tc.user, tc.groups, tc.umask, tc.capabilities, tc.seccomp)
1705
1706
1707 if err == nil {
1708 return false
1709 }
1710
1711 return assertDecisionJSONContains(t, err, "invalid mount list")
1712 }
1713
1714 if err := quick.Check(f, &quick.Config{MaxCount: 50, Rand: testRand}); err != nil {
1715 t.Errorf("Test_Rego_MountPolicy_BadType: %v", err)
1716 }
1717 }
1718
1719 func Test_Rego_MountPolicy_BadOption(t *testing.T) {
1720 f := func(p *generatedConstraints) bool {
1721 tc, err := setupSimpleRegoCreateContainerTest(p)
1722 if err != nil {
1723 t.Error(err)
1724 return false
1725 }
1726
1727 mindex := randMinMax(testRand, 0, int32(len(tc.mounts)-1))
1728 mountToChange := tc.mounts[mindex]
1729 oindex := randMinMax(testRand, 0, int32(len(mountToChange.Options)-1))
1730 tc.mounts[mindex].Options[oindex] = randString(testRand, maxGeneratedMountOptionLength)
1731
1732 _, _, _, err = tc.policy.EnforceCreateContainerPolicy(p.ctx, tc.sandboxID, tc.containerID, tc.argList, tc.envList, tc.workingDir, tc.mounts, false, tc.noNewPrivileges, tc.user, tc.groups, tc.umask, tc.capabilities, tc.seccomp)
1733
1734
1735 if err == nil {
1736 t.Error("We changed a mount option and it didn't result in an error")
1737 return false
1738 }
1739
1740 return assertDecisionJSONContains(t, err, "invalid mount list")
1741 }
1742
1743 if err := quick.Check(f, &quick.Config{MaxCount: 50, Rand: testRand}); err != nil {
1744 t.Errorf("Test_Rego_MountPolicy_BadOption: %v", err)
1745 }
1746 }
1747
1748 func Test_Rego_MountPolicy_MountPrivilegedWhenNotAllowed(t *testing.T) {
1749 f := func(p *generatedConstraints) bool {
1750 tc, err := setupRegoPrivilegedMountTest(p)
1751 if err != nil {
1752 t.Error(err)
1753 return false
1754 }
1755
1756 mindex := randMinMax(testRand, 0, int32(len(tc.mounts)-1))
1757 mountToChange := tc.mounts[mindex]
1758 oindex := randMinMax(testRand, 0, int32(len(mountToChange.Options)-1))
1759 tc.mounts[mindex].Options[oindex] = randString(testRand, maxGeneratedMountOptionLength)
1760
1761 _, _, _, err = tc.policy.EnforceCreateContainerPolicy(p.ctx, tc.sandboxID, tc.containerID, tc.argList, tc.envList, tc.workingDir, tc.mounts, false, tc.noNewPrivileges, tc.user, tc.groups, tc.umask, tc.capabilities, tc.seccomp)
1762
1763
1764 if err == nil {
1765 t.Error("We tried to mount a privileged mount when not allowed and it didn't result in an error")
1766 return false
1767 }
1768
1769 return assertDecisionJSONContains(t, err, "invalid mount list")
1770 }
1771
1772 if err := quick.Check(f, &quick.Config{MaxCount: 50, Rand: testRand}); err != nil {
1773 t.Errorf("Test_Rego_MountPolicy_BadOption: %v", err)
1774 }
1775 }
1776
1777
1778
1779 func Test_Rego_Version_Unregistered_Enforcement_Point(t *testing.T) {
1780 gc := generateConstraints(testRand, maxContainersInGeneratedConstraints)
1781 securityPolicy := gc.toPolicy()
1782 policy, err := newRegoPolicy(securityPolicy.marshalRego(), []oci.Mount{}, []oci.Mount{})
1783 if err != nil {
1784 t.Fatalf("unable to create a new Rego policy: %v", err)
1785 }
1786
1787 enforcementPoint := testDataGenerator.uniqueEnforcementPoint()
1788 _, err = policy.queryEnforcementPoint(enforcementPoint)
1789
1790
1791 if err == nil {
1792 t.Fatal("an error was not thrown when asking whether an unregistered enforcement point was available")
1793 }
1794 }
1795
1796
1797
1798
1799
1800 func Test_Rego_Version_Future_Enforcement_Point(t *testing.T) {
1801 gc := generateConstraints(testRand, maxContainersInGeneratedConstraints)
1802 securityPolicy := gc.toPolicy()
1803 policy, err := newRegoPolicy(securityPolicy.marshalRego(), []oci.Mount{}, []oci.Mount{})
1804 if err != nil {
1805 t.Fatalf("unable to create a new Rego policy: %v", err)
1806 }
1807
1808 err = policy.injectTestAPI()
1809 if err != nil {
1810 t.Fatal(err)
1811 }
1812
1813 _, err = policy.queryEnforcementPoint("__fixture_for_future_test__")
1814
1815
1816 if err == nil {
1817 t.Fatalf("an error was not thrown when asking whether an enforcement point from the future was available")
1818 }
1819
1820 expected_error := "enforcement point rule __fixture_for_future_test__ is invalid"
1821 if err.Error() != expected_error {
1822 t.Fatalf("error message when asking for a future enforcement point was incorrect.")
1823 }
1824 }
1825
1826
1827
1828
1829
1830 func Test_Rego_Version_Unavailable_Enforcement_Point(t *testing.T) {
1831 code := "package policy\n\napi_version := \"0.0.1\""
1832 policy, err := newRegoPolicy(code, []oci.Mount{}, []oci.Mount{})
1833 if err != nil {
1834 t.Fatalf("unable to create a new Rego policy: %v", err)
1835 }
1836
1837 err = policy.injectTestAPI()
1838 if err != nil {
1839 t.Fatal(err)
1840 }
1841
1842 info, err := policy.queryEnforcementPoint("__fixture_for_allowed_test_true__")
1843
1844 if err != nil {
1845 t.Fatalf("unable to query whether enforcement point is available: %v", err)
1846 }
1847
1848 if info.availableByPolicyVersion {
1849 t.Error("unavailable enforcement incorrectly indicated as available")
1850 }
1851
1852 allowed, err := info.defaultResults.Bool("allowed")
1853
1854 if err != nil {
1855 t.Error(err)
1856 }
1857
1858 if !allowed {
1859 t.Error("default behavior was incorrect for unavailable enforcement point")
1860 }
1861 }
1862
1863 func Test_Rego_Enforcement_Point_Allowed(t *testing.T) {
1864 code := "package policy\n\napi_version := \"0.0.1\""
1865 policy, err := newRegoPolicy(code, []oci.Mount{}, []oci.Mount{})
1866 if err != nil {
1867 t.Fatalf("unable to create a new Rego policy: %v", err)
1868 }
1869
1870 err = policy.injectTestAPI()
1871 if err != nil {
1872 t.Fatal(err)
1873 }
1874
1875 input := make(map[string]interface{})
1876 results, err := policy.applyDefaults("__fixture_for_allowed_test_false__", input)
1877 if err != nil {
1878 t.Fatalf("applied defaults for an enforcement point receieved an error: %v", err)
1879 }
1880
1881 allowed, err := results.Bool("allowed")
1882
1883 if err != nil {
1884 t.Error(err)
1885 }
1886
1887 if allowed {
1888 t.Fatal("result of allowed for an available enforcement point was not the specified default (false)")
1889 }
1890
1891 input = make(map[string]interface{})
1892 results, err = policy.applyDefaults("__fixture_for_allowed_test_true__", input)
1893 if err != nil {
1894 t.Fatalf("applied defaults for an enforcement point receieved an error: %v", err)
1895 }
1896
1897 allowed, err = results.Bool("allowed")
1898
1899 if err != nil {
1900 t.Error(err)
1901 }
1902
1903 if !allowed {
1904 t.Error("result of allowed for an available enforcement point was not the specified default (true)")
1905 }
1906 }
1907
1908 func Test_Rego_Enforcement_Point_Extra(t *testing.T) {
1909 ctx := context.Background()
1910 code := `package policy
1911
1912 api_version := "0.0.1"
1913
1914 __fixture_for_allowed_extra__ := {"allowed": true}
1915 `
1916 policy, err := newRegoPolicy(code, []oci.Mount{}, []oci.Mount{})
1917 if err != nil {
1918 t.Fatalf("unable to create a new Rego policy: %v", err)
1919 }
1920
1921 err = policy.injectTestAPI()
1922 if err != nil {
1923 t.Fatal(err)
1924 }
1925
1926 input := make(map[string]interface{})
1927 results, err := policy.enforce(ctx, "__fixture_for_allowed_extra__", input)
1928 if err != nil {
1929 t.Fatalf("enforcement produced an error: %v", err)
1930 }
1931
1932 allowed, err := results.Bool("allowed")
1933
1934 if err != nil {
1935 t.Error(err)
1936 }
1937
1938 if !allowed {
1939 t.Error("result of allowed for an available enforcement point was not the policy value (true)")
1940 }
1941
1942 if extra, ok := results["__test__"]; ok {
1943 if extra != "test" {
1944 t.Errorf("extra value was not specified default: %s != test", extra)
1945 }
1946 } else {
1947 t.Error("extra value is missing from enforcement result")
1948 }
1949 }
1950
1951 func Test_Rego_No_API_Version(t *testing.T) {
1952 code := "package policy"
1953 policy, err := newRegoPolicy(code, []oci.Mount{}, []oci.Mount{})
1954 if err != nil {
1955 t.Fatalf("unable to create a new Rego policy: %v", err)
1956 }
1957
1958 err = policy.injectTestAPI()
1959 if err != nil {
1960 t.Fatal(err)
1961 }
1962
1963 _, err = policy.queryEnforcementPoint("__fixture_for_allowed_test_true__")
1964
1965 if err == nil {
1966 t.Error("querying an enforcement point without an api_version did not produce an error")
1967 }
1968
1969 if err.Error() != noAPIVersionError {
1970 t.Errorf("querying an enforcement point without an api_version produced an incorrect error: %s", err)
1971 }
1972 }
1973
1974 func Test_Rego_ExecInContainerPolicy(t *testing.T) {
1975 f := func(p *generatedConstraints) bool {
1976 tc, err := setupRegoRunningContainerTest(p, false)
1977 if err != nil {
1978 t.Error(err)
1979 return false
1980 }
1981
1982 container := selectContainerFromRunningContainers(tc.runningContainers, testRand)
1983 capabilities := container.container.Capabilities.toExternal()
1984
1985 process := selectExecProcess(container.container.ExecProcesses, testRand)
1986 envList := buildEnvironmentVariablesFromEnvRules(container.container.EnvRules, testRand)
1987 user := buildIDNameFromConfig(container.container.User.UserIDName, testRand)
1988 groups := buildGroupIDNamesFromUser(container.container.User, testRand)
1989 umask := container.container.User.Umask
1990
1991 _, _, _, err = tc.policy.EnforceExecInContainerPolicy(p.ctx, container.containerID, process.Command, envList, container.container.WorkingDir, container.container.NoNewPrivileges, user, groups, umask, &capabilities)
1992
1993
1994 if err != nil {
1995 t.Error(err)
1996 return false
1997 }
1998
1999 return true
2000 }
2001
2002 if err := quick.Check(f, &quick.Config{MaxCount: 25, Rand: testRand}); err != nil {
2003 t.Errorf("Test_Rego_ExecInContainerPolicy: %v", err)
2004 }
2005 }
2006
2007 func Test_Rego_ExecInContainerPolicy_No_Matches(t *testing.T) {
2008 f := func(p *generatedConstraints) bool {
2009 tc, err := setupRegoRunningContainerTest(p, false)
2010 if err != nil {
2011 t.Error(err)
2012 return false
2013 }
2014
2015 container := selectContainerFromRunningContainers(tc.runningContainers, testRand)
2016 capabilities := container.container.Capabilities.toExternal()
2017
2018 process := generateContainerExecProcess(testRand)
2019 envList := buildEnvironmentVariablesFromEnvRules(container.container.EnvRules, testRand)
2020 user := buildIDNameFromConfig(container.container.User.UserIDName, testRand)
2021 groups := buildGroupIDNamesFromUser(container.container.User, testRand)
2022 umask := container.container.User.Umask
2023
2024 _, _, _, err = tc.policy.EnforceExecInContainerPolicy(p.ctx, container.containerID, process.Command, envList, container.container.WorkingDir, container.container.NoNewPrivileges, user, groups, umask, &capabilities)
2025 if err == nil {
2026 t.Error("Test unexpectedly passed")
2027 return false
2028 }
2029
2030 return true
2031 }
2032
2033 if err := quick.Check(f, &quick.Config{MaxCount: 25, Rand: testRand}); err != nil {
2034 t.Errorf("Test_Rego_ExecInContainerPolicy_No_Matches: %v", err)
2035 }
2036 }
2037
2038 func Test_Rego_ExecInContainerPolicy_Command_No_Match(t *testing.T) {
2039 f := func(p *generatedConstraints) bool {
2040 tc, err := setupRegoRunningContainerTest(p, false)
2041 if err != nil {
2042 t.Error(err)
2043 return false
2044 }
2045
2046 container := selectContainerFromRunningContainers(tc.runningContainers, testRand)
2047 envList := buildEnvironmentVariablesFromEnvRules(container.container.EnvRules, testRand)
2048
2049 user := buildIDNameFromConfig(container.container.User.UserIDName, testRand)
2050 groups := buildGroupIDNamesFromUser(container.container.User, testRand)
2051 umask := container.container.User.Umask
2052 capabilities := container.container.Capabilities.toExternal()
2053
2054 command := generateCommand(testRand)
2055 _, _, _, err = tc.policy.EnforceExecInContainerPolicy(p.ctx, container.containerID, command, envList, container.container.WorkingDir, container.container.NoNewPrivileges, user, groups, umask, &capabilities)
2056
2057
2058 if err == nil {
2059 t.Error("Unexpected success when enforcing policy")
2060 return false
2061 }
2062
2063 return assertDecisionJSONContains(t, err, "invalid command")
2064 }
2065
2066 if err := quick.Check(f, &quick.Config{MaxCount: 25, Rand: testRand}); err != nil {
2067 t.Errorf("Test_Rego_ExecInContainerPolicy_Command_No_Match: %v", err)
2068 }
2069 }
2070
2071 func Test_Rego_ExecInContainerPolicy_Some_Env_Not_Allowed(t *testing.T) {
2072 f := func(p *generatedConstraints) bool {
2073 tc, err := setupRegoRunningContainerTest(p, false)
2074 if err != nil {
2075 t.Error(err)
2076 return false
2077 }
2078
2079 container := selectContainerFromRunningContainers(tc.runningContainers, testRand)
2080 process := selectExecProcess(container.container.ExecProcesses, testRand)
2081 envList := generateEnvironmentVariables(testRand)
2082 user := buildIDNameFromConfig(container.container.User.UserIDName, testRand)
2083 groups := buildGroupIDNamesFromUser(container.container.User, testRand)
2084 umask := container.container.User.Umask
2085 capabilities := container.container.Capabilities.toExternal()
2086
2087 _, _, _, err = tc.policy.EnforceExecInContainerPolicy(p.ctx, container.containerID, process.Command, envList, container.container.WorkingDir, container.container.NoNewPrivileges, user, groups, umask, &capabilities)
2088
2089
2090 if err == nil {
2091 t.Error("Unexpected success when enforcing policy")
2092 return false
2093 }
2094
2095 return assertDecisionJSONContains(t, err, "invalid env list")
2096 }
2097
2098 if err := quick.Check(f, &quick.Config{MaxCount: 25, Rand: testRand}); err != nil {
2099 t.Errorf("Test_Rego_ExecInContainerPolicy_Some_Env_Not_Allowed: %v", err)
2100 }
2101 }
2102
2103 func Test_Rego_ExecInContainerPolicy_WorkingDir_No_Match(t *testing.T) {
2104 f := func(p *generatedConstraints) bool {
2105 tc, err := setupRegoRunningContainerTest(p, false)
2106 if err != nil {
2107 t.Error(err)
2108 return false
2109 }
2110
2111 container := selectContainerFromRunningContainers(tc.runningContainers, testRand)
2112 process := selectExecProcess(container.container.ExecProcesses, testRand)
2113 envList := buildEnvironmentVariablesFromEnvRules(container.container.EnvRules, testRand)
2114 workingDir := generateWorkingDir(testRand)
2115 user := buildIDNameFromConfig(container.container.User.UserIDName, testRand)
2116 groups := buildGroupIDNamesFromUser(container.container.User, testRand)
2117 umask := container.container.User.Umask
2118 capabilities := container.container.Capabilities.toExternal()
2119
2120 _, _, _, err = tc.policy.EnforceExecInContainerPolicy(p.ctx, container.containerID, process.Command, envList, workingDir, container.container.NoNewPrivileges, user, groups, umask, &capabilities)
2121
2122
2123 if err == nil {
2124 t.Error("Unexpected success when enforcing policy")
2125 return false
2126 }
2127
2128 return assertDecisionJSONContains(t, err, "invalid working directory")
2129 }
2130
2131 if err := quick.Check(f, &quick.Config{MaxCount: 25, Rand: testRand}); err != nil {
2132 t.Errorf("Test_Rego_ExecInContainerPolicy_WorkingDir_No_Match: %v", err)
2133 }
2134 }
2135
2136 func Test_Rego_ExecInContainerPolicy_Capabilities_No_Match(t *testing.T) {
2137 f := func(p *generatedConstraints) bool {
2138 tc, err := setupRegoRunningContainerTest(p, false)
2139 if err != nil {
2140 t.Error(err)
2141 return false
2142 }
2143
2144 container := selectContainerFromRunningContainers(tc.runningContainers, testRand)
2145 process := selectExecProcess(container.container.ExecProcesses, testRand)
2146 envList := buildEnvironmentVariablesFromEnvRules(container.container.EnvRules, testRand)
2147 user := buildIDNameFromConfig(container.container.User.UserIDName, testRand)
2148 groups := buildGroupIDNamesFromUser(container.container.User, testRand)
2149 umask := container.container.User.Umask
2150
2151 capabilities := copyLinuxCapabilities(container.container.Capabilities.toExternal())
2152 capabilities.Bounding = superCapabilitySet(testRand, capabilities.Bounding)
2153
2154 _, _, _, err = tc.policy.EnforceExecInContainerPolicy(p.ctx, container.containerID, process.Command, envList, container.container.WorkingDir, container.container.NoNewPrivileges, user, groups, umask, &capabilities)
2155
2156
2157 if err == nil {
2158 t.Error("Unexpected success with bounding as a superset of allowed capabilities")
2159 return false
2160 }
2161
2162 if !assertDecisionJSONContains(t, err, "capabilities don't match") {
2163 t.Errorf("Didn't find expected error message\n%v\n", err)
2164 return false
2165 }
2166
2167 capabilities = copyLinuxCapabilities(container.container.Capabilities.toExternal())
2168 capabilities.Effective = superCapabilitySet(testRand, capabilities.Effective)
2169
2170 _, _, _, err = tc.policy.EnforceExecInContainerPolicy(p.ctx, container.containerID, process.Command, envList, container.container.WorkingDir, container.container.NoNewPrivileges, user, groups, umask, &capabilities)
2171
2172
2173 if err == nil {
2174 t.Error("Unexpected success with effective as a superset of allowed capabilities")
2175 return false
2176 }
2177
2178 if !assertDecisionJSONContains(t, err, "capabilities don't match") {
2179 t.Errorf("Didn't find expected error message\n%v\n", err)
2180 return false
2181 }
2182
2183 capabilities = copyLinuxCapabilities(container.container.Capabilities.toExternal())
2184 capabilities.Inheritable = superCapabilitySet(testRand, capabilities.Inheritable)
2185
2186 _, _, _, err = tc.policy.EnforceExecInContainerPolicy(p.ctx, container.containerID, process.Command, envList, container.container.WorkingDir, container.container.NoNewPrivileges, user, groups, umask, &capabilities)
2187
2188
2189 if err == nil {
2190 t.Error("Unexpected success with inheritable as a superset of allowed capabilities")
2191 return false
2192 }
2193
2194 if !assertDecisionJSONContains(t, err, "capabilities don't match") {
2195 t.Errorf("Didn't find expected error message\n%v\n", err)
2196 return false
2197 }
2198
2199 capabilities = copyLinuxCapabilities(container.container.Capabilities.toExternal())
2200 capabilities.Permitted = superCapabilitySet(testRand, capabilities.Permitted)
2201
2202 _, _, _, err = tc.policy.EnforceExecInContainerPolicy(p.ctx, container.containerID, process.Command, envList, container.container.WorkingDir, container.container.NoNewPrivileges, user, groups, umask, &capabilities)
2203
2204
2205 if err == nil {
2206 t.Error("Unexpected success with permitted as a superset of allowed capabilities")
2207 return false
2208 }
2209
2210 if !assertDecisionJSONContains(t, err, "capabilities don't match") {
2211 t.Errorf("Didn't find expected error message\n%v\n", err)
2212 return false
2213 }
2214
2215 capabilities = copyLinuxCapabilities(container.container.Capabilities.toExternal())
2216 capabilities.Ambient = superCapabilitySet(testRand, capabilities.Ambient)
2217
2218 _, _, _, err = tc.policy.EnforceExecInContainerPolicy(p.ctx, container.containerID, process.Command, envList, container.container.WorkingDir, container.container.NoNewPrivileges, user, groups, umask, &capabilities)
2219
2220
2221 if err == nil {
2222 t.Error("Unexpected success with ambient as a superset of allowed capabilities")
2223 return false
2224 }
2225
2226 if !assertDecisionJSONContains(t, err, "capabilities don't match") {
2227 t.Errorf("Didn't find expected error message\n%v\n", err)
2228 return false
2229 }
2230
2231 return true
2232 }
2233
2234 if err := quick.Check(f, &quick.Config{MaxCount: 25, Rand: testRand}); err != nil {
2235 t.Errorf("Test_Rego_ExecInContainerPolicy_Capabilities_No_Match: %v", err)
2236 }
2237 }
2238
2239 func Test_Rego_ExecInContainerPolicy_CapabilitiesIsNil(t *testing.T) {
2240 constraints := generateConstraints(testRand, 1)
2241 tc, err := setupRegoRunningContainerTest(constraints, false)
2242 if err != nil {
2243 t.Fatal(err)
2244 }
2245
2246 container := selectContainerFromRunningContainers(tc.runningContainers, testRand)
2247 process := selectExecProcess(container.container.ExecProcesses, testRand)
2248 envList := buildEnvironmentVariablesFromEnvRules(container.container.EnvRules, testRand)
2249 user := buildIDNameFromConfig(container.container.User.UserIDName, testRand)
2250 groups := buildGroupIDNamesFromUser(container.container.User, testRand)
2251 umask := container.container.User.Umask
2252
2253 _, _, _, err = tc.policy.EnforceExecInContainerPolicy(constraints.ctx, container.containerID, process.Command, envList, container.container.WorkingDir, container.container.NoNewPrivileges, user, groups, umask, nil)
2254
2255 if err == nil {
2256 t.Fatal("Unexpected success with nil capabilities")
2257 }
2258
2259 if err.Error() != capabilitiesNilError {
2260 t.Fatal("No error message given for denial by capability being nil")
2261 }
2262 }
2263
2264 func Test_Rego_ExecInContainerPolicy_CapabilitiesAreEmpty(t *testing.T) {
2265 constraints := generateConstraints(testRand, 1)
2266 constraints.containers[0].Capabilities.Bounding = make([]string, 0)
2267 constraints.containers[0].Capabilities.Effective = make([]string, 0)
2268 constraints.containers[0].Capabilities.Inheritable = make([]string, 0)
2269 constraints.containers[0].Capabilities.Permitted = make([]string, 0)
2270 constraints.containers[0].Capabilities.Ambient = make([]string, 0)
2271
2272 tc, err := setupRegoRunningContainerTest(constraints, false)
2273 if err != nil {
2274 t.Fatal(err)
2275 }
2276
2277 capabilities := oci.LinuxCapabilities{}
2278
2279 container := selectContainerFromRunningContainers(tc.runningContainers, testRand)
2280 process := selectExecProcess(container.container.ExecProcesses, testRand)
2281 envList := buildEnvironmentVariablesFromEnvRules(container.container.EnvRules, testRand)
2282 user := buildIDNameFromConfig(container.container.User.UserIDName, testRand)
2283 groups := buildGroupIDNamesFromUser(container.container.User, testRand)
2284 umask := container.container.User.Umask
2285
2286 _, _, _, err = tc.policy.EnforceExecInContainerPolicy(constraints.ctx, container.containerID, process.Command, envList, container.container.WorkingDir, container.container.NoNewPrivileges, user, groups, umask, &capabilities)
2287
2288 if err != nil {
2289 t.Fatal("Unexpected failure")
2290 }
2291 }
2292
2293 func Test_Rego_ExecInContainerPolicy_Capabilities_Drop(t *testing.T) {
2294 f := func(p *generatedConstraints) bool {
2295 p.allowCapabilityDropping = true
2296 tc, err := setupRegoRunningContainerTest(p, false)
2297 if err != nil {
2298 t.Error(err)
2299 return false
2300 }
2301
2302 container := selectContainerFromRunningContainers(tc.runningContainers, testRand)
2303 process := selectExecProcess(container.container.ExecProcesses, testRand)
2304 envList := buildEnvironmentVariablesFromEnvRules(container.container.EnvRules, testRand)
2305 user := buildIDNameFromConfig(container.container.User.UserIDName, testRand)
2306 groups := buildGroupIDNamesFromUser(container.container.User, testRand)
2307 umask := container.container.User.Umask
2308
2309 capabilities := copyLinuxCapabilities(container.container.Capabilities.toExternal())
2310 capabilities.Bounding = superCapabilitySet(testRand, capabilities.Bounding)
2311
2312 extraCapabilities := generateCapabilities(testRand)
2313 capabilities.Bounding = append(capabilities.Bounding, extraCapabilities.Bounding...)
2314 capabilities.Effective = append(capabilities.Effective, extraCapabilities.Effective...)
2315 capabilities.Inheritable = append(capabilities.Inheritable, extraCapabilities.Inheritable...)
2316 capabilities.Permitted = append(capabilities.Permitted, extraCapabilities.Permitted...)
2317 capabilities.Ambient = append(capabilities.Ambient, extraCapabilities.Ambient...)
2318
2319 _, actual, _, err := tc.policy.EnforceExecInContainerPolicy(p.ctx, container.containerID, process.Command, envList, container.container.WorkingDir, container.container.NoNewPrivileges, user, groups, umask, &capabilities)
2320
2321 if err != nil {
2322 t.Errorf("Expected exec in container to be allowed. It wasn't for extra capabilities: %v", err)
2323 return false
2324 }
2325
2326 if !areStringArraysEqual(actual.Bounding, container.container.Capabilities.Bounding) {
2327 t.Errorf("bounding capabilities were not dropped correctly.")
2328 return false
2329 }
2330
2331 if !areStringArraysEqual(actual.Effective, container.container.Capabilities.Effective) {
2332 t.Errorf("effective capabilities were not dropped correctly.")
2333 return false
2334 }
2335
2336 if !areStringArraysEqual(actual.Inheritable, container.container.Capabilities.Inheritable) {
2337 t.Errorf("inheritable capabilities were not dropped correctly.")
2338 return false
2339 }
2340
2341 if !areStringArraysEqual(actual.Permitted, container.container.Capabilities.Permitted) {
2342 t.Errorf("permitted capabilities were not dropped correctly.")
2343 return false
2344 }
2345
2346 if !areStringArraysEqual(actual.Ambient, container.container.Capabilities.Ambient) {
2347 t.Errorf("ambient capabilities were not dropped correctly.")
2348 return false
2349 }
2350
2351 return true
2352 }
2353
2354 if err := quick.Check(f, &quick.Config{MaxCount: 25, Rand: testRand}); err != nil {
2355 t.Errorf("Test_Rego_ExecInContainerPolicy_Capabilities_Drop: %v", err)
2356 }
2357 }
2358
2359 func Test_Rego_ExecInContainerPolicy_DropEnvs(t *testing.T) {
2360 testFunc := func(gc *generatedConstraints) bool {
2361 gc.allowEnvironmentVariableDropping = true
2362 tc, err := setupRegoRunningContainerTest(gc, false)
2363 if err != nil {
2364 t.Error(err)
2365 return false
2366 }
2367
2368 container := selectContainerFromRunningContainers(tc.runningContainers, testRand)
2369 capabilities := container.container.Capabilities.toExternal()
2370
2371 process := selectExecProcess(container.container.ExecProcesses, testRand)
2372 expected := buildEnvironmentVariablesFromEnvRules(container.container.EnvRules, testRand)
2373
2374 extraRules := generateEnvironmentVariableRules(testRand)
2375 extraEnvs := buildEnvironmentVariablesFromEnvRules(extraRules, testRand)
2376
2377 envList := append(expected, extraEnvs...)
2378 user := buildIDNameFromConfig(container.container.User.UserIDName, testRand)
2379 groups := buildGroupIDNamesFromUser(container.container.User, testRand)
2380 umask := container.container.User.Umask
2381
2382 actual, _, _, err := tc.policy.EnforceExecInContainerPolicy(gc.ctx, container.containerID, process.Command, envList, container.container.WorkingDir, container.container.NoNewPrivileges, user, groups, umask, &capabilities)
2383
2384 if err != nil {
2385 t.Errorf("expected exec in container process to be allowed. It wasn't: %v", err)
2386 return false
2387 }
2388
2389 if !areStringArraysEqual(actual, expected) {
2390 t.Errorf("environment variables were not dropped correctly.")
2391 return false
2392 }
2393
2394 return true
2395 }
2396
2397 if err := quick.Check(testFunc, &quick.Config{MaxCount: 25, Rand: testRand}); err != nil {
2398 t.Errorf("Test_Rego_ExecInContainerPolicy_DropEnvs: %v", err)
2399 }
2400 }
2401
2402 func Test_Rego_MaliciousEnvList(t *testing.T) {
2403 template := `package policy
2404 create_container := {
2405 "allowed": true,
2406 "env_list": ["%s"]
2407 }
2408
2409 exec_in_container := {
2410 "allowed": true,
2411 "env_list": ["%s"]
2412 }
2413
2414 exec_external := {
2415 "allowed": true,
2416 "env_list": ["%s"]
2417 }`
2418
2419 generateEnv := func(r *rand.Rand) string {
2420 return randVariableString(r, maxGeneratedEnvironmentVariableRuleLength)
2421 }
2422
2423 generateEnvs := func(envSet stringSet) []string {
2424 numVars := atLeastOneAtMost(testRand, maxGeneratedEnvironmentVariableRules)
2425 return envSet.randUniqueArray(testRand, generateEnv, numVars)
2426 }
2427
2428 testFunc := func(gc *generatedConstraints) bool {
2429 envSet := make(stringSet)
2430 rego := fmt.Sprintf(
2431 template,
2432 strings.Join(generateEnvs(envSet), `","`),
2433 strings.Join(generateEnvs(envSet), `","`),
2434 strings.Join(generateEnvs(envSet), `","`))
2435
2436 policy, err := newRegoPolicy(rego, []oci.Mount{}, []oci.Mount{})
2437 if err != nil {
2438 t.Errorf("error creating policy: %v", err)
2439 return false
2440 }
2441
2442 user := generateIDName(testRand)
2443 capabilities := &oci.LinuxCapabilities{}
2444 seccomp := ""
2445
2446 envList := generateEnvs(envSet)
2447 toKeep, _, _, err := policy.EnforceCreateContainerPolicy(gc.ctx, "", "", []string{}, envList, "", []oci.Mount{}, false, true, user, nil, "", capabilities, seccomp)
2448 if len(toKeep) > 0 {
2449 t.Error("invalid environment variables not filtered from list returned from create_container")
2450 return false
2451 }
2452
2453 envList = generateEnvs(envSet)
2454 toKeep, _, _, err = policy.EnforceExecInContainerPolicy(gc.ctx, "", []string{}, envList, "", true, user, nil, "", capabilities)
2455 if len(toKeep) > 0 {
2456 t.Error("invalid environment variables not filtered from list returned from exec_in_container")
2457 return false
2458 }
2459
2460 envList = generateEnvs(envSet)
2461 toKeep, _, err = policy.EnforceExecExternalProcessPolicy(gc.ctx, []string{}, envList, "")
2462 if len(toKeep) > 0 {
2463 t.Error("invalid environment variables not filtered from list returned from exec_external")
2464 return false
2465 }
2466
2467 return true
2468 }
2469
2470 if err := quick.Check(testFunc, &quick.Config{MaxCount: 50, Rand: testRand}); err != nil {
2471 t.Errorf("Test_Rego_MaliciousEnvList: %v", err)
2472 }
2473 }
2474
2475 func Test_Rego_InvalidEnvList(t *testing.T) {
2476 rego := fmt.Sprintf(`package policy
2477 api_version := "%s"
2478 framework_version := "%s"
2479
2480 create_container := {
2481 "allowed": true,
2482 "env_list": {"an_object": 1}
2483 }
2484 exec_in_container := {
2485 "allowed": true,
2486 "env_list": "string"
2487 }
2488 exec_external := {
2489 "allowed": true,
2490 "env_list": true
2491 }`, apiVersion, frameworkVersion)
2492
2493 policy, err := newRegoPolicy(rego, []oci.Mount{}, []oci.Mount{})
2494 if err != nil {
2495 t.Fatalf("error creating policy: %v", err)
2496 }
2497
2498 ctx := context.Background()
2499 user := generateIDName(testRand)
2500 capabilities := &oci.LinuxCapabilities{}
2501 seccomp := ""
2502 _, _, _, err = policy.EnforceCreateContainerPolicy(ctx, "", "", []string{}, []string{}, "", []oci.Mount{}, false, true, user, nil, "", capabilities, seccomp)
2503 if err == nil {
2504 t.Errorf("expected call to create_container to fail")
2505 } else if err.Error() != "policy returned incorrect type for 'env_list', expected []interface{}, received map[string]interface {}" {
2506 t.Errorf("incorrected error message from call to create_container: %v", err)
2507 }
2508
2509 _, _, _, err = policy.EnforceExecInContainerPolicy(ctx, "", []string{}, []string{}, "", true, user, nil, "", capabilities)
2510 if err == nil {
2511 t.Errorf("expected call to exec_in_container to fail")
2512 } else if err.Error() != "policy returned incorrect type for 'env_list', expected []interface{}, received string" {
2513 t.Errorf("incorrected error message from call to exec_in_container: %v", err)
2514 }
2515
2516 _, _, err = policy.EnforceExecExternalProcessPolicy(ctx, []string{}, []string{}, "")
2517 if err == nil {
2518 t.Errorf("expected call to exec_external to fail")
2519 } else if err.Error() != "policy returned incorrect type for 'env_list', expected []interface{}, received bool" {
2520 t.Errorf("incorrected error message from call to exec_external: %v", err)
2521 }
2522 }
2523
2524 func Test_Rego_InvalidEnvList_Member(t *testing.T) {
2525 rego := fmt.Sprintf(`package policy
2526 api_version := "%s"
2527 framework_version := "%s"
2528
2529 create_container := {
2530 "allowed": true,
2531 "env_list": ["one", "two", 3]
2532 }
2533 exec_in_container := {
2534 "allowed": true,
2535 "env_list": ["one", true, "three"]
2536 }
2537 exec_external := {
2538 "allowed": true,
2539 "env_list": ["one", ["two"], "three"]
2540 }`, apiVersion, frameworkVersion)
2541
2542 policy, err := newRegoPolicy(rego, []oci.Mount{}, []oci.Mount{})
2543 if err != nil {
2544 t.Fatalf("error creating policy: %v", err)
2545 }
2546
2547 ctx := context.Background()
2548 user := generateIDName(testRand)
2549 capabilities := &oci.LinuxCapabilities{}
2550 seccomp := ""
2551
2552 _, _, _, err = policy.EnforceCreateContainerPolicy(ctx, "", "", []string{}, []string{}, "", []oci.Mount{}, false, true, user, nil, "", capabilities, seccomp)
2553 if err == nil {
2554 t.Errorf("expected call to create_container to fail")
2555 } else if err.Error() != "members of env_list from policy must be strings, received json.Number" {
2556 t.Errorf("incorrected error message from call to create_container: %v", err)
2557 }
2558
2559 _, _, _, err = policy.EnforceExecInContainerPolicy(ctx, "", []string{}, []string{}, "", true, user, nil, "", capabilities)
2560 if err == nil {
2561 t.Errorf("expected call to exec_in_container to fail")
2562 } else if err.Error() != "members of env_list from policy must be strings, received bool" {
2563 t.Errorf("incorrected error message from call to exec_in_container: %v", err)
2564 }
2565
2566 _, _, err = policy.EnforceExecExternalProcessPolicy(ctx, []string{}, []string{}, "")
2567 if err == nil {
2568 t.Errorf("expected call to exec_external to fail")
2569 } else if err.Error() != "members of env_list from policy must be strings, received []interface {}" {
2570 t.Errorf("incorrected error message from call to exec_external: %v", err)
2571 }
2572 }
2573
2574 func Test_Rego_EnforceEnvironmentVariablePolicy_MissingRequired(t *testing.T) {
2575 testFunc := func(gc *generatedConstraints) bool {
2576 container := selectContainerFromContainerList(gc.containers, testRand)
2577
2578 requiredRule := EnvRuleConfig{
2579 Strategy: "string",
2580 Rule: randVariableString(testRand, maxGeneratedEnvironmentVariableRuleLength),
2581 Required: true,
2582 }
2583
2584 container.EnvRules = append(container.EnvRules, requiredRule)
2585
2586 tc, err := setupRegoCreateContainerTest(gc, container, false)
2587 if err != nil {
2588 t.Error(err)
2589 return false
2590 }
2591
2592 envList := make([]string, 0, len(container.EnvRules))
2593 for _, env := range tc.envList {
2594 if env != requiredRule.Rule {
2595 envList = append(envList, env)
2596 }
2597 }
2598
2599 _, _, _, err = tc.policy.EnforceCreateContainerPolicy(gc.ctx, tc.sandboxID, tc.containerID, tc.argList, envList, tc.workingDir, tc.mounts, false, tc.noNewPrivileges, tc.user, tc.groups, tc.umask, tc.capabilities, tc.seccomp)
2600
2601
2602 if err == nil {
2603 t.Errorf("Expected container setup to fail.")
2604 return false
2605 }
2606
2607 return true
2608 }
2609
2610 if err := quick.Check(testFunc, &quick.Config{MaxCount: 50, Rand: testRand}); err != nil {
2611 t.Errorf("Test_Rego_EnforceEnvironmentVariablePolicy_MissingRequired: %v", err)
2612 }
2613 }
2614
2615 func Test_Rego_ExecExternalProcessPolicy(t *testing.T) {
2616 f := func(p *generatedConstraints) bool {
2617 tc, err := setupExternalProcessTest(p)
2618 if err != nil {
2619 t.Error(err)
2620 return false
2621 }
2622
2623 process := selectExternalProcessFromConstraints(p, testRand)
2624 envList := buildEnvironmentVariablesFromEnvRules(process.envRules, testRand)
2625
2626 _, _, err = tc.policy.EnforceExecExternalProcessPolicy(p.ctx, process.command, envList, process.workingDir)
2627 if err != nil {
2628 t.Error("Policy enforcement unexpectedly was denied")
2629 return false
2630 }
2631
2632 return true
2633 }
2634
2635 if err := quick.Check(f, &quick.Config{MaxCount: 50, Rand: testRand}); err != nil {
2636 t.Errorf("Test_Rego_ExecExternalProcessPolicy: %v", err)
2637 }
2638 }
2639
2640 func Test_Rego_ExecExternalProcessPolicy_No_Matches(t *testing.T) {
2641 f := func(p *generatedConstraints) bool {
2642 tc, err := setupExternalProcessTest(p)
2643 if err != nil {
2644 t.Error(err)
2645 return false
2646 }
2647
2648 process := generateExternalProcess(testRand)
2649 envList := buildEnvironmentVariablesFromEnvRules(process.envRules, testRand)
2650
2651 _, _, err = tc.policy.EnforceExecExternalProcessPolicy(p.ctx, process.command, envList, process.workingDir)
2652 if err == nil {
2653 t.Error("Policy was unexpectedly not enforced")
2654 return false
2655 }
2656
2657 return true
2658 }
2659
2660 if err := quick.Check(f, &quick.Config{MaxCount: 50, Rand: testRand}); err != nil {
2661 t.Errorf("Test_Rego_ExecExternalProcessPolicy_No_Matches: %v", err)
2662 }
2663 }
2664
2665 func Test_Rego_ExecExternalProcessPolicy_Command_No_Match(t *testing.T) {
2666 f := func(p *generatedConstraints) bool {
2667 tc, err := setupExternalProcessTest(p)
2668 if err != nil {
2669 t.Error(err)
2670 return false
2671 }
2672
2673 process := selectExternalProcessFromConstraints(p, testRand)
2674 envList := buildEnvironmentVariablesFromEnvRules(process.envRules, testRand)
2675 command := generateCommand(testRand)
2676
2677 _, _, err = tc.policy.EnforceExecExternalProcessPolicy(p.ctx, command, envList, process.workingDir)
2678 if err == nil {
2679 t.Error("Policy was unexpectedly not enforced")
2680 return false
2681 }
2682
2683 return assertDecisionJSONContains(t, err, "invalid command")
2684 }
2685
2686 if err := quick.Check(f, &quick.Config{MaxCount: 50, Rand: testRand}); err != nil {
2687 t.Errorf("Test_Rego_ExecExternalProcessPolicy_Command_No_Match: %v", err)
2688 }
2689 }
2690
2691 func Test_Rego_ExecExternalProcessPolicy_Some_Env_Not_Allowed(t *testing.T) {
2692 f := func(p *generatedConstraints) bool {
2693 tc, err := setupExternalProcessTest(p)
2694 if err != nil {
2695 t.Error(err)
2696 return false
2697 }
2698
2699 process := selectExternalProcessFromConstraints(p, testRand)
2700 envList := generateEnvironmentVariables(testRand)
2701
2702 _, _, err = tc.policy.EnforceExecExternalProcessPolicy(p.ctx, process.command, envList, process.workingDir)
2703 if err == nil {
2704 t.Error("Policy was unexpectedly not enforced")
2705 return false
2706 }
2707
2708 return assertDecisionJSONContains(t, err, "invalid env list")
2709 }
2710
2711 if err := quick.Check(f, &quick.Config{MaxCount: 50, Rand: testRand}); err != nil {
2712 t.Errorf("Test_Rego_ExecExternalProcessPolicy_Some_Env_Not_Allowed: %v", err)
2713 }
2714 }
2715
2716 func Test_Rego_ExecExternalProcessPolicy_WorkingDir_No_Match(t *testing.T) {
2717 f := func(p *generatedConstraints) bool {
2718 tc, err := setupExternalProcessTest(p)
2719 if err != nil {
2720 t.Error(err)
2721 return false
2722 }
2723
2724 process := selectExternalProcessFromConstraints(p, testRand)
2725 envList := buildEnvironmentVariablesFromEnvRules(process.envRules, testRand)
2726 workingDir := generateWorkingDir(testRand)
2727
2728 _, _, err = tc.policy.EnforceExecExternalProcessPolicy(p.ctx, process.command, envList, workingDir)
2729 if err == nil {
2730 t.Error("Policy was unexpectedly not enforced")
2731 return false
2732 }
2733
2734 return assertDecisionJSONContains(t, err, "invalid working directory")
2735 }
2736
2737 if err := quick.Check(f, &quick.Config{MaxCount: 50, Rand: testRand}); err != nil {
2738 t.Errorf("Test_Rego_ExecExternalProcessPolicy_WorkingDir_No_Match: %v", err)
2739 }
2740 }
2741
2742 func Test_Rego_ExecExternalProcessPolicy_DropEnvs(t *testing.T) {
2743 testFunc := func(gc *generatedConstraints) bool {
2744 gc.allowEnvironmentVariableDropping = true
2745 tc, err := setupExternalProcessTest(gc)
2746 if err != nil {
2747 t.Error(err)
2748 return false
2749 }
2750
2751 process := selectExternalProcessFromConstraints(gc, testRand)
2752 expected := buildEnvironmentVariablesFromEnvRules(process.envRules, testRand)
2753
2754 extraRules := generateEnvironmentVariableRules(testRand)
2755 extraEnvs := buildEnvironmentVariablesFromEnvRules(extraRules, testRand)
2756
2757 envList := append(expected, extraEnvs...)
2758
2759 actual, _, err := tc.policy.EnforceExecExternalProcessPolicy(gc.ctx, process.command, envList, process.workingDir)
2760
2761 if err != nil {
2762 t.Errorf("expected exec in container process to be allowed. It wasn't: %v", err)
2763 return false
2764 }
2765
2766 if !areStringArraysEqual(actual, expected) {
2767 t.Errorf("environment variables were not dropped correctly.")
2768 return false
2769 }
2770
2771 return true
2772 }
2773
2774 if err := quick.Check(testFunc, &quick.Config{MaxCount: 25, Rand: testRand}); err != nil {
2775 t.Errorf("Test_Rego_ExecExternalProcessPolicy_DropEnvs: %v", err)
2776 }
2777 }
2778
2779 func Test_Rego_ExecExternalProcessPolicy_DropEnvs_Multiple(t *testing.T) {
2780 envRules := setupEnvRuleSets(3)
2781
2782 gc := generateConstraints(testRand, 1)
2783 gc.allowEnvironmentVariableDropping = true
2784 process0 := generateExternalProcess(testRand)
2785
2786 process1 := process0.clone()
2787 process1.envRules = append(envRules[0], envRules[1]...)
2788
2789 process2 := process0.clone()
2790 process2.envRules = append(process1.envRules, envRules[2]...)
2791
2792 gc.externalProcesses = []*externalProcess{process0, process1, process2}
2793 securityPolicy := gc.toPolicy()
2794 defaultMounts := generateMounts(testRand)
2795 privilegedMounts := generateMounts(testRand)
2796
2797 policy, err := newRegoPolicy(securityPolicy.marshalRego(),
2798 toOCIMounts(defaultMounts),
2799 toOCIMounts(privilegedMounts))
2800 if err != nil {
2801 t.Fatal(err)
2802 }
2803
2804 envs0 := buildEnvironmentVariablesFromEnvRules(envRules[0], testRand)
2805 envs1 := buildEnvironmentVariablesFromEnvRules(envRules[1], testRand)
2806 envs2 := buildEnvironmentVariablesFromEnvRules(envRules[2], testRand)
2807 envList := append(envs0, envs1...)
2808 envList = append(envList, envs2...)
2809
2810 actual, _, err := policy.EnforceExecExternalProcessPolicy(gc.ctx, process2.command, envList, process2.workingDir)
2811
2812
2813 if err != nil {
2814 t.Errorf("Expected container creation to be allowed. It wasn't: %v", err)
2815 }
2816
2817 if !areStringArraysEqual(actual, envList) {
2818 t.Error("environment variables were not dropped correctly.")
2819 }
2820 }
2821
2822 func Test_Rego_ExecExternalProcessPolicy_DropEnvs_Multiple_NoMatch(t *testing.T) {
2823 envRules := setupEnvRuleSets(3)
2824
2825 gc := generateConstraints(testRand, 1)
2826 gc.allowEnvironmentVariableDropping = true
2827
2828 process0 := generateExternalProcess(testRand)
2829
2830 process1 := process0.clone()
2831 process1.envRules = append(envRules[0], envRules[1]...)
2832
2833 process2 := process0.clone()
2834 process2.envRules = append(envRules[0], envRules[2]...)
2835
2836 gc.externalProcesses = []*externalProcess{process0, process1, process2}
2837 securityPolicy := gc.toPolicy()
2838 defaultMounts := generateMounts(testRand)
2839 privilegedMounts := generateMounts(testRand)
2840
2841 policy, err := newRegoPolicy(securityPolicy.marshalRego(),
2842 toOCIMounts(defaultMounts),
2843 toOCIMounts(privilegedMounts))
2844 if err != nil {
2845 t.Fatal(err)
2846 }
2847
2848 envs0 := buildEnvironmentVariablesFromEnvRules(envRules[0], testRand)
2849 envs1 := buildEnvironmentVariablesFromEnvRules(envRules[1], testRand)
2850 envs2 := buildEnvironmentVariablesFromEnvRules(envRules[2], testRand)
2851 var extraLen int
2852 if len(envs1) > len(envs2) {
2853 extraLen = len(envs2)
2854 } else {
2855 extraLen = len(envs1)
2856 }
2857 envList := append(envs0, envs1[:extraLen]...)
2858 envList = append(envList, envs2[:extraLen]...)
2859
2860 actual, _, err := policy.EnforceExecExternalProcessPolicy(gc.ctx, process2.command, envList, process2.workingDir)
2861
2862
2863 if err == nil {
2864 t.Error("expected container creation to not be allowed.")
2865 }
2866
2867 if actual != nil {
2868 t.Error("envList should be nil.")
2869 }
2870 }
2871
2872 func Test_Rego_ShutdownContainerPolicy_Running_Container(t *testing.T) {
2873 p := generateConstraints(testRand, maxContainersInGeneratedConstraints)
2874
2875 tc, err := setupRegoRunningContainerTest(p, false)
2876 if err != nil {
2877 t.Fatalf("Unable to set up test: %v", err)
2878 }
2879
2880 container := selectContainerFromRunningContainers(tc.runningContainers, testRand)
2881
2882 err = tc.policy.EnforceShutdownContainerPolicy(p.ctx, container.containerID)
2883 if err != nil {
2884 t.Fatal("Expected shutdown of running container to be allowed, it wasn't")
2885 }
2886 }
2887
2888 func Test_Rego_ShutdownContainerPolicy_Not_Running_Container(t *testing.T) {
2889 p := generateConstraints(testRand, maxContainersInGeneratedConstraints)
2890
2891 tc, err := setupRegoRunningContainerTest(p, false)
2892 if err != nil {
2893 t.Fatalf("Unable to set up test: %v", err)
2894 }
2895
2896 notRunningContainerID := testDataGenerator.uniqueContainerID()
2897
2898 err = tc.policy.EnforceShutdownContainerPolicy(p.ctx, notRunningContainerID)
2899 if err == nil {
2900 t.Fatal("Expected shutdown of not running container to be denied, it wasn't")
2901 }
2902 }
2903
2904 func Test_Rego_SignalContainerProcessPolicy_InitProcess_Allowed(t *testing.T) {
2905 f := func(p *generatedConstraints) bool {
2906 hasAllowedSignals := generateConstraintsContainer(testRand, 1, maxLayersInGeneratedContainer)
2907 hasAllowedSignals.Signals = generateListOfSignals(testRand, 1, maxSignalNumber)
2908 p.containers = append(p.containers, hasAllowedSignals)
2909
2910 tc, err := setupRegoRunningContainerTest(p, false)
2911 if err != nil {
2912 t.Error(err)
2913 return false
2914 }
2915
2916 containerID, err := idForRunningContainer(hasAllowedSignals, tc.runningContainers)
2917 if err != nil {
2918 r, err := runContainer(tc.policy, hasAllowedSignals, tc.defaultMounts, tc.privilegedMounts, false)
2919 if err != nil {
2920 t.Errorf("Unable to setup test running container: %v", err)
2921 return false
2922 }
2923 containerID = r.containerID
2924 }
2925
2926 signal := selectSignalFromSignals(testRand, hasAllowedSignals.Signals)
2927 err = tc.policy.EnforceSignalContainerProcessPolicy(p.ctx, containerID, signal, true, hasAllowedSignals.Command)
2928
2929 if err != nil {
2930 t.Errorf("Signal init process unexpectedly failed: %v", err)
2931 return false
2932 }
2933
2934 return true
2935 }
2936
2937 if err := quick.Check(f, &quick.Config{MaxCount: 25, Rand: testRand}); err != nil {
2938 t.Errorf("Test_Rego_SignalContainerProcessPolicy_InitProcess_Allowed: %v", err)
2939 }
2940 }
2941
2942 func Test_Rego_SignalContainerProcessPolicy_InitProcess_Not_Allowed(t *testing.T) {
2943 f := func(p *generatedConstraints) bool {
2944 hasNoAllowedSignals := generateConstraintsContainer(testRand, 1, maxLayersInGeneratedContainer)
2945 hasNoAllowedSignals.Signals = make([]syscall.Signal, 0)
2946
2947 p.containers = append(p.containers, hasNoAllowedSignals)
2948
2949 tc, err := setupRegoRunningContainerTest(p, false)
2950 if err != nil {
2951 t.Error(err)
2952 return false
2953 }
2954
2955 containerID, err := idForRunningContainer(hasNoAllowedSignals, tc.runningContainers)
2956 if err != nil {
2957 r, err := runContainer(tc.policy, hasNoAllowedSignals, tc.defaultMounts, tc.privilegedMounts, false)
2958 if err != nil {
2959 t.Errorf("Unable to setup test running container: %v", err)
2960 return false
2961 }
2962 containerID = r.containerID
2963 }
2964
2965 signal := generateSignal(testRand)
2966 err = tc.policy.EnforceSignalContainerProcessPolicy(p.ctx, containerID, signal, true, hasNoAllowedSignals.Command)
2967
2968 if err == nil {
2969 t.Errorf("Signal init process unexpectedly passed: %v", err)
2970 return false
2971 }
2972
2973 return true
2974 }
2975
2976 if err := quick.Check(f, &quick.Config{MaxCount: 25, Rand: testRand}); err != nil {
2977 t.Errorf("Test_Rego_SignalContainerProcessPolicy_InitProcess_Not_Allowed: %v", err)
2978 }
2979 }
2980
2981 func Test_Rego_SignalContainerProcessPolicy_InitProcess_Bad_ContainerID(t *testing.T) {
2982 f := func(p *generatedConstraints) bool {
2983 hasAllowedSignals := generateConstraintsContainer(testRand, 1, maxLayersInGeneratedContainer)
2984 hasAllowedSignals.Signals = generateListOfSignals(testRand, 1, maxSignalNumber)
2985 p.containers = append(p.containers, hasAllowedSignals)
2986
2987 tc, err := setupRegoRunningContainerTest(p, false)
2988 if err != nil {
2989 t.Error(err)
2990 return false
2991 }
2992
2993 _, err = idForRunningContainer(hasAllowedSignals, tc.runningContainers)
2994 if err != nil {
2995 _, err := runContainer(tc.policy, hasAllowedSignals, tc.defaultMounts, tc.privilegedMounts, false)
2996 if err != nil {
2997 t.Errorf("Unable to setup test running container: %v", err)
2998 return false
2999 }
3000 }
3001
3002 signal := selectSignalFromSignals(testRand, hasAllowedSignals.Signals)
3003 badContainerID := generateContainerID(testRand)
3004 err = tc.policy.EnforceSignalContainerProcessPolicy(p.ctx, badContainerID, signal, true, hasAllowedSignals.Command)
3005
3006 if err == nil {
3007 t.Errorf("Signal init process unexpectedly succeeded: %v", err)
3008 return false
3009 }
3010
3011 return true
3012 }
3013
3014 if err := quick.Check(f, &quick.Config{MaxCount: 25, Rand: testRand}); err != nil {
3015 t.Errorf("Test_Rego_SignalContainerProcessPolicy_InitProcess_Bad_ContainerID: %v", err)
3016 }
3017 }
3018
3019 func Test_Rego_SignalContainerProcessPolicy_ExecProcess_Allowed(t *testing.T) {
3020 f := func(p *generatedConstraints) bool {
3021 containerUnderTest := generateConstraintsContainer(testRand, 1, maxLayersInGeneratedContainer)
3022
3023 ep := generateExecProcesses(testRand)
3024 ep[0].Signals = generateListOfSignals(testRand, 1, 4)
3025 containerUnderTest.ExecProcesses = ep
3026 processUnderTest := ep[0]
3027
3028 p.containers = append(p.containers, containerUnderTest)
3029
3030 tc, err := setupRegoRunningContainerTest(p, false)
3031 if err != nil {
3032 t.Error(err)
3033 return false
3034 }
3035
3036 containerID, err := idForRunningContainer(containerUnderTest, tc.runningContainers)
3037 if err != nil {
3038 r, err := runContainer(tc.policy, containerUnderTest, tc.defaultMounts, tc.privilegedMounts, false)
3039 if err != nil {
3040 t.Errorf("Unable to setup test running container: %v", err)
3041 return false
3042 }
3043 containerID = r.containerID
3044 }
3045
3046 envList := buildEnvironmentVariablesFromEnvRules(containerUnderTest.EnvRules, testRand)
3047 user := buildIDNameFromConfig(containerUnderTest.User.UserIDName, testRand)
3048 groups := buildGroupIDNamesFromUser(containerUnderTest.User, testRand)
3049 umask := containerUnderTest.User.Umask
3050 capabilities := containerUnderTest.Capabilities.toExternal()
3051
3052 _, _, _, err = tc.policy.EnforceExecInContainerPolicy(p.ctx, containerID, processUnderTest.Command, envList, containerUnderTest.WorkingDir, containerUnderTest.NoNewPrivileges, user, groups, umask, &capabilities)
3053 if err != nil {
3054 t.Errorf("Unable to exec process for test: %v", err)
3055 return false
3056 }
3057
3058 signal := selectSignalFromSignals(testRand, processUnderTest.Signals)
3059
3060 err = tc.policy.EnforceSignalContainerProcessPolicy(p.ctx, containerID, signal, false, processUnderTest.Command)
3061 if err != nil {
3062 t.Errorf("Signal init process unexpectedly failed: %v", err)
3063 return false
3064 }
3065
3066 return true
3067 }
3068
3069 if err := quick.Check(f, &quick.Config{MaxCount: 25, Rand: testRand}); err != nil {
3070 t.Errorf("Test_Rego_SignalContainerProcessPolicy_ExecProcess_Allowed: %v", err)
3071 }
3072 }
3073
3074 func Test_Rego_SignalContainerProcessPolicy_ExecProcess_Not_Allowed(t *testing.T) {
3075 f := func(p *generatedConstraints) bool {
3076 containerUnderTest := generateConstraintsContainer(testRand, 1, maxLayersInGeneratedContainer)
3077
3078 ep := generateExecProcesses(testRand)
3079 ep[0].Signals = make([]syscall.Signal, 0)
3080 containerUnderTest.ExecProcesses = ep
3081 processUnderTest := ep[0]
3082
3083 p.containers = append(p.containers, containerUnderTest)
3084
3085 tc, err := setupRegoRunningContainerTest(p, false)
3086 if err != nil {
3087 t.Error(err)
3088 return false
3089 }
3090
3091 containerID, err := idForRunningContainer(containerUnderTest, tc.runningContainers)
3092 if err != nil {
3093 r, err := runContainer(tc.policy, containerUnderTest, tc.defaultMounts, tc.privilegedMounts, false)
3094 if err != nil {
3095 t.Errorf("Unable to setup test running container: %v", err)
3096 return false
3097 }
3098 containerID = r.containerID
3099 }
3100
3101 envList := buildEnvironmentVariablesFromEnvRules(containerUnderTest.EnvRules, testRand)
3102 user := buildIDNameFromConfig(containerUnderTest.User.UserIDName, testRand)
3103 groups := buildGroupIDNamesFromUser(containerUnderTest.User, testRand)
3104 umask := containerUnderTest.User.Umask
3105 capabilities := containerUnderTest.Capabilities.toExternal()
3106
3107 _, _, _, err = tc.policy.EnforceExecInContainerPolicy(p.ctx, containerID, processUnderTest.Command, envList, containerUnderTest.WorkingDir, containerUnderTest.NoNewPrivileges, user, groups, umask, &capabilities)
3108 if err != nil {
3109 t.Errorf("Unable to exec process for test: %v", err)
3110 return false
3111 }
3112
3113 signal := generateSignal(testRand)
3114
3115 err = tc.policy.EnforceSignalContainerProcessPolicy(p.ctx, containerID, signal, false, processUnderTest.Command)
3116 if err == nil {
3117 t.Errorf("Signal init process unexpectedly succeeded: %v", err)
3118 return false
3119 }
3120
3121 return true
3122 }
3123
3124 if err := quick.Check(f, &quick.Config{MaxCount: 25, Rand: testRand}); err != nil {
3125 t.Errorf("Test_Rego_SignalContainerProcessPolicy_ExecProcess_Not_Allowed: %v", err)
3126 }
3127 }
3128
3129 func Test_Rego_SignalContainerProcessPolicy_ExecProcess_Bad_Command(t *testing.T) {
3130 f := func(p *generatedConstraints) bool {
3131 containerUnderTest := generateConstraintsContainer(testRand, 1, maxLayersInGeneratedContainer)
3132
3133 ep := generateExecProcesses(testRand)
3134 ep[0].Signals = generateListOfSignals(testRand, 1, 4)
3135 containerUnderTest.ExecProcesses = ep
3136 processUnderTest := ep[0]
3137
3138 p.containers = append(p.containers, containerUnderTest)
3139
3140 tc, err := setupRegoRunningContainerTest(p, false)
3141 if err != nil {
3142 t.Error(err)
3143 return false
3144 }
3145
3146 containerID, err := idForRunningContainer(containerUnderTest, tc.runningContainers)
3147 if err != nil {
3148 r, err := runContainer(tc.policy, containerUnderTest, tc.defaultMounts, tc.privilegedMounts, false)
3149 if err != nil {
3150 t.Errorf("Unable to setup test running container: %v", err)
3151 return false
3152 }
3153 containerID = r.containerID
3154 }
3155
3156 envList := buildEnvironmentVariablesFromEnvRules(containerUnderTest.EnvRules, testRand)
3157 user := buildIDNameFromConfig(containerUnderTest.User.UserIDName, testRand)
3158 groups := buildGroupIDNamesFromUser(containerUnderTest.User, testRand)
3159 umask := containerUnderTest.User.Umask
3160 capabilities := containerUnderTest.Capabilities.toExternal()
3161
3162 _, _, _, err = tc.policy.EnforceExecInContainerPolicy(p.ctx, containerID, processUnderTest.Command, envList, containerUnderTest.WorkingDir, containerUnderTest.NoNewPrivileges, user, groups, umask, &capabilities)
3163 if err != nil {
3164 t.Errorf("Unable to exec process for test: %v", err)
3165 return false
3166 }
3167
3168 signal := selectSignalFromSignals(testRand, processUnderTest.Signals)
3169 badCommand := generateCommand(testRand)
3170
3171 err = tc.policy.EnforceSignalContainerProcessPolicy(p.ctx, containerID, signal, false, badCommand)
3172 if err == nil {
3173 t.Errorf("Signal init process unexpectedly succeeded: %v", err)
3174 return false
3175 }
3176
3177 return true
3178 }
3179
3180 if err := quick.Check(f, &quick.Config{MaxCount: 25, Rand: testRand}); err != nil {
3181 t.Errorf("Test_Rego_SignalContainerProcessPolicy_ExecProcess_Bad_Command: %v", err)
3182 }
3183 }
3184
3185 func Test_Rego_SignalContainerProcessPolicy_ExecProcess_Bad_ContainerID(t *testing.T) {
3186 f := func(p *generatedConstraints) bool {
3187 containerUnderTest := generateConstraintsContainer(testRand, 1, maxLayersInGeneratedContainer)
3188
3189 ep := generateExecProcesses(testRand)
3190 ep[0].Signals = generateListOfSignals(testRand, 1, 4)
3191 containerUnderTest.ExecProcesses = ep
3192 processUnderTest := ep[0]
3193
3194 p.containers = append(p.containers, containerUnderTest)
3195
3196 tc, err := setupRegoRunningContainerTest(p, false)
3197 if err != nil {
3198 t.Error(err)
3199 return false
3200 }
3201
3202 containerID, err := idForRunningContainer(containerUnderTest, tc.runningContainers)
3203 if err != nil {
3204 r, err := runContainer(tc.policy, containerUnderTest, tc.defaultMounts, tc.privilegedMounts, false)
3205 if err != nil {
3206 t.Errorf("Unable to setup test running container: %v", err)
3207 return false
3208 }
3209 containerID = r.containerID
3210 }
3211
3212 envList := buildEnvironmentVariablesFromEnvRules(containerUnderTest.EnvRules, testRand)
3213 user := buildIDNameFromConfig(containerUnderTest.User.UserIDName, testRand)
3214 groups := buildGroupIDNamesFromUser(containerUnderTest.User, testRand)
3215 umask := containerUnderTest.User.Umask
3216 capabilities := containerUnderTest.Capabilities.toExternal()
3217
3218 _, _, _, err = tc.policy.EnforceExecInContainerPolicy(p.ctx, containerID, processUnderTest.Command, envList, containerUnderTest.WorkingDir, containerUnderTest.NoNewPrivileges, user, groups, umask, &capabilities)
3219 if err != nil {
3220 t.Errorf("Unable to exec process for test: %v", err)
3221 return false
3222 }
3223
3224 signal := selectSignalFromSignals(testRand, processUnderTest.Signals)
3225 badContainerID := generateContainerID(testRand)
3226
3227 err = tc.policy.EnforceSignalContainerProcessPolicy(p.ctx, badContainerID, signal, false, processUnderTest.Command)
3228 if err == nil {
3229 t.Errorf("Signal init process unexpectedly succeeded: %v", err)
3230 return false
3231 }
3232
3233 return true
3234 }
3235
3236 if err := quick.Check(f, &quick.Config{MaxCount: 25, Rand: testRand}); err != nil {
3237 t.Errorf("Test_Rego_SignalContainerProcessPolicy_ExecProcess_Bad_ContainerID: %v", err)
3238 }
3239 }
3240
3241 func Test_Rego_Plan9MountPolicy(t *testing.T) {
3242 gc := generateConstraints(testRand, maxContainersInGeneratedConstraints)
3243
3244 tc, err := setupPlan9MountTest(gc)
3245 if err != nil {
3246 t.Fatalf("unable to setup test: %v", err)
3247 }
3248
3249 err = tc.policy.EnforcePlan9MountPolicy(gc.ctx, tc.uvmPathForShare)
3250 if err != nil {
3251 t.Fatalf("Policy enforcement unexpectedly was denied: %v", err)
3252 }
3253
3254 _, _, _, err = tc.policy.EnforceCreateContainerPolicy(
3255 gc.ctx,
3256 tc.sandboxID,
3257 tc.containerID,
3258 tc.argList,
3259 tc.envList,
3260 tc.workingDir,
3261 tc.mounts,
3262 false,
3263 tc.noNewPrivileges,
3264 tc.user,
3265 tc.groups,
3266 tc.umask,
3267 tc.capabilities,
3268 tc.seccomp,
3269 )
3270
3271 if err != nil {
3272 t.Fatalf("Policy enforcement unexpectedly was denied: %v", err)
3273 }
3274 }
3275
3276 func Test_Rego_Plan9MountPolicy_No_Matches(t *testing.T) {
3277 gc := generateConstraints(testRand, maxContainersInGeneratedConstraints)
3278
3279 tc, err := setupPlan9MountTest(gc)
3280 if err != nil {
3281 t.Fatalf("unable to setup test: %v", err)
3282 }
3283
3284 mount := generateUVMPathForShare(testRand, tc.containerID)
3285 for {
3286 if mount != tc.uvmPathForShare {
3287 break
3288 }
3289 mount = generateUVMPathForShare(testRand, tc.containerID)
3290 }
3291
3292 err = tc.policy.EnforcePlan9MountPolicy(gc.ctx, mount)
3293 if err != nil {
3294 t.Fatalf("Policy enforcement unexpectedly was denied: %v", err)
3295 }
3296
3297 _, _, _, err = tc.policy.EnforceCreateContainerPolicy(
3298 gc.ctx,
3299 tc.sandboxID,
3300 tc.containerID,
3301 tc.argList,
3302 tc.envList,
3303 tc.workingDir,
3304 tc.mounts,
3305 false,
3306 tc.noNewPrivileges,
3307 tc.user,
3308 tc.groups,
3309 tc.umask,
3310 tc.capabilities,
3311 tc.seccomp,
3312 )
3313
3314 if err == nil {
3315 t.Fatal("Policy enforcement unexpectedly was allowed")
3316 }
3317 }
3318
3319 func Test_Rego_Plan9MountPolicy_Invalid(t *testing.T) {
3320 gc := generateConstraints(testRand, maxContainersInGeneratedConstraints)
3321
3322 tc, err := setupPlan9MountTest(gc)
3323 if err != nil {
3324 t.Fatalf("unable to setup test: %v", err)
3325 }
3326
3327 mount := randString(testRand, maxGeneratedMountSourceLength)
3328 err = tc.policy.EnforcePlan9MountPolicy(gc.ctx, mount)
3329 if err == nil {
3330 t.Fatal("Policy enforcement unexpectedly was allowed", err)
3331 }
3332 }
3333
3334 func Test_Rego_Plan9UnmountPolicy(t *testing.T) {
3335 gc := generateConstraints(testRand, maxContainersInGeneratedConstraints)
3336
3337 tc, err := setupPlan9MountTest(gc)
3338 if err != nil {
3339 t.Fatalf("unable to setup test: %v", err)
3340 }
3341
3342 err = tc.policy.EnforcePlan9MountPolicy(gc.ctx, tc.uvmPathForShare)
3343 if err != nil {
3344 t.Fatalf("Couldn't mount as part of setup: %v", err)
3345 }
3346
3347 err = tc.policy.EnforcePlan9UnmountPolicy(gc.ctx, tc.uvmPathForShare)
3348 if err != nil {
3349 t.Fatalf("Policy enforcement unexpectedly was denied: %v", err)
3350 }
3351
3352 _, _, _, err = tc.policy.EnforceCreateContainerPolicy(
3353 gc.ctx,
3354 tc.sandboxID,
3355 tc.containerID,
3356 tc.argList,
3357 tc.envList,
3358 tc.workingDir,
3359 tc.mounts,
3360 false,
3361 tc.noNewPrivileges,
3362 tc.user,
3363 tc.groups,
3364 tc.umask,
3365 tc.capabilities,
3366 tc.seccomp,
3367 )
3368
3369 if err == nil {
3370 t.Fatal("Policy enforcement unexpectedly was allowed")
3371 }
3372 }
3373
3374 func Test_Rego_Plan9UnmountPolicy_No_Matches(t *testing.T) {
3375 gc := generateConstraints(testRand, maxContainersInGeneratedConstraints)
3376
3377 tc, err := setupPlan9MountTest(gc)
3378 if err != nil {
3379 t.Fatalf("unable to setup test: %v", err)
3380 }
3381
3382 mount := generateUVMPathForShare(testRand, tc.containerID)
3383 err = tc.policy.EnforcePlan9MountPolicy(gc.ctx, mount)
3384 if err != nil {
3385 t.Fatalf("Couldn't mount as part of setup: %v", err)
3386 }
3387
3388 badMount := randString(testRand, maxPlan9MountTargetLength)
3389 err = tc.policy.EnforcePlan9UnmountPolicy(gc.ctx, badMount)
3390 if err == nil {
3391 t.Fatalf("Policy enforcement unexpectedly was allowed")
3392 }
3393 }
3394
3395 func Test_Rego_GetPropertiesPolicy_On(t *testing.T) {
3396 f := func(constraints *generatedConstraints) bool {
3397 tc, err := setupGetPropertiesTest(constraints, true)
3398 if err != nil {
3399 t.Error(err)
3400 return false
3401 }
3402
3403 err = tc.policy.EnforceGetPropertiesPolicy(constraints.ctx)
3404 if err != nil {
3405 t.Error("Policy enforcement unexpectedly was denied")
3406 return false
3407 }
3408
3409 return true
3410 }
3411
3412 if err := quick.Check(f, &quick.Config{MaxCount: 50}); err != nil {
3413 t.Errorf("Test_Rego_GetPropertiesPolicy_On: %v", err)
3414 }
3415 }
3416
3417 func Test_Rego_GetPropertiesPolicy_Off(t *testing.T) {
3418 f := func(constraints *generatedConstraints) bool {
3419 tc, err := setupGetPropertiesTest(constraints, false)
3420 if err != nil {
3421 t.Error(err)
3422 return false
3423 }
3424
3425 err = tc.policy.EnforceGetPropertiesPolicy(constraints.ctx)
3426 if err == nil {
3427 t.Error("Policy enforcement unexpectedly was allowed")
3428 return false
3429 }
3430
3431 return true
3432 }
3433
3434 if err := quick.Check(f, &quick.Config{MaxCount: 50}); err != nil {
3435 t.Errorf("Test_Rego_GetPropertiesPolicy_Off: %v", err)
3436 }
3437 }
3438
3439 func Test_Rego_DumpStacksPolicy_On(t *testing.T) {
3440 f := func(constraints *generatedConstraints) bool {
3441 tc, err := setupDumpStacksTest(constraints, true)
3442 if err != nil {
3443 t.Error(err)
3444 return false
3445 }
3446
3447 err = tc.policy.EnforceDumpStacksPolicy(constraints.ctx)
3448 if err != nil {
3449 t.Errorf("Policy enforcement unexpectedly was denied: %v", err)
3450 return false
3451 }
3452
3453 return true
3454 }
3455
3456 if err := quick.Check(f, &quick.Config{MaxCount: 50}); err != nil {
3457 t.Errorf("Test_Rego_DumpStacksPolicy_On: %v", err)
3458 }
3459 }
3460
3461 func Test_Rego_DumpStacksPolicy_Off(t *testing.T) {
3462 f := func(constraints *generatedConstraints) bool {
3463 tc, err := setupDumpStacksTest(constraints, false)
3464 if err != nil {
3465 t.Error(err)
3466 return false
3467 }
3468
3469 err = tc.policy.EnforceDumpStacksPolicy(constraints.ctx)
3470 if err == nil {
3471 t.Error("Policy enforcement unexpectedly was allowed")
3472 return false
3473 }
3474
3475 return true
3476 }
3477
3478 if err := quick.Check(f, &quick.Config{MaxCount: 50}); err != nil {
3479 t.Errorf("Test_Rego_DumpStacksPolicy_Off: %v", err)
3480 }
3481 }
3482
3483 func Test_EnforceRuntimeLogging_Allowed(t *testing.T) {
3484 gc := generateConstraints(testRand, maxContainersInGeneratedConstraints)
3485 gc.allowRuntimeLogging = true
3486
3487 tc, err := setupRegoPolicyOnlyTest(gc)
3488 if err != nil {
3489 t.Fatalf("unable to setup test: %v", err)
3490 }
3491
3492 err = tc.policy.EnforceRuntimeLoggingPolicy(gc.ctx)
3493 if err != nil {
3494 t.Fatalf("Policy enforcement unexpectedly was denied: %v", err)
3495 }
3496 }
3497
3498 func Test_EnforceRuntimeLogging_Not_Allowed(t *testing.T) {
3499 gc := generateConstraints(testRand, maxContainersInGeneratedConstraints)
3500 gc.allowRuntimeLogging = false
3501
3502 tc, err := setupRegoPolicyOnlyTest(gc)
3503 if err != nil {
3504 t.Fatalf("unable to setup test: %v", err)
3505 }
3506
3507 err = tc.policy.EnforceRuntimeLoggingPolicy(gc.ctx)
3508 if err == nil {
3509 t.Fatalf("Policy enforcement unexpectedly was allowed")
3510 }
3511 }
3512
3513 func Test_Rego_LoadFragment_Container(t *testing.T) {
3514 f := func(p *generatedConstraints) bool {
3515 tc, err := setupRegoFragmentTestConfigWithIncludes(p, []string{"containers"})
3516 if err != nil {
3517 t.Error(err)
3518 return false
3519 }
3520
3521 fragment := tc.fragments[0]
3522 container := tc.containers[0]
3523
3524 err = tc.policy.LoadFragment(p.ctx, fragment.info.issuer, fragment.info.feed, fragment.code)
3525 if err != nil {
3526 t.Error("unable to load fragment: %w", err)
3527 return false
3528 }
3529
3530 containerID, err := mountImageForContainer(tc.policy, container.container)
3531 if err != nil {
3532 t.Error("unable to mount image for fragment container: %w", err)
3533 return false
3534 }
3535
3536 _, _, _, err = tc.policy.EnforceCreateContainerPolicy(p.ctx,
3537 container.sandboxID,
3538 containerID,
3539 copyStrings(container.container.Command),
3540 copyStrings(container.envList),
3541 container.container.WorkingDir,
3542 copyMounts(container.mounts),
3543 false,
3544 container.container.NoNewPrivileges,
3545 container.user,
3546 container.groups,
3547 container.container.User.Umask,
3548 container.capabilities,
3549 container.seccomp,
3550 )
3551
3552 if err != nil {
3553 t.Error("unable to create container from fragment: %w", err)
3554 return false
3555 }
3556
3557 if tc.policy.rego.IsModuleActive(rpi.ModuleID(fragment.info.issuer, fragment.info.feed)) {
3558 t.Error("module not removed after load")
3559 return false
3560 }
3561
3562 return true
3563 }
3564
3565 if err := quick.Check(f, &quick.Config{MaxCount: 25, Rand: testRand}); err != nil {
3566 t.Errorf("Test_Rego_LoadFragment_Container: %v", err)
3567 }
3568 }
3569
3570 func Test_Rego_LoadFragment_Fragment(t *testing.T) {
3571 f := func(p *generatedConstraints) bool {
3572 tc, err := setupRegoFragmentTestConfigWithIncludes(p, []string{"fragments"})
3573 if err != nil {
3574 t.Error(err)
3575 return false
3576 }
3577
3578 fragment := tc.fragments[0]
3579 subFragment := tc.subFragments[0]
3580
3581 err = tc.policy.LoadFragment(p.ctx, fragment.info.issuer, fragment.info.feed, fragment.code)
3582 if err != nil {
3583 t.Error("unable to load fragment: %w", err)
3584 return false
3585 }
3586
3587 err = tc.policy.LoadFragment(p.ctx, subFragment.info.issuer, subFragment.info.feed, subFragment.code)
3588 if err != nil {
3589 t.Error("unable to load sub-fragment from fragment: %w", err)
3590 return false
3591 }
3592
3593 container := selectContainerFromContainerList(subFragment.constraints.containers, testRand)
3594 _, err = mountImageForContainer(tc.policy, container)
3595 if err != nil {
3596 t.Error("unable to mount image for sub-fragment container: %w", err)
3597 return false
3598 }
3599
3600 if tc.policy.rego.IsModuleActive(rpi.ModuleID(fragment.info.issuer, fragment.info.feed)) {
3601 t.Error("module not removed after load")
3602 return false
3603 }
3604
3605 return true
3606 }
3607
3608 if err := quick.Check(f, &quick.Config{MaxCount: 15, Rand: testRand}); err != nil {
3609 t.Errorf("Test_Rego_LoadFragment_Fragment: %v", err)
3610 }
3611 }
3612
3613 func Test_Rego_LoadFragment_ExternalProcess(t *testing.T) {
3614 f := func(p *generatedConstraints) bool {
3615 tc, err := setupRegoFragmentTestConfigWithIncludes(p, []string{"external_processes"})
3616 if err != nil {
3617 t.Error(err)
3618 return false
3619 }
3620
3621 fragment := tc.fragments[0]
3622 process := tc.externalProcesses[0]
3623
3624 err = tc.policy.LoadFragment(p.ctx, fragment.info.issuer, fragment.info.feed, fragment.code)
3625 if err != nil {
3626 t.Error("unable to load fragment: %w", err)
3627 return false
3628 }
3629
3630 envList := buildEnvironmentVariablesFromEnvRules(process.envRules, testRand)
3631 _, _, err = tc.policy.EnforceExecExternalProcessPolicy(p.ctx, process.command, envList, process.workingDir)
3632 if err != nil {
3633 t.Error("unable to execute external process from fragment: %w", err)
3634 return false
3635 }
3636
3637 if tc.policy.rego.IsModuleActive(rpi.ModuleID(fragment.info.issuer, fragment.info.feed)) {
3638 t.Error("module not removed after load")
3639 return false
3640 }
3641
3642 return true
3643 }
3644
3645 if err := quick.Check(f, &quick.Config{MaxCount: 25, Rand: testRand}); err != nil {
3646 t.Errorf("Test_Rego_LoadFragment_ExternalProcess: %v", err)
3647 }
3648 }
3649
3650 func Test_Rego_LoadFragment_BadIssuer(t *testing.T) {
3651 f := func(p *generatedConstraints) bool {
3652 tc, err := setupSimpleRegoFragmentTestConfig(p)
3653 if err != nil {
3654 t.Error(err)
3655 return false
3656 }
3657
3658 fragment := tc.fragments[0]
3659 issuer := testDataGenerator.uniqueFragmentIssuer()
3660 err = tc.policy.LoadFragment(p.ctx, issuer, fragment.info.feed, fragment.code)
3661 if err == nil {
3662 t.Error("expected to be unable to load fragment due to bad issuer")
3663 return false
3664 }
3665
3666 if !assertDecisionJSONContains(t, err, "invalid fragment issuer") {
3667 t.Error("expected error string to contain 'invalid fragment issuer'")
3668 return false
3669 }
3670
3671 if tc.policy.rego.IsModuleActive(rpi.ModuleID(issuer, fragment.info.feed)) {
3672 t.Error("module not removed upon failure")
3673 return false
3674 }
3675
3676 return true
3677 }
3678
3679 if err := quick.Check(f, &quick.Config{MaxCount: 25, Rand: testRand}); err != nil {
3680 t.Errorf("Test_Rego_LoadFragment_BadIssuer: %v", err)
3681 }
3682 }
3683
3684 func Test_Rego_LoadFragment_BadFeed(t *testing.T) {
3685 f := func(p *generatedConstraints) bool {
3686 tc, err := setupSimpleRegoFragmentTestConfig(p)
3687 if err != nil {
3688 t.Error(err)
3689 return false
3690 }
3691
3692 fragment := tc.fragments[0]
3693 feed := testDataGenerator.uniqueFragmentFeed()
3694 err = tc.policy.LoadFragment(p.ctx, fragment.info.issuer, feed, fragment.code)
3695 if err == nil {
3696 t.Error("expected to be unable to load fragment due to bad feed")
3697 return false
3698 }
3699
3700 if !assertDecisionJSONContains(t, err, "invalid fragment feed") {
3701 t.Error("expected error string to contain 'invalid fragment feed'")
3702 return false
3703 }
3704
3705 if tc.policy.rego.IsModuleActive(rpi.ModuleID(fragment.info.issuer, feed)) {
3706 t.Error("module not removed upon failure")
3707 return false
3708 }
3709
3710 return true
3711 }
3712
3713 if err := quick.Check(f, &quick.Config{MaxCount: 25, Rand: testRand}); err != nil {
3714 t.Errorf("Test_Rego_LoadFragment_BadFeed: %v", err)
3715 }
3716 }
3717
3718 func Test_Rego_LoadFragment_InvalidSVN(t *testing.T) {
3719 f := func(p *generatedConstraints) bool {
3720 tc, err := setupRegoFragmentSVNErrorTestConfig(p)
3721 if err != nil {
3722 t.Error(err)
3723 return false
3724 }
3725
3726 fragment := tc.fragments[0]
3727 err = tc.policy.LoadFragment(p.ctx, fragment.info.issuer, fragment.info.feed, fragment.code)
3728 if err == nil {
3729 t.Error("expected to be unable to load fragment due to invalid svn")
3730 return false
3731 }
3732
3733 if !assertDecisionJSONContains(t, err, "fragment svn is below the specified minimum") {
3734 t.Error("expected error string to contain 'fragment svn is below the specified minimum'")
3735 return false
3736 }
3737
3738 if tc.policy.rego.IsModuleActive(rpi.ModuleID(fragment.info.issuer, fragment.info.feed)) {
3739 t.Error("module not removed upon failure")
3740 return false
3741 }
3742
3743 return true
3744 }
3745
3746 if err := quick.Check(f, &quick.Config{MaxCount: 25, Rand: testRand}); err != nil {
3747 t.Errorf("Test_Rego_LoadFragment_InvalidSVN: %v", err)
3748 }
3749 }
3750
3751 func Test_Rego_LoadFragment_Fragment_InvalidSVN(t *testing.T) {
3752 f := func(p *generatedConstraints) bool {
3753 tc, err := setupRegoSubfragmentSVNErrorTestConfig(p)
3754 if err != nil {
3755 t.Error(err)
3756 return false
3757 }
3758
3759 fragment := tc.fragments[0]
3760 err = tc.policy.LoadFragment(p.ctx, fragment.info.issuer, fragment.info.feed, fragment.code)
3761 if err != nil {
3762 t.Error("unable to load fragment: %w", err)
3763 return false
3764 }
3765
3766 subFragment := tc.subFragments[0]
3767 err = tc.policy.LoadFragment(p.ctx, subFragment.info.issuer, subFragment.info.feed, subFragment.code)
3768 if err == nil {
3769 t.Error("expected to be unable to load subfragment due to invalid svn")
3770 return false
3771 }
3772
3773 if !assertDecisionJSONContains(t, err, "fragment svn is below the specified minimum") {
3774 t.Error("expected error string to contain 'fragment svn is below the specified minimum'")
3775 return false
3776 }
3777
3778 if tc.policy.rego.IsModuleActive(rpi.ModuleID(subFragment.info.issuer, fragment.info.feed)) {
3779 t.Error("module not removed upon failure")
3780 return false
3781 }
3782
3783 return true
3784 }
3785
3786 if err := quick.Check(f, &quick.Config{MaxCount: 25, Rand: testRand}); err != nil {
3787 t.Errorf("Test_Rego_LoadFragment_Fragment_InvalidSVN: %v", err)
3788 }
3789 }
3790
3791 func Test_Rego_LoadFragment_SemverVersion(t *testing.T) {
3792 f := func(p *generatedConstraints) bool {
3793 p.fragments = generateFragments(testRand, 1)
3794 p.fragments[0].minimumSVN = generateSemver(testRand)
3795 securityPolicy := p.toPolicy()
3796
3797 defaultMounts := toOCIMounts(generateMounts(testRand))
3798 privilegedMounts := toOCIMounts(generateMounts(testRand))
3799 policy, err := newRegoPolicy(securityPolicy.marshalRego(), defaultMounts, privilegedMounts)
3800
3801 if err != nil {
3802 t.Fatalf("error compiling policy: %v", err)
3803 }
3804
3805 issuer := p.fragments[0].issuer
3806 feed := p.fragments[0].feed
3807
3808 fragmentConstraints := generateConstraints(testRand, 1)
3809 fragmentConstraints.svn = mustIncrementSVN(p.fragments[0].minimumSVN)
3810 code := fragmentConstraints.toFragment().marshalRego()
3811
3812 err = policy.LoadFragment(p.ctx, issuer, feed, code)
3813 if err != nil {
3814 t.Error("unable to load fragment: %w", err)
3815 return false
3816 }
3817
3818 if policy.rego.IsModuleActive(rpi.ModuleID(issuer, feed)) {
3819 t.Error("module not removed after load")
3820 return false
3821 }
3822
3823 return true
3824 }
3825
3826 if err := quick.Check(f, &quick.Config{MaxCount: 25, Rand: testRand}); err != nil {
3827 t.Errorf("Test_Rego_LoadFragment_SemverVersion: %v", err)
3828 }
3829 }
3830
3831 func Test_Rego_LoadFragment_SVNMismatch(t *testing.T) {
3832 f := func(p *generatedConstraints) bool {
3833 tc, err := setupRegoFragmentSVNMismatchTestConfig(p)
3834 if err != nil {
3835 t.Error(err)
3836 return false
3837 }
3838
3839 fragment := tc.fragments[0]
3840 err = tc.policy.LoadFragment(p.ctx, fragment.info.issuer, fragment.info.feed, fragment.code)
3841 if err == nil {
3842 t.Error("expected to be unable to load fragment due to invalid version")
3843 return false
3844 }
3845
3846 if !assertDecisionJSONContains(t, err, "fragment svn and the specified minimum are different types") {
3847 t.Error("expected error string to contain 'fragment svn and the specified minimum are different types'")
3848 return false
3849 }
3850
3851 if tc.policy.rego.IsModuleActive(rpi.ModuleID(fragment.info.issuer, fragment.info.feed)) {
3852 t.Error("module not removed upon failure")
3853 return false
3854 }
3855
3856 return true
3857 }
3858
3859 if err := quick.Check(f, &quick.Config{MaxCount: 25, Rand: testRand}); err != nil {
3860 t.Errorf("Test_Rego_LoadFragment_SVNMismatch: %v", err)
3861 }
3862 }
3863
3864 func Test_Rego_LoadFragment_SameIssuerTwoFeeds(t *testing.T) {
3865 f := func(p *generatedConstraints) bool {
3866 tc, err := setupRegoFragmentTwoFeedTestConfig(p, true, false)
3867 if err != nil {
3868 t.Error(err)
3869 return false
3870 }
3871
3872 for _, fragment := range tc.fragments {
3873 err = tc.policy.LoadFragment(p.ctx, fragment.info.issuer, fragment.info.feed, fragment.code)
3874 if err != nil {
3875 t.Error("unable to load fragment: %w", err)
3876 return false
3877 }
3878 }
3879
3880 for _, container := range tc.containers {
3881 containerID, err := mountImageForContainer(tc.policy, container.container)
3882 if err != nil {
3883 t.Error("unable to mount image for fragment container: %w", err)
3884 return false
3885 }
3886
3887 _, _, _, err = tc.policy.EnforceCreateContainerPolicy(p.ctx,
3888 container.sandboxID,
3889 containerID,
3890 copyStrings(container.container.Command),
3891 copyStrings(container.envList),
3892 container.container.WorkingDir,
3893 copyMounts(container.mounts),
3894 false,
3895 container.container.NoNewPrivileges,
3896 container.user,
3897 container.groups,
3898 container.container.User.Umask,
3899 container.capabilities,
3900 container.seccomp,
3901 )
3902
3903 if err != nil {
3904 t.Error("unable to create container from fragment: %w", err)
3905 return false
3906 }
3907 }
3908
3909 return true
3910 }
3911
3912 if err := quick.Check(f, &quick.Config{MaxCount: 15, Rand: testRand}); err != nil {
3913 t.Errorf("Test_Rego_LoadFragment_SameIssuerTwoFeeds: %v", err)
3914 }
3915 }
3916
3917 func Test_Rego_LoadFragment_TwoFeeds(t *testing.T) {
3918 f := func(p *generatedConstraints) bool {
3919 tc, err := setupRegoFragmentTwoFeedTestConfig(p, false, false)
3920 if err != nil {
3921 t.Error(err)
3922 return false
3923 }
3924
3925 for _, fragment := range tc.fragments {
3926 err = tc.policy.LoadFragment(p.ctx, fragment.info.issuer, fragment.info.feed, fragment.code)
3927 if err != nil {
3928 t.Error("unable to load fragment: %w", err)
3929 return false
3930 }
3931 }
3932
3933 for _, container := range tc.containers {
3934 containerID, err := mountImageForContainer(tc.policy, container.container)
3935 if err != nil {
3936 t.Error("unable to mount image for fragment container: %w", err)
3937 return false
3938 }
3939
3940 _, _, _, err = tc.policy.EnforceCreateContainerPolicy(p.ctx,
3941 container.sandboxID,
3942 containerID,
3943 copyStrings(container.container.Command),
3944 copyStrings(container.envList),
3945 container.container.WorkingDir,
3946 copyMounts(container.mounts),
3947 false,
3948 container.container.NoNewPrivileges,
3949 container.user,
3950 container.groups,
3951 container.container.User.Umask,
3952 container.capabilities,
3953 container.seccomp,
3954 )
3955
3956 if err != nil {
3957 t.Error("unable to create container from fragment: %w", err)
3958 return false
3959 }
3960 }
3961
3962 return true
3963 }
3964
3965 if err := quick.Check(f, &quick.Config{MaxCount: 15, Rand: testRand}); err != nil {
3966 t.Errorf("Test_Rego_LoadFragment_TwoFeeds: %v", err)
3967 }
3968 }
3969
3970 func Test_Rego_LoadFragment_SameFeedTwice(t *testing.T) {
3971 f := func(p *generatedConstraints) bool {
3972 tc, err := setupRegoFragmentTwoFeedTestConfig(p, true, true)
3973 if err != nil {
3974 t.Error(err)
3975 return false
3976 }
3977
3978 err = tc.policy.LoadFragment(p.ctx, tc.fragments[0].info.issuer, tc.fragments[0].info.feed, tc.fragments[0].code)
3979 if err != nil {
3980 t.Error("unable to load fragment the first time: %w", err)
3981 return false
3982 }
3983
3984 err = tc.policy.LoadFragment(p.ctx, tc.fragments[1].info.issuer, tc.fragments[1].info.feed, tc.fragments[1].code)
3985 if err != nil {
3986 t.Error("expected to be able to load the same issuer/feed twice: %w", err)
3987 return false
3988 }
3989
3990 for _, container := range tc.containers {
3991 containerID, err := mountImageForContainer(tc.policy, container.container)
3992 if err != nil {
3993 t.Error("unable to mount image for fragment container: %w", err)
3994 return false
3995 }
3996
3997 _, _, _, err = tc.policy.EnforceCreateContainerPolicy(p.ctx,
3998 container.sandboxID,
3999 containerID,
4000 copyStrings(container.container.Command),
4001 copyStrings(container.envList),
4002 container.container.WorkingDir,
4003 copyMounts(container.mounts),
4004 false,
4005 container.container.NoNewPrivileges,
4006 container.user,
4007 container.groups,
4008 container.container.User.Umask,
4009 container.capabilities,
4010 container.seccomp,
4011 )
4012
4013 if err != nil {
4014 t.Error("unable to create container from fragment: %w", err)
4015 return false
4016 }
4017 }
4018
4019 return true
4020 }
4021
4022 if err := quick.Check(f, &quick.Config{MaxCount: 15, Rand: testRand}); err != nil {
4023 t.Errorf("Test_Rego_LoadFragment_SameFragmentTwice: %v", err)
4024 }
4025 }
4026
4027 func Test_Rego_LoadFragment_ExcludedContainer(t *testing.T) {
4028 f := func(p *generatedConstraints) bool {
4029 tc, err := setupRegoFragmentTestConfigWithExcludes(p, []string{"containers"})
4030 if err != nil {
4031 t.Error(err)
4032 return false
4033 }
4034
4035 fragment := tc.fragments[0]
4036 container := tc.containers[0]
4037
4038 err = tc.policy.LoadFragment(p.ctx, fragment.info.issuer, fragment.info.feed, fragment.code)
4039 if err != nil {
4040 t.Error("unable to load fragment: %w", err)
4041 return false
4042 }
4043
4044 _, err = mountImageForContainer(tc.policy, container.container)
4045 if err == nil {
4046 t.Error("expected to be unable to mount image for fragment container")
4047 return false
4048 }
4049
4050 return true
4051 }
4052
4053 if err := quick.Check(f, &quick.Config{MaxCount: 15, Rand: testRand}); err != nil {
4054 t.Errorf("Test_Rego_LoadFragment_ExcludedContainer: %v", err)
4055 }
4056 }
4057
4058 func Test_Rego_LoadFragment_ExcludedFragment(t *testing.T) {
4059 f := func(p *generatedConstraints) bool {
4060 tc, err := setupRegoFragmentTestConfigWithExcludes(p, []string{"fragments"})
4061 if err != nil {
4062 t.Error(err)
4063 return false
4064 }
4065
4066 fragment := tc.fragments[0]
4067 subFragment := tc.subFragments[0]
4068
4069 err = tc.policy.LoadFragment(p.ctx, fragment.info.issuer, fragment.info.feed, fragment.code)
4070 if err != nil {
4071 t.Error("unable to load fragment: %w", err)
4072 return false
4073 }
4074
4075 err = tc.policy.LoadFragment(p.ctx, subFragment.info.issuer, subFragment.info.feed, subFragment.code)
4076 if err == nil {
4077 t.Error("expected to be unable to load a sub-fragment from a fragment")
4078 return false
4079 }
4080
4081 return true
4082 }
4083
4084 if err := quick.Check(f, &quick.Config{MaxCount: 15, Rand: testRand}); err != nil {
4085 t.Errorf("Test_Rego_LoadFragment_ExcludedFragment: %v", err)
4086 }
4087 }
4088
4089 func Test_Rego_LoadFragment_ExcludedExternalProcess(t *testing.T) {
4090 f := func(p *generatedConstraints) bool {
4091 tc, err := setupRegoFragmentTestConfigWithExcludes(p, []string{"external_processes"})
4092 if err != nil {
4093 t.Error(err)
4094 return false
4095 }
4096
4097 fragment := tc.fragments[0]
4098 process := tc.externalProcesses[0]
4099
4100 err = tc.policy.LoadFragment(p.ctx, fragment.info.issuer, fragment.info.feed, fragment.code)
4101 if err != nil {
4102 t.Error("unable to load fragment: %w", err)
4103 return false
4104 }
4105
4106 envList := buildEnvironmentVariablesFromEnvRules(process.envRules, testRand)
4107
4108 _, _, err = tc.policy.EnforceExecExternalProcessPolicy(p.ctx, process.command, envList, process.workingDir)
4109 if err == nil {
4110 t.Error("expected to be unable to execute external process from a fragment")
4111 return false
4112 }
4113
4114 return true
4115 }
4116
4117 if err := quick.Check(f, &quick.Config{MaxCount: 25, Rand: testRand}); err != nil {
4118 t.Errorf("Test_Rego_LoadFragment_ExcludedExternalProcess: %v", err)
4119 }
4120 }
4121
4122 func Test_Rego_LoadFragment_FragmentNamespace(t *testing.T) {
4123 ctx := context.Background()
4124 deviceHash := generateRootHash(testRand)
4125 key := randVariableString(testRand, 32)
4126 value := randVariableString(testRand, 32)
4127 fragmentCode := fmt.Sprintf(`package fragment
4128
4129 svn := 1
4130 framework_version := "%s"
4131
4132 layer := "%s"
4133
4134 mount_device := {"allowed": allowed, "metadata": [addCustom]} {
4135 allowed := input.deviceHash == layer
4136 addCustom := {
4137 "name": "custom",
4138 "action": "add",
4139 "key": "%s",
4140 "value": "%s"
4141 }
4142 }`, frameworkVersion, deviceHash, key, value)
4143
4144 issuer := testDataGenerator.uniqueFragmentIssuer()
4145 feed := testDataGenerator.uniqueFragmentFeed()
4146 policyCode := fmt.Sprintf(`package policy
4147
4148 api_version := "%s"
4149 framework_version := "%s"
4150
4151 default load_fragment := {"allowed": false}
4152
4153 load_fragment := {"allowed": true, "add_module": true} {
4154 input.issuer == "%s"
4155 input.feed == "%s"
4156 data[input.namespace].svn >= 1
4157 }
4158
4159 mount_device := data.fragment.mount_device
4160 `, apiVersion, frameworkVersion, issuer, feed)
4161
4162 policy, err := newRegoPolicy(policyCode, []oci.Mount{}, []oci.Mount{})
4163 if err != nil {
4164 t.Fatalf("unable to create Rego policy: %v", err)
4165 }
4166
4167 err = policy.LoadFragment(ctx, issuer, feed, fragmentCode)
4168 if err != nil {
4169 t.Fatalf("unable to load fragment: %v", err)
4170 }
4171
4172 err = policy.EnforceDeviceMountPolicy(ctx, "/mnt/foo", deviceHash)
4173 if err != nil {
4174 t.Fatalf("unable to mount device: %v", err)
4175 }
4176
4177 if test, err := policy.rego.GetMetadata("custom", key); err == nil {
4178 if test != value {
4179 t.Error("incorrect metadata value stored by fragment")
4180 }
4181 } else {
4182 t.Errorf("unable to located metadata key stored by fragment: %v", err)
4183 }
4184 }
4185
4186 func Test_Rego_Scratch_Mount_Policy(t *testing.T) {
4187 for _, tc := range []struct {
4188 unencryptedAllowed bool
4189 encrypted bool
4190 failureExpected bool
4191 }{
4192 {
4193 unencryptedAllowed: false,
4194 encrypted: false,
4195 failureExpected: true,
4196 },
4197 {
4198 unencryptedAllowed: false,
4199 encrypted: true,
4200 failureExpected: false,
4201 },
4202 {
4203 unencryptedAllowed: true,
4204 encrypted: false,
4205 failureExpected: false,
4206 },
4207 {
4208 unencryptedAllowed: true,
4209 encrypted: true,
4210 failureExpected: false,
4211 },
4212 } {
4213 t.Run(fmt.Sprintf("UnencryptedAllowed_%t_And_Encrypted_%t", tc.unencryptedAllowed, tc.encrypted), func(t *testing.T) {
4214 gc := generateConstraints(testRand, maxContainersInGeneratedConstraints)
4215 smConfig, err := setupRegoScratchMountTest(gc, tc.unencryptedAllowed)
4216 if err != nil {
4217 t.Fatalf("unable to setup test: %s", err)
4218 }
4219
4220 scratchPath := generateMountTarget(testRand)
4221 err = smConfig.policy.EnforceScratchMountPolicy(gc.ctx, scratchPath, tc.encrypted)
4222 if tc.failureExpected {
4223 if err == nil {
4224 t.Fatal("policy enforcement should've been denied")
4225 }
4226 } else {
4227 if err != nil {
4228 t.Fatalf("policy enforcement unexpectedly was denied: %s", err)
4229 }
4230 }
4231 })
4232 }
4233 }
4234
4235
4236
4237
4238 func Test_Rego_Scratch_Unmount_Policy(t *testing.T) {
4239 for _, tc := range []struct {
4240 unencryptedAllowed bool
4241 encrypted bool
4242 failureExpected bool
4243 }{
4244 {
4245 unencryptedAllowed: true,
4246 encrypted: false,
4247 failureExpected: false,
4248 },
4249 {
4250 unencryptedAllowed: true,
4251 encrypted: true,
4252 failureExpected: false,
4253 },
4254 {
4255 unencryptedAllowed: false,
4256 encrypted: true,
4257 failureExpected: false,
4258 },
4259 } {
4260 t.Run(fmt.Sprintf("UnencryptedAllowed_%t_And_Encrypted_%t", tc.unencryptedAllowed, tc.encrypted), func(t *testing.T) {
4261 gc := generateConstraints(testRand, maxContainersInGeneratedConstraints)
4262 smConfig, err := setupRegoScratchMountTest(gc, tc.unencryptedAllowed)
4263 if err != nil {
4264 t.Fatalf("unable to setup test: %s", err)
4265 }
4266
4267 scratchPath := generateMountTarget(testRand)
4268 err = smConfig.policy.EnforceScratchMountPolicy(gc.ctx, scratchPath, tc.encrypted)
4269 if err != nil {
4270 t.Fatalf("scratch_mount policy enforcement unexpectedly was denied: %s", err)
4271 }
4272
4273 err = smConfig.policy.EnforceScratchUnmountPolicy(gc.ctx, scratchPath)
4274 if err != nil {
4275 t.Fatalf("scratch_unmount policy enforcement unexpectedly was denied: %s", err)
4276 }
4277 })
4278 }
4279 }
4280
4281 func Test_Rego_StdioAccess_Allowed(t *testing.T) {
4282 gc := generateConstraints(testRand, 1)
4283 gc.containers[0].AllowStdioAccess = true
4284 gc.externalProcesses = generateExternalProcesses(testRand)
4285 gc.externalProcesses[0].allowStdioAccess = true
4286 tc, err := setupRegoCreateContainerTest(gc, gc.containers[0], false)
4287 if err != nil {
4288 t.Fatalf("error setting up test: %v", err)
4289 }
4290
4291 _, _, allow_stdio_access, err := tc.policy.EnforceCreateContainerPolicy(
4292 gc.ctx,
4293 tc.sandboxID,
4294 tc.containerID,
4295 tc.argList,
4296 tc.envList,
4297 tc.workingDir,
4298 tc.mounts,
4299 false,
4300 tc.noNewPrivileges,
4301 tc.user,
4302 tc.groups,
4303 tc.umask,
4304 tc.capabilities,
4305 tc.seccomp,
4306 )
4307
4308 if err != nil {
4309 t.Errorf("create_container not allowed: %v", err)
4310 }
4311
4312 if !allow_stdio_access {
4313 t.Errorf("expected allow_stdio_access to be true")
4314 }
4315
4316
4317 _, _, allow_stdio_access, err = tc.policy.EnforceExecInContainerPolicy(
4318 gc.ctx,
4319 tc.containerID,
4320 gc.containers[0].ExecProcesses[0].Command,
4321 tc.envList,
4322 tc.workingDir,
4323 tc.noNewPrivileges,
4324 tc.user,
4325 tc.groups,
4326 tc.umask,
4327 tc.capabilities,
4328 )
4329
4330 if err != nil {
4331 t.Errorf("exec_in_container not allowed: %v", err)
4332 }
4333
4334 if !allow_stdio_access {
4335 t.Errorf("expected allow_stdio_access to be true")
4336 }
4337
4338 envList := buildEnvironmentVariablesFromEnvRules(gc.externalProcesses[0].envRules, testRand)
4339 _, allow_stdio_access, err = tc.policy.EnforceExecExternalProcessPolicy(
4340 gc.ctx,
4341 gc.externalProcesses[0].command,
4342 envList,
4343 gc.externalProcesses[0].workingDir,
4344 )
4345
4346 if err != nil {
4347 t.Errorf("exec_external not allowed: %v", err)
4348 }
4349
4350 if !allow_stdio_access {
4351 t.Errorf("expected allow_stdio_access to be true")
4352 }
4353 }
4354
4355 func Test_Rego_EnforeCreateContainerPolicy_StdioAccess_NotAllowed(t *testing.T) {
4356 gc := generateConstraints(testRand, 1)
4357 gc.containers[0].AllowStdioAccess = false
4358 tc, err := setupRegoCreateContainerTest(gc, gc.containers[0], false)
4359 if err != nil {
4360 t.Fatalf("error setting up test: %v", err)
4361 }
4362
4363 _, _, allow_stdio_access, err := tc.policy.EnforceCreateContainerPolicy(
4364 tc.ctx,
4365 tc.sandboxID,
4366 tc.containerID,
4367 tc.argList,
4368 tc.envList,
4369 tc.workingDir,
4370 tc.mounts,
4371 false,
4372 tc.noNewPrivileges,
4373 tc.user,
4374 tc.groups,
4375 tc.umask,
4376 tc.capabilities,
4377 tc.seccomp,
4378 )
4379
4380 if err != nil {
4381 t.Errorf("create_container not allowed: %v", err)
4382 }
4383
4384 if allow_stdio_access {
4385 t.Errorf("expected allow_stdio_access to be false")
4386 }
4387 }
4388
4389 func Test_Rego_Container_StdioAccess_NotDecidable(t *testing.T) {
4390 gc := generateConstraints(testRand, 1)
4391 container0 := gc.containers[0]
4392 container0.AllowStdioAccess = true
4393 container1, err := container0.clone()
4394 if err != nil {
4395 t.Fatalf("unable to clone container: %v", err)
4396 }
4397
4398 container1.AllowStdioAccess = false
4399 gc.containers = append(gc.containers, container1)
4400
4401 container0.ExecProcesses = append(container0.ExecProcesses, container0.ExecProcesses[0].clone())
4402
4403 gc.externalProcesses = generateExternalProcesses(testRand)
4404 gc.externalProcesses = append(gc.externalProcesses, gc.externalProcesses[0].clone())
4405 gc.externalProcesses[0].allowStdioAccess = true
4406
4407 tc, err := setupRegoCreateContainerTest(gc, gc.containers[0], false)
4408 if err != nil {
4409 t.Fatalf("error setting up test: %v", err)
4410 }
4411
4412 _, _, allow_stdio_access, err := tc.policy.EnforceCreateContainerPolicy(
4413 tc.ctx,
4414 tc.sandboxID,
4415 tc.containerID,
4416 tc.argList,
4417 tc.envList,
4418 tc.workingDir,
4419 tc.mounts,
4420 false,
4421 tc.noNewPrivileges,
4422 tc.user,
4423 tc.groups,
4424 tc.umask,
4425 tc.capabilities,
4426 tc.seccomp,
4427 )
4428
4429 if err == nil {
4430 t.Errorf("expected create_container to not be allowed")
4431 }
4432
4433 if allow_stdio_access {
4434 t.Errorf("expected allow_stdio_access to be false")
4435 }
4436 }
4437
4438 func Test_Rego_ExecExternal_StdioAccess_NotAllowed(t *testing.T) {
4439 gc := generateConstraints(testRand, 1)
4440 gc.externalProcesses = generateExternalProcesses(testRand)
4441 gc.externalProcesses = append(gc.externalProcesses, gc.externalProcesses[0].clone())
4442 gc.externalProcesses[0].allowStdioAccess = !gc.externalProcesses[0].allowStdioAccess
4443
4444 policy, err := newRegoPolicy(gc.toPolicy().marshalRego(), []oci.Mount{}, []oci.Mount{})
4445 if err != nil {
4446 t.Fatalf("error marshaling policy: %v", err)
4447 }
4448
4449 envList := buildEnvironmentVariablesFromEnvRules(gc.externalProcesses[0].envRules, testRand)
4450 _, allow_stdio_access, err := policy.EnforceExecExternalProcessPolicy(
4451 gc.ctx,
4452 gc.externalProcesses[0].command,
4453 envList,
4454 gc.externalProcesses[0].workingDir,
4455 )
4456
4457 if err == nil {
4458 t.Errorf("expected exec_external to not be allowed")
4459 }
4460
4461 if allow_stdio_access {
4462 t.Errorf("expected allow_stdio_access to be false")
4463 }
4464 }
4465
4466 func Test_Rego_EnforceCreateContainerPolicy_AllowElevatedAllowsPrivilegedContainer(t *testing.T) {
4467 gc := generateConstraints(testRand, 1)
4468 gc.containers[0].AllowElevated = true
4469 tc, err := setupRegoCreateContainerTest(gc, gc.containers[0], false)
4470 if err != nil {
4471 t.Fatalf("error setting up test: %v", err)
4472 }
4473
4474 _, _, _, err = tc.policy.EnforceCreateContainerPolicy(
4475 tc.ctx,
4476 tc.sandboxID,
4477 tc.containerID,
4478 tc.argList,
4479 tc.envList,
4480 tc.workingDir,
4481 tc.mounts,
4482 false,
4483 tc.noNewPrivileges,
4484 tc.user,
4485 tc.groups,
4486 tc.umask,
4487 tc.capabilities,
4488 tc.seccomp,
4489 )
4490
4491 if err != nil {
4492 t.Fatalf("expected privilege escalation to be allowed: %s", err)
4493 }
4494 }
4495
4496 func Test_Rego_EnforceCreateContainerPolicy_AllowElevatedAllowsUnprivilegedContainer(t *testing.T) {
4497 gc := generateConstraints(testRand, 1)
4498 gc.containers[0].AllowElevated = true
4499 tc, err := setupRegoCreateContainerTest(gc, gc.containers[0], false)
4500 if err != nil {
4501 t.Fatalf("error setting up test: %v", err)
4502 }
4503
4504 _, _, _, err = tc.policy.EnforceCreateContainerPolicy(
4505 tc.ctx,
4506 tc.sandboxID,
4507 tc.containerID,
4508 tc.argList,
4509 tc.envList,
4510 tc.workingDir,
4511 tc.mounts,
4512 false,
4513 tc.noNewPrivileges,
4514 tc.user,
4515 tc.groups,
4516 tc.umask,
4517 tc.capabilities,
4518 tc.seccomp,
4519 )
4520
4521 if err != nil {
4522 t.Fatalf("expected lack of escalation to be fine: %s", err)
4523 }
4524 }
4525
4526 func Test_Rego_EnforceCreateContainerPolicy_NoAllowElevatedDenysPrivilegedContainer(t *testing.T) {
4527 gc := generateConstraints(testRand, 1)
4528 gc.containers[0].AllowElevated = false
4529 tc, err := setupRegoCreateContainerTest(gc, gc.containers[0], false)
4530 if err != nil {
4531 t.Fatalf("error setting up test: %v", err)
4532 }
4533
4534 _, _, _, err = tc.policy.EnforceCreateContainerPolicy(
4535 tc.ctx,
4536 tc.sandboxID,
4537 tc.containerID,
4538 tc.argList,
4539 tc.envList,
4540 tc.workingDir,
4541 tc.mounts,
4542 true,
4543 tc.noNewPrivileges,
4544 tc.user,
4545 tc.groups,
4546 tc.umask,
4547 tc.capabilities,
4548 tc.seccomp,
4549 )
4550
4551 if err == nil {
4552 t.Fatal("expected escalation to be denied")
4553 }
4554 }
4555
4556 func Test_Rego_EnforceCreateContainerPolicy_NoAllowElevatedAllowsUnprivilegedContainer(t *testing.T) {
4557 gc := generateConstraints(testRand, 1)
4558 gc.containers[0].AllowElevated = false
4559 tc, err := setupRegoCreateContainerTest(gc, gc.containers[0], false)
4560 if err != nil {
4561 t.Fatalf("error setting up test: %v", err)
4562 }
4563
4564 _, _, _, err = tc.policy.EnforceCreateContainerPolicy(
4565 tc.ctx,
4566 tc.sandboxID,
4567 tc.containerID,
4568 tc.argList,
4569 tc.envList,
4570 tc.workingDir,
4571 tc.mounts,
4572 false,
4573 tc.noNewPrivileges,
4574 tc.user,
4575 tc.groups,
4576 tc.umask,
4577 tc.capabilities,
4578 tc.seccomp,
4579 )
4580
4581 if err != nil {
4582 t.Fatalf("expected lack of escalation to be fine: %s", err)
4583 }
4584 }
4585
4586 func Test_Rego_CreateContainer_NoNewPrivileges_Default(t *testing.T) {
4587 gc := generateConstraints(testRand, maxContainersInGeneratedConstraints)
4588 tc, err := setupFrameworkVersionSimpleTest(gc, "0.1.0", frameworkVersion)
4589 if err != nil {
4590 t.Fatalf("error setting up test: %v", err)
4591 }
4592
4593 input := map[string]interface{}{}
4594 result, err := tc.policy.rego.RawQuery("data.framework.candidate_containers", input)
4595
4596 if err != nil {
4597 t.Fatalf("unable to query containers: %v", err)
4598 }
4599
4600 containers, ok := result[0].Expressions[0].Value.([]interface{})
4601 if !ok {
4602 t.Fatal("unable to extract containers from result")
4603 }
4604
4605 if len(containers) != len(gc.containers) {
4606 t.Error("incorrect number of candidate containers.")
4607 }
4608
4609 for _, container := range containers {
4610 object := container.(map[string]interface{})
4611 err := assertKeyValue(object, "no_new_privileges", false)
4612 if err != nil {
4613 t.Error(err)
4614 }
4615 }
4616 }
4617
4618 func Test_Rego_CreateContainer_User_Default(t *testing.T) {
4619 gc := generateConstraints(testRand, maxContainersInGeneratedConstraints)
4620 tc, err := setupFrameworkVersionSimpleTest(gc, "0.1.0", frameworkVersion)
4621 if err != nil {
4622 t.Fatalf("error setting up test: %v", err)
4623 }
4624
4625 input := map[string]interface{}{}
4626 result, err := tc.policy.rego.RawQuery("data.framework.candidate_containers", input)
4627
4628 if err != nil {
4629 t.Fatalf("unable to query containers: %v", err)
4630 }
4631
4632 containers, ok := result[0].Expressions[0].Value.([]interface{})
4633 if !ok {
4634 t.Fatal("unable to extract containers from result")
4635 }
4636
4637 if len(containers) != len(gc.containers) {
4638 t.Error("incorrect number of candidate containers.")
4639 }
4640
4641 for _, container := range containers {
4642 object := container.(map[string]interface{})
4643 user, ok := object["user"].(map[string]interface{})
4644 if !ok {
4645 t.Error("unable to extract user from container")
4646 continue
4647 }
4648
4649 err := assertKeyValue(user, "umask", "0022")
4650 if err != nil {
4651 t.Error(err)
4652 }
4653
4654 if user_idname, ok := user["user_idname"].(map[string]interface{}); ok {
4655 err = assertKeyValue(user_idname, "strategy", "any")
4656 if err != nil {
4657 t.Error(err)
4658 }
4659 } else {
4660 t.Error("unable to extract user_idname from user")
4661 }
4662
4663 if group_idnames, ok := user["group_idnames"].([]interface{}); ok {
4664 if len(group_idnames) != 1 {
4665 t.Error("incorrect number of group_idnames")
4666 } else {
4667 group_idname := group_idnames[0].(map[string]interface{})
4668 err = assertKeyValue(group_idname, "strategy", "any")
4669 if err != nil {
4670 t.Error(err)
4671 }
4672 }
4673 }
4674 }
4675 }
4676
4677 func Test_Rego_CreateContainer_Capabilities_Default(t *testing.T) {
4678 gc := generateConstraints(testRand, maxContainersInGeneratedConstraints)
4679 tc, err := setupFrameworkVersionSimpleTest(gc, "0.1.0", frameworkVersion)
4680 if err != nil {
4681 t.Fatalf("error setting up test: %v", err)
4682 }
4683
4684 input := map[string]interface{}{
4685 "privileged": false,
4686 }
4687 result, err := tc.policy.rego.RawQuery("data.framework.candidate_containers", input)
4688
4689 if err != nil {
4690 t.Fatalf("unable to query containers: %v", err)
4691 }
4692
4693 containers, ok := result[0].Expressions[0].Value.([]interface{})
4694 if !ok {
4695 t.Fatal("unable to extract containers from result")
4696 }
4697
4698 if len(containers) != len(gc.containers) {
4699 t.Error("incorrect number of candidate containers.")
4700 }
4701
4702 for _, container := range containers {
4703 object := container.(map[string]interface{})
4704 capabilities, ok := object["capabilities"]
4705 if !ok {
4706 t.Error("unable to extract capabilities from container")
4707 continue
4708 }
4709
4710 if capabilities != nil {
4711 t.Error("capabilities should be nil by default")
4712 }
4713 }
4714 }
4715
4716 func Test_Rego_CreateContainer_AllowCapabilityDropping_Default(t *testing.T) {
4717 gc := generateConstraints(testRand, 1)
4718 tc, err := setupFrameworkVersionSimpleTest(gc, "0.1.0", frameworkVersion)
4719 if err != nil {
4720 t.Fatalf("error setting up test: %v", err)
4721 }
4722
4723 input := map[string]interface{}{}
4724 result, err := tc.policy.rego.RawQuery("data.framework.allow_capability_dropping", input)
4725
4726 if err != nil {
4727 t.Fatalf("unable to query allow_capability_dropping: %v", err)
4728 }
4729
4730 actualValue, ok := result[0].Expressions[0].Value.(bool)
4731 if !ok {
4732 t.Fatal("unable to extract allow_capability_dropping from result")
4733 }
4734
4735 if actualValue != false {
4736 t.Error("unexpected allow_capability_dropping value")
4737 }
4738 }
4739
4740 func Test_Rego_CreateContainer_Seccomp_Default(t *testing.T) {
4741 gc := generateConstraints(testRand, maxContainersInGeneratedConstraints)
4742 tc, err := setupFrameworkVersionSimpleTest(gc, "0.1.0", frameworkVersion)
4743 if err != nil {
4744 t.Fatalf("error setting up test: %v", err)
4745 }
4746
4747 input := map[string]interface{}{}
4748 result, err := tc.policy.rego.RawQuery("data.framework.candidate_containers", input)
4749
4750 if err != nil {
4751 t.Fatalf("unable to query containers: %v", err)
4752 }
4753
4754 containers, ok := result[0].Expressions[0].Value.([]interface{})
4755 if !ok {
4756 t.Fatal("unable to extract containers from result")
4757 }
4758
4759 if len(containers) != len(gc.containers) {
4760 t.Error("incorrect number of candidate containers.")
4761 }
4762
4763 for _, container := range containers {
4764 object := container.(map[string]interface{})
4765 err := assertKeyValue(object, "seccomp_profile_sha256", "")
4766 if err != nil {
4767 t.Error(err)
4768 }
4769 }
4770 }
4771
4772 func Test_FrameworkVersion_Missing(t *testing.T) {
4773 gc := generateConstraints(testRand, 1)
4774 tc, err := setupFrameworkVersionSimpleTest(gc, "", frameworkVersion)
4775 if err != nil {
4776 t.Fatalf("unable to setup test: %v", err)
4777 }
4778
4779 containerID := testDataGenerator.uniqueContainerID()
4780 c := selectContainerFromContainerList(gc.containers, testRand)
4781
4782 layerPaths, err := testDataGenerator.createValidOverlayForContainer(tc.policy, c)
4783
4784 err = tc.policy.EnforceOverlayMountPolicy(gc.ctx, containerID, layerPaths, testDataGenerator.uniqueMountTarget())
4785 if err == nil {
4786 t.Error("unexpected success. Missing framework_version should trigger an error.")
4787 }
4788
4789 assertDecisionJSONContains(t, err, fmt.Sprintf("framework_version is missing. Current version: %s", frameworkVersion))
4790 }
4791
4792 func Test_Fragment_FrameworkVersion_Missing(t *testing.T) {
4793 gc := generateConstraints(testRand, 1)
4794 tc, err := setupFrameworkVersionTest(gc, frameworkVersion, frameworkVersion, 1, "", []string{})
4795 if err != nil {
4796 t.Fatalf("unable to setup test: %v", err)
4797 }
4798
4799 fragment := tc.fragments[0]
4800 err = tc.policy.LoadFragment(gc.ctx, fragment.info.issuer, fragment.info.feed, fragment.code)
4801 if err == nil {
4802 t.Error("unexpected success. Missing framework_version should trigger an error.")
4803 }
4804
4805 assertDecisionJSONContains(t, err, fmt.Sprintf("fragment framework_version is missing. Current version: %s", frameworkVersion))
4806 }
4807
4808 func Test_FrameworkVersion_In_Future(t *testing.T) {
4809 gc := generateConstraints(testRand, 1)
4810 tc, err := setupFrameworkVersionSimpleTest(gc, "100.0.0", frameworkVersion)
4811 if err != nil {
4812 t.Fatalf("unable to setup test: %v", err)
4813 }
4814
4815 containerID := testDataGenerator.uniqueContainerID()
4816 c := selectContainerFromContainerList(gc.containers, testRand)
4817
4818 layerPaths, err := testDataGenerator.createValidOverlayForContainer(tc.policy, c)
4819
4820 err = tc.policy.EnforceOverlayMountPolicy(gc.ctx, containerID, layerPaths, testDataGenerator.uniqueMountTarget())
4821 if err == nil {
4822 t.Error("unexpected success. Future framework_version should trigger an error.")
4823 }
4824
4825 assertDecisionJSONContains(t, err, fmt.Sprintf("framework_version is ahead of the current version: 100.0.0 is greater than %s", frameworkVersion))
4826 }
4827
4828 func Test_Fragment_FrameworkVersion_In_Future(t *testing.T) {
4829 gc := generateConstraints(testRand, 1)
4830 tc, err := setupFrameworkVersionTest(gc, frameworkVersion, frameworkVersion, 1, "100.0.0", []string{})
4831 if err != nil {
4832 t.Fatalf("unable to setup test: %v", err)
4833 }
4834
4835 fragment := tc.fragments[0]
4836 err = tc.policy.LoadFragment(gc.ctx, fragment.info.issuer, fragment.info.feed, fragment.code)
4837 if err == nil {
4838 t.Error("unexpected success. Future framework_version should trigger an error.")
4839 }
4840
4841 assertDecisionJSONContains(t, err, fmt.Sprintf("fragment framework_version is ahead of the current version: 100.0.0 is greater than %s", frameworkVersion))
4842 }
4843
4844 func Test_Rego_MissingEnvList(t *testing.T) {
4845 code := fmt.Sprintf(`package policy
4846
4847 api_version := "%s"
4848
4849 create_container := {"allowed": true}
4850 exec_in_container := {"allowed": true}
4851 exec_external := {"allowed": true}
4852 `, apiVersion)
4853
4854 policy, err := newRegoPolicy(code, []oci.Mount{}, []oci.Mount{})
4855 if err != nil {
4856 t.Fatalf("error compiling the rego policy: %v", err)
4857 }
4858
4859 ctx := context.Background()
4860 sandboxID := generateSandboxID(testRand)
4861 containerID := generateContainerID(testRand)
4862 command := generateCommand(testRand)
4863 expectedEnvs := generateEnvironmentVariables(testRand)
4864 workingDir := generateWorkingDir(testRand)
4865 privileged := randBool(testRand)
4866 noNewPrivileges := randBool(testRand)
4867 user := generateIDName(testRand)
4868 groups := []IDName{}
4869 umask := generateUmask(testRand)
4870 capabilities := generateCapabilities(testRand)
4871 seccomp := ""
4872
4873 actualEnvs, _, _, err := policy.EnforceCreateContainerPolicy(
4874 ctx,
4875 sandboxID,
4876 containerID,
4877 command,
4878 expectedEnvs,
4879 workingDir,
4880 []oci.Mount{},
4881 privileged,
4882 noNewPrivileges,
4883 user,
4884 groups,
4885 umask,
4886 capabilities,
4887 seccomp,
4888 )
4889
4890 if err != nil {
4891 t.Errorf("unexpected error when calling EnforceCreateContainerPolicy: %v", err)
4892 }
4893
4894 if !areStringArraysEqual(actualEnvs, expectedEnvs) {
4895 t.Error("invalid envList returned from EnforceCreateContainerPolicy")
4896 }
4897
4898 actualEnvs, _, _, err = policy.EnforceExecInContainerPolicy(ctx, containerID, command, expectedEnvs, workingDir, noNewPrivileges, user, groups, umask, capabilities)
4899
4900 if err != nil {
4901 t.Errorf("unexpected error when calling EnforceExecInContainerPolicy: %v", err)
4902 }
4903
4904 if !areStringArraysEqual(actualEnvs, expectedEnvs) {
4905 t.Error("invalid envList returned from EnforceExecInContainerPolicy")
4906 }
4907
4908 actualEnvs, _, err = policy.EnforceExecExternalProcessPolicy(ctx, command, expectedEnvs, workingDir)
4909
4910 if err != nil {
4911 t.Errorf("unexpected error when calling EnfForceExecExternalProcessPolicy: %v", err)
4912 }
4913
4914 if !areStringArraysEqual(actualEnvs, expectedEnvs) {
4915 t.Error("invalid envList returned from EnforceExecExternalProcessPolicy")
4916 }
4917 }
4918
4919 func Test_Rego_EnvListGetsRedacted(t *testing.T) {
4920 c := generateConstraints(testRand, 1)
4921
4922
4923 c.allowEnvironmentVariableDropping = false
4924
4925
4926 tc, err := setupRegoCreateContainerTest(c, c.containers[0], false)
4927 if err != nil {
4928 t.Fatal(err)
4929 }
4930
4931 var envList []string
4932 envVar := "FOO=BAR"
4933 envList = append(envList, envVar)
4934
4935 _, _, _, err = tc.policy.EnforceCreateContainerPolicy(tc.ctx, tc.sandboxID, tc.containerID, tc.argList, envList, "bunk", tc.mounts, false, tc.noNewPrivileges, tc.user, tc.groups, tc.umask, tc.capabilities, tc.seccomp)
4936
4937
4938 if err == nil {
4939 t.Fatal("Unexpected success when enforcing policy")
4940 }
4941
4942 if !assertDecisionJSONDoesNotContain(t, err, envVar) {
4943 t.Fatal("EnvList wasn't redacted in error message")
4944 }
4945
4946 if !assertDecisionJSONContains(t, err, `FOO=\u003c\u003credacted\u003e\u003e`) {
4947 t.Fatal("EnvList redaction format wasn't as expected")
4948 }
4949 }
4950
4951 func Test_Rego_EnforceCreateContainer_ConflictingAllowStdioAccessHasErrorMessage(t *testing.T) {
4952 constraints := generateConstraints(testRand, 1)
4953 constraints.containers[0].AllowStdioAccess = true
4954
4955
4956
4957 duplicate := &securityPolicyContainer{
4958 Command: constraints.containers[0].Command,
4959 EnvRules: constraints.containers[0].EnvRules,
4960 WorkingDir: constraints.containers[0].WorkingDir,
4961 Mounts: constraints.containers[0].Mounts,
4962 Layers: constraints.containers[0].Layers,
4963 Capabilities: constraints.containers[0].Capabilities,
4964 ExecProcesses: generateExecProcesses(testRand),
4965 Signals: generateListOfSignals(testRand, 0, maxSignalNumber),
4966 AllowElevated: constraints.containers[0].AllowElevated,
4967 AllowStdioAccess: false,
4968 NoNewPrivileges: constraints.containers[0].NoNewPrivileges,
4969 User: constraints.containers[0].User,
4970 SeccompProfileSHA256: constraints.containers[0].SeccompProfileSHA256,
4971 }
4972
4973 constraints.containers = append(constraints.containers, duplicate)
4974
4975 tc, err := setupRegoCreateContainerTest(constraints, constraints.containers[0], false)
4976 if err != nil {
4977 t.Fatal(err)
4978 }
4979
4980 _, _, _, err = tc.policy.EnforceCreateContainerPolicy(tc.ctx, tc.sandboxID, tc.containerID, tc.argList, tc.envList, tc.workingDir, tc.mounts, false, tc.noNewPrivileges, tc.user, tc.groups, tc.umask, tc.capabilities, tc.seccomp)
4981
4982
4983 if err == nil {
4984 t.Fatalf("Unexpected success when enforcing policy")
4985 }
4986
4987 if !assertDecisionJSONContains(t, err, "containers only distinguishable by allow_stdio_access") {
4988 t.Fatal("No error message given for conflicting allow_stdio_access on otherwise 'same' containers")
4989 }
4990 }
4991
4992 func Test_Rego_ExecExternalProcessPolicy_ConflictingAllowStdioAccessHasErrorMessage(t *testing.T) {
4993 constraints := generateConstraints(testRand, 1)
4994 process := generateExternalProcess(testRand)
4995 process.allowStdioAccess = false
4996 duplicate := process.clone()
4997 duplicate.allowStdioAccess = true
4998
4999 constraints.externalProcesses = append(constraints.externalProcesses, process)
5000 constraints.externalProcesses = append(constraints.externalProcesses, duplicate)
5001 securityPolicy := constraints.toPolicy()
5002 defaultMounts := generateMounts(testRand)
5003 privilegedMounts := generateMounts(testRand)
5004
5005 policy, err := newRegoPolicy(securityPolicy.marshalRego(),
5006 toOCIMounts(defaultMounts),
5007 toOCIMounts(privilegedMounts))
5008 if err != nil {
5009 t.Fatal(err)
5010 }
5011
5012 envList := buildEnvironmentVariablesFromEnvRules(process.envRules, testRand)
5013
5014 _, _, err = policy.EnforceExecExternalProcessPolicy(constraints.ctx, process.command, envList, process.workingDir)
5015 if err == nil {
5016 t.Fatal("Policy was unexpectedly not enforced")
5017 }
5018
5019 if !assertDecisionJSONContains(t, err, "external processes only distinguishable by allow_stdio_access") {
5020 t.Fatal("No error message given for conflicting allow_stdio_access on otherwise 'same' external processes")
5021 }
5022 }
5023
5024 func Test_Rego_Enforce_CreateContainer_RequiredEnvMissingHasErrorMessage(t *testing.T) {
5025 constraints := generateConstraints(testRand, 1)
5026 container := selectContainerFromContainerList(constraints.containers, testRand)
5027 requiredRule := EnvRuleConfig{
5028 Strategy: "string",
5029 Rule: randVariableString(testRand, maxGeneratedEnvironmentVariableRuleLength),
5030 Required: true,
5031 }
5032
5033 container.EnvRules = append(container.EnvRules, requiredRule)
5034
5035 tc, err := setupRegoCreateContainerTest(constraints, container, false)
5036 if err != nil {
5037 t.Fatal(err)
5038 }
5039
5040 envList := make([]string, 0, len(container.EnvRules))
5041 for _, env := range tc.envList {
5042 if env != requiredRule.Rule {
5043 envList = append(envList, env)
5044 }
5045 }
5046
5047 _, _, _, err = tc.policy.EnforceCreateContainerPolicy(tc.ctx, tc.sandboxID, tc.containerID, tc.argList, envList, tc.workingDir, tc.mounts, false, tc.noNewPrivileges, tc.user, tc.groups, tc.umask, tc.capabilities, tc.seccomp)
5048
5049
5050 if err == nil {
5051 t.Fatalf("Unexpected success when enforcing policy")
5052 }
5053
5054 if !assertDecisionJSONContains(t, err, "missing required environment variable") {
5055 t.Fatal("No error message given for missing required environment variable")
5056 }
5057 }
5058
5059 func Test_Rego_ExecInContainerPolicy_RequiredEnvMissingHasErrorMessage(t *testing.T) {
5060 constraints := generateConstraints(testRand, 1)
5061 container := selectContainerFromContainerList(constraints.containers, testRand)
5062 neededEnv := randVariableString(testRand, maxGeneratedEnvironmentVariableRuleLength)
5063 requiredRule := EnvRuleConfig{
5064 Strategy: "string",
5065 Rule: neededEnv,
5066 Required: true,
5067 }
5068
5069 container.EnvRules = append(container.EnvRules, requiredRule)
5070
5071 tc, err := setupRegoRunningContainerTest(constraints, false)
5072 if err != nil {
5073 t.Fatal(err)
5074 }
5075
5076 running := selectContainerFromRunningContainers(tc.runningContainers, testRand)
5077
5078 process := selectExecProcess(running.container.ExecProcesses, testRand)
5079
5080 allEnvs := buildEnvironmentVariablesFromEnvRules(running.container.EnvRules, testRand)
5081 envList := make([]string, 0, len(container.EnvRules))
5082 for _, env := range allEnvs {
5083 if env != requiredRule.Rule {
5084 envList = append(envList, env)
5085 }
5086 }
5087 user := buildIDNameFromConfig(running.container.User.UserIDName, testRand)
5088 groups := buildGroupIDNamesFromUser(running.container.User, testRand)
5089 umask := running.container.User.Umask
5090 capabilities := running.container.Capabilities.toExternal()
5091
5092 _, _, _, err = tc.policy.EnforceExecInContainerPolicy(constraints.ctx, running.containerID, process.Command, envList, running.container.WorkingDir, running.container.NoNewPrivileges, user, groups, umask, &capabilities)
5093
5094
5095 if err == nil {
5096 t.Fatal("Unexpected success when enforcing policy")
5097 }
5098
5099 if !assertDecisionJSONContains(t, err, "missing required environment variable") {
5100 fmt.Print(err.Error())
5101 t.Fatal("No error message given for missing required environment variable")
5102 }
5103 }
5104
5105 func Test_Rego_ExecExternalProcessPolicy_RequiredEnvMissingHasErrorMessage(t *testing.T) {
5106 constraints := generateConstraints(testRand, 1)
5107 process := generateExternalProcess(testRand)
5108 neededEnv := randVariableString(testRand, maxGeneratedEnvironmentVariableRuleLength)
5109 requiredRule := EnvRuleConfig{
5110 Strategy: "string",
5111 Rule: neededEnv,
5112 Required: true,
5113 }
5114
5115 process.envRules = append(process.envRules, requiredRule)
5116
5117 constraints.externalProcesses = append(constraints.externalProcesses, process)
5118 securityPolicy := constraints.toPolicy()
5119 defaultMounts := generateMounts(testRand)
5120 privilegedMounts := generateMounts(testRand)
5121
5122 policy, err := newRegoPolicy(securityPolicy.marshalRego(),
5123 toOCIMounts(defaultMounts),
5124 toOCIMounts(privilegedMounts))
5125 if err != nil {
5126 t.Fatal(err)
5127 }
5128
5129 allEnvs := buildEnvironmentVariablesFromEnvRules(process.envRules, testRand)
5130 envList := make([]string, 0, len(process.envRules))
5131 for _, env := range allEnvs {
5132 if env != requiredRule.Rule {
5133 envList = append(envList, env)
5134 }
5135 }
5136
5137 _, _, err = policy.EnforceExecExternalProcessPolicy(constraints.ctx, process.command, envList, process.workingDir)
5138 if err == nil {
5139 t.Fatal("Policy was unexpectedly not enforced")
5140 }
5141
5142 if !assertDecisionJSONContains(t, err, "missing required environment variable") {
5143 fmt.Print(err.Error())
5144 t.Fatal("No error message given for missing required environment variable")
5145 }
5146 }
5147
5148 func Test_Rego_EnforceContainerNoNewPrivilegesPolicy_FalseAllowsFalse(t *testing.T) {
5149 p := generateConstraints(testRand, 1)
5150 p.containers[0].NoNewPrivileges = false
5151
5152 tc, err := setupSimpleRegoCreateContainerTest(p)
5153 if err != nil {
5154 t.Fatal(err)
5155 }
5156
5157 _, _, _, err = tc.policy.EnforceCreateContainerPolicy(tc.ctx, tc.sandboxID, tc.containerID, tc.argList, tc.envList, tc.workingDir, tc.mounts, false, false, tc.user, tc.groups, tc.umask, tc.capabilities, tc.seccomp)
5158
5159 if err != nil {
5160 t.Fatal("Unexpected failure with false")
5161 }
5162 }
5163
5164 func Test_Rego_EnforceContainerNoNewPrivilegesPolicy_FalseAllowsTrue(t *testing.T) {
5165 p := generateConstraints(testRand, 1)
5166 p.containers[0].NoNewPrivileges = false
5167
5168 tc, err := setupSimpleRegoCreateContainerTest(p)
5169 if err != nil {
5170 t.Fatal(err)
5171 }
5172
5173 _, _, _, err = tc.policy.EnforceCreateContainerPolicy(p.ctx, tc.sandboxID, tc.containerID, tc.argList, tc.envList, tc.workingDir, tc.mounts, false, true, tc.user, tc.groups, tc.umask, tc.capabilities, tc.seccomp)
5174
5175 if err != nil {
5176 t.Fatal("Unexpected failure with true")
5177 }
5178 }
5179
5180 func Test_Rego_EnforceContainerNoNewPrivilegesPolicy_TrueDisallowsFalse(t *testing.T) {
5181 p := generateConstraints(testRand, 1)
5182 p.containers[0].NoNewPrivileges = true
5183
5184 tc, err := setupSimpleRegoCreateContainerTest(p)
5185 if err != nil {
5186 t.Fatal(err)
5187 }
5188
5189 _, _, _, err = tc.policy.EnforceCreateContainerPolicy(p.ctx, tc.sandboxID, tc.containerID, tc.argList, tc.envList, tc.workingDir, tc.mounts, false, false, tc.user, tc.groups, tc.umask, tc.capabilities, tc.seccomp)
5190
5191 if err == nil {
5192 t.Fatal("Unexpected success with false")
5193 }
5194
5195 if !assertDecisionJSONContains(t, err, "invalid noNewPrivileges") {
5196 t.Fatal("Expected error message is missing")
5197 }
5198 }
5199
5200 func Test_Rego_EnforceContainerNoNewPrivilegesPolicy_TrueAllowsTrue(t *testing.T) {
5201 p := generateConstraints(testRand, 1)
5202 p.containers[0].NoNewPrivileges = true
5203
5204 tc, err := setupSimpleRegoCreateContainerTest(p)
5205 if err != nil {
5206 t.Fatal(err)
5207 }
5208
5209 _, _, _, err = tc.policy.EnforceCreateContainerPolicy(p.ctx, tc.sandboxID, tc.containerID, tc.argList, tc.envList, tc.workingDir, tc.mounts, false, true, tc.user, tc.groups, tc.umask, tc.capabilities, tc.seccomp)
5210
5211 if err != nil {
5212 t.Fatal("Unexpected failure with true")
5213 }
5214 }
5215
5216 func Test_Rego_EnforceExecInContainerNoNewPrivilegesPolicy_FalseAllowsFalse(t *testing.T) {
5217 p := generateConstraints(testRand, 1)
5218 p.containers[0].NoNewPrivileges = false
5219
5220 tc, err := setupRegoRunningContainerTest(p, false)
5221 if err != nil {
5222 t.Fatal(err)
5223 }
5224
5225 container := selectContainerFromRunningContainers(tc.runningContainers, testRand)
5226 process := selectExecProcess(container.container.ExecProcesses, testRand)
5227 envList := buildEnvironmentVariablesFromEnvRules(container.container.EnvRules, testRand)
5228 user := buildIDNameFromConfig(container.container.User.UserIDName, testRand)
5229 groups := buildGroupIDNamesFromUser(container.container.User, testRand)
5230 umask := container.container.User.Umask
5231 capabilities := container.container.Capabilities.toExternal()
5232
5233 _, _, _, err = tc.policy.EnforceExecInContainerPolicy(p.ctx, container.containerID, process.Command, envList, container.container.WorkingDir, false, user, groups, umask, &capabilities)
5234
5235 if err != nil {
5236 t.Fatal("Unexpected failure with false")
5237 }
5238 }
5239
5240 func Test_Rego_EnforceExecInContainerNoNewPrivilegesPolicy_FalseAllowsTrue(t *testing.T) {
5241 p := generateConstraints(testRand, 1)
5242 p.containers[0].NoNewPrivileges = false
5243
5244 tc, err := setupRegoRunningContainerTest(p, false)
5245 if err != nil {
5246 t.Fatal(err)
5247 }
5248
5249 container := selectContainerFromRunningContainers(tc.runningContainers, testRand)
5250 process := selectExecProcess(container.container.ExecProcesses, testRand)
5251 envList := buildEnvironmentVariablesFromEnvRules(container.container.EnvRules, testRand)
5252 user := buildIDNameFromConfig(container.container.User.UserIDName, testRand)
5253 groups := buildGroupIDNamesFromUser(container.container.User, testRand)
5254 umask := container.container.User.Umask
5255 capabilities := container.container.Capabilities.toExternal()
5256
5257 _, _, _, err = tc.policy.EnforceExecInContainerPolicy(p.ctx, container.containerID, process.Command, envList, container.container.WorkingDir, true, user, groups, umask, &capabilities)
5258
5259 if err != nil {
5260 t.Fatal("Unexpected failure with true")
5261 }
5262 }
5263
5264 func Test_Rego_EnforceExecInContainerNoNewPrivilegesPolicy_TrueDisallowsFalse(t *testing.T) {
5265 p := generateConstraints(testRand, 1)
5266 p.containers[0].NoNewPrivileges = true
5267
5268 tc, err := setupRegoRunningContainerTest(p, false)
5269 if err != nil {
5270 t.Fatal(err)
5271 }
5272
5273 container := selectContainerFromRunningContainers(tc.runningContainers, testRand)
5274 process := selectExecProcess(container.container.ExecProcesses, testRand)
5275 envList := buildEnvironmentVariablesFromEnvRules(container.container.EnvRules, testRand)
5276 user := buildIDNameFromConfig(container.container.User.UserIDName, testRand)
5277 groups := buildGroupIDNamesFromUser(container.container.User, testRand)
5278 umask := container.container.User.Umask
5279 capabilities := container.container.Capabilities.toExternal()
5280
5281 _, _, _, err = tc.policy.EnforceExecInContainerPolicy(p.ctx, container.containerID, process.Command, envList, container.container.WorkingDir, false, user, groups, umask, &capabilities)
5282
5283 if err == nil {
5284 t.Fatal("Unexpected success with false")
5285 }
5286
5287 if !assertDecisionJSONContains(t, err, "invalid noNewPrivileges") {
5288 t.Fatal("Expected error message is missing")
5289 }
5290 }
5291
5292 func Test_Rego_EnforceExecInContainerNoNewPrivilegesPolicy_TrueAllowsTrue(t *testing.T) {
5293 p := generateConstraints(testRand, 1)
5294 p.containers[0].NoNewPrivileges = true
5295
5296 tc, err := setupRegoRunningContainerTest(p, false)
5297 if err != nil {
5298 t.Fatal(err)
5299 }
5300
5301 container := selectContainerFromRunningContainers(tc.runningContainers, testRand)
5302 process := selectExecProcess(container.container.ExecProcesses, testRand)
5303 envList := buildEnvironmentVariablesFromEnvRules(container.container.EnvRules, testRand)
5304 user := buildIDNameFromConfig(container.container.User.UserIDName, testRand)
5305 groups := buildGroupIDNamesFromUser(container.container.User, testRand)
5306 umask := container.container.User.Umask
5307 capabilities := container.container.Capabilities.toExternal()
5308
5309 _, _, _, err = tc.policy.EnforceExecInContainerPolicy(p.ctx, container.containerID, process.Command, envList, container.container.WorkingDir, true, user, groups, umask, &capabilities)
5310
5311 if err != nil {
5312 t.Fatal("Unexpected failure with true")
5313 }
5314 }
5315
5316 func Test_Rego_EnforceContainerUserPolicy_UserName_NoMatches(t *testing.T) {
5317 f := func(p *generatedConstraints) bool {
5318 tc, err := setupSimpleRegoCreateContainerTest(p)
5319 if err != nil {
5320 t.Error(err)
5321 return false
5322 }
5323
5324 user := generateIDName(testRand)
5325
5326 _, _, _, err = tc.policy.EnforceCreateContainerPolicy(p.ctx, tc.sandboxID, tc.containerID, tc.argList, tc.envList, tc.workingDir, tc.mounts, false, tc.noNewPrivileges, user, tc.groups, tc.umask, tc.capabilities, tc.seccomp)
5327
5328 if err == nil {
5329 return false
5330 }
5331
5332 return assertDecisionJSONContains(t, err, "invalid user")
5333 }
5334
5335 if err := quick.Check(f, &quick.Config{MaxCount: 25, Rand: testRand}); err != nil {
5336 t.Errorf("Test_Rego_EnforceContainerUserPolicy_UserName_NoMatches: %v", err)
5337 }
5338 }
5339
5340 func Test_Rego_EnforceContainerUserPolicy_GroupNames_NoMatches(t *testing.T) {
5341 f := func(p *generatedConstraints) bool {
5342 tc, err := setupSimpleRegoCreateContainerTest(p)
5343 if err != nil {
5344 t.Error(err)
5345 return false
5346 }
5347
5348 groups := append(tc.groups, generateIDName(testRand))
5349
5350 _, _, _, err = tc.policy.EnforceCreateContainerPolicy(p.ctx, tc.sandboxID, tc.containerID, tc.argList, tc.envList, tc.workingDir, tc.mounts, false, tc.noNewPrivileges, tc.user, groups, tc.umask, tc.capabilities, tc.seccomp)
5351
5352 if err == nil {
5353 return false
5354 }
5355
5356 return assertDecisionJSONContains(t, err, "invalid user")
5357 }
5358
5359 if err := quick.Check(f, &quick.Config{MaxCount: 25, Rand: testRand}); err != nil {
5360 t.Errorf("Test_Rego_EnforceContainerUserPolicy_GroupNames_NoMatches: %v", err)
5361 }
5362 }
5363
5364 func Test_Rego_EnforceContainerUserPolicy_Umask_NoMatches(t *testing.T) {
5365 f := func(p *generatedConstraints) bool {
5366 tc, err := setupSimpleRegoCreateContainerTest(p)
5367 if err != nil {
5368 t.Error(err)
5369 return false
5370 }
5371
5372 umask := "0888"
5373
5374 _, _, _, err = tc.policy.EnforceCreateContainerPolicy(p.ctx, tc.sandboxID, tc.containerID, tc.argList, tc.envList, tc.workingDir, tc.mounts, false, tc.noNewPrivileges, tc.user, tc.groups, umask, tc.capabilities, tc.seccomp)
5375
5376 if err == nil {
5377 return false
5378 }
5379
5380 return assertDecisionJSONContains(t, err, "invalid user")
5381 }
5382
5383 if err := quick.Check(f, &quick.Config{MaxCount: 25, Rand: testRand}); err != nil {
5384 t.Errorf("Test_Rego_EnforceContainerUserPolicy_Umask_NoMatches: %v", err)
5385 }
5386 }
5387
5388 func Test_Rego_EnforceExecInContainerUserPolicy_Username_NoMatches(t *testing.T) {
5389 f := func(p *generatedConstraints) bool {
5390 tc, err := setupRegoRunningContainerTest(p, false)
5391 if err != nil {
5392 t.Error(err)
5393 return false
5394 }
5395
5396 container := selectContainerFromRunningContainers(tc.runningContainers, testRand)
5397 process := selectExecProcess(container.container.ExecProcesses, testRand)
5398 envList := buildEnvironmentVariablesFromEnvRules(container.container.EnvRules, testRand)
5399 groups := buildGroupIDNamesFromUser(container.container.User, testRand)
5400 umask := container.container.User.Umask
5401 capabilities := container.container.Capabilities.toExternal()
5402
5403 user := generateIDName(testRand)
5404
5405 _, _, _, err = tc.policy.EnforceExecInContainerPolicy(p.ctx, container.containerID, process.Command, envList, container.container.WorkingDir, container.container.NoNewPrivileges, user, groups, umask, &capabilities)
5406
5407
5408 if err == nil {
5409 return false
5410 }
5411
5412 return assertDecisionJSONContains(t, err, "invalid user")
5413 }
5414
5415 if err := quick.Check(f, &quick.Config{MaxCount: 10, Rand: testRand}); err != nil {
5416 t.Errorf("Test_Rego_EnforceExecInContainerUserPolicy_Username_NoMatches: %v", err)
5417 }
5418 }
5419
5420 func Test_Rego_EnforceExecInContainerUserPolicy_GroupNames_NoMatches(t *testing.T) {
5421 f := func(p *generatedConstraints) bool {
5422 tc, err := setupRegoRunningContainerTest(p, false)
5423 if err != nil {
5424 t.Error(err)
5425 return false
5426 }
5427
5428 container := selectContainerFromRunningContainers(tc.runningContainers, testRand)
5429 process := selectExecProcess(container.container.ExecProcesses, testRand)
5430 envList := buildEnvironmentVariablesFromEnvRules(container.container.EnvRules, testRand)
5431 user := buildIDNameFromConfig(container.container.User.UserIDName, testRand)
5432 groups := buildGroupIDNamesFromUser(container.container.User, testRand)
5433 umask := container.container.User.Umask
5434 capabilities := container.container.Capabilities.toExternal()
5435
5436 groups = append(groups, generateIDName(testRand))
5437
5438 _, _, _, err = tc.policy.EnforceExecInContainerPolicy(p.ctx, container.containerID, process.Command, envList, container.container.WorkingDir, container.container.NoNewPrivileges, user, groups, umask, &capabilities)
5439
5440
5441 if err == nil {
5442 return false
5443 }
5444
5445 return assertDecisionJSONContains(t, err, "invalid user")
5446 }
5447
5448 if err := quick.Check(f, &quick.Config{MaxCount: 10, Rand: testRand}); err != nil {
5449 t.Errorf("Test_Rego_EnforceExecInContainerUserPolicy_GroupNames_NoMatches: %v", err)
5450 }
5451 }
5452
5453 func Test_Rego_EnforceExecInContainerUserPolicy_Umask_NoMatches(t *testing.T) {
5454 f := func(p *generatedConstraints) bool {
5455 tc, err := setupRegoRunningContainerTest(p, false)
5456 if err != nil {
5457 t.Error(err)
5458 return false
5459 }
5460
5461 container := selectContainerFromRunningContainers(tc.runningContainers, testRand)
5462 process := selectExecProcess(container.container.ExecProcesses, testRand)
5463 envList := buildEnvironmentVariablesFromEnvRules(container.container.EnvRules, testRand)
5464 user := buildIDNameFromConfig(container.container.User.UserIDName, testRand)
5465 groups := buildGroupIDNamesFromUser(container.container.User, testRand)
5466 capabilities := container.container.Capabilities.toExternal()
5467
5468
5469
5470
5471 umask := "8888"
5472
5473 _, _, _, err = tc.policy.EnforceExecInContainerPolicy(p.ctx, container.containerID, process.Command, envList, container.container.WorkingDir, container.container.NoNewPrivileges, user, groups, umask, &capabilities)
5474
5475
5476 if err == nil {
5477 return false
5478 }
5479
5480 return assertDecisionJSONContains(t, err, "invalid user")
5481 }
5482
5483 if err := quick.Check(f, &quick.Config{MaxCount: 10, Rand: testRand}); err != nil {
5484 t.Errorf("Test_Rego_EnforceExecInContainerUserPolicy_Umask_NoMatches: %v", err)
5485 }
5486 }
5487
5488 func Test_Rego_EnforceCreateContainerUserPolicy_UserIDName_Re2Match(t *testing.T) {
5489 gc := generateConstraints(testRand, 1)
5490 gc.containers[0].User.UserIDName = IDNameConfig{
5491 Strategy: IDNameStrategyRegex,
5492 Rule: "foo\\d+",
5493 }
5494
5495 tc, err := setupSimpleRegoCreateContainerTest(gc)
5496 if err != nil {
5497 t.Fatalf("unable to setup test: %v", err)
5498 }
5499
5500 user := IDName{
5501 ID: "1000",
5502 Name: "foo123",
5503 }
5504
5505 _, _, _, err = tc.policy.EnforceCreateContainerPolicy(tc.ctx, tc.sandboxID, tc.containerID, tc.argList, tc.envList, tc.workingDir, tc.mounts, false, tc.noNewPrivileges, user, tc.groups, tc.umask, tc.capabilities, tc.seccomp)
5506 if err != nil {
5507 t.Errorf("Expected container setup to be allowed. It wasn't: %v", err)
5508 }
5509 }
5510
5511 func Test_Rego_EnforceCreateContainerUserPolicy_UserIDName_AnyMatch(t *testing.T) {
5512 gc := generateConstraints(testRand, 1)
5513 gc.containers[0].User.UserIDName = IDNameConfig{
5514 Strategy: IDNameStrategyAny,
5515 Rule: "",
5516 }
5517
5518 tc, err := setupSimpleRegoCreateContainerTest(gc)
5519 if err != nil {
5520 t.Fatalf("unable to setup test: %v", err)
5521 }
5522
5523 user := generateIDName(testRand)
5524
5525 _, _, _, err = tc.policy.EnforceCreateContainerPolicy(tc.ctx, tc.sandboxID, tc.containerID, tc.argList, tc.envList, tc.workingDir, tc.mounts, false, tc.noNewPrivileges, user, tc.groups, tc.umask, tc.capabilities, tc.seccomp)
5526 if err != nil {
5527 t.Errorf("Expected container setup to be allowed. It wasn't: %v", err)
5528 }
5529 }
5530
5531 func Test_Rego_EnforceCreateContainerUserPolicy_GroupIDName_Re2Match(t *testing.T) {
5532 gc := generateConstraints(testRand, 1)
5533 gc.containers[0].User.GroupIDNames = append(gc.containers[0].User.GroupIDNames, IDNameConfig{
5534 Strategy: IDNameStrategyRegex,
5535 Rule: "foo\\d+",
5536 })
5537
5538 tc, err := setupSimpleRegoCreateContainerTest(gc)
5539 if err != nil {
5540 t.Fatalf("unable to setup test: %v", err)
5541 }
5542
5543 groups := append(tc.groups, IDName{ID: "1000", Name: "foo123"})
5544
5545 _, _, _, err = tc.policy.EnforceCreateContainerPolicy(tc.ctx, tc.sandboxID, tc.containerID, tc.argList, tc.envList, tc.workingDir, tc.mounts, false, tc.noNewPrivileges, tc.user, groups, tc.umask, tc.capabilities, tc.seccomp)
5546 if err != nil {
5547 t.Errorf("Expected container setup to be allowed. It wasn't: %v", err)
5548 }
5549 }
5550
5551 func Test_Rego_EnforceCreateContainerUserPolicy_GroupIDName_AnyMatch(t *testing.T) {
5552 gc := generateConstraints(testRand, 1)
5553 gc.containers[0].User.GroupIDNames = append(gc.containers[0].User.GroupIDNames, IDNameConfig{
5554 Strategy: IDNameStrategyAny,
5555 Rule: "",
5556 })
5557
5558 tc, err := setupSimpleRegoCreateContainerTest(gc)
5559 if err != nil {
5560 t.Fatalf("unable to setup test: %v", err)
5561 }
5562
5563 groups := append(tc.groups, generateIDName(testRand))
5564
5565 _, _, _, err = tc.policy.EnforceCreateContainerPolicy(tc.ctx, tc.sandboxID, tc.containerID, tc.argList, tc.envList, tc.workingDir, tc.mounts, false, tc.noNewPrivileges, tc.user, groups, tc.umask, tc.capabilities, tc.seccomp)
5566 if err != nil {
5567 t.Errorf("Expected container setup to be allowed. It wasn't: %v", err)
5568 }
5569 }
5570
5571 func Test_Rego_EnforceCreateContainerSeccompPolicy_NoMatch(t *testing.T) {
5572 gc := generateConstraints(testRand, 1)
5573
5574 tc, err := setupSimpleRegoCreateContainerTest(gc)
5575 if err != nil {
5576 t.Fatalf("unable to setup test: %v", err)
5577 }
5578
5579 seccomp := generateRootHash(testRand)
5580
5581 _, _, _, err = tc.policy.EnforceCreateContainerPolicy(tc.ctx, tc.sandboxID, tc.containerID, tc.argList, tc.envList, tc.workingDir, tc.mounts, false, tc.noNewPrivileges, tc.user, tc.groups, tc.umask, tc.capabilities, seccomp)
5582 if err == nil {
5583 t.Error("Expected container setup to not be allowed.")
5584 } else if !assertDecisionJSONContains(t, err, "invalid seccomp") {
5585 t.Error("`invalid seccomp` missing from error message")
5586 }
5587 }
5588
5589 func Test_Rego_FrameworkSVN(t *testing.T) {
5590 gc := generateConstraints(testRand, 1)
5591 securityPolicy := gc.toPolicy()
5592 defaultMounts := generateMounts(testRand)
5593 privilegedMounts := generateMounts(testRand)
5594
5595 code := securityPolicy.marshalRego()
5596 code = strings.Replace(code, "framework_version", "framework_svn", 1)
5597
5598 policy, err := newRegoPolicy(code,
5599 toOCIMounts(defaultMounts),
5600 toOCIMounts(privilegedMounts))
5601 if err != nil {
5602 t.Fatalf("unable to create policy: %v", err)
5603 }
5604
5605 value, err := policy.rego.RawQuery("data.framework.policy_framework_version", map[string]interface{}{})
5606 if err != nil {
5607 t.Fatalf("unable to query policy: %v", err)
5608 }
5609
5610 policyFrameworkVersion, ok := value[0].Expressions[0].Value.(string)
5611 if ok {
5612 if policyFrameworkVersion != frameworkVersion {
5613 t.Error("policy_framework_version is not set correctly from framework_svn")
5614 }
5615 } else {
5616 t.Error("no result set from querying data.framework.policy_framework_version")
5617 }
5618 }
5619
5620 func Test_Rego_Fragment_FrameworkSVN(t *testing.T) {
5621 gc := generateConstraints(testRand, 1)
5622 gc.fragments = generateFragments(testRand, 1)
5623
5624 gc.fragments = generateFragments(testRand, 1)
5625 gc.fragments[0].minimumSVN = generateSemver(testRand)
5626 securityPolicy := gc.toPolicy()
5627
5628 defaultMounts := toOCIMounts(generateMounts(testRand))
5629 privilegedMounts := toOCIMounts(generateMounts(testRand))
5630 policy, err := newRegoPolicy(securityPolicy.marshalRego(), defaultMounts, privilegedMounts)
5631
5632 if err != nil {
5633 t.Fatalf("error compiling policy: %v", err)
5634 }
5635
5636 fragmentConstraints := generateConstraints(testRand, 1)
5637 fragmentConstraints.svn = mustIncrementSVN(gc.fragments[0].minimumSVN)
5638 code := fragmentConstraints.toFragment().marshalRego()
5639
5640 policy.rego.AddModule(fragmentConstraints.namespace, &rpi.RegoModule{
5641 Namespace: fragmentConstraints.namespace,
5642 Feed: gc.fragments[0].feed,
5643 Issuer: gc.fragments[0].issuer,
5644 Code: code,
5645 })
5646
5647 input := map[string]interface{}{
5648 "namespace": fragmentConstraints.namespace,
5649 }
5650 result, err := policy.rego.RawQuery("data.framework.fragment_framework_version", input)
5651
5652 if err != nil {
5653 t.Fatalf("error querying policy: %v", err)
5654 }
5655
5656 fragmentFrameworkVersion, ok := result[0].Expressions[0].Value.(string)
5657
5658 if ok {
5659 if fragmentFrameworkVersion != frameworkVersion {
5660 t.Error("fragment_framework_version is not set correctly from framework_svn")
5661 }
5662 } else {
5663 t.Error("no result set from querying data.framework.fragment_framework_version")
5664 }
5665 }
5666
5667 func Test_Rego_APISVN(t *testing.T) {
5668 gc := generateConstraints(testRand, 1)
5669 securityPolicy := gc.toPolicy()
5670 defaultMounts := generateMounts(testRand)
5671 privilegedMounts := generateMounts(testRand)
5672
5673 code := securityPolicy.marshalRego()
5674 code = strings.Replace(code, "api_version", "api_svn", 1)
5675
5676 policy, err := newRegoPolicy(code,
5677 toOCIMounts(defaultMounts),
5678 toOCIMounts(privilegedMounts))
5679 if err != nil {
5680 t.Fatalf("unable to create policy: %v", err)
5681 }
5682
5683 value, err := policy.rego.RawQuery("data.framework.policy_api_version", map[string]interface{}{})
5684 if err != nil {
5685 t.Fatalf("unable to query policy: %v", err)
5686 }
5687
5688 policyAPIVersion, ok := value[0].Expressions[0].Value.(string)
5689 if ok {
5690 if policyAPIVersion != apiVersion {
5691 t.Error("policy_api_version is not set correctly from api_svn")
5692 }
5693 } else {
5694 t.Error("no result set from querying data.framework.policy_api_version")
5695 }
5696 }
5697
5698 func Test_Rego_NoReason(t *testing.T) {
5699 code := `package policy
5700
5701 api_version := "0.0.1"
5702
5703 mount_device := {"allowed": false}
5704 `
5705 policy, err := newRegoPolicy(code, []oci.Mount{}, []oci.Mount{})
5706 if err != nil {
5707 t.Fatalf("unable to create policy: %v", err)
5708 }
5709
5710 ctx := context.Background()
5711 err = policy.EnforceDeviceMountPolicy(ctx, generateMountTarget(testRand), generateRootHash(testRand))
5712 if err == nil {
5713 t.Error("expected error, got nil")
5714 }
5715
5716 assertDecisionJSONContains(t, err, noReasonMessage)
5717 }
5718
5719 func Test_Rego_ErrorTruncation(t *testing.T) {
5720 f := func(p *generatedConstraints) bool {
5721 tc, err := setupSimpleRegoCreateContainerTest(p)
5722 if err != nil {
5723 t.Error(err)
5724 return false
5725 }
5726
5727 maxErrorMessageLength := int(randMinMax(testRand, 128, 4*1024))
5728 tc.policy.maxErrorMessageLength = maxErrorMessageLength
5729
5730 _, _, _, err = tc.policy.EnforceCreateContainerPolicy(tc.ctx, tc.sandboxID, tc.containerID, tc.argList, tc.envList, randString(testRand, 20), tc.mounts, false, tc.noNewPrivileges, tc.user, tc.groups, tc.umask, tc.capabilities, tc.seccomp)
5731
5732 if err == nil {
5733 return false
5734 }
5735
5736 if len(err.Error()) > maxErrorMessageLength {
5737 return assertDecisionJSONContains(t, err, `"reason.error_objects","input","reason"`)
5738 }
5739
5740 policyDecisionJSON, err := ExtractPolicyDecision(err.Error())
5741 if err != nil {
5742 t.Errorf("unable to extract policy decision JSON: %v", err)
5743 return false
5744 }
5745
5746 var policyDecision map[string]interface{}
5747 err = json.Unmarshal([]byte(policyDecisionJSON), &policyDecision)
5748 if err != nil {
5749 t.Errorf("unable to unmarshal policy decision: %v", err)
5750 }
5751
5752 if truncated, ok := policyDecision["truncated"].([]interface{}); ok {
5753 if truncated[0].(string) != "reason.error_objects" {
5754 t.Error("first item to be truncated should be reason.error_objects")
5755 return false
5756 } else if len(truncated) > 1 && truncated[1].(string) != "input" {
5757 t.Error("second item to be truncated should be input")
5758 return false
5759 }
5760 }
5761
5762 return true
5763 }
5764
5765 if err := quick.Check(f, &quick.Config{MaxCount: 50, Rand: testRand}); err != nil {
5766 t.Errorf("Test_Rego_EnforceOverlayMountPolicy_No_Matches failed: %v", err)
5767 }
5768 }
5769
5770 func Test_Rego_ErrorTruncation_Unable(t *testing.T) {
5771 gc := generateConstraints(testRand, maxContainersInGeneratedConstraints)
5772 tc, err := setupRegoOverlayTest(gc, false)
5773 if err != nil {
5774 t.Fatal(err)
5775 }
5776
5777 maxErrorMessageLength := 32
5778 tc.policy.maxErrorMessageLength = maxErrorMessageLength
5779 err = tc.policy.EnforceOverlayMountPolicy(gc.ctx, tc.containerID, tc.layers, testDataGenerator.uniqueMountTarget())
5780
5781 if err == nil {
5782 t.Fatal("Policy did not throw the expected error")
5783 }
5784
5785 assertDecisionJSONContains(t, err, `"reason.error_objects","input","reason"`)
5786 }
5787
5788 func Test_Rego_ErrorTruncation_CustomPolicy(t *testing.T) {
5789 code := fmt.Sprintf(`package policy
5790
5791 api_version := "0.1.0"
5792
5793 mount_device := {"allowed": false}
5794
5795 reason := {"custom_error": "%s"}
5796 `, randString(testRand, 2048))
5797
5798 policy, err := newRegoPolicy(code, []oci.Mount{}, []oci.Mount{})
5799 if err != nil {
5800 t.Fatalf("unable to create policy: %v", err)
5801 }
5802
5803 policy.maxErrorMessageLength = 512
5804 ctx := context.Background()
5805 err = policy.EnforceDeviceMountPolicy(ctx, generateMountTarget(testRand), generateRootHash(testRand))
5806 if err == nil {
5807 t.Error("expected error, got nil")
5808 }
5809
5810 assertDecisionJSONContains(t, err, `"input","reason"`)
5811 }
5812
5813 func Test_Rego_Missing_Enforcement_Point(t *testing.T) {
5814 code := `package policy
5815
5816 api_svn := "0.10.0"
5817
5818 mount_device := {"allowed": true}
5819 unmount_device := {"allowed": true}
5820 mount_overlay := {"allowed": true}
5821 unmount_overlay := {"allowed": true}
5822
5823 reason := {"errors": data.framework.errors}
5824 `
5825
5826 policy, err := newRegoPolicy(code, []oci.Mount{}, []oci.Mount{})
5827 if err != nil {
5828 t.Fatalf("unable to create policy: %v", err)
5829 }
5830
5831 sandboxID := generateSandboxID(testRand)
5832 containerID := generateContainerID(testRand)
5833 argList := generateCommand(testRand)
5834 envList := generateEnvironmentVariables(testRand)
5835 workingDir := generateWorkingDir(testRand)
5836 mounts := []oci.Mount{}
5837 user := generateIDName(testRand)
5838 groups := []IDName{}
5839 umask := generateUmask(testRand)
5840 capabilities := &oci.LinuxCapabilities{
5841 Bounding: DefaultUnprivilegedCapabilities(),
5842 Effective: DefaultUnprivilegedCapabilities(),
5843 Inheritable: EmptyCapabiltiesSet(),
5844 Permitted: DefaultUnprivilegedCapabilities(),
5845 Ambient: EmptyCapabiltiesSet(),
5846 }
5847
5848 ctx := context.Background()
5849 _, _, _, err = policy.EnforceCreateContainerPolicy(
5850 ctx,
5851 sandboxID,
5852 containerID,
5853 argList,
5854 envList,
5855 workingDir,
5856 mounts,
5857 false,
5858 false,
5859 user,
5860 groups,
5861 umask,
5862 capabilities,
5863 "",
5864 )
5865
5866 assertDecisionJSONContains(t, err, "rule for create_container is missing from policy")
5867 }
5868
5869 func Test_Rego_Capabiltiies_Placeholder_Object_Privileged(t *testing.T) {
5870 gc := generateConstraints(testRand, 1)
5871 gc.containers[0].Capabilities = &capabilitiesInternal{
5872 Bounding: DefaultPrivilegedCapabilities(),
5873 Effective: DefaultPrivilegedCapabilities(),
5874 Inheritable: DefaultPrivilegedCapabilities(),
5875 Permitted: DefaultPrivilegedCapabilities(),
5876 Ambient: EmptyCapabiltiesSet(),
5877 }
5878 tc, err := setupSimpleRegoCreateContainerTest(gc)
5879 if err != nil {
5880 t.Fatal(err)
5881 }
5882
5883 _, _, _, err = tc.policy.EnforceCreateContainerPolicy(tc.ctx, tc.sandboxID, tc.containerID, tc.argList, tc.envList, randString(testRand, 20), tc.mounts, false, tc.noNewPrivileges, tc.user, tc.groups, tc.umask, tc.capabilities, tc.seccomp)
5884
5885 if err == nil {
5886 t.Fatal("Policy did not throw the expected error")
5887 }
5888
5889 assertDecisionJSONContains(t, err, "[privileged]")
5890 assertDecisionJSONDoesNotContain(t, err, DefaultPrivilegedCapabilities()...)
5891 }
5892
5893 func Test_Rego_Capabiltiies_Placeholder_Object_Unprivileged(t *testing.T) {
5894 gc := generateConstraints(testRand, 1)
5895 gc.containers[0].Capabilities = &capabilitiesInternal{
5896 Bounding: DefaultUnprivilegedCapabilities(),
5897 Effective: DefaultUnprivilegedCapabilities(),
5898 Inheritable: EmptyCapabiltiesSet(),
5899 Permitted: DefaultUnprivilegedCapabilities(),
5900 Ambient: EmptyCapabiltiesSet(),
5901 }
5902 tc, err := setupSimpleRegoCreateContainerTest(gc)
5903 if err != nil {
5904 t.Fatal(err)
5905 }
5906
5907 _, _, _, err = tc.policy.EnforceCreateContainerPolicy(tc.ctx, tc.sandboxID, tc.containerID, tc.argList, tc.envList, randString(testRand, 20), tc.mounts, false, tc.noNewPrivileges, tc.user, tc.groups, tc.umask, tc.capabilities, tc.seccomp)
5908
5909 if err == nil {
5910 t.Fatal("Policy did not throw the expected error")
5911 }
5912
5913 assertDecisionJSONContains(t, err, "[unprivileged]")
5914 assertDecisionJSONDoesNotContain(t, err, DefaultUnprivilegedCapabilities()...)
5915 }
5916
5917
5918
5919
5920
5921 func generateExternalProcesses(r *rand.Rand) []*externalProcess {
5922 var processes []*externalProcess
5923
5924 numProcesses := atLeastOneAtMost(r, maxExternalProcessesInGeneratedConstraints)
5925 for i := 0; i < int(numProcesses); i++ {
5926 processes = append(processes, generateExternalProcess(r))
5927 }
5928
5929 return processes
5930 }
5931
5932 func generateExternalProcess(r *rand.Rand) *externalProcess {
5933 return &externalProcess{
5934 command: generateCommand(r),
5935 envRules: generateEnvironmentVariableRules(r),
5936 workingDir: generateWorkingDir(r),
5937 allowStdioAccess: randBool(r),
5938 }
5939 }
5940
5941 func randChoices(r *rand.Rand, numChoices int, numItems int) []int {
5942 shuffle := r.Perm(numItems)
5943 if numChoices > numItems {
5944 return shuffle
5945 }
5946
5947 return shuffle[:numChoices]
5948 }
5949
5950 func randChoicesWithReplacement(r *rand.Rand, numChoices int, numItems int) []int {
5951 choices := make([]int, numChoices)
5952 for i := 0; i < numChoices; i++ {
5953 choices[i] = r.Intn(numItems)
5954 }
5955
5956 return choices
5957 }
5958
5959 func randChooseStrings(r *rand.Rand, items []string, numChoices int) []string {
5960 numItems := len(items)
5961 choiceIndices := randChoices(r, numChoices, numItems)
5962 choices := make([]string, numChoices)
5963 for i, index := range choiceIndices {
5964 choices[i] = items[index]
5965 }
5966 return choices
5967 }
5968
5969 func randChooseStringsWithReplacement(r *rand.Rand, items []string, numChoices int) []string {
5970 numItems := len(items)
5971 choiceIndices := randChoicesWithReplacement(r, numChoices, numItems)
5972 choices := make([]string, numChoices)
5973 for i, index := range choiceIndices {
5974 choices[i] = items[index]
5975 }
5976 return choices
5977 }
5978
5979 func selectExternalProcessFromConstraints(constraints *generatedConstraints, r *rand.Rand) *externalProcess {
5980 numberOfProcessesInConstraints := len(constraints.externalProcesses)
5981 return constraints.externalProcesses[r.Intn(numberOfProcessesInConstraints)]
5982 }
5983
5984 func (constraints *generatedConstraints) toPolicy() *securityPolicyInternal {
5985 return &securityPolicyInternal{
5986 Containers: constraints.containers,
5987 ExternalProcesses: constraints.externalProcesses,
5988 Fragments: constraints.fragments,
5989 AllowPropertiesAccess: constraints.allowGetProperties,
5990 AllowDumpStacks: constraints.allowDumpStacks,
5991 AllowRuntimeLogging: constraints.allowRuntimeLogging,
5992 AllowEnvironmentVariableDropping: constraints.allowEnvironmentVariableDropping,
5993 AllowUnencryptedScratch: constraints.allowUnencryptedScratch,
5994 AllowCapabilityDropping: constraints.allowCapabilityDropping,
5995 }
5996 }
5997
5998 func (constraints *generatedConstraints) toFragment() *securityPolicyFragment {
5999 return &securityPolicyFragment{
6000 Namespace: constraints.namespace,
6001 SVN: constraints.svn,
6002 Containers: constraints.containers,
6003 ExternalProcesses: constraints.externalProcesses,
6004 Fragments: constraints.fragments,
6005 }
6006 }
6007
6008 func toOCIMounts(mounts []mountInternal) []oci.Mount {
6009 result := make([]oci.Mount, len(mounts))
6010 for i, mount := range mounts {
6011 result[i] = oci.Mount{
6012 Source: mount.Source,
6013 Destination: mount.Destination,
6014 Options: mount.Options,
6015 Type: mount.Type,
6016 }
6017 }
6018 return result
6019 }
6020
6021
6027
6028 func copyStrings(values []string) []string {
6029 valuesCopy := make([]string, len(values))
6030 copy(valuesCopy, values)
6031 return valuesCopy
6032 }
6033
6034 func copyMounts(mounts []oci.Mount) []oci.Mount {
6035 bytes, err := json.Marshal(mounts)
6036 if err != nil {
6037 panic(err)
6038 }
6039
6040 mountsCopy := make([]oci.Mount, len(mounts))
6041 err = json.Unmarshal(bytes, &mountsCopy)
6042 if err != nil {
6043 panic(err)
6044 }
6045
6046 return mountsCopy
6047 }
6048
6049 func copyMountsInternal(mounts []mountInternal) []mountInternal {
6050 var mountsCopy []mountInternal
6051
6052 for _, in := range mounts {
6053 out := mountInternal{
6054 Source: in.Source,
6055 Destination: in.Destination,
6056 Type: in.Type,
6057 Options: copyStrings(in.Options),
6058 }
6059
6060 mountsCopy = append(mountsCopy, out)
6061 }
6062
6063 return mountsCopy
6064 }
6065
6066 func copyLinuxCapabilities(caps oci.LinuxCapabilities) oci.LinuxCapabilities {
6067 bytes, err := json.Marshal(caps)
6068 if err != nil {
6069 panic(err)
6070 }
6071
6072 capsCopy := oci.LinuxCapabilities{}
6073 err = json.Unmarshal(bytes, &capsCopy)
6074 if err != nil {
6075 panic(err)
6076 }
6077
6078 return capsCopy
6079 }
6080
6081 func copyLinuxSeccomp(seccomp oci.LinuxSeccomp) oci.LinuxSeccomp {
6082 bytes, err := json.Marshal(seccomp)
6083 if err != nil {
6084 panic(err)
6085 }
6086
6087 seccompCopy := oci.LinuxSeccomp{}
6088 err = json.Unmarshal(bytes, &seccompCopy)
6089 if err != nil {
6090 panic(err)
6091 }
6092
6093 return seccompCopy
6094 }
6095
6096 type regoOverlayTestConfig struct {
6097 layers []string
6098 containerID string
6099 policy *regoEnforcer
6100 }
6101
6102 func setupRegoOverlayTest(gc *generatedConstraints, valid bool) (tc *regoOverlayTestConfig, err error) {
6103 securityPolicy := gc.toPolicy()
6104 policy, err := newRegoPolicy(securityPolicy.marshalRego(), []oci.Mount{}, []oci.Mount{})
6105 if err != nil {
6106 return nil, err
6107 }
6108
6109 containerID := testDataGenerator.uniqueContainerID()
6110 c := selectContainerFromContainerList(gc.containers, testRand)
6111
6112 var layerPaths []string
6113 if valid {
6114 layerPaths, err = testDataGenerator.createValidOverlayForContainer(policy, c)
6115 if err != nil {
6116 return nil, fmt.Errorf("error creating valid overlay: %w", err)
6117 }
6118 } else {
6119 layerPaths, err = testDataGenerator.createInvalidOverlayForContainer(policy, c)
6120 if err != nil {
6121 return nil, fmt.Errorf("error creating invalid overlay: %w", err)
6122 }
6123 }
6124
6125
6126 return ®oOverlayTestConfig{
6127 layers: copyStrings(layerPaths),
6128 containerID: containerID,
6129 policy: policy,
6130 }, nil
6131 }
6132
6133 type regoContainerTestConfig struct {
6134 envList []string
6135 argList []string
6136 workingDir string
6137 containerID string
6138 sandboxID string
6139 mounts []oci.Mount
6140 noNewPrivileges bool
6141 user IDName
6142 groups []IDName
6143 umask string
6144 capabilities *oci.LinuxCapabilities
6145 seccomp string
6146 policy *regoEnforcer
6147 ctx context.Context
6148 }
6149
6150 func setupSimpleRegoCreateContainerTest(gc *generatedConstraints) (tc *regoContainerTestConfig, err error) {
6151 c := selectContainerFromContainerList(gc.containers, testRand)
6152 return setupRegoCreateContainerTest(gc, c, false)
6153 }
6154
6155 func setupRegoPrivilegedMountTest(gc *generatedConstraints) (tc *regoContainerTestConfig, err error) {
6156 c := selectContainerFromContainerList(gc.containers, testRand)
6157 return setupRegoCreateContainerTest(gc, c, true)
6158 }
6159
6160 func setupRegoCreateContainerTest(gc *generatedConstraints, testContainer *securityPolicyContainer, privilegedError bool) (tc *regoContainerTestConfig, err error) {
6161 securityPolicy := gc.toPolicy()
6162 defaultMounts := generateMounts(testRand)
6163 privilegedMounts := generateMounts(testRand)
6164
6165 policy, err := newRegoPolicy(securityPolicy.marshalRego(),
6166 toOCIMounts(defaultMounts),
6167 toOCIMounts(privilegedMounts))
6168 if err != nil {
6169 return nil, err
6170 }
6171
6172 containerID, err := mountImageForContainer(policy, testContainer)
6173 if err != nil {
6174 return nil, err
6175 }
6176
6177 envList := buildEnvironmentVariablesFromEnvRules(testContainer.EnvRules, testRand)
6178 sandboxID := testDataGenerator.uniqueSandboxID()
6179
6180 mounts := testContainer.Mounts
6181 mounts = append(mounts, defaultMounts...)
6182 if privilegedError {
6183 testContainer.AllowElevated = false
6184 }
6185
6186 if testContainer.AllowElevated || privilegedError {
6187 mounts = append(mounts, privilegedMounts...)
6188 }
6189 mountSpec := buildMountSpecFromMountArray(mounts, sandboxID, testRand)
6190
6191 user := IDName{}
6192 if testContainer.User.UserIDName.Strategy != IDNameStrategyRegex {
6193 user = buildIDNameFromConfig(testContainer.User.UserIDName, testRand)
6194 }
6195 groups := buildGroupIDNamesFromUser(testContainer.User, testRand)
6196 umask := testContainer.User.Umask
6197
6198 var capabilities *oci.LinuxCapabilities
6199 if testContainer.Capabilities != nil {
6200 capsExternal := copyLinuxCapabilities(testContainer.Capabilities.toExternal())
6201 capabilities = &capsExternal
6202 } else {
6203 capabilities = nil
6204 }
6205 seccomp := testContainer.SeccompProfileSHA256
6206
6207
6208 return ®oContainerTestConfig{
6209 envList: copyStrings(envList),
6210 argList: copyStrings(testContainer.Command),
6211 workingDir: testContainer.WorkingDir,
6212 containerID: containerID,
6213 sandboxID: sandboxID,
6214 mounts: copyMounts(mountSpec.Mounts),
6215 noNewPrivileges: testContainer.NoNewPrivileges,
6216 user: user,
6217 groups: groups,
6218 umask: umask,
6219 capabilities: capabilities,
6220 seccomp: seccomp,
6221 policy: policy,
6222 ctx: gc.ctx,
6223 }, nil
6224 }
6225
6226 func setupRegoRunningContainerTest(gc *generatedConstraints, privileged bool) (tc *regoRunningContainerTestConfig, err error) {
6227 securityPolicy := gc.toPolicy()
6228 defaultMounts := generateMounts(testRand)
6229 privilegedMounts := generateMounts(testRand)
6230
6231 policy, err := newRegoPolicy(securityPolicy.marshalRego(),
6232 toOCIMounts(defaultMounts),
6233 toOCIMounts(privilegedMounts))
6234 if err != nil {
6235 return nil, err
6236 }
6237
6238 var runningContainers []regoRunningContainer
6239 numOfRunningContainers := int(atLeastOneAtMost(testRand, int32(len(gc.containers))))
6240 containersToRun := randChoicesWithReplacement(testRand, numOfRunningContainers, len(gc.containers))
6241 for _, i := range containersToRun {
6242 containerToStart := gc.containers[i]
6243 r, err := runContainer(policy, containerToStart, defaultMounts, privilegedMounts, privileged)
6244 if err != nil {
6245 return nil, err
6246 }
6247 runningContainers = append(runningContainers, *r)
6248 }
6249
6250 return ®oRunningContainerTestConfig{
6251 runningContainers: runningContainers,
6252 policy: policy,
6253 defaultMounts: copyMountsInternal(defaultMounts),
6254 privilegedMounts: copyMountsInternal(privilegedMounts),
6255 }, nil
6256 }
6257
6258 func runContainer(enforcer *regoEnforcer, container *securityPolicyContainer, defaultMounts []mountInternal, privilegedMounts []mountInternal, privileged bool) (*regoRunningContainer, error) {
6259 ctx := context.Background()
6260 containerID, err := mountImageForContainer(enforcer, container)
6261 if err != nil {
6262 return nil, err
6263 }
6264
6265 envList := buildEnvironmentVariablesFromEnvRules(container.EnvRules, testRand)
6266 user := buildIDNameFromConfig(container.User.UserIDName, testRand)
6267 groups := buildGroupIDNamesFromUser(container.User, testRand)
6268 umask := container.User.Umask
6269 sandboxID := generateSandboxID(testRand)
6270
6271 mounts := container.Mounts
6272 mounts = append(mounts, defaultMounts...)
6273 if container.AllowElevated {
6274 mounts = append(mounts, privilegedMounts...)
6275 }
6276 mountSpec := buildMountSpecFromMountArray(mounts, sandboxID, testRand)
6277 var capabilities oci.LinuxCapabilities
6278 if container.Capabilities == nil {
6279 if privileged {
6280 capabilities = capabilitiesInternal{
6281 Bounding: DefaultPrivilegedCapabilities(),
6282 Inheritable: DefaultPrivilegedCapabilities(),
6283 Effective: DefaultPrivilegedCapabilities(),
6284 Permitted: DefaultPrivilegedCapabilities(),
6285 Ambient: []string{},
6286 }.toExternal()
6287 } else {
6288 capabilities = capabilitiesInternal{
6289 Bounding: DefaultUnprivilegedCapabilities(),
6290 Inheritable: []string{},
6291 Effective: DefaultUnprivilegedCapabilities(),
6292 Permitted: DefaultUnprivilegedCapabilities(),
6293 Ambient: []string{},
6294 }.toExternal()
6295 }
6296 } else {
6297 capabilities = container.Capabilities.toExternal()
6298 }
6299 seccomp := container.SeccompProfileSHA256
6300
6301 _, _, _, err = enforcer.EnforceCreateContainerPolicy(ctx, sandboxID, containerID, container.Command, envList, container.WorkingDir, mountSpec.Mounts, privileged, container.NoNewPrivileges, user, groups, umask, &capabilities, seccomp)
6302 if err != nil {
6303 return nil, err
6304 }
6305
6306 return ®oRunningContainer{
6307 container: container,
6308 envList: envList,
6309 containerID: containerID,
6310 }, nil
6311 }
6312
6313 type regoRunningContainerTestConfig struct {
6314 runningContainers []regoRunningContainer
6315 policy *regoEnforcer
6316 defaultMounts []mountInternal
6317 privilegedMounts []mountInternal
6318 }
6319
6320 type regoRunningContainer struct {
6321 container *securityPolicyContainer
6322 envList []string
6323 containerID string
6324 }
6325
6326 func setupExternalProcessTest(gc *generatedConstraints) (tc *regoExternalPolicyTestConfig, err error) {
6327 gc.externalProcesses = generateExternalProcesses(testRand)
6328 securityPolicy := gc.toPolicy()
6329 defaultMounts := generateMounts(testRand)
6330 privilegedMounts := generateMounts(testRand)
6331
6332 policy, err := newRegoPolicy(securityPolicy.marshalRego(),
6333 toOCIMounts(defaultMounts),
6334 toOCIMounts(privilegedMounts))
6335 if err != nil {
6336 return nil, err
6337 }
6338
6339 return ®oExternalPolicyTestConfig{
6340 policy: policy,
6341 }, nil
6342 }
6343
6344 type regoExternalPolicyTestConfig struct {
6345 policy *regoEnforcer
6346 }
6347
6348 func setupPlan9MountTest(gc *generatedConstraints) (tc *regoPlan9MountTestConfig, err error) {
6349 securityPolicy := gc.toPolicy()
6350 defaultMounts := generateMounts(testRand)
6351 privilegedMounts := generateMounts(testRand)
6352
6353 testContainer := selectContainerFromContainerList(gc.containers, testRand)
6354 mountIndex := atMost(testRand, int32(len(testContainer.Mounts)-1))
6355 testMount := &testContainer.Mounts[mountIndex]
6356 testMount.Source = plan9Prefix
6357 testMount.Type = "secret"
6358
6359 policy, err := newRegoPolicy(securityPolicy.marshalRego(),
6360 toOCIMounts(defaultMounts),
6361 toOCIMounts(privilegedMounts))
6362 if err != nil {
6363 return nil, err
6364 }
6365
6366 containerID, err := mountImageForContainer(policy, testContainer)
6367 if err != nil {
6368 return nil, err
6369 }
6370
6371 uvmPathForShare := generateUVMPathForShare(testRand, containerID)
6372
6373 envList := buildEnvironmentVariablesFromEnvRules(testContainer.EnvRules, testRand)
6374 sandboxID := testDataGenerator.uniqueSandboxID()
6375
6376 mounts := testContainer.Mounts
6377 mounts = append(mounts, defaultMounts...)
6378
6379 if testContainer.AllowElevated {
6380 mounts = append(mounts, privilegedMounts...)
6381 }
6382 mountSpec := buildMountSpecFromMountArray(mounts, sandboxID, testRand)
6383 mountSpec.Mounts = append(mountSpec.Mounts, oci.Mount{
6384 Source: uvmPathForShare,
6385 Destination: testMount.Destination,
6386 Options: testMount.Options,
6387 Type: testMount.Type,
6388 })
6389
6390 user := buildIDNameFromConfig(testContainer.User.UserIDName, testRand)
6391 groups := buildGroupIDNamesFromUser(testContainer.User, testRand)
6392 umask := testContainer.User.Umask
6393
6394 capabilities := testContainer.Capabilities.toExternal()
6395 seccomp := testContainer.SeccompProfileSHA256
6396
6397
6398 return ®oPlan9MountTestConfig{
6399 envList: copyStrings(envList),
6400 argList: copyStrings(testContainer.Command),
6401 workingDir: testContainer.WorkingDir,
6402 containerID: containerID,
6403 sandboxID: sandboxID,
6404 mounts: copyMounts(mountSpec.Mounts),
6405 noNewPrivileges: testContainer.NoNewPrivileges,
6406 user: user,
6407 groups: groups,
6408 umask: umask,
6409 uvmPathForShare: uvmPathForShare,
6410 policy: policy,
6411 capabilities: &capabilities,
6412 seccomp: seccomp,
6413 }, nil
6414 }
6415
6416 type regoPlan9MountTestConfig struct {
6417 envList []string
6418 argList []string
6419 workingDir string
6420 containerID string
6421 sandboxID string
6422 mounts []oci.Mount
6423 uvmPathForShare string
6424 noNewPrivileges bool
6425 user IDName
6426 groups []IDName
6427 umask string
6428 policy *regoEnforcer
6429 capabilities *oci.LinuxCapabilities
6430 seccomp string
6431 }
6432
6433 func setupGetPropertiesTest(gc *generatedConstraints, allowPropertiesAccess bool) (tc *regoGetPropertiesTestConfig, err error) {
6434 gc.allowGetProperties = allowPropertiesAccess
6435
6436 securityPolicy := gc.toPolicy()
6437 defaultMounts := generateMounts(testRand)
6438 privilegedMounts := generateMounts(testRand)
6439
6440 policy, err := newRegoPolicy(securityPolicy.marshalRego(),
6441 toOCIMounts(defaultMounts),
6442 toOCIMounts(privilegedMounts))
6443 if err != nil {
6444 return nil, err
6445 }
6446
6447 return ®oGetPropertiesTestConfig{
6448 policy: policy,
6449 }, nil
6450 }
6451
6452 type regoGetPropertiesTestConfig struct {
6453 policy *regoEnforcer
6454 }
6455
6456 func setupDumpStacksTest(constraints *generatedConstraints, allowDumpStacks bool) (tc *regoGetPropertiesTestConfig, err error) {
6457 constraints.allowDumpStacks = allowDumpStacks
6458
6459 securityPolicy := constraints.toPolicy()
6460 defaultMounts := generateMounts(testRand)
6461 privilegedMounts := generateMounts(testRand)
6462
6463 policy, err := newRegoPolicy(securityPolicy.marshalRego(),
6464 toOCIMounts(defaultMounts),
6465 toOCIMounts(privilegedMounts))
6466 if err != nil {
6467 return nil, err
6468 }
6469
6470 return ®oGetPropertiesTestConfig{
6471 policy: policy,
6472 }, nil
6473 }
6474
6475 type regoDumpStacksTestConfig struct {
6476 policy *regoEnforcer
6477 }
6478
6479 func mountImageForContainer(policy *regoEnforcer, container *securityPolicyContainer) (string, error) {
6480 ctx := context.Background()
6481 containerID := testDataGenerator.uniqueContainerID()
6482
6483 layerPaths, err := testDataGenerator.createValidOverlayForContainer(policy, container)
6484 if err != nil {
6485 return "", fmt.Errorf("error creating valid overlay: %w", err)
6486 }
6487
6488
6489 err = policy.EnforceOverlayMountPolicy(ctx, containerID, copyStrings(layerPaths), testDataGenerator.uniqueMountTarget())
6490 if err != nil {
6491 return "", fmt.Errorf("error mounting filesystem: %w", err)
6492 }
6493
6494 return containerID, nil
6495 }
6496
6497 type regoPolicyOnlyTestConfig struct {
6498 policy *regoEnforcer
6499 }
6500
6501 func setupRegoPolicyOnlyTest(gc *generatedConstraints) (tc *regoPolicyOnlyTestConfig, err error) {
6502 securityPolicy := gc.toPolicy()
6503 policy, err := newRegoPolicy(securityPolicy.marshalRego(), []oci.Mount{}, []oci.Mount{})
6504 if err != nil {
6505 return nil, err
6506 }
6507
6508
6509 return ®oPolicyOnlyTestConfig{
6510 policy: policy,
6511 }, nil
6512 }
6513
6514 type regoFragmentTestConfig struct {
6515 fragments []*regoFragment
6516 containers []*regoFragmentContainer
6517 externalProcesses []*externalProcess
6518 subFragments []*regoFragment
6519 plan9Mounts []string
6520 mountSpec []string
6521 policy *regoEnforcer
6522 }
6523
6524 type regoFragmentContainer struct {
6525 container *securityPolicyContainer
6526 envList []string
6527 sandboxID string
6528 mounts []oci.Mount
6529 user IDName
6530 groups []IDName
6531 capabilities *oci.LinuxCapabilities
6532 seccomp string
6533 }
6534
6535 func setupSimpleRegoFragmentTestConfig(gc *generatedConstraints) (*regoFragmentTestConfig, error) {
6536 return setupRegoFragmentTestConfig(gc, 1, []string{"containers"}, []string{}, false, false, false, false)
6537 }
6538
6539 func setupRegoFragmentTestConfigWithIncludes(gc *generatedConstraints, includes []string) (*regoFragmentTestConfig, error) {
6540 return setupRegoFragmentTestConfig(gc, 1, includes, []string{}, false, false, false, false)
6541 }
6542
6543 func setupRegoFragmentTestConfigWithExcludes(gc *generatedConstraints, excludes []string) (*regoFragmentTestConfig, error) {
6544 return setupRegoFragmentTestConfig(gc, 1, []string{}, excludes, false, false, false, false)
6545 }
6546
6547 func setupRegoFragmentSVNErrorTestConfig(gc *generatedConstraints) (*regoFragmentTestConfig, error) {
6548 return setupRegoFragmentTestConfig(gc, 1, []string{"containers"}, []string{}, true, false, false, false)
6549 }
6550
6551 func setupRegoSubfragmentSVNErrorTestConfig(gc *generatedConstraints) (*regoFragmentTestConfig, error) {
6552 return setupRegoFragmentTestConfig(gc, 1, []string{"fragments"}, []string{}, true, false, false, false)
6553 }
6554
6555 func setupRegoFragmentTwoFeedTestConfig(gc *generatedConstraints, sameIssuer bool, sameFeed bool) (*regoFragmentTestConfig, error) {
6556 return setupRegoFragmentTestConfig(gc, 2, []string{"containers"}, []string{}, false, sameIssuer, sameFeed, false)
6557 }
6558
6559 func setupRegoFragmentSVNMismatchTestConfig(gc *generatedConstraints) (*regoFragmentTestConfig, error) {
6560 return setupRegoFragmentTestConfig(gc, 2, []string{"containers"}, []string{}, false, false, false, true)
6561 }
6562
6563 func compareSVNs(lhs string, rhs string) int {
6564 lhs_int, err := strconv.Atoi(lhs)
6565 if err == nil {
6566 rhs_int, err := strconv.Atoi(rhs)
6567 if err == nil {
6568 return lhs_int - rhs_int
6569 }
6570 }
6571
6572 panic("unable to compare SVNs")
6573 }
6574
6575 func setupRegoFragmentTestConfig(gc *generatedConstraints, numFragments int, includes []string, excludes []string, svnError bool, sameIssuer bool, sameFeed bool, svnMismatch bool) (tc *regoFragmentTestConfig, err error) {
6576 gc.fragments = generateFragments(testRand, int32(numFragments))
6577
6578 if sameIssuer {
6579 for _, fragment := range gc.fragments {
6580 fragment.issuer = gc.fragments[0].issuer
6581 if sameFeed {
6582 fragment.feed = gc.fragments[0].feed
6583 }
6584 }
6585 }
6586
6587 subSVNError := svnError
6588 if len(includes) > 0 && includes[0] == "fragments" {
6589 svnError = false
6590 }
6591 fragments := selectFragmentsFromConstraints(gc, numFragments, includes, excludes, svnError, frameworkVersion, svnMismatch)
6592
6593 containers := make([]*regoFragmentContainer, numFragments)
6594 subFragments := make([]*regoFragment, numFragments)
6595 externalProcesses := make([]*externalProcess, numFragments)
6596 plan9Mounts := make([]string, numFragments)
6597 for i, fragment := range fragments {
6598 container := fragment.selectContainer()
6599
6600 envList := buildEnvironmentVariablesFromEnvRules(container.EnvRules, testRand)
6601 sandboxID := testDataGenerator.uniqueSandboxID()
6602 user := buildIDNameFromConfig(container.User.UserIDName, testRand)
6603 groups := buildGroupIDNamesFromUser(container.User, testRand)
6604 capabilities := copyLinuxCapabilities(container.Capabilities.toExternal())
6605 seccomp := container.SeccompProfileSHA256
6606
6607 mounts := container.Mounts
6608 mountSpec := buildMountSpecFromMountArray(mounts, sandboxID, testRand)
6609 containers[i] = ®oFragmentContainer{
6610 container: container,
6611 envList: envList,
6612 sandboxID: sandboxID,
6613 mounts: mountSpec.Mounts,
6614 user: user,
6615 groups: groups,
6616 capabilities: &capabilities,
6617 seccomp: seccomp,
6618 }
6619
6620 for _, include := range fragment.info.includes {
6621 switch include {
6622 case "fragments":
6623 subFragments[i] = selectFragmentsFromConstraints(fragment.constraints, 1, []string{"containers"}, []string{}, subSVNError, frameworkVersion, false)[0]
6624 break
6625
6626 case "external_processes":
6627 externalProcesses[i] = selectExternalProcessFromConstraints(fragment.constraints, testRand)
6628 break
6629 }
6630 }
6631
6632
6633
6634
6635 fragment.info.includes = removeStringsFromArray(fragment.info.includes, excludes)
6636
6637 code := fragment.constraints.toFragment().marshalRego()
6638 fragment.code = setFrameworkVersion(code, frameworkVersion)
6639 }
6640
6641 if sameFeed {
6642 includeSet := make(map[string]bool)
6643 minSVN := strconv.Itoa(maxGeneratedVersion)
6644 for _, fragment := range gc.fragments {
6645 svn := fragment.minimumSVN
6646 if compareSVNs(svn, minSVN) < 0 {
6647 minSVN = svn
6648 }
6649 for _, include := range fragment.includes {
6650 includeSet[include] = true
6651 }
6652 }
6653 frag := gc.fragments[0]
6654 frag.minimumSVN = minSVN
6655 frag.includes = make([]string, 0, len(includeSet))
6656 for include := range includeSet {
6657 frag.includes = append(frag.includes, include)
6658 }
6659
6660 gc.fragments = []*fragment{frag}
6661
6662 }
6663
6664 securityPolicy := gc.toPolicy()
6665 defaultMounts := toOCIMounts(generateMounts(testRand))
6666 privilegedMounts := toOCIMounts(generateMounts(testRand))
6667 policy, err := newRegoPolicy(securityPolicy.marshalRego(), defaultMounts, privilegedMounts)
6668
6669 if err != nil {
6670 return nil, err
6671 }
6672
6673 return ®oFragmentTestConfig{
6674 fragments: fragments,
6675 containers: containers,
6676 subFragments: subFragments,
6677 externalProcesses: externalProcesses,
6678 plan9Mounts: plan9Mounts,
6679 policy: policy,
6680 }, nil
6681 }
6682
6683 type regoDropEnvsTestConfig struct {
6684 envList []string
6685 expected []string
6686 argList []string
6687 workingDir string
6688 containerID string
6689 sandboxID string
6690 mounts []oci.Mount
6691 policy *regoEnforcer
6692 capabilities oci.LinuxCapabilities
6693 }
6694
6695 func setupEnvRuleSets(count int) [][]EnvRuleConfig {
6696 numEnvRules := []int{int(randMinMax(testRand, 1, 4)),
6697 int(randMinMax(testRand, 1, 4)),
6698 int(randMinMax(testRand, 1, 4))}
6699 envRuleLookup := make(stringSet)
6700 envRules := make([][]EnvRuleConfig, count)
6701
6702 for i := 0; i < count; i++ {
6703 rules := envRuleLookup.randUniqueArray(testRand, func(r *rand.Rand) string {
6704 return randVariableString(r, 10)
6705 }, int32(numEnvRules[i]))
6706
6707 envRules[i] = make([]EnvRuleConfig, numEnvRules[i])
6708 for j, rule := range rules {
6709 envRules[i][j] = EnvRuleConfig{
6710 Strategy: "string",
6711 Rule: rule,
6712 }
6713 }
6714 }
6715
6716 return envRules
6717 }
6718
6719 func setupRegoDropEnvsTest(disjoint bool) (*regoContainerTestConfig, error) {
6720 gc := generateConstraints(testRand, 1)
6721 gc.allowEnvironmentVariableDropping = true
6722
6723 const numContainers int = 3
6724 envRules := setupEnvRuleSets(numContainers)
6725 containers := make([]*securityPolicyContainer, numContainers)
6726 envs := make([][]string, numContainers)
6727
6728 for i := 0; i < numContainers; i++ {
6729 c, err := gc.containers[0].clone()
6730 if err != nil {
6731 return nil, err
6732 }
6733 containers[i] = c
6734 envs[i] = buildEnvironmentVariablesFromEnvRules(envRules[i], testRand)
6735 if i == 0 {
6736 c.EnvRules = envRules[i]
6737 } else if disjoint {
6738 c.EnvRules = append(envRules[0], envRules[i]...)
6739 } else {
6740 c.EnvRules = append(containers[i-1].EnvRules, envRules[i]...)
6741 }
6742 }
6743
6744 gc.containers = containers
6745 securityPolicy := gc.toPolicy()
6746 defaultMounts := generateMounts(testRand)
6747 privilegedMounts := generateMounts(testRand)
6748
6749 policy, err := newRegoPolicy(securityPolicy.marshalRego(),
6750 toOCIMounts(defaultMounts),
6751 toOCIMounts(privilegedMounts))
6752
6753 if err != nil {
6754 return nil, err
6755 }
6756
6757 containerIDs := make([]string, numContainers)
6758 for i, c := range gc.containers {
6759 containerID, err := mountImageForContainer(policy, c)
6760 if err != nil {
6761 return nil, err
6762 }
6763
6764 containerIDs[i] = containerID
6765 }
6766
6767 var envList []string
6768 if disjoint {
6769 var extraLen int
6770 if len(envs[1]) < len(envs[2]) {
6771 extraLen = len(envs[1])
6772 } else {
6773 extraLen = len(envs[2])
6774 }
6775 envList = append(envs[0], envs[1][:extraLen]...)
6776 envList = append(envList, envs[2][:extraLen]...)
6777 } else {
6778 envList = append(envs[0], envs[1]...)
6779 envList = append(envList, envs[2]...)
6780 }
6781
6782 user := buildIDNameFromConfig(containers[2].User.UserIDName, testRand)
6783 groups := buildGroupIDNamesFromUser(containers[2].User, testRand)
6784 umask := containers[2].User.Umask
6785
6786 sandboxID := testDataGenerator.uniqueSandboxID()
6787
6788 mounts := containers[2].Mounts
6789 mounts = append(mounts, defaultMounts...)
6790 if containers[2].AllowElevated {
6791 mounts = append(mounts, privilegedMounts...)
6792 }
6793
6794 mountSpec := buildMountSpecFromMountArray(mounts, sandboxID, testRand)
6795 capabilities := copyLinuxCapabilities(containers[2].Capabilities.toExternal())
6796 seccomp := containers[2].SeccompProfileSHA256
6797
6798
6799 return ®oContainerTestConfig{
6800 envList: copyStrings(envList),
6801 argList: copyStrings(containers[2].Command),
6802 workingDir: containers[2].WorkingDir,
6803 containerID: containerIDs[2],
6804 sandboxID: sandboxID,
6805 mounts: copyMounts(mountSpec.Mounts),
6806 noNewPrivileges: containers[2].NoNewPrivileges,
6807 user: user,
6808 groups: groups,
6809 umask: umask,
6810 policy: policy,
6811 capabilities: &capabilities,
6812 seccomp: seccomp,
6813 ctx: gc.ctx,
6814 }, nil
6815 }
6816
6817 type regoFrameworkVersionTestConfig struct {
6818 policy *regoEnforcer
6819 fragments []*regoFragment
6820 }
6821
6822 func setFrameworkVersion(code string, version string) string {
6823 template := `framework_version := "%s"`
6824 old := fmt.Sprintf(template, frameworkVersion)
6825 if version == "" {
6826 return strings.Replace(code, old, "", 1)
6827 }
6828
6829 new := fmt.Sprintf(template, version)
6830 return strings.Replace(code, old, new, 1)
6831 }
6832
6833 func setupFrameworkVersionSimpleTest(gc *generatedConstraints, policyVersion string, version string) (*regoFrameworkVersionTestConfig, error) {
6834 return setupFrameworkVersionTest(gc, policyVersion, version, 0, "", []string{})
6835 }
6836
6837 func setupFrameworkVersionTest(gc *generatedConstraints, policyVersion string, version string, numFragments int, fragmentVersion string, includes []string) (*regoFrameworkVersionTestConfig, error) {
6838 fragments := make([]*regoFragment, 0, numFragments)
6839 if numFragments > 0 {
6840 gc.fragments = generateFragments(testRand, int32(numFragments))
6841 fragments = selectFragmentsFromConstraints(gc, numFragments, includes, []string{}, false, fragmentVersion, false)
6842 }
6843
6844 securityPolicy := gc.toPolicy()
6845 policy, err := newRegoPolicy(setFrameworkVersion(securityPolicy.marshalRego(), policyVersion), []oci.Mount{}, []oci.Mount{})
6846 if err != nil {
6847 return nil, err
6848 }
6849
6850 code := strings.Replace(frameworkCodeTemplate, "@@FRAMEWORK_VERSION@@", version, 1)
6851 policy.rego.RemoveModule("framework.rego")
6852 policy.rego.AddModule("framework.rego", &rpi.RegoModule{Namespace: "framework", Code: code})
6853 err = policy.rego.Compile()
6854 if err != nil {
6855 return nil, err
6856 }
6857
6858 return ®oFrameworkVersionTestConfig{policy: policy, fragments: fragments}, nil
6859 }
6860
6861 type regoFragment struct {
6862 info *fragment
6863 constraints *generatedConstraints
6864 code string
6865 }
6866
6867 func (f *regoFragment) selectContainer() *securityPolicyContainer {
6868 return selectContainerFromContainerList(f.constraints.containers, testRand)
6869 }
6870
6871 func mustIncrementSVN(svn string) string {
6872 svn_semver, err := semver.Parse(svn)
6873
6874 if err == nil {
6875 svn_semver.IncrementMajor()
6876 return svn_semver.String()
6877 }
6878
6879 svn_int, err := strconv.Atoi(svn)
6880
6881 if err == nil {
6882 return strconv.Itoa(svn_int + 1)
6883 }
6884
6885 panic("Could not increment SVN")
6886 }
6887
6888 func selectFragmentsFromConstraints(gc *generatedConstraints, numFragments int, includes []string, excludes []string, svnError bool, frameworkVersion string, svnMismatch bool) []*regoFragment {
6889 choices := randChoices(testRand, numFragments, len(gc.fragments))
6890 fragments := make([]*regoFragment, numFragments)
6891 for i, choice := range choices {
6892 config := gc.fragments[choice]
6893 config.includes = addStringsToArray(config.includes, includes)
6894
6895
6896 config.includes = addStringsToArray(config.includes, excludes)
6897
6898 constraints := generateConstraints(testRand, maxContainersInGeneratedConstraints)
6899 for _, include := range config.includes {
6900 switch include {
6901 case "fragments":
6902 constraints.fragments = generateFragments(testRand, 1)
6903 for _, fragment := range constraints.fragments {
6904 fragment.includes = addStringsToArray(fragment.includes, []string{"containers"})
6905 }
6906 break
6907
6908 case "external_processes":
6909 constraints.externalProcesses = generateExternalProcesses(testRand)
6910 break
6911 }
6912 }
6913
6914 svn := config.minimumSVN
6915 if svnMismatch {
6916 if randBool(testRand) {
6917 svn = generateSemver(testRand)
6918 } else {
6919 config.minimumSVN = generateSemver(testRand)
6920 }
6921 }
6922
6923 constraints.svn = svn
6924 if svnError {
6925 config.minimumSVN = mustIncrementSVN(config.minimumSVN)
6926 }
6927
6928 code := constraints.toFragment().marshalRego()
6929 code = setFrameworkVersion(code, frameworkVersion)
6930
6931 fragments[i] = ®oFragment{
6932 info: config,
6933 constraints: constraints,
6934 code: code,
6935 }
6936 }
6937
6938 return fragments
6939 }
6940
6941 func generateSandboxID(r *rand.Rand) string {
6942 return randVariableString(r, maxGeneratedSandboxIDLength)
6943 }
6944
6945 func generateEnforcementPoint(r *rand.Rand) string {
6946 first := randChar(r)
6947 return first + randString(r, atMost(r, maxGeneratedEnforcementPointLength))
6948 }
6949
6950 func (gen *dataGenerator) uniqueSandboxID() string {
6951 return gen.sandboxIDs.randUnique(gen.rng, generateSandboxID)
6952 }
6953
6954 func (gen *dataGenerator) uniqueEnforcementPoint() string {
6955 return gen.enforcementPoints.randUnique(gen.rng, generateEnforcementPoint)
6956 }
6957
6958 func buildMountSpecFromMountArray(mounts []mountInternal, sandboxID string, r *rand.Rand) *oci.Spec {
6959 mountSpec := new(oci.Spec)
6960
6961
6962
6963 numberOfMounts := int32(len(mounts))
6964 numberOfMatches := randMinMax(r, 1, numberOfMounts)
6965 usedIndexes := map[int]struct{}{}
6966 for numberOfMatches > 0 {
6967 anIndex := -1
6968 if (numberOfMatches * 2) > numberOfMounts {
6969
6970 exists := true
6971
6972 for exists {
6973 anIndex = int(randMinMax(r, 0, numberOfMounts-1))
6974 _, exists = usedIndexes[anIndex]
6975 }
6976 } else {
6977
6978
6979 exists := true
6980
6981 for exists {
6982 anIndex++
6983 _, exists = usedIndexes[anIndex]
6984 }
6985 }
6986
6987 mount := mounts[anIndex]
6988
6989 source := substituteUVMPath(sandboxID, mount).Source
6990 mountSpec.Mounts = append(mountSpec.Mounts, oci.Mount{
6991 Source: source,
6992 Destination: mount.Destination,
6993 Options: mount.Options,
6994 Type: mount.Type,
6995 })
6996 usedIndexes[anIndex] = struct{}{}
6997
6998 numberOfMatches--
6999 }
7000
7001 return mountSpec
7002 }
7003
7004
7005 var apiTestCode string
7006
7007 func (p *regoEnforcer) injectTestAPI() error {
7008 p.rego.RemoveModule("api.rego")
7009 p.rego.AddModule("api.rego", &rpi.RegoModule{Namespace: "api", Code: apiTestCode})
7010
7011 return p.rego.Compile()
7012 }
7013
7014 func selectContainerFromRunningContainers(containers []regoRunningContainer, r *rand.Rand) regoRunningContainer {
7015 numContainers := len(containers)
7016 return containers[r.Intn(numContainers)]
7017 }
7018
7019 func selectExecProcess(processes []containerExecProcess, r *rand.Rand) containerExecProcess {
7020 numProcesses := len(processes)
7021 return processes[r.Intn(numProcesses)]
7022 }
7023
7024 func idForRunningContainer(container *securityPolicyContainer, running []regoRunningContainer) (string, error) {
7025 for _, c := range running {
7026 if c.container == container {
7027 return c.containerID, nil
7028 }
7029 }
7030
7031 return "", errors.New("Container isn't running")
7032 }
7033
7034 func selectSignalFromSignals(r *rand.Rand, signals []syscall.Signal) syscall.Signal {
7035 numSignals := len(signals)
7036 return signals[r.Intn(numSignals)]
7037 }
7038
7039 func generateUVMPathForShare(r *rand.Rand, containerID string) string {
7040 return fmt.Sprintf("%s/%s%s",
7041 guestpath.LCOWRootPrefixInUVM,
7042 containerID,
7043 fmt.Sprintf(guestpath.LCOWMountPathPrefixFmt, atMost(r, maxPlan9MountIndex)))
7044 }
7045
7046 func generateFragments(r *rand.Rand, minFragments int32) []*fragment {
7047 numFragments := randMinMax(r, minFragments, maxFragmentsInGeneratedConstraints)
7048
7049 fragments := make([]*fragment, numFragments)
7050 for i := 0; i < int(numFragments); i++ {
7051 fragments[i] = generateFragment(r)
7052 }
7053
7054 return fragments
7055 }
7056
7057 func generateFragmentIssuer(r *rand.Rand) string {
7058 return randString(r, maxGeneratedFragmentIssuerLength)
7059 }
7060
7061 func generateFragmentFeed(r *rand.Rand) string {
7062 return randString(r, maxGeneratedFragmentFeedLength)
7063 }
7064
7065 func (gen *dataGenerator) uniqueFragmentNamespace() string {
7066 return gen.fragmentNamespaces.randUnique(gen.rng, generateFragmentNamespace)
7067 }
7068
7069 func (gen *dataGenerator) uniqueFragmentIssuer() string {
7070 return gen.fragmentIssuers.randUnique(gen.rng, generateFragmentIssuer)
7071 }
7072
7073 func (gen *dataGenerator) uniqueFragmentFeed() string {
7074 return gen.fragmentFeeds.randUnique(gen.rng, generateFragmentFeed)
7075 }
7076
7077 func generateFragment(r *rand.Rand) *fragment {
7078 possibleIncludes := []string{"containers", "fragments", "external_processes"}
7079 numChoices := int(atLeastOneAtMost(r, int32(len(possibleIncludes))))
7080 includes := randChooseStrings(r, possibleIncludes, numChoices)
7081 return &fragment{
7082 issuer: testDataGenerator.uniqueFragmentIssuer(),
7083 feed: testDataGenerator.uniqueFragmentFeed(),
7084 minimumSVN: generateSVN(r),
7085 includes: includes,
7086 }
7087 }
7088
7089 func generateLinuxID(r *rand.Rand) uint32 {
7090 return r.Uint32()
7091 }
7092
7093 func addStringsToArray(values []string, valuesToAdd []string) []string {
7094 toAdd := []string{}
7095 for _, valueToAdd := range valuesToAdd {
7096 add := true
7097 for _, value := range values {
7098 if value == valueToAdd {
7099 add = false
7100 break
7101 }
7102 }
7103 if add {
7104 toAdd = append(toAdd, valueToAdd)
7105 }
7106 }
7107
7108 return append(values, toAdd...)
7109 }
7110
7111 func removeStringsFromArray(values []string, valuesToRemove []string) []string {
7112 remain := make([]string, 0, len(values))
7113 for _, value := range values {
7114 keep := true
7115 for _, toRemove := range valuesToRemove {
7116 if value == toRemove {
7117 keep = false
7118 break
7119 }
7120 }
7121 if keep {
7122 remain = append(remain, value)
7123 }
7124 }
7125
7126 return remain
7127 }
7128
7129 func areStringArraysEqual(lhs []string, rhs []string) bool {
7130 if len(lhs) != len(rhs) {
7131 return false
7132 }
7133
7134 sort.Strings(lhs)
7135 sort.Strings(rhs)
7136
7137 for i, a := range lhs {
7138 if a != rhs[i] {
7139 return false
7140 }
7141 }
7142
7143 return true
7144 }
7145
7146 func (c securityPolicyContainer) clone() (*securityPolicyContainer, error) {
7147 contents, err := json.Marshal(c)
7148 if err != nil {
7149 return nil, err
7150 }
7151
7152 var clone securityPolicyContainer
7153 err = json.Unmarshal(contents, &clone)
7154 if err != nil {
7155 return nil, err
7156 }
7157
7158 return &clone, nil
7159 }
7160
7161 func (p externalProcess) clone() *externalProcess {
7162 envRules := make([]EnvRuleConfig, len(p.envRules))
7163 copy(envRules, p.envRules)
7164
7165 return &externalProcess{
7166 command: copyStrings(p.command),
7167 envRules: envRules,
7168 workingDir: p.workingDir,
7169 allowStdioAccess: p.allowStdioAccess,
7170 }
7171 }
7172
7173 func (p containerExecProcess) clone() containerExecProcess {
7174 return containerExecProcess{
7175 Command: copyStrings(p.Command),
7176 Signals: p.Signals,
7177 }
7178 }
7179
7180 func (c *securityPolicyContainer) toContainer() *Container {
7181 execProcesses := make([]ExecProcessConfig, len(c.ExecProcesses))
7182 for i, ep := range c.ExecProcesses {
7183 execProcesses[i] = ExecProcessConfig(ep)
7184 }
7185
7186 capabilities := CapabilitiesConfig{
7187 Bounding: c.Capabilities.Bounding,
7188 Effective: c.Capabilities.Effective,
7189 Inheritable: c.Capabilities.Inheritable,
7190 Permitted: c.Capabilities.Permitted,
7191 Ambient: c.Capabilities.Ambient,
7192 }
7193
7194 return &Container{
7195 Command: CommandArgs(stringArrayToStringMap(c.Command)),
7196 EnvRules: envRuleArrayToEnvRules(c.EnvRules),
7197 Layers: Layers(stringArrayToStringMap(c.Layers)),
7198 WorkingDir: c.WorkingDir,
7199 Mounts: mountArrayToMounts(c.Mounts),
7200 AllowElevated: c.AllowElevated,
7201 ExecProcesses: execProcesses,
7202 Signals: c.Signals,
7203 AllowStdioAccess: c.AllowStdioAccess,
7204 NoNewPrivileges: c.NoNewPrivileges,
7205 User: c.User,
7206 Capabilities: &capabilities,
7207 SeccompProfileSHA256: c.SeccompProfileSHA256,
7208 }
7209 }
7210
7211 func envRuleArrayToEnvRules(envRules []EnvRuleConfig) EnvRules {
7212 elements := make(map[string]EnvRuleConfig)
7213 for i, envRule := range envRules {
7214 elements[strconv.Itoa(i)] = envRule
7215 }
7216 return EnvRules{
7217 Elements: elements,
7218 Length: len(envRules),
7219 }
7220 }
7221
7222 func mountArrayToMounts(mounts []mountInternal) Mounts {
7223 elements := make(map[string]Mount)
7224 for i, mount := range mounts {
7225 elements[strconv.Itoa(i)] = Mount{
7226 Source: mount.Source,
7227 Destination: mount.Destination,
7228 Type: mount.Type,
7229 Options: Options(stringArrayToStringMap(mount.Options)),
7230 }
7231 }
7232
7233 return Mounts{
7234 Elements: elements,
7235 Length: len(mounts),
7236 }
7237 }
7238
7239 func (p externalProcess) toConfig() ExternalProcessConfig {
7240 return ExternalProcessConfig{
7241 Command: p.command,
7242 WorkingDir: p.workingDir,
7243 AllowStdioAccess: p.allowStdioAccess,
7244 }
7245 }
7246
7247 func (f fragment) toConfig() FragmentConfig {
7248 return FragmentConfig{
7249 Issuer: f.issuer,
7250 Feed: f.feed,
7251 MinimumSVN: f.minimumSVN,
7252 Includes: f.includes,
7253 }
7254 }
7255
7256 func stringArrayToStringMap(values []string) StringArrayMap {
7257 elements := make(map[string]string)
7258 for i, value := range values {
7259 elements[strconv.Itoa(i)] = value
7260 }
7261
7262 return StringArrayMap{
7263 Elements: elements,
7264 Length: len(values),
7265 }
7266 }
7267
7268 func (s *stringSet) randUniqueArray(r *rand.Rand, generator func(*rand.Rand) string, numItems int32) []string {
7269 items := make([]string, numItems)
7270 for i := 0; i < int(numItems); i++ {
7271 items[i] = s.randUnique(r, generator)
7272 }
7273 return items
7274 }
7275
7276 type regoScratchMountPolicyTestConfig struct {
7277 policy *regoEnforcer
7278 }
7279
7280 func setupRegoScratchMountTest(
7281 gc *generatedConstraints,
7282 unencryptedScratch bool,
7283 ) (tc *regoScratchMountPolicyTestConfig, err error) {
7284 securityPolicy := gc.toPolicy()
7285 securityPolicy.AllowUnencryptedScratch = unencryptedScratch
7286
7287 defaultMounts := generateMounts(testRand)
7288 privilegedMounts := generateMounts(testRand)
7289 policy, err := newRegoPolicy(securityPolicy.marshalRego(), toOCIMounts(defaultMounts), toOCIMounts(privilegedMounts))
7290 if err != nil {
7291 return nil, err
7292 }
7293 return ®oScratchMountPolicyTestConfig{
7294 policy: policy,
7295 }, nil
7296 }
7297
7298 func verifyPolicyRules(apiVersion string, enforcementPoints map[string]interface{}, policyCode string) error {
7299 query := rego.New(
7300 rego.Query("data.policy"),
7301 rego.Module("policy.rego", policyCode),
7302 rego.Module("framework.rego", FrameworkCode),
7303 )
7304
7305 ctx := context.Background()
7306 resultSet, err := query.Eval(ctx)
7307 if err != nil {
7308 return fmt.Errorf("unable to query policy template rules: %w", err)
7309 }
7310
7311 policyTemplateRules := resultSet[0].Expressions[0].Value.(map[string]interface{})
7312 policyTemplateAPIVersion := policyTemplateRules["api_version"].(string)
7313
7314 if policyTemplateAPIVersion != apiVersion {
7315 return fmt.Errorf("Policy template version != api version: %s != %s", apiVersion, policyTemplateAPIVersion)
7316 }
7317
7318 for rule := range enforcementPoints {
7319 if _, ok := policyTemplateRules[rule]; !ok {
7320 return fmt.Errorf("Rule %s in API is missing from policy template", rule)
7321 }
7322 }
7323
7324 for rule := range policyTemplateRules {
7325 if rule == "api_version" || rule == "framework_version" || rule == "reason" {
7326 continue
7327 }
7328
7329 if _, ok := enforcementPoints[rule]; !ok {
7330 return fmt.Errorf("Rule %s in policy template is missing from API", rule)
7331 }
7332 }
7333
7334 return nil
7335 }
7336
7337 func buildIDNameFromConfig(config IDNameConfig, r *rand.Rand) IDName {
7338 switch config.Strategy {
7339 case IDNameStrategyName:
7340 return IDName{
7341 ID: generateIDNameID(r),
7342 Name: config.Rule,
7343 }
7344
7345 case IDNameStrategyID:
7346 return IDName{
7347 ID: config.Rule,
7348 Name: generateIDNameName(r),
7349 }
7350
7351 case IDNameStrategyAny:
7352 return generateIDName(r)
7353
7354 default:
7355 panic(fmt.Sprintf("unsupported ID Name strategy: %v", config.Strategy))
7356 }
7357 }
7358
7359 func buildGroupIDNamesFromUser(user UserConfig, r *rand.Rand) []IDName {
7360 groupIDNames := make([]IDName, 0)
7361
7362
7363 numberOfGroups := int32(len(user.GroupIDNames))
7364 numberOfMatches := randMinMax(r, 1, numberOfGroups)
7365 usedIndexes := map[int]struct{}{}
7366 for numberOfMatches > 0 {
7367 anIndex := -1
7368 if (numberOfMatches * 2) > numberOfGroups {
7369
7370 exists := true
7371
7372 for exists {
7373 anIndex = int(randMinMax(r, 0, numberOfGroups-1))
7374 _, exists = usedIndexes[anIndex]
7375 }
7376 } else {
7377
7378
7379 exists := true
7380
7381 for exists {
7382 anIndex++
7383 _, exists = usedIndexes[anIndex]
7384 }
7385 }
7386
7387 if user.GroupIDNames[anIndex].Strategy == IDNameStrategyRegex {
7388
7389 numberOfMatches--
7390 continue
7391 }
7392
7393 groupIDName := buildIDNameFromConfig(user.GroupIDNames[anIndex], r)
7394 groupIDNames = append(groupIDNames, groupIDName)
7395 usedIndexes[anIndex] = struct{}{}
7396
7397 numberOfMatches--
7398 }
7399
7400 return groupIDNames
7401 }
7402
7403 func generateIDNameName(r *rand.Rand) string {
7404 return randVariableString(r, maxGeneratedNameLength)
7405 }
7406
7407 func generateIDNameID(r *rand.Rand) string {
7408 id := r.Uint32()
7409 return strconv.FormatUint(uint64(id), 10)
7410 }
7411
7412 func generateIDName(r *rand.Rand) IDName {
7413 return IDName{
7414 ID: generateIDNameID(r),
7415 Name: generateIDNameName(r),
7416 }
7417 }
7418
7419 func generateCapabilities(r *rand.Rand) *oci.LinuxCapabilities {
7420 return &oci.LinuxCapabilities{
7421 Bounding: generateCapabilitiesSet(r, 0),
7422 Effective: generateCapabilitiesSet(r, 0),
7423 Inheritable: generateCapabilitiesSet(r, 0),
7424 Permitted: generateCapabilitiesSet(r, 0),
7425 Ambient: generateCapabilitiesSet(r, 0),
7426 }
7427 }
7428
7429 func generateSemver(r *rand.Rand) string {
7430 major := randMinMax(r, 0, maxGeneratedVersion)
7431 minor := randMinMax(r, 0, maxGeneratedVersion)
7432 patch := randMinMax(r, 0, maxGeneratedVersion)
7433 return fmt.Sprintf("%d.%d.%d", major, minor, patch)
7434 }
7435
7436 func alterCapabilitySet(r *rand.Rand, set []string) []string {
7437 newSet := copyStrings(set)
7438
7439 if len(newSet) == 0 {
7440 return generateCapabilitiesSet(r, 1)
7441 }
7442
7443 alterations := atLeastNAtMostM(r, 1, 4)
7444 for i := alterations; i > 0; i-- {
7445 if len(newSet) == 0 {
7446 newSet = generateCapabilitiesSet(r, 1)
7447 } else {
7448 action := atMost(r, 2)
7449 if action == 0 {
7450 newSet = superCapabilitySet(r, newSet)
7451 } else if action == 1 {
7452 newSet = subsetCapabilitySet(r, newSet)
7453 } else {
7454 replace := atMost(r, int32((len(newSet) - 1)))
7455 newSet[replace] = generateCapability(r)
7456 }
7457 }
7458 }
7459
7460 return newSet
7461 }
7462
7463 func subsetCapabilitySet(r *rand.Rand, set []string) []string {
7464 newSet := make([]string, 0)
7465
7466 setSize := int32(len(set))
7467 if setSize == 0 {
7468
7469 return newSet
7470 } else if setSize == 1 {
7471
7472 return newSet
7473 }
7474
7475
7476 numberOfMatches := randMinMax(r, 0, setSize-1)
7477 usedIndexes := map[int]struct{}{}
7478 for i := numberOfMatches; i > 0; i-- {
7479 anIndex := -1
7480 if ((setSize - int32(len(usedIndexes))) * 2) > i {
7481
7482
7483 exists := true
7484
7485 for exists {
7486 anIndex = int(randMinMax(r, 0, setSize-1))
7487 _, exists = usedIndexes[anIndex]
7488 }
7489 } else {
7490
7491
7492 exists := true
7493
7494 for exists {
7495 anIndex++
7496 _, exists = usedIndexes[anIndex]
7497 }
7498 }
7499
7500 newSet = append(newSet, set[anIndex])
7501 usedIndexes[anIndex] = struct{}{}
7502 }
7503
7504 return newSet
7505 }
7506
7507 func superCapabilitySet(r *rand.Rand, set []string) []string {
7508 newSet := copyStrings(set)
7509
7510 additions := atLeastNAtMostM(r, 1, 12)
7511 for i := additions; i > 0; i-- {
7512 newSet = append(newSet, generateCapability(r))
7513 }
7514
7515 return newSet
7516 }
7517
7518 func (c capabilitiesInternal) toExternal() oci.LinuxCapabilities {
7519 return oci.LinuxCapabilities{
7520 Bounding: c.Bounding,
7521 Effective: c.Effective,
7522 Inheritable: c.Inheritable,
7523 Permitted: c.Permitted,
7524 Ambient: c.Ambient,
7525 }
7526 }
7527
7528 func assertKeyValue(object map[string]interface{}, key string, expectedValue interface{}) error {
7529 if actualValue, ok := object[key]; ok {
7530 if actualValue != expectedValue {
7531 return fmt.Errorf("incorrect value for no_new_privileges: %t != %t (expected)", actualValue, expectedValue)
7532 }
7533 } else {
7534 return fmt.Errorf("missing value for %s", key)
7535 }
7536
7537 return nil
7538 }
7539
7540 func assertDecisionJSONContains(t *testing.T, err error, expectedValues ...string) bool {
7541 if err == nil {
7542 t.Errorf("expected error to contain %v but got nil", expectedValues)
7543 return false
7544 }
7545
7546 policyDecision, err := ExtractPolicyDecision(err.Error())
7547 if err != nil {
7548 t.Errorf("unable to extract policy decision from error: %v", err)
7549 return false
7550 }
7551
7552 for _, expected := range expectedValues {
7553 if !strings.Contains(policyDecision, expected) {
7554 t.Errorf("expected error to contain %q", expected)
7555 return false
7556 }
7557 }
7558
7559 return true
7560 }
7561
7562 func assertDecisionJSONDoesNotContain(t *testing.T, err error, expectedValues ...string) bool {
7563 if err == nil {
7564 t.Errorf("expected error to contain %v but got nil", expectedValues)
7565 return false
7566 }
7567
7568 policyDecision, err := ExtractPolicyDecision(err.Error())
7569 if err != nil {
7570 t.Errorf("unable to extract policy decision from error: %v", err)
7571 return false
7572 }
7573
7574 for _, expected := range expectedValues {
7575 if strings.Contains(policyDecision, expected) {
7576 t.Errorf("expected error to not contain %q", expected)
7577 return false
7578 }
7579 }
7580
7581 return true
7582 }
7583
View as plain text