Skip to content
This repository has been archived by the owner on Aug 14, 2020. It is now read-only.

Commit

Permalink
Merge pull request #673 from lucab/to-upstream/selinux-context
Browse files Browse the repository at this point in the history
spec: add os/linux/selinux-context isolator
  • Loading branch information
jonboulle authored Nov 15, 2016
2 parents 1b1431b + 34360b3 commit 7f02c81
Show file tree
Hide file tree
Showing 4 changed files with 227 additions and 0 deletions.
97 changes: 97 additions & 0 deletions schema/types/isolator_linux_specific.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"encoding/json"
"errors"
"fmt"
"strings"
"unicode"
)

Expand All @@ -29,6 +30,7 @@ const (
LinuxSeccompRetainSetName = "os/linux/seccomp-retain-set"
LinuxOOMScoreAdjName = "os/linux/oom-score-adj"
LinuxCPUSharesName = "os/linux/cpu-shares"
LinuxSELinuxContextName = "os/linux/selinux-context"
)

var LinuxIsolatorNames = make(map[ACIdentifier]struct{})
Expand All @@ -42,6 +44,7 @@ func init() {
LinuxCPUSharesName: func() IsolatorValue { v := LinuxCPUShares(1024); return &v },
LinuxSeccompRemoveSetName: func() IsolatorValue { return &LinuxSeccompRemoveSet{} },
LinuxSeccompRetainSetName: func() IsolatorValue { return &LinuxSeccompRetainSet{} },
LinuxSELinuxContextName: func() IsolatorValue { return &LinuxSELinuxContext{} },
} {
AddIsolatorName(name, LinuxIsolatorNames)
AddIsolatorValueConstructor(name, con)
Expand Down Expand Up @@ -430,3 +433,97 @@ func (l LinuxOOMScoreAdj) AsIsolator() Isolator {
value: &l,
}
}

type LinuxSELinuxUser string
type LinuxSELinuxRole string
type LinuxSELinuxType string
type LinuxSELinuxLevel string

type linuxSELinuxValue struct {
User LinuxSELinuxUser `json:"user"`
Role LinuxSELinuxRole `json:"role"`
Type LinuxSELinuxType `json:"type"`
Level LinuxSELinuxLevel `json:"level"`
}

type LinuxSELinuxContext struct {
val linuxSELinuxValue
}

func (l LinuxSELinuxContext) AssertValid() error {
if l.val.User == "" || strings.Contains(string(l.val.User), ":") {
return fmt.Errorf("invalid user value %q", l.val.User)
}
if l.val.Role == "" || strings.Contains(string(l.val.Role), ":") {
return fmt.Errorf("invalid role value %q", l.val.Role)
}
if l.val.Type == "" || strings.Contains(string(l.val.Type), ":") {
return fmt.Errorf("invalid type value %q", l.val.Type)
}
if l.val.Level == "" {
return fmt.Errorf("invalid level value %q", l.val.Level)
}
return nil
}

func (l *LinuxSELinuxContext) UnmarshalJSON(b []byte) error {
var v linuxSELinuxValue
err := json.Unmarshal(b, &v)
if err != nil {
return err
}
l.val = v
return nil
}

func (l LinuxSELinuxContext) User() LinuxSELinuxUser {
return l.val.User
}

func (l LinuxSELinuxContext) Role() LinuxSELinuxRole {
return l.val.Role
}

func (l LinuxSELinuxContext) Type() LinuxSELinuxType {
return l.val.Type
}

func (l LinuxSELinuxContext) Level() LinuxSELinuxLevel {
return l.val.Level
}

func (l LinuxSELinuxContext) multipleAllowed() bool {
return false
}

func (l LinuxSELinuxContext) Conflicts() []ACIdentifier {
return nil
}

func NewLinuxSELinuxContext(selinuxUser, selinuxRole, selinuxType, selinuxLevel string) (*LinuxSELinuxContext, error) {
l := LinuxSELinuxContext{
linuxSELinuxValue{
LinuxSELinuxUser(selinuxUser),
LinuxSELinuxRole(selinuxRole),
LinuxSELinuxType(selinuxType),
LinuxSELinuxLevel(selinuxLevel),
},
}
if err := l.AssertValid(); err != nil {
return nil, err
}
return &l, nil
}

func (l LinuxSELinuxContext) AsIsolator() (*Isolator, error) {
b, err := json.Marshal(l.val)
if err != nil {
return nil, err
}
rm := json.RawMessage(b)
return &Isolator{
Name: LinuxSELinuxContextName,
ValueRaw: &rm,
value: &l,
}, nil
}
70 changes: 70 additions & 0 deletions schema/types/isolator_linux_specific_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,76 @@ func TestNewLinuxCapabilitiesRetainSet(t *testing.T) {

}

