1
2
3
4 package securitypolicy
5
6 import (
7 "context"
8 "encoding/base64"
9 "encoding/json"
10 "fmt"
11 "regexp"
12 "strconv"
13 "strings"
14 "sync"
15 "syscall"
16
17 oci "github.com/opencontainers/runtime-spec/specs-go"
18
19 specInternal "github.com/Microsoft/hcsshim/internal/guest/spec"
20 "github.com/Microsoft/hcsshim/internal/guestpath"
21 "github.com/pkg/errors"
22 )
23
24 type createEnforcerFunc func(base64EncodedPolicy string, criMounts, criPrivilegedMounts []oci.Mount, maxErrorMessageLength int) (SecurityPolicyEnforcer, error)
25
26 type EnvList []string
27
28 const (
29 openDoorEnforcer = "open_door"
30 standardEnforcer = "standard"
31 )
32
33 var (
34 registeredEnforcers = map[string]createEnforcerFunc{}
35 defaultEnforcer = standardEnforcer
36 )
37
38 func init() {
39 registeredEnforcers[openDoorEnforcer] = createOpenDoorEnforcer
40 registeredEnforcers[standardEnforcer] = createStandardEnforcer
41 }
42
43 type SecurityPolicyEnforcer interface {
44 EnforceDeviceMountPolicy(ctx context.Context, target string, deviceHash string) (err error)
45 EnforceDeviceUnmountPolicy(ctx context.Context, unmountTarget string) (err error)
46 EnforceOverlayMountPolicy(ctx context.Context, containerID string, layerPaths []string, target string) (err error)
47 EnforceOverlayUnmountPolicy(ctx context.Context, target string) (err error)
48 EnforceCreateContainerPolicy(
49 ctx context.Context,
50 sandboxID string,
51 containerID string,
52 argList []string,
53 envList []string,
54 workingDir string,
55 mounts []oci.Mount,
56 privileged bool,
57 noNewPrivileges bool,
58 user IDName,
59 groups []IDName,
60 umask string,
61 capabilities *oci.LinuxCapabilities,
62 seccompProfileSHA256 string,
63 ) (EnvList, *oci.LinuxCapabilities, bool, error)
64 ExtendDefaultMounts([]oci.Mount) error
65 EncodedSecurityPolicy() string
66 EnforceExecInContainerPolicy(
67 ctx context.Context,
68 containerID string,
69 argList []string,
70 envList []string,
71 workingDir string,
72 noNewPrivileges bool,
73 user IDName,
74 groups []IDName,
75 umask string,
76 capabilities *oci.LinuxCapabilities,
77 ) (EnvList, *oci.LinuxCapabilities, bool, error)
78 EnforceExecExternalProcessPolicy(ctx context.Context, argList []string, envList []string, workingDir string) (EnvList, bool, error)
79 EnforceShutdownContainerPolicy(ctx context.Context, containerID string) error
80 EnforceSignalContainerProcessPolicy(ctx context.Context, containerID string, signal syscall.Signal, isInitProcess bool, startupArgList []string) error
81 EnforcePlan9MountPolicy(ctx context.Context, target string) (err error)
82 EnforcePlan9UnmountPolicy(ctx context.Context, target string) (err error)
83 EnforceGetPropertiesPolicy(ctx context.Context) error
84 EnforceDumpStacksPolicy(ctx context.Context) error
85 EnforceRuntimeLoggingPolicy(ctx context.Context) (err error)
86 LoadFragment(ctx context.Context, issuer string, feed string, code string) error
87 EnforceScratchMountPolicy(ctx context.Context, scratchPath string, encrypted bool) (err error)
88 EnforceScratchUnmountPolicy(ctx context.Context, scratchPath string) (err error)
89 GetUserInfo(containerID string, spec *oci.Process) (IDName, []IDName, string, error)
90 }
91
92 type stringSet map[string]struct{}
93
94 func (s stringSet) add(item string) {
95 s[item] = struct{}{}
96 }
97
98 func (s stringSet) contains(item string) bool {
99 _, contains := s[item]
100 return contains
101 }
102
103 func newSecurityPolicyFromBase64JSON(base64EncodedPolicy string) (*SecurityPolicy, error) {
104
105
106
107
108 jsonPolicy, err := base64.StdEncoding.DecodeString(base64EncodedPolicy)
109 if err != nil {
110 return nil, errors.Wrap(err, "unable to decode policy from Base64 format")
111 }
112
113
114 securityPolicy := new(SecurityPolicy)
115 err = json.Unmarshal(jsonPolicy, securityPolicy)
116 if err != nil {
117 return nil, errors.Wrap(err, "unable to unmarshal JSON policy")
118 }
119
120 return securityPolicy, nil
121 }
122
123
124
125 func createOpenDoorEnforcer(base64EncodedPolicy string, _, _ []oci.Mount, _ int) (SecurityPolicyEnforcer, error) {
126
127
128
129 if base64EncodedPolicy == "" {
130 return &OpenDoorSecurityPolicyEnforcer{}, nil
131 }
132
133 securityPolicy, err := newSecurityPolicyFromBase64JSON(base64EncodedPolicy)
134 if err != nil {
135 return nil, err
136 }
137
138 policyContainers := securityPolicy.Containers
139 if !securityPolicy.AllowAll || policyContainers.Length > 0 || len(policyContainers.Elements) > 0 {
140 return nil, ErrInvalidOpenDoorPolicy
141 }
142 return &OpenDoorSecurityPolicyEnforcer{
143 encodedSecurityPolicy: base64EncodedPolicy,
144 }, nil
145 }
146
147 func (c Containers) toInternal() ([]*securityPolicyContainer, error) {
148 containerMapLength := len(c.Elements)
149 internal := make([]*securityPolicyContainer, containerMapLength)
150
151 for i := 0; i < containerMapLength; i++ {
152 index := strconv.Itoa(i)
153 cConf, ok := c.Elements[index]
154 if !ok {
155 return nil, fmt.Errorf("container constraint with index %q not found", index)
156 }
157 cInternal, err := cConf.toInternal()
158 if err != nil {
159 return nil, err
160 }
161 internal[i] = cInternal
162 }
163
164 return internal, nil
165 }
166
167
168
169
170 func createStandardEnforcer(
171 base64EncodedPolicy string,
172 criMounts,
173 criPrivilegedMounts []oci.Mount,
174 maxErrorMessageLength int,
175 ) (SecurityPolicyEnforcer, error) {
176 securityPolicy, err := newSecurityPolicyFromBase64JSON(base64EncodedPolicy)
177 if err != nil {
178 return nil, err
179 }
180
181 if securityPolicy.AllowAll {
182 return createOpenDoorEnforcer(base64EncodedPolicy, criMounts, criPrivilegedMounts, maxErrorMessageLength)
183 }
184
185 containers, err := securityPolicy.Containers.toInternal()
186 if err != nil {
187 return nil, err
188 }
189
190 enforcer := NewStandardSecurityPolicyEnforcer(containers, base64EncodedPolicy)
191
192 if err := enforcer.ExtendDefaultMounts(criMounts); err != nil {
193 return nil, err
194 }
195
196 addPrivilegedMountsWrapper := WithPrivilegedMounts(criPrivilegedMounts)
197 if err := addPrivilegedMountsWrapper(enforcer); err != nil {
198 return nil, err
199 }
200 return enforcer, nil
201 }
202
203
204
205
206 func CreateSecurityPolicyEnforcer(
207 enforcer string,
208 base64EncodedPolicy string,
209 criMounts,
210 criPrivilegedMounts []oci.Mount,
211 maxErrorMessageLength int,
212 ) (SecurityPolicyEnforcer, error) {
213 if enforcer == "" {
214 enforcer = defaultEnforcer
215 if base64EncodedPolicy == "" {
216 enforcer = openDoorEnforcer
217 }
218 }
219 if createEnforcer, ok := registeredEnforcers[enforcer]; !ok {
220 return nil, fmt.Errorf("unknown enforcer: %q", enforcer)
221 } else {
222 return createEnforcer(base64EncodedPolicy, criMounts, criPrivilegedMounts, maxErrorMessageLength)
223 }
224 }
225
226
227
228 func newMountConstraint(src, dst string, mType string, mOpts []string) mountInternal {
229 return mountInternal{
230 Source: src,
231 Destination: dst,
232 Type: mType,
233 Options: mOpts,
234 }
235 }
236
237 type standardEnforcerOpt func(e *StandardSecurityPolicyEnforcer) error
238
239
240
241
242 func WithPrivilegedMounts(mounts []oci.Mount) standardEnforcerOpt {
243 return func(e *StandardSecurityPolicyEnforcer) error {
244 for _, c := range e.Containers {
245 if c.AllowElevated {
246 for _, m := range mounts {
247 mi := mountInternal{
248 Source: m.Source,
249 Destination: m.Destination,
250 Type: m.Type,
251 Options: m.Options,
252 }
253 c.Mounts = append(c.Mounts, mi)
254 }
255 }
256 }
257 return nil
258 }
259 }
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276 type StandardSecurityPolicyEnforcer struct {
277
278 encodedSecurityPolicy string
279
280 Containers []*securityPolicyContainer
281
282
283
284
285
286
287 Devices map[string]string
288
289
290
291
292
293
294
295
296
297 ContainerIndexToContainerIds map[int]map[string]struct{}
298
299
300 startedContainers map[string]struct{}
301
302 mutex *sync.Mutex
303
304
305
306
307 DefaultMounts []mountInternal
308
309
310
311
312 DefaultEnvs []EnvRuleConfig
313 }
314
315 var _ SecurityPolicyEnforcer = (*StandardSecurityPolicyEnforcer)(nil)
316
317 func NewStandardSecurityPolicyEnforcer(
318 containers []*securityPolicyContainer,
319 encoded string,
320 ) *StandardSecurityPolicyEnforcer {
321 return &StandardSecurityPolicyEnforcer{
322 encodedSecurityPolicy: encoded,
323 Containers: containers,
324 Devices: map[string]string{},
325 ContainerIndexToContainerIds: map[int]map[string]struct{}{},
326 startedContainers: map[string]struct{}{},
327 mutex: &sync.Mutex{},
328 }
329 }
330
331
332
333
334
335
336
337
338
339
340
341 func (pe *StandardSecurityPolicyEnforcer) EnforceDeviceMountPolicy(ctx context.Context, target string, deviceHash string) (err error) {
342 pe.mutex.Lock()
343 defer pe.mutex.Unlock()
344
345 if len(pe.Containers) < 1 {
346 return errors.New("policy doesn't allow mounting containers")
347 }
348
349 if deviceHash == "" {
350 return errors.New("device is missing verity root hash")
351 }
352
353 for _, container := range pe.Containers {
354 for _, layer := range container.Layers {
355 if deviceHash == layer {
356 if existingHash := pe.Devices[target]; existingHash != "" {
357 return fmt.Errorf(
358 "conflicting device hashes for target %s: old=%s, new=%s",
359 target,
360 existingHash,
361 deviceHash,
362 )
363 }
364 pe.Devices[target] = deviceHash
365 return nil
366 }
367 }
368 }
369
370 return fmt.Errorf("roothash %s for mount %s doesn't match policy", deviceHash, target)
371 }
372
373
374
375
376
377
378
379 func (pe *StandardSecurityPolicyEnforcer) EnforceDeviceUnmountPolicy(ctx context.Context, unmountTarget string) (err error) {
380 pe.mutex.Lock()
381 defer pe.mutex.Unlock()
382
383 if _, ok := pe.Devices[unmountTarget]; !ok {
384 return fmt.Errorf("device doesn't exist: %s", unmountTarget)
385 }
386 delete(pe.Devices, unmountTarget)
387
388 return nil
389 }
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404 func (pe *StandardSecurityPolicyEnforcer) EnforceOverlayMountPolicy(ctx context.Context, containerID string, layerPaths []string, target string) (err error) {
405 pe.mutex.Lock()
406 defer pe.mutex.Unlock()
407
408 if len(pe.Containers) < 1 {
409 return errors.New("policy doesn't allow mounting containers")
410 }
411
412 if _, e := pe.startedContainers[containerID]; e {
413 return errors.New("container has already been started")
414 }
415
416 var incomingOverlay []string
417 for _, layer := range layerPaths {
418 if hash, ok := pe.Devices[layer]; !ok {
419 return fmt.Errorf("overlay layer isn't mounted: %s", layer)
420 } else {
421 incomingOverlay = append(incomingOverlay, hash)
422 }
423 }
424
425
426 var matchedContainers []int
427 for i, container := range pe.Containers {
428 if equalForOverlay(incomingOverlay, container.Layers) {
429 matchedContainers = append(matchedContainers, i)
430 }
431 }
432
433 if len(matchedContainers) == 0 {
434 errmsg := fmt.Sprintf("layerPaths '%v' doesn't match any valid overlay", layerPaths)
435 return errors.New(errmsg)
436 }
437
438 for _, i := range matchedContainers {
439 existing := pe.ContainerIndexToContainerIds[i]
440 if len(existing) >= len(matchedContainers) {
441 errmsg := fmt.Sprintf("layerPaths '%v' already used in maximum number of container overlays. This is likely because the security policy allows the container to be run only once.", layerPaths)
442 return errors.New(errmsg)
443 }
444 pe.expandMatchesForContainerIndex(i, containerID)
445 }
446
447 return nil
448 }
449
450
451
452
453
454
455
456
457
458
459 func (pe *StandardSecurityPolicyEnforcer) EnforceCreateContainerPolicy(
460 ctx context.Context,
461 sandboxID string,
462 containerID string,
463 argList []string,
464 envList []string,
465 workingDir string,
466 mounts []oci.Mount,
467 privileged bool,
468 noNewPrivileges bool,
469 user IDName,
470 groups []IDName,
471 umask string,
472 caps *oci.LinuxCapabilities,
473 seccomp string,
474 ) (allowedEnvs EnvList,
475 allowedCapabilities *oci.LinuxCapabilities,
476 stdioAccessAllowed bool,
477 err error) {
478 pe.mutex.Lock()
479 defer pe.mutex.Unlock()
480
481 if len(pe.Containers) < 1 {
482 return nil, nil, true, errors.New("policy doesn't allow mounting containers")
483 }
484
485 if _, e := pe.startedContainers[containerID]; e {
486 return nil, nil, true, errors.New("container has already been started")
487 }
488
489 if err = pe.enforceCommandPolicy(containerID, argList); err != nil {
490 return nil, nil, true, err
491 }
492
493 if err = pe.enforceEnvironmentVariablePolicy(containerID, envList); err != nil {
494 return nil, nil, true, err
495 }
496
497 if err = pe.enforceWorkingDirPolicy(containerID, workingDir); err != nil {
498 return nil, nil, true, err
499 }
500
501 if err = pe.enforcePrivilegedPolicy(containerID, privileged); err != nil {
502 return nil, nil, true, err
503 }
504
505 if err = pe.enforceMountPolicy(sandboxID, containerID, mounts); err != nil {
506 return nil, nil, true, err
507 }
508
509
510 pe.startedContainers[containerID] = struct{}{}
511
512 return envList, caps, true, nil
513 }
514
515
516
517 func (*StandardSecurityPolicyEnforcer) EnforceExecInContainerPolicy(_ context.Context, _ string, _ []string, envList []string, _ string, _ bool, _ IDName, _ []IDName, _ string, caps *oci.LinuxCapabilities) (EnvList, *oci.LinuxCapabilities, bool, error) {
518 return envList, caps, true, nil
519 }
520
521
522
523 func (*StandardSecurityPolicyEnforcer) EnforceExecExternalProcessPolicy(_ context.Context, _ []string, envList []string, _ string) (EnvList, bool, error) {
524 return envList, true, nil
525 }
526
527
528
529 func (*StandardSecurityPolicyEnforcer) EnforceShutdownContainerPolicy(context.Context, string) error {
530 return nil
531 }
532
533
534
535 func (*StandardSecurityPolicyEnforcer) EnforceSignalContainerProcessPolicy(context.Context, string, syscall.Signal, bool, []string) error {
536 return nil
537 }
538
539
540
541 func (*StandardSecurityPolicyEnforcer) EnforcePlan9MountPolicy(context.Context, string) error {
542 return nil
543 }
544
545
546
547 func (*StandardSecurityPolicyEnforcer) EnforcePlan9UnmountPolicy(context.Context, string) error {
548 return nil
549 }
550
551
552
553 func (*StandardSecurityPolicyEnforcer) EnforceOverlayUnmountPolicy(context.Context, string) error {
554 return nil
555 }
556
557
558
559 func (*StandardSecurityPolicyEnforcer) EnforceGetPropertiesPolicy(context.Context) error {
560 return nil
561 }
562
563
564
565 func (*StandardSecurityPolicyEnforcer) EnforceDumpStacksPolicy(context.Context) error {
566 return nil
567 }
568
569
570
571 func (*StandardSecurityPolicyEnforcer) EnforceRuntimeLoggingPolicy(context.Context) error {
572 return nil
573 }
574
575
576
577 func (*StandardSecurityPolicyEnforcer) LoadFragment(context.Context, string, string, string) error {
578 return nil
579 }
580
581
582
583 func (StandardSecurityPolicyEnforcer) EnforceScratchMountPolicy(context.Context, string, bool) error {
584 return nil
585 }
586
587
588
589 func (StandardSecurityPolicyEnforcer) EnforceScratchUnmountPolicy(context.Context, string) error {
590 return nil
591 }
592
593
594 func (StandardSecurityPolicyEnforcer) GetUserInfo(containerID string, spec *oci.Process) (IDName, []IDName, string, error) {
595 return IDName{}, nil, "", nil
596 }
597
598 func (pe *StandardSecurityPolicyEnforcer) enforceCommandPolicy(containerID string, argList []string) (err error) {
599
600
601
602 possibleIndices := pe.possibleIndicesForID(containerID)
603
604
605
606
607
608
609 matchingCommandFound := false
610 for _, possibleIndex := range possibleIndices {
611 cmd := pe.Containers[possibleIndex].Command
612 if stringSlicesEqual(cmd, argList) {
613 matchingCommandFound = true
614 } else {
615
616
617 pe.narrowMatchesForContainerIndex(possibleIndex, containerID)
618 }
619 }
620
621 if !matchingCommandFound {
622 errmsg := fmt.Sprintf("command %v doesn't match policy", argList)
623 return errors.New(errmsg)
624 }
625
626 return nil
627 }
628
629 func (pe *StandardSecurityPolicyEnforcer) enforceEnvironmentVariablePolicy(containerID string, envList []string) (err error) {
630
631
632
633 possibleIndices := pe.possibleIndicesForID(containerID)
634
635 for _, envVariable := range envList {
636 matchingRuleFoundForSomeContainer := false
637 for _, possibleIndex := range possibleIndices {
638 envRules := pe.Containers[possibleIndex].EnvRules
639 ok := envIsMatchedByRule(envVariable, envRules)
640 if ok {
641 matchingRuleFoundForSomeContainer = true
642 } else {
643
644
645 pe.narrowMatchesForContainerIndex(possibleIndex, containerID)
646 }
647 }
648
649 if !matchingRuleFoundForSomeContainer {
650 return fmt.Errorf("env variable %s unmatched by policy rule", envVariable)
651 }
652 }
653
654 return nil
655 }
656
657 func (pe *StandardSecurityPolicyEnforcer) enforceWorkingDirPolicy(containerID string, workingDir string) error {
658 possibleIndices := pe.possibleIndicesForID(containerID)
659
660 matched := false
661 for _, pIndex := range possibleIndices {
662 pWorkingDir := pe.Containers[pIndex].WorkingDir
663 if pWorkingDir == workingDir {
664 matched = true
665 } else {
666 pe.narrowMatchesForContainerIndex(pIndex, containerID)
667 }
668 }
669 if !matched {
670 return fmt.Errorf("working_dir %q unmatched by policy rule", workingDir)
671 }
672 return nil
673 }
674
675 func (pe *StandardSecurityPolicyEnforcer) enforcePrivilegedPolicy(containerID string, privileged bool) error {
676
677 if !privileged {
678 return nil
679 }
680
681 possibleIndices := pe.possibleIndicesForID(containerID)
682
683 matched := false
684 for _, pIndex := range possibleIndices {
685 pAllowElevated := pe.Containers[pIndex].AllowElevated
686 if pAllowElevated {
687 matched = true
688 } else {
689 pe.narrowMatchesForContainerIndex(pIndex, containerID)
690 }
691 }
692 if !matched {
693 return errors.New("privileged escalation unmatched by policy rule")
694 }
695 return nil
696 }
697
698 func envIsMatchedByRule(envVariable string, rules []EnvRuleConfig) bool {
699 for _, rule := range rules {
700 switch rule.Strategy {
701 case "string":
702 if rule.Rule == envVariable {
703 return true
704 }
705 case "re2":
706
707 matched, _ := regexp.MatchString(rule.Rule, envVariable)
708 if matched {
709 return true
710 }
711 }
712 }
713
714 return false
715 }
716
717
718 func (pe *StandardSecurityPolicyEnforcer) expandMatchesForContainerIndex(index int, idToAdd string) {
719 _, keyExists := pe.ContainerIndexToContainerIds[index]
720 if !keyExists {
721 pe.ContainerIndexToContainerIds[index] = map[string]struct{}{}
722 }
723
724 pe.ContainerIndexToContainerIds[index][idToAdd] = struct{}{}
725 }
726
727
728 func (pe *StandardSecurityPolicyEnforcer) narrowMatchesForContainerIndex(index int, idToRemove string) {
729 delete(pe.ContainerIndexToContainerIds[index], idToRemove)
730 }
731
732 func equalForOverlay(a1 []string, a2 []string) bool {
733
734
735
736 if len(a1) != len(a2) {
737 return false
738 }
739 topIndex := len(a2) - 1
740 for i, v := range a1 {
741 if v != a2[topIndex-i] {
742 return false
743 }
744 }
745 return true
746 }
747
748
749 func (pe *StandardSecurityPolicyEnforcer) possibleIndicesForID(containerID string) []int {
750 var possibleIndices []int
751 for index, ids := range pe.ContainerIndexToContainerIds {
752 for id := range ids {
753 if containerID == id {
754 possibleIndices = append(possibleIndices, index)
755 }
756 }
757 }
758 return possibleIndices
759 }
760
761 func (pe *StandardSecurityPolicyEnforcer) enforceDefaultMounts(specMount oci.Mount) error {
762 for _, mountConstraint := range pe.DefaultMounts {
763 if err := mountConstraint.validate(specMount); err == nil {
764 return nil
765 }
766 }
767 return fmt.Errorf("mount not allowed by default mount constraints: %+v", specMount)
768 }
769
770
771
772 func (pe *StandardSecurityPolicyEnforcer) ExtendDefaultMounts(defaultMounts []oci.Mount) error {
773 pe.mutex.Lock()
774 defer pe.mutex.Unlock()
775
776 for _, mnt := range defaultMounts {
777 pe.DefaultMounts = append(pe.DefaultMounts, newMountConstraint(
778 mnt.Source,
779 mnt.Destination,
780 mnt.Type,
781 mnt.Options,
782 ))
783 }
784 return nil
785 }
786
787
788
789
790
791 func (pe *StandardSecurityPolicyEnforcer) enforceMountPolicy(sandboxID, containerID string, mounts []oci.Mount) (err error) {
792 possibleIndices := pe.possibleIndicesForID(containerID)
793
794 for _, mount := range mounts {
795
796 if err := pe.enforceDefaultMounts(mount); err == nil {
797 continue
798 }
799
800 mountOk := false
801
802
803 for _, pIndex := range possibleIndices {
804 cont := pe.Containers[pIndex]
805 if err = cont.matchMount(sandboxID, mount); err == nil {
806 mountOk = true
807 } else {
808 pe.narrowMatchesForContainerIndex(pIndex, containerID)
809 }
810 }
811
812 if !mountOk {
813 retErr := fmt.Errorf("mount %+v is not allowed by mount constraints", mount)
814 return retErr
815 }
816 }
817
818 return nil
819 }
820
821
822
823
824
825
826
827
828
829 func (m *mountInternal) validate(mSpec oci.Mount) error {
830 if m.Type != mSpec.Type {
831 return fmt.Errorf("mount type not allowed by policy: expected=%q, actual=%q", m.Type, mSpec.Type)
832 }
833 if ok, _ := regexp.MatchString(m.Source, mSpec.Source); !ok {
834 return fmt.Errorf("mount source not allowed by policy: expected=%q, actual=%q", m.Source, mSpec.Source)
835 }
836 if m.Destination != mSpec.Destination && m.Destination != "" {
837 return fmt.Errorf("mount destination not allowed by policy: expected=%q, actual=%q", m.Destination, mSpec.Destination)
838 }
839 if !stringSlicesEqual(m.Options, mSpec.Options) {
840 return fmt.Errorf("mount options not allowed by policy: expected=%q, actual=%q", m.Options, mSpec.Options)
841 }
842 return nil
843 }
844
845
846
847 func (c *securityPolicyContainer) matchMount(sandboxID string, m oci.Mount) (err error) {
848 for _, constraint := range c.Mounts {
849
850
851 constraint = substituteUVMPath(sandboxID, constraint)
852 if err = constraint.validate(m); err == nil {
853 return nil
854 }
855 }
856 return fmt.Errorf("mount is not allowed by policy: %+v", m)
857 }
858
859
860
861
862 func substituteUVMPath(sandboxID string, m mountInternal) mountInternal {
863 if strings.HasPrefix(m.Source, guestpath.SandboxMountPrefix) {
864 m.Source = specInternal.SandboxMountSource(sandboxID, m.Source)
865 } else if strings.HasPrefix(m.Source, guestpath.HugePagesMountPrefix) {
866 m.Source = specInternal.HugePagesMountSource(sandboxID, m.Source)
867 }
868 return m
869 }
870
871 func stringSlicesEqual(slice1, slice2 []string) bool {
872 if len(slice1) != len(slice2) {
873 return false
874 }
875
876 for i := 0; i < len(slice1); i++ {
877 if slice1[i] != slice2[i] {
878 return false
879 }
880 }
881 return true
882 }
883
884 func (pe *StandardSecurityPolicyEnforcer) EncodedSecurityPolicy() string {
885 return pe.encodedSecurityPolicy
886 }
887
888 type OpenDoorSecurityPolicyEnforcer struct {
889 encodedSecurityPolicy string
890 }
891
892 var _ SecurityPolicyEnforcer = (*OpenDoorSecurityPolicyEnforcer)(nil)
893
894 func (OpenDoorSecurityPolicyEnforcer) EnforceDeviceMountPolicy(context.Context, string, string) error {
895 return nil
896 }
897
898 func (OpenDoorSecurityPolicyEnforcer) EnforceDeviceUnmountPolicy(context.Context, string) error {
899 return nil
900 }
901
902 func (OpenDoorSecurityPolicyEnforcer) EnforceOverlayMountPolicy(context.Context, string, []string, string) error {
903 return nil
904 }
905
906 func (OpenDoorSecurityPolicyEnforcer) EnforceOverlayUnmountPolicy(context.Context, string) error {
907 return nil
908 }
909
910 func (OpenDoorSecurityPolicyEnforcer) EnforceCreateContainerPolicy(_ context.Context, _, _ string, _ []string, envList []string, _ string, _ []oci.Mount, _ bool, _ bool, _ IDName, _ []IDName, _ string, caps *oci.LinuxCapabilities, _ string) (EnvList, *oci.LinuxCapabilities, bool, error) {
911 return envList, caps, true, nil
912 }
913
914 func (OpenDoorSecurityPolicyEnforcer) EnforceExecInContainerPolicy(_ context.Context, _ string, _ []string, envList []string, _ string, _ bool, _ IDName, _ []IDName, _ string, caps *oci.LinuxCapabilities) (EnvList, *oci.LinuxCapabilities, bool, error) {
915 return envList, caps, true, nil
916 }
917
918 func (OpenDoorSecurityPolicyEnforcer) EnforceExecExternalProcessPolicy(_ context.Context, _ []string, envList []string, _ string) (EnvList, bool, error) {
919 return envList, true, nil
920 }
921
922 func (*OpenDoorSecurityPolicyEnforcer) EnforceShutdownContainerPolicy(context.Context, string) error {
923 return nil
924 }
925
926 func (*OpenDoorSecurityPolicyEnforcer) EnforceSignalContainerProcessPolicy(context.Context, string, syscall.Signal, bool, []string) error {
927 return nil
928 }
929
930 func (*OpenDoorSecurityPolicyEnforcer) EnforcePlan9MountPolicy(context.Context, string) error {
931 return nil
932 }
933
934 func (*OpenDoorSecurityPolicyEnforcer) EnforcePlan9UnmountPolicy(context.Context, string) error {
935 return nil
936 }
937
938 func (OpenDoorSecurityPolicyEnforcer) EnforceGetPropertiesPolicy(context.Context) error {
939 return nil
940 }
941
942 func (OpenDoorSecurityPolicyEnforcer) EnforceDumpStacksPolicy(context.Context) error {
943 return nil
944 }
945
946 func (OpenDoorSecurityPolicyEnforcer) LoadFragment(context.Context, string, string, string) error {
947 return nil
948 }
949
950 func (OpenDoorSecurityPolicyEnforcer) ExtendDefaultMounts([]oci.Mount) error {
951 return nil
952 }
953
954 func (OpenDoorSecurityPolicyEnforcer) EnforceRuntimeLoggingPolicy(context.Context) error {
955 return nil
956 }
957
958 func (oe *OpenDoorSecurityPolicyEnforcer) EncodedSecurityPolicy() string {
959 return oe.encodedSecurityPolicy
960 }
961
962 func (OpenDoorSecurityPolicyEnforcer) EnforceScratchMountPolicy(context.Context, string, bool) error {
963 return nil
964 }
965
966 func (OpenDoorSecurityPolicyEnforcer) EnforceScratchUnmountPolicy(context.Context, string) error {
967 return nil
968 }
969
970 func (OpenDoorSecurityPolicyEnforcer) GetUserInfo(containerID string, spec *oci.Process) (IDName, []IDName, string, error) {
971 return IDName{}, nil, "", nil
972 }
973
974 type ClosedDoorSecurityPolicyEnforcer struct {
975 encodedSecurityPolicy string
976 }
977
978 var _ SecurityPolicyEnforcer = (*ClosedDoorSecurityPolicyEnforcer)(nil)
979
980 func (ClosedDoorSecurityPolicyEnforcer) EnforceDeviceMountPolicy(context.Context, string, string) error {
981 return errors.New("mounting is denied by policy")
982 }
983
984 func (ClosedDoorSecurityPolicyEnforcer) EnforceDeviceUnmountPolicy(context.Context, string) error {
985 return errors.New("unmounting is denied by policy")
986 }
987
988 func (ClosedDoorSecurityPolicyEnforcer) EnforceOverlayMountPolicy(context.Context, string, []string, string) error {
989 return errors.New("creating an overlay fs is denied by policy")
990 }
991
992 func (ClosedDoorSecurityPolicyEnforcer) EnforceOverlayUnmountPolicy(context.Context, string) error {
993 return errors.New("removing an overlay fs is denied by policy")
994 }
995
996 func (ClosedDoorSecurityPolicyEnforcer) EnforceCreateContainerPolicy(context.Context, string, string, []string, []string, string, []oci.Mount, bool, bool, IDName, []IDName, string, *oci.LinuxCapabilities, string) (EnvList, *oci.LinuxCapabilities, bool, error) {
997 return nil, nil, false, errors.New("running commands is denied by policy")
998 }
999
1000 func (ClosedDoorSecurityPolicyEnforcer) EnforceExecInContainerPolicy(context.Context, string, []string, []string, string, bool, IDName, []IDName, string, *oci.LinuxCapabilities) (EnvList, *oci.LinuxCapabilities, bool, error) {
1001 return nil, nil, false, errors.New("starting additional processes in a container is denied by policy")
1002 }
1003
1004 func (ClosedDoorSecurityPolicyEnforcer) EnforceExecExternalProcessPolicy(context.Context, []string, []string, string) (EnvList, bool, error) {
1005 return nil, false, errors.New("starting additional processes in uvm is denied by policy")
1006 }
1007
1008 func (*ClosedDoorSecurityPolicyEnforcer) EnforceShutdownContainerPolicy(context.Context, string) error {
1009 return errors.New("shutting down containers is denied by policy")
1010 }
1011
1012 func (*ClosedDoorSecurityPolicyEnforcer) EnforceSignalContainerProcessPolicy(context.Context, string, syscall.Signal, bool, []string) error {
1013 return errors.New("signalling container processes is denied by policy")
1014 }
1015
1016 func (*ClosedDoorSecurityPolicyEnforcer) EnforcePlan9MountPolicy(context.Context, string) error {
1017 return errors.New("mounting is denied by policy")
1018 }
1019
1020 func (*ClosedDoorSecurityPolicyEnforcer) EnforcePlan9UnmountPolicy(context.Context, string) error {
1021 return errors.New("unmounting is denied by policy")
1022 }
1023
1024 func (ClosedDoorSecurityPolicyEnforcer) EnforceGetPropertiesPolicy(context.Context) error {
1025 return errors.New("getting container properties is denied by policy")
1026 }
1027
1028 func (ClosedDoorSecurityPolicyEnforcer) EnforceDumpStacksPolicy(context.Context) error {
1029 return errors.New("getting stack dumps is denied by policy")
1030 }
1031
1032 func (ClosedDoorSecurityPolicyEnforcer) LoadFragment(context.Context, string, string, string) error {
1033 return errors.New("loading fragments is denied by policy")
1034 }
1035
1036 func (ClosedDoorSecurityPolicyEnforcer) ExtendDefaultMounts(_ []oci.Mount) error {
1037 return nil
1038 }
1039
1040 func (ClosedDoorSecurityPolicyEnforcer) EnforceRuntimeLoggingPolicy(context.Context) error {
1041 return errors.New("runtime logging is denied by policy")
1042 }
1043
1044 func (ClosedDoorSecurityPolicyEnforcer) EncodedSecurityPolicy() string {
1045 return ""
1046 }
1047
1048 func (ClosedDoorSecurityPolicyEnforcer) EnforceScratchMountPolicy(context.Context, string, bool) error {
1049 return errors.New("mounting scratch is denied by the policy")
1050 }
1051
1052 func (ClosedDoorSecurityPolicyEnforcer) EnforceScratchUnmountPolicy(context.Context, string) error {
1053 return errors.New("unmounting scratch is denied by the policy")
1054 }
1055
1056 func (ClosedDoorSecurityPolicyEnforcer) GetUserInfo(containerID string, spec *oci.Process) (IDName, []IDName, string, error) {
1057 return IDName{}, nil, "", nil
1058 }
1059
View as plain text