|
| 1 | +package types |
| 2 | + |
| 3 | +import ( |
| 4 | + "fmt" |
| 5 | + |
| 6 | + "k8s.io/apimachinery/pkg/apis/meta/v1" |
| 7 | + |
| 8 | + "k8s.io/api/policy/v1beta1" |
| 9 | + v1rbac "k8s.io/api/rbac/v1" |
| 10 | +) |
| 11 | + |
| 12 | +const ( |
| 13 | + rbacV1APIVersion = "rbac.authorization.k8s.io/v1" |
| 14 | + rbacAPIGroup = "rbac.authorization.k8s.io" |
| 15 | + Role = "Role" |
| 16 | + RoleBinding = "RoleBinding" |
| 17 | + ServiceAccount = "ServiceAccount" |
| 18 | +) |
| 19 | + |
| 20 | +type SASecuritySpecList []*SASecuritySpec |
| 21 | + |
| 22 | +func (sl SASecuritySpecList) Less(i, j int) bool { |
| 23 | + keyI := fmt.Sprintf("%s:%s", sl[i].Namespace, sl[i].ServiceAccount) |
| 24 | + keyJ := fmt.Sprintf("%s:%s", sl[j].Namespace, sl[j].ServiceAccount) |
| 25 | + |
| 26 | + return keyI < keyJ |
| 27 | +} |
| 28 | + |
| 29 | +func (sl SASecuritySpecList) Len() int { return len(sl) } |
| 30 | + |
| 31 | +func (sl SASecuritySpecList) Swap(i, j int) { sl[i], sl[j] = sl[j], sl[i] } |
| 32 | + |
| 33 | +type SASecuritySpec struct { |
| 34 | + PSPName string // psp name |
| 35 | + |
| 36 | + ServiceAccount string // serviceAccount |
| 37 | + |
| 38 | + Namespace string // namespace |
| 39 | + |
| 40 | + ContainerSecuritySpecList []ContainerSecuritySpec |
| 41 | + |
| 42 | + PodSecuritySpecList []PodSecuritySpec |
| 43 | +} |
| 44 | + |
| 45 | +func NewSASecuritySpec(ns, sa string) *SASecuritySpec { |
| 46 | + return &SASecuritySpec{ |
| 47 | + ServiceAccount: sa, |
| 48 | + Namespace: ns, |
| 49 | + ContainerSecuritySpecList: []ContainerSecuritySpec{}, |
| 50 | + PodSecuritySpecList: []PodSecuritySpec{}, |
| 51 | + } |
| 52 | +} |
| 53 | + |
| 54 | +func (s *SASecuritySpec) IsDefaultServiceAccount() bool { |
| 55 | + return s.ServiceAccount == "default" |
| 56 | +} |
| 57 | + |
| 58 | +func (s *SASecuritySpec) AddContainerSecuritySpec(css ContainerSecuritySpec) { |
| 59 | + s.ContainerSecuritySpecList = append(s.ContainerSecuritySpecList, css) |
| 60 | +} |
| 61 | + |
| 62 | +func (s *SASecuritySpec) AddPodSecuritySpec(pss PodSecuritySpec) { |
| 63 | + s.PodSecuritySpecList = append(s.PodSecuritySpecList, pss) |
| 64 | +} |
| 65 | + |
| 66 | +func (s *SASecuritySpec) GeneratePSPName() string { |
| 67 | + if s.PSPName == "" { |
| 68 | + s.PSPName = fmt.Sprintf("psp-for-%s-%s", s.Namespace, s.ServiceAccount) |
| 69 | + } |
| 70 | + |
| 71 | + return s.PSPName |
| 72 | +} |
| 73 | + |
| 74 | +func (s *SASecuritySpec) GenerateComment() string { |
| 75 | + decision := "will be" |
| 76 | + |
| 77 | + if s.IsDefaultServiceAccount() { |
| 78 | + decision = "will not be" |
| 79 | + } |
| 80 | + |
| 81 | + return fmt.Sprintf("# Pod security policies %s created for service account: %s in namespace %s for images: %s", decision, s.ServiceAccount, s.Namespace, s.GetImages()) |
| 82 | +} |
| 83 | + |
| 84 | +func (s *SASecuritySpec) GetImages() []string { |
| 85 | + imageList := []string{} |
| 86 | + |
| 87 | + for _, css := range s.ContainerSecuritySpecList { |
| 88 | + imageList = append(imageList, css.ImageName) |
| 89 | + } |
| 90 | + |
| 91 | + return imageList |
| 92 | +} |
| 93 | + |
| 94 | +func (s *SASecuritySpec) GenerateRole() *v1rbac.Role { |
| 95 | + roleName := fmt.Sprintf("use-psp-by-%s:%s", s.Namespace, s.ServiceAccount) |
| 96 | + |
| 97 | + rule := v1rbac.PolicyRule{ |
| 98 | + Verbs: []string{"use"}, |
| 99 | + APIGroups: []string{"policy"}, |
| 100 | + Resources: []string{"podsecuritypolicies"}, |
| 101 | + ResourceNames: []string{s.GeneratePSPName()}, |
| 102 | + } |
| 103 | + |
| 104 | + return &v1rbac.Role{ |
| 105 | + TypeMeta: v1.TypeMeta{ |
| 106 | + Kind: Role, |
| 107 | + APIVersion: rbacV1APIVersion, |
| 108 | + }, |
| 109 | + ObjectMeta: v1.ObjectMeta{ |
| 110 | + Namespace: s.Namespace, |
| 111 | + Name: roleName, |
| 112 | + }, |
| 113 | + Rules: []v1rbac.PolicyRule{rule}, |
| 114 | + } |
| 115 | +} |
| 116 | + |
| 117 | +func (s *SASecuritySpec) GenerateRoleBinding() *v1rbac.RoleBinding { |
| 118 | + roleBindingName := fmt.Sprintf("use-psp-by-%s:%s-binding", s.Namespace, s.ServiceAccount) |
| 119 | + roleName := fmt.Sprintf("use-psp-by-%s:%s", s.Namespace, s.ServiceAccount) |
| 120 | + |
| 121 | + return &v1rbac.RoleBinding{ |
| 122 | + TypeMeta: v1.TypeMeta{ |
| 123 | + Kind: RoleBinding, |
| 124 | + APIVersion: rbacV1APIVersion, |
| 125 | + }, |
| 126 | + ObjectMeta: v1.ObjectMeta{ |
| 127 | + Namespace: s.Namespace, |
| 128 | + Name: roleBindingName, |
| 129 | + }, |
| 130 | + Subjects: []v1rbac.Subject{ |
| 131 | + {Kind: ServiceAccount, Name: s.ServiceAccount, Namespace: s.Namespace}, |
| 132 | + }, |
| 133 | + RoleRef: v1rbac.RoleRef{ |
| 134 | + APIGroup: rbacAPIGroup, |
| 135 | + Kind: Role, |
| 136 | + Name: roleName, |
| 137 | + }, |
| 138 | + } |
| 139 | +} |
| 140 | + |
| 141 | +type PSPGrant struct { |
| 142 | + Comment string |
| 143 | + PodSecurityPolicy *v1beta1.PodSecurityPolicy |
| 144 | + Role *v1rbac.Role |
| 145 | + RoleBinding *v1rbac.RoleBinding |
| 146 | +} |
0 commit comments