From ba00bf0fdabc9a9b2ab9cea84847e76b85803410 Mon Sep 17 00:00:00 2001 From: Paul Weil Date: Thu, 18 Feb 2016 18:17:08 -0500 Subject: [PATCH] UPSTREAM: : add scc describer --- .../k8s.io/kubernetes/pkg/kubectl/describe.go | 112 ++++++++++++++++++ .../kubernetes/pkg/kubectl/describe_test.go | 17 +++ 2 files changed, 129 insertions(+) diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/describe.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/describe.go index db10d8c7ffac..54bac5fed2eb 100644 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/describe.go +++ b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/describe.go @@ -23,6 +23,7 @@ import ( "io" "reflect" "sort" + "strconv" "strings" "time" @@ -93,6 +94,8 @@ func describerMap(c *client.Client) map[unversioned.GroupKind]Describer { extensions.Kind("Deployment"): &DeploymentDescriber{clientset.FromUnversionedClient(c)}, extensions.Kind("Job"): &JobDescriber{c}, extensions.Kind("Ingress"): &IngressDescriber{c}, + + api.Kind("SecurityContextConstraints"): &SecurityContextConstraintsDescriber{c}, } return m @@ -415,6 +418,115 @@ func describeQuota(resourceQuota *api.ResourceQuota) (string, error) { }) } +// SecurityContextConstraintsDescriber generates information about an SCC +type SecurityContextConstraintsDescriber struct { + client.Interface +} + +func (d *SecurityContextConstraintsDescriber) Describe(namespace, name string) (string, error) { + scc, err := d.SecurityContextConstraints().Get(name) + if err != nil { + return "", err + } + return describeSecurityContextConstraints(scc) +} + +func describeSecurityContextConstraints(scc *api.SecurityContextConstraints) (string, error) { + return tabbedString(func(out io.Writer) error { + fmt.Fprintf(out, "Name:\t%s\n", scc.Name) + + if scc.Priority != nil { + fmt.Fprintf(out, "Priority:\t%s\n", strconv.Itoa(*scc.Priority)) + } + + fmt.Fprintf(out, "Access:\t\n") + fmt.Fprintf(out, " Users:\t%s\n", stringOrNone(strings.Join(scc.Users, ","))) + fmt.Fprintf(out, " Groups:\t%s\n", stringOrNone(strings.Join(scc.Groups, ","))) + + fmt.Fprintf(out, "Settings:\t\n") + fmt.Fprintf(out, " Allow Privileged:\t%t\n", scc.AllowPrivilegedContainer) + fmt.Fprintf(out, " Default Add Capabilities:\t%s\n", capsToString(scc.DefaultAddCapabilities)) + fmt.Fprintf(out, " Required Drop Capabilities:\t%s\n", capsToString(scc.RequiredDropCapabilities)) + fmt.Fprintf(out, " Allowed Capabilities:\t%s\n", capsToString(scc.AllowedCapabilities)) + fmt.Fprintf(out, " Allow Host Dir Volumes:\t%t\n", scc.AllowHostDirVolumePlugin) + fmt.Fprintf(out, " Allow Host Network:\t%t\n", scc.AllowHostNetwork) + fmt.Fprintf(out, " Allow Host Ports:\t%t\n", scc.AllowHostPorts) + fmt.Fprintf(out, " Allow Host PID:\t%t\n", scc.AllowHostPID) + fmt.Fprintf(out, " Allow Host IPC:\t%t\n", scc.AllowHostIPC) + + fmt.Fprintf(out, " Run As User Strategy: %s\t\n", string(scc.RunAsUser.Type)) + uid := "" + if scc.RunAsUser.UID != nil { + uid = strconv.FormatInt(*scc.RunAsUser.UID, 10) + } + fmt.Fprintf(out, " UID:\t%s\n", stringOrNone(uid)) + + uidRangeMin := "" + if scc.RunAsUser.UIDRangeMin != nil { + uidRangeMin = strconv.FormatInt(*scc.RunAsUser.UIDRangeMin, 10) + } + fmt.Fprintf(out, " UID Range Min:\t%s\n", stringOrNone(uidRangeMin)) + + uidRangeMax := "" + if scc.RunAsUser.UIDRangeMax != nil { + uidRangeMax = strconv.FormatInt(*scc.RunAsUser.UIDRangeMax, 10) + } + fmt.Fprintf(out, " UID Range Max:\t%s\n", stringOrNone(uidRangeMax)) + + fmt.Fprintf(out, " SELinux Context Strategy: %s\t\n", string(scc.SELinuxContext.Type)) + var user, role, seLinuxType, level string + if scc.SELinuxContext.SELinuxOptions != nil { + user = scc.SELinuxContext.SELinuxOptions.User + role = scc.SELinuxContext.SELinuxOptions.Role + seLinuxType = scc.SELinuxContext.SELinuxOptions.Type + level = scc.SELinuxContext.SELinuxOptions.Level + } + fmt.Fprintf(out, " User:\t%s\n", stringOrNone(user)) + fmt.Fprintf(out, " Role:\t%s\n", stringOrNone(role)) + fmt.Fprintf(out, " Type:\t%s\n", stringOrNone(seLinuxType)) + fmt.Fprintf(out, " Level:\t%s\n", stringOrNone(level)) + + fmt.Fprintf(out, " FSGroup Strategy: %s\t\n", string(scc.FSGroup.Type)) + fmt.Fprintf(out, " Ranges:\t%s\n", idRangeToString(scc.FSGroup.Ranges)) + + fmt.Fprintf(out, " Supplemental Groups Strategy: %s\t\n", string(scc.SupplementalGroups.Type)) + fmt.Fprintf(out, " Ranges:\t%s\n", idRangeToString(scc.SupplementalGroups.Ranges)) + + return nil + }) +} + +func stringOrNone(s string) string { + if len(s) > 0 { + return s + } + return "" +} + +func idRangeToString(ranges []api.IDRange) string { + formattedString := "" + if ranges != nil { + strRanges := []string{} + for _, r := range ranges { + strRanges = append(strRanges, fmt.Sprintf("%d-%d", r.Min, r.Max)) + } + formattedString = strings.Join(strRanges, ",") + } + return stringOrNone(formattedString) +} + +func capsToString(caps []api.Capability) string { + formattedString := "" + if caps != nil { + strCaps := []string{} + for _, c := range caps { + strCaps = append(strCaps, string(c)) + } + formattedString = strings.Join(strCaps, ",") + } + return stringOrNone(formattedString) +} + // PodDescriber generates information about a pod and the replication controllers that // create it. type PodDescriber struct { diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/describe_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/describe_test.go index 43420fa144aa..0df1342df777 100644 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/describe_test.go +++ b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/describe_test.go @@ -521,3 +521,20 @@ func TestDescribeDeployment(t *testing.T) { t.Errorf("unexpected out: %s", out) } } + +func TestDescribeSCC(t *testing.T) { + scc := &api.SecurityContextConstraints{ + ObjectMeta: api.ObjectMeta{ + Name: "bar", + }, + } + fake := testclient.NewSimpleFake(scc) + d := SecurityContextConstraintsDescriber{fake} + out, err := d.Describe(scc.Namespace, scc.Name) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + if !strings.Contains(out, "bar") { + t.Errorf("unexpected out: %s", out) + } +}