From a711f59be8726469f727778b4a08d6d67580d48d Mon Sep 17 00:00:00 2001 From: Paul Weil Date: Fri, 30 Oct 2015 15:01:37 -0400 Subject: [PATCH] OS integration SCC priority field --- api/swagger-spec/api-v1.json | 6 +++ .../securitycontextconstraints.go | 2 + pkg/security/admission/admission.go | 2 +- pkg/security/admission/admission_test.go | 4 +- pkg/security/admission/bypriority.go | 20 +++++++ pkg/security/admission/bypriority_test.go | 43 +++++++++++++++ pkg/security/admission/byrestrictions.go | 52 ------------------- 7 files changed, 75 insertions(+), 54 deletions(-) create mode 100644 pkg/security/admission/bypriority.go create mode 100644 pkg/security/admission/bypriority_test.go delete mode 100644 pkg/security/admission/byrestrictions.go diff --git a/api/swagger-spec/api-v1.json b/api/swagger-spec/api-v1.json index 60717ba4c79f..c0061286db77 100644 --- a/api/swagger-spec/api-v1.json +++ b/api/swagger-spec/api-v1.json @@ -14741,6 +14741,7 @@ "v1.SecurityContextConstraints": { "id": "v1.SecurityContextConstraints", "required": [ + "sortPriority", "allowPrivilegedContainer", "allowedCapabilities", "allowHostDirVolumePlugin", @@ -14761,6 +14762,11 @@ "metadata": { "$ref": "v1.ObjectMeta" }, + "sortPriority": { + "type": "integer", + "format": "int32", + "description": "influences the sort order when evaluating SCCs available to the user" + }, "allowPrivilegedContainer": { "type": "boolean", "description": "allow containers to run as privileged" diff --git a/pkg/cmd/server/bootstrappolicy/securitycontextconstraints.go b/pkg/cmd/server/bootstrappolicy/securitycontextconstraints.go index f03db7a116ee..5e65763b7125 100644 --- a/pkg/cmd/server/bootstrappolicy/securitycontextconstraints.go +++ b/pkg/cmd/server/bootstrappolicy/securitycontextconstraints.go @@ -66,6 +66,8 @@ func GetBootstrapSecurityContextConstraints(sccNameToAdditionalGroups map[string SupplementalGroups: kapi.SupplementalGroupsStrategyOptions{ Type: kapi.SupplementalGroupsStrategyRunAsAny, }, + // by default if you have access to the admin strategy then use it + SortPriority: 1, }, // SecurityContextConstraintNonRoot does not allow host access, allocates SELinux labels // and allows the user to request a specific UID or provide the default in the dockerfile. diff --git a/pkg/security/admission/admission.go b/pkg/security/admission/admission.go index 6c3d075ed87a..5123ae779dd4 100644 --- a/pkg/security/admission/admission.go +++ b/pkg/security/admission/admission.go @@ -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) diff --git a/pkg/security/admission/admission_test.go b/pkg/security/admission/admission_test.go index bdc555ef77b3..94d85b1cd9f8 100644 --- a/pkg/security/admission/admission_test.go +++ b/pkg/security/admission/admission_test.go @@ -68,9 +68,11 @@ func TestAdmit(t *testing.T) { Type: kapi.SupplementalGroupsStrategyMustRunAs, }, Groups: []string{"system:serviceaccounts"}, + // give this scc priority since it is what we want to validate with + SortPriority: 1, } // 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{ diff --git a/pkg/security/admission/bypriority.go b/pkg/security/admission/bypriority.go new file mode 100644 index 000000000000..e076dbcb8010 --- /dev/null +++ b/pkg/security/admission/bypriority.go @@ -0,0 +1,20 @@ +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 { + if s[i].SortPriority == s[j].SortPriority { + return s[i].Name < s[j].Name + } + return s[i].SortPriority > s[j].SortPriority +} diff --git a/pkg/security/admission/bypriority_test.go b/pkg/security/admission/bypriority_test.go new file mode 100644 index 000000000000..c47c161bb426 --- /dev/null +++ b/pkg/security/admission/bypriority_test.go @@ -0,0 +1,43 @@ +package admission + +import ( + "sort" + "testing" + + kapi "k8s.io/kubernetes/pkg/api" +) + +func TestByPriority(t *testing.T) { + tests := map[string]struct { + sccs []*kapi.SecurityContextConstraints + expected []string + }{ + "sort with priorities": { + 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 with equal priorities": { + sccs: []*kapi.SecurityContextConstraints{testSCC("one", 1), testSCC("foo", 2), testSCC("bar", 2), testSCC("baz", 2), testSCC("barbaz", 2)}, + expected: []string{"bar", "barbaz", "baz", "foo", "one"}, + }, + } + + for testCaseName, testCase := range tests { + sort.Sort(ByPriority(testCase.sccs)) + + for i, scc := range testCase.sccs { + if scc.Name != testCase.expected[i] { + t.Errorf("%s found %s at element %d but expected %s", testCaseName, scc.Name, i, testCase.expected[i]) + } + } + } +} + +func testSCC(name string, priority int) *kapi.SecurityContextConstraints { + return &kapi.SecurityContextConstraints{ + ObjectMeta: kapi.ObjectMeta{ + Name: name, + }, + SortPriority: priority, + } +} diff --git a/pkg/security/admission/byrestrictions.go b/pkg/security/admission/byrestrictions.go deleted file mode 100644 index 1e925db261f0..000000000000 --- a/pkg/security/admission/byrestrictions.go +++ /dev/null @@ -1,52 +0,0 @@ -package admission - -import ( - kapi "k8s.io/kubernetes/pkg/api" -) - -// ByRestrictions is a helper to sort SCCs in order of most restrictive to least restrictive. -type ByRestrictions []*kapi.SecurityContextConstraints - -func (s ByRestrictions) Len() int { - return len(s) -} -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]) -} - -// 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 { - points := 0 - - // make sure these are always valued higher than the combination of the highest strategies - if constraint.AllowPrivilegedContainer { - points += 20 - } - // 9 gives us a value slightly higher than an SCC that allows run as any in both strategies since - // we're allowing access to the host system - if constraint.AllowHostDirVolumePlugin { - points += 10 - } - - // strategies in order of least restrictive to most restrictive - switch constraint.SELinuxContext.Type { - case kapi.SELinuxStrategyRunAsAny: - points += 4 - case kapi.SELinuxStrategyMustRunAs: - points += 1 - } - - switch constraint.RunAsUser.Type { - case kapi.RunAsUserStrategyRunAsAny: - points += 4 - case kapi.RunAsUserStrategyMustRunAsNonRoot: - points += 3 - case kapi.RunAsUserStrategyMustRunAsRange: - points += 2 - case kapi.RunAsUserStrategyMustRunAs: - points += 1 - } - return points -}