1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2024-12-14 11:57:48 +00:00
kyverno/pkg/userinfo/roleRef.go
Shivkumar Dudhani 8c1d79ab28
linter suggestions (#655)
* cleanup phase 1

* linter fixes phase 2
2020-01-24 12:05:53 -08:00

129 lines
4.1 KiB
Go

package userinfo
import (
"fmt"
"strings"
"github.com/golang/glog"
"github.com/nirmata/kyverno/pkg/engine/rbac"
v1beta1 "k8s.io/api/admission/v1beta1"
authenticationv1 "k8s.io/api/authentication/v1"
rbacv1 "k8s.io/api/rbac/v1"
labels "k8s.io/apimachinery/pkg/labels"
rbaclister "k8s.io/client-go/listers/rbac/v1"
)
const (
clusterrolekind = "ClusterRole"
rolekind = "Role"
)
//GetRoleRef gets the list of roles and cluster roles for the incoming api-request
func GetRoleRef(rbLister rbaclister.RoleBindingLister, crbLister rbaclister.ClusterRoleBindingLister, request *v1beta1.AdmissionRequest) (roles []string, clusterRoles []string, err error) {
// rolebindings
roleBindings, err := rbLister.List(labels.NewSelector())
if err != nil {
return roles, clusterRoles, fmt.Errorf("failed to list rolebindings: %v", err)
}
rs, crs, err := getRoleRefByRoleBindings(roleBindings, request.UserInfo)
if err != nil {
return roles, clusterRoles, err
}
roles = append(roles, rs...)
clusterRoles = append(clusterRoles, crs...)
// clusterrolebindings
clusterroleBindings, err := crbLister.List(labels.NewSelector())
if err != nil {
return roles, clusterRoles, fmt.Errorf("failed to list clusterrolebindings: %v", err)
}
crs, err = getRoleRefByClusterRoleBindings(clusterroleBindings, request.UserInfo)
if err != nil {
return roles, clusterRoles, err
}
clusterRoles = append(clusterRoles, crs...)
return roles, clusterRoles, nil
}
func getRoleRefByRoleBindings(roleBindings []*rbacv1.RoleBinding, userInfo authenticationv1.UserInfo) (roles []string, clusterRoles []string, err error) {
for _, rolebinding := range roleBindings {
for _, subject := range rolebinding.Subjects {
if !matchSubjectsMap(subject, userInfo) {
continue
}
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, nil
}
// RoleRef in ClusterRoleBindings can only reference a ClusterRole in the global namespace
func getRoleRefByClusterRoleBindings(clusterroleBindings []*rbacv1.ClusterRoleBinding, userInfo authenticationv1.UserInfo) (clusterRoles []string, err error) {
for _, clusterRoleBinding := range clusterroleBindings {
for _, subject := range clusterRoleBinding.Subjects {
if !matchSubjectsMap(subject, userInfo) {
continue
}
if clusterRoleBinding.RoleRef.Kind == clusterrolekind {
clusterRoles = append(clusterRoles, clusterRoleBinding.RoleRef.Name)
}
}
}
return clusterRoles, nil
}
// matchSubjectsMap checks if userInfo found in subject
// return true directly if found a match
// subject.kind can only be ServiceAccount, User and Group
func matchSubjectsMap(subject rbacv1.Subject, userInfo authenticationv1.UserInfo) bool {
// ServiceAccount
if isServiceaccountUserInfo(userInfo.Username) {
return matchServiceAccount(subject, userInfo)
}
// User or Group
return matchUserOrGroup(subject, userInfo)
}
func isServiceaccountUserInfo(username string) bool {
if strings.Contains(username, rbac.SaPrefix) {
return true
}
return false
}
// matchServiceAccount checks if userInfo sa matche the subject sa
// serviceaccount represents as saPrefix:namespace:name in userInfo
func matchServiceAccount(subject rbacv1.Subject, userInfo authenticationv1.UserInfo) bool {
subjectServiceAccount := subject.Namespace + ":" + subject.Name
if userInfo.Username[len(rbac.SaPrefix):] != subjectServiceAccount {
glog.V(3).Infof("service account not match, expect %s, got %s", subjectServiceAccount, userInfo.Username[len(rbac.SaPrefix):])
return false
}
return true
}
// matchUserOrGroup checks if userInfo contains user or group info in a subject
func matchUserOrGroup(subject rbacv1.Subject, userInfo authenticationv1.UserInfo) bool {
keys := append(userInfo.Groups, userInfo.Username)
for _, key := range keys {
if subject.Name == key {
return true
}
}
glog.V(3).Infof("user/group '%v' info not found in request userInfo: %v", subject.Name, keys)
return false
}