Skip to content

Commit

Permalink
add service account to security context struct
Browse files Browse the repository at this point in the history
Signed-off-by: kaizhe <derek0405@gmail.com>
  • Loading branch information
Kaizhe committed Jan 8, 2020
1 parent 49d3faa commit c32b6fb
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 28 deletions.
59 changes: 40 additions & 19 deletions advisor/processor/get.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package processor

import (
"fmt"

"github.com/sysdiglabs/kube-psp-advisor/advisor/types"

"k8s.io/api/core/v1"
v12 "k8s.io/apimachinery/pkg/apis/meta/v1"
v1meta "k8s.io/apimachinery/pkg/apis/meta/v1"
)

const (
Expand All @@ -23,14 +25,15 @@ func (p *Processor) getSecuritySpecFromDaemonSets() ([]types.ContainerSecuritySp
cspList := []types.ContainerSecuritySpec{}
pspList := []types.PodSecuritySpec{}

daemonSetList, err := clientset.AppsV1().DaemonSets(p.namespace).List(v12.ListOptions{})
daemonSetList, err := clientset.AppsV1().DaemonSets(p.namespace).List(v1meta.ListOptions{})

if err != nil {
return cspList, pspList, err
}

for _, ds := range daemonSetList.Items {
sa := p.serviceAccountMap[ds.Spec.Template.Spec.ServiceAccountName]
sa := p.GetServiceAccount(ds.Namespace, ds.Spec.Template.Spec.ServiceAccountName)

cspList2, podSecurityPosture := p.gen.GetSecuritySpecFromPodSpec(types.Metadata{
Name: ds.Name,
Kind: DaemonSet,
Expand All @@ -48,7 +51,7 @@ func (p *Processor) getSecuritySpecFromReplicaSets() ([]types.ContainerSecurityS
cssList := []types.ContainerSecuritySpec{}
pssList := []types.PodSecuritySpec{}

replicaSetList, err := clientset.AppsV1().ReplicaSets(p.namespace).List(v12.ListOptions{})
replicaSetList, err := clientset.AppsV1().ReplicaSets(p.namespace).List(v1meta.ListOptions{})

if err != nil {
return cssList, pssList, err
Expand All @@ -59,7 +62,7 @@ func (p *Processor) getSecuritySpecFromReplicaSets() ([]types.ContainerSecurityS
continue
}

sa := p.serviceAccountMap[rs.Spec.Template.Spec.ServiceAccountName]
sa := p.GetServiceAccount(rs.Namespace, rs.Spec.Template.Spec.ServiceAccountName)
cspList2, psc := p.gen.GetSecuritySpecFromPodSpec(types.Metadata{
Name: rs.Name,
Kind: ReplicaSet,
Expand All @@ -77,14 +80,14 @@ func (p *Processor) getSecuritySpecFromStatefulSets() ([]types.ContainerSecurity
cssList := []types.ContainerSecuritySpec{}
pssList := []types.PodSecuritySpec{}

statefulSetList, err := clientset.AppsV1().StatefulSets(p.namespace).List(v12.ListOptions{})
statefulSetList, err := clientset.AppsV1().StatefulSets(p.namespace).List(v1meta.ListOptions{})

if err != nil {
return cssList, pssList, err
}

for _, sts := range statefulSetList.Items {
sa := p.serviceAccountMap[sts.Spec.Template.Spec.ServiceAccountName]
sa := p.GetServiceAccount(sts.Namespace, sts.Spec.Template.Spec.ServiceAccountName)
cspList2, pss := p.gen.GetSecuritySpecFromPodSpec(types.Metadata{
Name: sts.Name,
Kind: StatefulSet,
Expand All @@ -102,14 +105,14 @@ func (p *Processor) getSecuritySpecFromReplicationController() ([]types.Containe
cssList := []types.ContainerSecuritySpec{}
pssList := []types.PodSecuritySpec{}

replicationControllerList, err := clientset.CoreV1().ReplicationControllers(p.namespace).List(v12.ListOptions{})
replicationControllerList, err := clientset.CoreV1().ReplicationControllers(p.namespace).List(v1meta.ListOptions{})

if err != nil {
return cssList, pssList, err
}

for _, rc := range replicationControllerList.Items {
sa := p.serviceAccountMap[rc.Spec.Template.Spec.ServiceAccountName]
sa := p.GetServiceAccount(rc.Namespace, rc.Spec.Template.Spec.ServiceAccountName)
cspList2, pss := p.gen.GetSecuritySpecFromPodSpec(types.Metadata{
Name: rc.Name,
Kind: ReplicationController,
Expand All @@ -127,14 +130,14 @@ func (p *Processor) getSecuritySpecFromCronJobs() ([]types.ContainerSecuritySpec
cssList := []types.ContainerSecuritySpec{}
pssList := []types.PodSecuritySpec{}

jobList, err := clientset.BatchV1beta1().CronJobs(p.namespace).List(v12.ListOptions{})
jobList, err := clientset.BatchV1beta1().CronJobs(p.namespace).List(v1meta.ListOptions{})

if err != nil {
return cssList, pssList, err
}

for _, cronJob := range jobList.Items {
sa := p.serviceAccountMap[cronJob.Spec.JobTemplate.Spec.Template.Spec.ServiceAccountName]
sa := p.GetServiceAccount(cronJob.Namespace, cronJob.Spec.JobTemplate.Spec.Template.Spec.ServiceAccountName)
cspList2, pss := p.gen.GetSecuritySpecFromPodSpec(types.Metadata{
Name: cronJob.Name,
Kind: CronJob,
Expand All @@ -152,7 +155,7 @@ func (p *Processor) getSecuritySpecFromJobs() ([]types.ContainerSecuritySpec, []
cssList := []types.ContainerSecuritySpec{}
pssList := []types.PodSecuritySpec{}

jobList, err := clientset.BatchV1().Jobs(p.namespace).List(v12.ListOptions{})
jobList, err := clientset.BatchV1().Jobs(p.namespace).List(v1meta.ListOptions{})

if err != nil {
return cssList, pssList, err
Expand All @@ -162,7 +165,7 @@ func (p *Processor) getSecuritySpecFromJobs() ([]types.ContainerSecuritySpec, []
if len(job.OwnerReferences) > 0 {
continue
}
sa := p.serviceAccountMap[job.Spec.Template.Spec.ServiceAccountName]
sa := p.GetServiceAccount(job.Namespace, job.Spec.Template.Spec.ServiceAccountName)
cspList2, pss := p.gen.GetSecuritySpecFromPodSpec(types.Metadata{
Name: job.Name,
Kind: Job,
Expand All @@ -180,14 +183,14 @@ func (p *Processor) getSecuritySpecFromDeployments() ([]types.ContainerSecurityS
cssList := []types.ContainerSecuritySpec{}
pssList := []types.PodSecuritySpec{}

deployments, err := clientset.AppsV1().Deployments(p.namespace).List(v12.ListOptions{})
deployments, err := clientset.AppsV1().Deployments(p.namespace).List(v1meta.ListOptions{})

if err != nil {
return cssList, pssList, err
}

for _, deploy := range deployments.Items {
sa := p.serviceAccountMap[deploy.Spec.Template.Spec.ServiceAccountName]
sa := p.GetServiceAccount(deploy.Namespace, deploy.Spec.Template.Spec.ServiceAccountName)
cspList2, pss := p.gen.GetSecuritySpecFromPodSpec(types.Metadata{
Name: deploy.Name,
Kind: Deployment,
Expand All @@ -205,7 +208,7 @@ func (p *Processor) getSecuritySpecFromPods() ([]types.ContainerSecuritySpec, []
cssList := []types.ContainerSecuritySpec{}
pssList := []types.PodSecuritySpec{}

pods, err := clientset.CoreV1().Pods(p.namespace).List(v12.ListOptions{})
pods, err := clientset.CoreV1().Pods(p.namespace).List(v1meta.ListOptions{})

if err != nil {
return cssList, pssList, err
Expand All @@ -216,7 +219,7 @@ func (p *Processor) getSecuritySpecFromPods() ([]types.ContainerSecuritySpec, []
continue
}

sa := p.serviceAccountMap[pod.Spec.ServiceAccountName]
sa := p.GetServiceAccount(pod.Namespace, pod.Spec.ServiceAccountName)
cspList2, podSecurityPosture := p.gen.GetSecuritySpecFromPodSpec(types.Metadata{
Name: pod.Name,
Kind: Pod,
Expand All @@ -232,14 +235,32 @@ func (p *Processor) getSecuritySpecFromPods() ([]types.ContainerSecuritySpec, []
func (p *Processor) getServiceAccountMap() (map[string]v1.ServiceAccount, error) {
serviceAccountMap := map[string]v1.ServiceAccount{}

serviceAccounts, err := p.k8sClient.CoreV1().ServiceAccounts(p.namespace).List(v12.ListOptions{})
serviceAccounts, err := p.k8sClient.CoreV1().ServiceAccounts(p.namespace).List(v1meta.ListOptions{})
if err != nil {
return serviceAccountMap, err
}

// service account is an namespaced object
for _, sa := range serviceAccounts.Items {
serviceAccountMap[sa.Name] = sa
key := fmt.Sprintf("%s:%s", sa.Namespace, sa.Name)
serviceAccountMap[key] = sa
}

return serviceAccountMap, nil
}

func (p *Processor) GetServiceAccount(ns, saName string) v1.ServiceAccount {
if saName == "" {
saName = "default"
}

key := fmt.Sprintf("%s:%s", ns, saName)

sa, exists := p.serviceAccountMap[key]

if !exists {
return v1.ServiceAccount{}
}

return sa
}
2 changes: 2 additions & 0 deletions advisor/types/securityspec.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ type ContainerSecuritySpec struct {
RunAsUser *int64 `json:"runAsUser,omitempty"`
RunAsGroup *int64 `json:"runAsGroup,omitempty"`
HostPorts []int32 `json:"hostPorts,omitempty"`
ServiceAccount string `json:"serviceAccount,omitempty"`
}

type PodSecuritySpec struct {
Expand All @@ -67,6 +68,7 @@ type PodSecuritySpec struct {
HostIPC bool `json:"hostIPC,omitempty"`
VolumeTypes []string `json:"volumeTypes,omitempty"`
MountHostPaths map[string]bool `json:"mountedHostPath,omitempty"`
ServiceAccount string `json:"serviceAccount,omitempty"`
}

type Metadata struct {
Expand Down
28 changes: 19 additions & 9 deletions generator/generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ func getVolumeTypes(spec v1.PodSpec, sa *v1.ServiceAccount) (volumeTypes []strin
}
}

// If don't opt out of automounting API credentils for a service account
// If don't opt out of automounting API credentials for a service account
// or a particular pod, "secret" needs to be into PSP allowed volume types.
if sa == nil || mountServiceAccountToken(spec, *sa) {
volumeTypeMap[volumeTypeSecret] = true
Expand Down Expand Up @@ -257,6 +257,7 @@ func (pg *Generator) GetSecuritySpecFromPodSpec(metadata types.Metadata, namespa
HostIPC: spec.HostIPC,
VolumeTypes: getVolumeTypes(spec, sa),
MountHostPaths: getVolumeHostPaths(spec),
ServiceAccount: getServiceAccountName(spec),
}

for _, container := range spec.InitContainers {
Expand All @@ -278,6 +279,7 @@ func (pg *Generator) GetSecuritySpecFromPodSpec(metadata types.Metadata, namespa
RunAsGroup: getRunAsGroup(container.SecurityContext, spec.SecurityContext),
RunAsUser: getRunAsUser(container.SecurityContext, spec.SecurityContext),
HostPorts: getHostPorts(container.Ports),
ServiceAccount: getServiceAccountName(spec),
}
cssList = append(cssList, csc)
}
Expand All @@ -301,6 +303,7 @@ func (pg *Generator) GetSecuritySpecFromPodSpec(metadata types.Metadata, namespa
RunAsGroup: getRunAsGroup(container.SecurityContext, spec.SecurityContext),
RunAsUser: getRunAsUser(container.SecurityContext, spec.SecurityContext),
HostPorts: getHostPorts(container.Ports),
ServiceAccount: getServiceAccountName(spec),
}
cssList = append(cssList, csc)
}
Expand Down Expand Up @@ -389,7 +392,8 @@ func (pg *Generator) GeneratePSP(
runAsNonRootCount++
}

if sc.RunAsUser != nil {
// runAsUser is set and not to root
if sc.RunAsUser != nil && *sc.RunAsUser != 0 {
runAsUser[*sc.RunAsUser] = true
runAsUserCount++
}
Expand All @@ -399,7 +403,7 @@ func (pg *Generator) GeneratePSP(
}

// set host ports
// TODO: need to integrate with listening port during the runtime, might cause false positive.
//TODO: need to integrate with listening port during the runtime, might cause false positive.
//for _, port := range sc.HostPorts {
// psp.Spec.HostPorts = append(psp.Spec.HostPorts, v1beta1.HostPortRange{Min: port, Max: port})
//}
Expand All @@ -419,12 +423,10 @@ func (pg *Generator) GeneratePSP(
if runAsUserCount == len(cssList) {
psp.Spec.RunAsUser.Rule = v1beta1.RunAsUserStrategyMustRunAs
for uid := range runAsUser {
if psp.Spec.RunAsUser.Rule == v1beta1.RunAsUserStrategyMustRunAsNonRoot && uid != 0 {
psp.Spec.RunAsUser.Ranges = append(psp.Spec.RunAsUser.Ranges, v1beta1.IDRange{
Min: uid,
Max: uid,
})
}
psp.Spec.RunAsUser.Ranges = append(psp.Spec.RunAsUser.Ranges, v1beta1.IDRange{
Min: uid,
Max: uid,
})
}
}

Expand Down Expand Up @@ -647,3 +649,11 @@ func (pg *Generator) FromPodObjString(podObjString string) (string, error) {

return "", fmt.Errorf("K8s Object not one of supported types")
}

func getServiceAccountName(spec v1.PodSpec) string {
if spec.ServiceAccountName == "" {
return "default"
}

return spec.ServiceAccountName
}

0 comments on commit c32b6fb

Please sign in to comment.