Skip to content

Commit

Permalink
scc sort by priority
Browse files Browse the repository at this point in the history
  • Loading branch information
pweil- committed Nov 2, 2015
1 parent 9dedbb4 commit 390e56c
Show file tree
Hide file tree
Showing 7 changed files with 142 additions and 4 deletions.
6 changes: 6 additions & 0 deletions api/swagger-spec/api-v1.json
Original file line number Diff line number Diff line change
Expand Up @@ -14741,6 +14741,7 @@
"v1.SecurityContextConstraints": {
"id": "v1.SecurityContextConstraints",
"required": [
"priority",
"allowPrivilegedContainer",
"allowedCapabilities",
"allowHostDirVolumePlugin",
Expand All @@ -14761,6 +14762,11 @@
"metadata": {
"$ref": "v1.ObjectMeta"
},
"priority": {
"type": "integer",
"format": "int32",
"description": "determines which SCC is used when multiple SCCs allow a particular pod; higher priority SCCs are preferred"
},
"allowPrivilegedContainer": {
"type": "boolean",
"description": "allow containers to run as privileged"
Expand Down
2 changes: 2 additions & 0 deletions pkg/cmd/server/bootstrappolicy/securitycontextconstraints.go
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,8 @@ func GetBootstrapSecurityContextConstraints(sccNameToAdditionalGroups map[string
SupplementalGroups: kapi.SupplementalGroupsStrategyOptions{
Type: kapi.SupplementalGroupsStrategyRunAsAny,
},
// prefer the anyuid SCC over ones that force a uid
Priority: 1,
},
}

Expand Down
2 changes: 1 addition & 1 deletion pkg/security/admission/admission.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ func (c *constraint) Admit(a kadmission.Attributes) error {

// remove duplicate constraints and sort
matchedConstraints = deduplicateSecurityContextConstraints(matchedConstraints)
sort.Sort(ByRestrictions(matchedConstraints))
sort.Sort(ByPriority(matchedConstraints))
providers, errs := c.createProvidersFromConstraints(a.GetNamespace(), matchedConstraints)
logProviders(pod, providers, errs)

Expand Down
2 changes: 1 addition & 1 deletion pkg/security/admission/admission_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ func TestAdmit(t *testing.T) {
Groups: []string{"system:serviceaccounts"},
}
// create scc that has specific requirements that shouldn't match but is permissioned to
// service accounts to test exact matches
// service accounts to test that we're matching first against the higher priority SCC.
var exactUID int64 = 999
saExactSCC := &kapi.SecurityContextConstraints{
ObjectMeta: kapi.ObjectMeta{
Expand Down
44 changes: 44 additions & 0 deletions pkg/security/admission/bypriority.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package admission

import (
kapi "k8s.io/kubernetes/pkg/api"
)

// ByRestrictions is a helper to sort SCCs based on priority. If priorities are equal
// a string compare of the name is used.
type ByPriority []*kapi.SecurityContextConstraints

func (s ByPriority) Len() int {
return len(s)
}
func (s ByPriority) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s ByPriority) Less(i, j int) bool {
iSCC := s[i]
jSCC := s[j]

// a higher priority is considered "less" so that it moves to the front of the line
if iSCC.Priority > jSCC.Priority {
return true
}

if iSCC.Priority < jSCC.Priority {
return false
}

// they are equal, let's try point values
iRestrictionScore := pointValue(iSCC)
jRestrictionScore := pointValue(jSCC)

// a lower restriction score is considered "less" so that it moves to the front of the line
// (the greater the score, the more lax the SCC is)
if iRestrictionScore < jRestrictionScore {
return true
}

if iRestrictionScore > jRestrictionScore {
return false
}

// they are still equal, sort by name
return iSCC.Name < jSCC.Name
}
86 changes: 86 additions & 0 deletions pkg/security/admission/bypriority_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package admission

import (
"sort"
"testing"

kapi "k8s.io/kubernetes/pkg/api"
)

func TestByPriority(t *testing.T) {
sccs := []*kapi.SecurityContextConstraints{testSCC("one", 1), testSCC("two", 2), testSCC("three", 3), testSCC("negative", -1), testSCC("super", 100)}
expected := []string{"super", "three", "two", "one", "negative"}

sort.Sort(ByPriority(sccs))

for i, scc := range sccs {
if scc.Name != expected[i] {
t.Errorf("sort by priority found %s at element %d but expected %s", scc.Name, i, expected[i])
}
}
}

func TestByPrioritiesScore(t *testing.T) {
privilegedSCC := testSCC("privileged", 1)
privilegedSCC.AllowPrivilegedContainer = true

nonPriviledSCC := testSCC("nonprivileged", 1)

hostDirSCC := testSCC("hostdir", 1)
hostDirSCC.AllowHostDirVolumePlugin = true

sccs := []*kapi.SecurityContextConstraints{nonPriviledSCC, privilegedSCC, hostDirSCC}
// with equal priorities expect that the SCCs will be sorted with hold behavior based on their score,
// most restrictive first
expected := []string{"nonprivileged", "hostdir", "privileged"}

sort.Sort(ByPriority(sccs))

for i, scc := range sccs {
if scc.Name != expected[i] {
t.Errorf("sort by score found %s at element %d but expected %s", scc.Name, i, expected[i])
}
}
}

func TestByPrioritiesName(t *testing.T) {
sccs := []*kapi.SecurityContextConstraints{testSCC("e", 1), testSCC("d", 1), testSCC("a", 1), testSCC("c", 1), testSCC("b", 1)}
// expect that with equal priorities AND an equal point value that SCCs are sorted by name
expected := []string{"a", "b", "c", "d", "e"}

sort.Sort(ByPriority(sccs))

for i, scc := range sccs {
if scc.Name != expected[i] {
t.Errorf("sort by priority found %s at element %d but expected %s", scc.Name, i, expected[i])
}
}
}

func TestByPrioritiesMixedSCCs(t *testing.T) {
privilegedSCC := testSCC("privileged", 1)
privilegedSCC.AllowPrivilegedContainer = true

nonPriviledSCC := testSCC("nonprivileged", 1)

sccs := []*kapi.SecurityContextConstraints{testSCC("priorityB", 5), testSCC("priorityA", 5), testSCC("super", 100), privilegedSCC, nonPriviledSCC}
// highest priority first, equal priority and equal score sorted by name, equal priority and non-equal score sorted most restrictive to least.
expected := []string{"super", "priorityA", "priorityB", "nonprivileged", "privileged"}

sort.Sort(ByPriority(sccs))

for i, scc := range sccs {
if scc.Name != expected[i] {
t.Errorf("sort by priority found %s at element %d but expected %s", scc.Name, i, expected[i])
}
}
}

func testSCC(name string, priority int) *kapi.SecurityContextConstraints {
return &kapi.SecurityContextConstraints{
ObjectMeta: kapi.ObjectMeta{
Name: name,
},
Priority: priority,
}
}
4 changes: 2 additions & 2 deletions pkg/security/admission/byrestrictions.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ func (s ByRestrictions) Len() int {
}
func (s ByRestrictions) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s ByRestrictions) Less(i, j int) bool {
return s.pointValue(s[i]) < s.pointValue(s[j])
return pointValue(s[i]) < pointValue(s[j])
}

// pointValue places a value on the SCC based on the settings of the SCC that can be used
// to determine how restrictive it is. The lower the number, the more restrictive it is.
func (s ByRestrictions) pointValue(constraint *kapi.SecurityContextConstraints) int {
func pointValue(constraint *kapi.SecurityContextConstraints) int {
points := 0

// make sure these are always valued higher than the combination of the highest strategies
Expand Down

0 comments on commit 390e56c

Please sign in to comment.