2019-11-11 14:52:09 -08:00
|
|
|
package userinfo
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
2020-07-10 15:23:07 -07:00
|
|
|
|
2020-10-07 11:12:31 -07:00
|
|
|
"github.com/kyverno/kyverno/pkg/config"
|
2022-12-22 07:39:54 +01:00
|
|
|
datautils "github.com/kyverno/kyverno/pkg/utils/data"
|
2022-04-06 22:43:07 +02:00
|
|
|
admissionv1 "k8s.io/api/admission/v1"
|
2019-11-11 14:52:09 -08:00
|
|
|
authenticationv1 "k8s.io/api/authentication/v1"
|
2019-11-11 15:43:13 -08:00
|
|
|
rbacv1 "k8s.io/api/rbac/v1"
|
|
|
|
labels "k8s.io/apimachinery/pkg/labels"
|
2022-05-17 17:51:03 +02:00
|
|
|
rbacv1listers "k8s.io/client-go/listers/rbac/v1"
|
2019-11-11 14:52:09 -08:00
|
|
|
)
|
|
|
|
|
2019-11-14 15:49:11 -08:00
|
|
|
const (
|
2022-04-11 10:47:18 +02:00
|
|
|
clusterroleKind = "ClusterRole"
|
|
|
|
roleKind = "Role"
|
2019-11-14 15:49:11 -08:00
|
|
|
)
|
|
|
|
|
2022-05-17 08:19:03 +02:00
|
|
|
// GetRoleRef gets the list of roles and cluster roles for the incoming api-request
|
2022-05-17 17:51:03 +02:00
|
|
|
func GetRoleRef(rbLister rbacv1listers.RoleBindingLister, crbLister rbacv1listers.ClusterRoleBindingLister, request *admissionv1.AdmissionRequest, dynamicConfig config.Configuration) ([]string, []string, error) {
|
2020-05-19 00:14:23 -07:00
|
|
|
keys := append(request.UserInfo.Groups, request.UserInfo.Username)
|
2022-12-22 07:39:54 +01:00
|
|
|
if datautils.SliceContains(keys, dynamicConfig.GetExcludeGroupRole()...) {
|
2022-04-11 10:47:18 +02:00
|
|
|
return nil, nil, nil
|
2020-05-19 00:14:23 -07:00
|
|
|
}
|
2019-11-11 15:43:13 -08:00
|
|
|
// rolebindings
|
2022-04-11 10:47:18 +02:00
|
|
|
roleBindings, err := rbLister.List(labels.Everything())
|
2019-11-11 14:52:09 -08:00
|
|
|
if err != nil {
|
2022-04-11 10:47:18 +02:00
|
|
|
return nil, nil, fmt.Errorf("failed to list rolebindings: %v", err)
|
2019-11-11 14:52:09 -08:00
|
|
|
}
|
2022-04-11 10:47:18 +02:00
|
|
|
rs, crs := getRoleRefByRoleBindings(roleBindings, request.UserInfo)
|
2019-11-11 14:52:09 -08:00
|
|
|
// clusterrolebindings
|
2023-02-20 12:06:49 +01:00
|
|
|
clusterroleBindings, err := crbLister.List(labels.Everything())
|
2019-11-11 14:52:09 -08:00
|
|
|
if err != nil {
|
2022-04-11 10:47:18 +02:00
|
|
|
return nil, nil, fmt.Errorf("failed to list clusterrolebindings: %v", err)
|
2019-11-11 14:52:09 -08:00
|
|
|
}
|
2022-04-11 10:47:18 +02:00
|
|
|
crs = append(crs, getRoleRefByClusterRoleBindings(clusterroleBindings, request.UserInfo)...)
|
|
|
|
return rs, crs, nil
|
2019-11-11 14:52:09 -08:00
|
|
|
}
|
|
|
|
|
2022-04-11 10:47:18 +02:00
|
|
|
func getRoleRefByRoleBindings(roleBindings []*rbacv1.RoleBinding, userInfo authenticationv1.UserInfo) (roles []string, clusterRoles []string) {
|
2019-11-11 15:43:13 -08:00
|
|
|
for _, rolebinding := range roleBindings {
|
2023-02-21 17:57:17 +01:00
|
|
|
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)
|
2019-11-11 14:52:09 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-04-11 10:47:18 +02:00
|
|
|
return roles, clusterRoles
|
2019-11-11 14:52:09 -08:00
|
|
|
}
|
|
|
|
|
2022-04-11 10:47:18 +02:00
|
|
|
func getRoleRefByClusterRoleBindings(clusterroleBindings []*rbacv1.ClusterRoleBinding, userInfo authenticationv1.UserInfo) (clusterRoles []string) {
|
2019-11-11 15:43:13 -08:00
|
|
|
for _, clusterRoleBinding := range clusterroleBindings {
|
2023-02-21 17:57:17 +01:00
|
|
|
if matchBindingSubjects(clusterRoleBinding.Subjects, userInfo, "") {
|
|
|
|
if clusterRoleBinding.RoleRef.Kind == clusterroleKind {
|
|
|
|
clusterRoles = append(clusterRoles, clusterRoleBinding.RoleRef.Name)
|
2019-11-11 14:52:09 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-04-11 10:47:18 +02:00
|
|
|
return clusterRoles
|
2019-11-11 14:52:09 -08:00
|
|
|
}
|
|
|
|
|
2023-02-21 17:57:17 +01:00
|
|
|
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
|
|
|
|
}
|
2019-11-11 14:52:09 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|