mirror of
https://github.com/kyverno/kyverno.git
synced 2024-12-15 17:51:20 +00:00
0fb8c723fe
Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>
102 lines
2.9 KiB
Go
102 lines
2.9 KiB
Go
package userinfo
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
authenticationv1 "k8s.io/api/authentication/v1"
|
|
rbacv1 "k8s.io/api/rbac/v1"
|
|
labels "k8s.io/apimachinery/pkg/labels"
|
|
"k8s.io/apimachinery/pkg/util/sets"
|
|
)
|
|
|
|
const (
|
|
clusterroleKind = "ClusterRole"
|
|
roleKind = "Role"
|
|
)
|
|
|
|
type RoleBindingLister interface {
|
|
List(labels.Selector) ([]*rbacv1.RoleBinding, error)
|
|
}
|
|
|
|
type ClusterRoleBindingLister interface {
|
|
List(labels.Selector) ([]*rbacv1.ClusterRoleBinding, error)
|
|
}
|
|
|
|
// GetRoleRef gets the list of roles and cluster roles for the incoming api-request
|
|
func GetRoleRef(rbLister RoleBindingLister, crbLister ClusterRoleBindingLister, userInfo authenticationv1.UserInfo) ([]string, []string, error) {
|
|
// rolebindings
|
|
roleBindings, err := rbLister.List(labels.Everything())
|
|
if err != nil {
|
|
return nil, nil, fmt.Errorf("failed to list rolebindings: %v", err)
|
|
}
|
|
rs, crs := getRoleRefByRoleBindings(roleBindings, userInfo)
|
|
// clusterrolebindings
|
|
clusterroleBindings, err := crbLister.List(labels.Everything())
|
|
if err != nil {
|
|
return nil, nil, fmt.Errorf("failed to list clusterrolebindings: %v", err)
|
|
}
|
|
crs = append(crs, getRoleRefByClusterRoleBindings(clusterroleBindings, userInfo)...)
|
|
if rs != nil {
|
|
rs = sets.List(sets.New(rs...))
|
|
}
|
|
if crs != nil {
|
|
crs = sets.List(sets.New(crs...))
|
|
}
|
|
return rs, crs, nil
|
|
}
|
|
|
|
func getRoleRefByRoleBindings(roleBindings []*rbacv1.RoleBinding, userInfo authenticationv1.UserInfo) ([]string, []string) {
|
|
var roles, clusterRoles []string
|
|
for _, rolebinding := range roleBindings {
|
|
if matchBindingSubjects(rolebinding.Subjects, userInfo, rolebinding.Namespace) {
|
|
switch rolebinding.RoleRef.Kind {
|
|
case roleKind:
|
|
roles = append(roles, rolebinding.Namespace+":"+rolebinding.RoleRef.Name)
|
|
case clusterroleKind:
|
|
clusterRoles = append(clusterRoles, rolebinding.RoleRef.Name)
|
|
}
|
|
}
|
|
}
|
|
return roles, clusterRoles
|
|
}
|
|
|
|
func getRoleRefByClusterRoleBindings(clusterroleBindings []*rbacv1.ClusterRoleBinding, userInfo authenticationv1.UserInfo) []string {
|
|
var clusterRoles []string
|
|
for _, clusterRoleBinding := range clusterroleBindings {
|
|
if matchBindingSubjects(clusterRoleBinding.Subjects, userInfo, "") {
|
|
if clusterRoleBinding.RoleRef.Kind == clusterroleKind {
|
|
clusterRoles = append(clusterRoles, clusterRoleBinding.RoleRef.Name)
|
|
}
|
|
}
|
|
}
|
|
return clusterRoles
|
|
}
|
|
|
|
func matchBindingSubjects(subjects []rbacv1.Subject, userInfo authenticationv1.UserInfo, namespace string) bool {
|
|
for _, subject := range subjects {
|
|
switch subject.Kind {
|
|
case rbacv1.ServiceAccountKind:
|
|
ns := subject.Namespace
|
|
if ns == "" {
|
|
ns = namespace
|
|
}
|
|
if ns != "" {
|
|
username := "system:serviceaccount:" + ns + ":" + subject.Name
|
|
if userInfo.Username == username {
|
|
return true
|
|
}
|
|
}
|
|
case rbacv1.GroupKind:
|
|
for _, group := range userInfo.Groups {
|
|
if group == subject.Name {
|
|
return true
|
|
}
|
|
}
|
|
case rbacv1.UserKind:
|
|
if userInfo.Username == subject.Name {
|
|
return true
|
|
}
|
|
}
|
|
}
|
|
return false
|
|
}
|