func TestNewLinuxSELinuxContext(t *testing.T) {
tests := []struct {
inUser string
inRole string
inType string
inLevel string

wuser LinuxSELinuxUser
wrole LinuxSELinuxRole
wtype LinuxSELinuxType
wlevel LinuxSELinuxLevel
werr bool
}{
{
"unconfined_u", "object_r", "user_home_t", "s0",
LinuxSELinuxUser("unconfined_u"),
LinuxSELinuxRole("object_r"),
LinuxSELinuxType("user_home_t"),
LinuxSELinuxLevel("s0"),
false,
},
{
"unconfined_u", "object_r", "user_home_t", "s0-s0:c0",
LinuxSELinuxUser("unconfined_u"),
LinuxSELinuxRole("object_r"),
LinuxSELinuxType("user_home_t"),
LinuxSELinuxLevel("s0-s0:c0"),
false,
},
{
"", "object_r", "user_home_t", "s0",
"",
"",
"",
"",
true,
},
{
"unconfined_u:unconfined_t", "object_r", "user_home_t", "s0",
"",
"",
"",
"",
true,
},
}
for i, tt := range tests {
c, err := NewLinuxSELinuxContext(tt.inUser, tt.inRole, tt.inType, tt.inLevel)
if tt.werr {
if err == nil {
t.Errorf("#%d: did not get expected error", i)
}
continue
}
if guser := c.User(); !reflect.DeepEqual(guser, tt.wuser) {
t.Errorf("#%d: got user %#v, want user %#v", i, guser, tt.wuser)
}
if grole := c.Role(); !reflect.DeepEqual(grole, tt.wrole) {
t.Errorf("#%d: got role %#v, want role %#v", i, grole, tt.wrole)
}
if gtype := c.Type(); !reflect.DeepEqual(gtype, tt.wtype) {
t.Errorf("#%d: got type %#v, want type %#v", i, gtype, tt.wtype)
}
if glevel := c.Level(); !reflect.DeepEqual(glevel, tt.wlevel) {
t.Errorf("#%d: got level %#v, want level %#v", i, glevel, tt.wlevel)
}
}

}

func TestNewLinuxCapabilitiesRevokeSet(t *testing.T) {
tests := []struct {
in []string
Expand Down
28 changes: 28 additions & 0 deletions schema/types/isolator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,34 @@ func TestIsolatorUnmarshal(t *testing.T) {
}`,
true,
},
{
`{
"name": "os/linux/selinux-context",
"value": {"user" : "user_u", "role": "role_r", "type": "type_r", "level": "s0-s0"}
}`,
false,
},
{
`{
"name": "os/linux/selinux-context",
"value": {"user" : "user_u", "role": "role_r", "type": "type_r", "level": "s0-s0:c0"}
}`,
false,
},
{
`{
"name": "os/linux/selinux-context",
"value": {"user" : "user_u", "role": "role_r:type_t", "type": "type_r", "level": "s0-s0"}
}`,
true,
},
{
`{
"name": "os/linux/selinux-context",
"value": {"user" : "user_u", "role": "", "type": "type_r", "level": "s0-s0"}
}`,
true,
},
}

for i, tt := range tests {
Expand Down
32 changes: 32 additions & 0 deletions spec/ace.md
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,38 @@ In the example above, the process will not be allowed to invoke `clock_adjtime(2

In the example above, the process will be only allowed to invoke syscalls specified in the custom network-related set (and any other syscall in the implementation-specific whitelist). All other syscalls will result in app termination via `SIGSYS` signal.

#### os/linux/selinux-context

* Scope: app/pod

**Parameters:**

* **user** case-sensitive string containing the user portion of the SELinux security context to be used to label the current pod or application.
* **role** case-sensitive string containing the role portion of the SELinux security context to be used to label the current pod or application.
* **type** case-sensitive string containing the type/domain portion of the SELinux security context to be used to label the current pod or application.
* **level** case-sensitive string containing the level portion of the SELinux security context to be used to label the current pod or application.

**Notes:**
1. Only a single `os/linux/selinux-context` isolator can be specified per-pod.
2. Only a single `os/linux/selinux-context` isolator can be specified per-app.
3. If a SELinux security context is specified at pod level, it applies to all processes involved in running the pod.
4. If specified both at pod and app level, app values override pod ones.
5. Implementations MAY ignore this isolator if the host does not support SELinux labeling.

**Example:**

```json
"name": "os/linux/selinux-context",
"value": {
"user": "system_u",
"role": "system_r",
"type": "dhcpc_t",
"level": "s0",
}
```

In the example above, the SELinux security context `system_u:system_r:dhcpc_t:s0` will be applied to a pod or to a single application, depending on where this isolator is specified.

#### os/linux/capabilities-remove-set

* Scope: app
Expand Down

0 comments on commit 7f02c81

Please sign in to comment.