mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-28 10:28:36 +00:00
validation added for deny request for generated resource
This commit is contained in:
parent
85d2ac9f84
commit
014db64ed2
3 changed files with 104 additions and 31 deletions
|
@ -272,6 +272,8 @@ func main() {
|
|||
pInformer.Kyverno().V1().ClusterPolicies(),
|
||||
kubeInformer.Rbac().V1().RoleBindings(),
|
||||
kubeInformer.Rbac().V1().ClusterRoleBindings(),
|
||||
kubeInformer.Rbac().V1().Roles(),
|
||||
kubeInformer.Rbac().V1().ClusterRoles(),
|
||||
eventGenerator,
|
||||
pCacheController.Cache,
|
||||
webhookRegistrationClient,
|
||||
|
|
|
@ -20,6 +20,8 @@ const (
|
|||
SaPrefix = "system:serviceaccount:"
|
||||
)
|
||||
|
||||
var defaultSuffixs = []string{"system:","kyverno:"}
|
||||
|
||||
//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) {
|
||||
keys := append(request.UserInfo.Groups, request.UserInfo.Username)
|
||||
|
@ -127,3 +129,51 @@ func matchUserOrGroup(subject rbacv1.Subject, userInfo authenticationv1.UserInfo
|
|||
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
//IsRoleAuthorize is role authorize or not
|
||||
func IsRoleAuthorize(rbLister rbaclister.RoleBindingLister, crbLister rbaclister.ClusterRoleBindingLister,rLister rbaclister.RoleLister, crLister rbaclister.ClusterRoleLister, request *v1beta1.AdmissionRequest) (bool,error) {
|
||||
|
||||
if strings.Contains(request.UserInfo.Username, SaPrefix) {
|
||||
roles,clusterRoles,err := GetRoleRef(rbLister,crbLister,request)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
for _,e := range clusterRoles {
|
||||
role,err := crLister.Get(e);
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
labels := role.GetLabels()
|
||||
if labels["kubernetes.io/bootstrapping"] == "rbac-defaults" {
|
||||
return true,nil
|
||||
}
|
||||
}
|
||||
for _,e := range roles {
|
||||
roleData := strings.Split(e, ":")
|
||||
role, err := rLister.Roles(roleData[0]).Get(roleData[1]);
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
labels := role.GetLabels()
|
||||
if labels["kubernetes.io/bootstrapping"] == "rbac-defaults" {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// User or Group
|
||||
var matchedRoles []bool
|
||||
for _,e := range request.UserInfo.Groups {
|
||||
for _,defaultSuffix := range defaultSuffixs {
|
||||
if strings.Contains(e,defaultSuffix) {
|
||||
matchedRoles = append(matchedRoles, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(matchedRoles) == len(request.UserInfo.Groups) {
|
||||
return true,nil
|
||||
}
|
||||
}
|
||||
|
||||
return false,nil
|
||||
}
|
|
@ -8,6 +8,7 @@ import (
|
|||
"fmt"
|
||||
"io/ioutil"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
|
@ -54,6 +55,12 @@ type WebhookServer struct {
|
|||
// list/get role binding resource
|
||||
rbLister rbaclister.RoleBindingLister
|
||||
|
||||
// list/get role binding resource
|
||||
rLister rbaclister.RoleLister
|
||||
|
||||
// list/get role binding resource
|
||||
crLister rbaclister.ClusterRoleLister
|
||||
|
||||
// return true if role bining store has synced atleast once
|
||||
rbSynced cache.InformerSynced
|
||||
|
||||
|
@ -106,6 +113,8 @@ func NewWebhookServer(
|
|||
pInformer kyvernoinformer.ClusterPolicyInformer,
|
||||
rbInformer rbacinformer.RoleBindingInformer,
|
||||
crbInformer rbacinformer.ClusterRoleBindingInformer,
|
||||
rInformer rbacinformer.RoleInformer,
|
||||
crInformer rbacinformer.ClusterRoleInformer,
|
||||
eventGen event.Interface,
|
||||
pCache policycache.Interface,
|
||||
webhookRegistrationClient *webhookconfig.WebhookRegistrationClient,
|
||||
|
@ -137,8 +146,10 @@ func NewWebhookServer(
|
|||
pLister: pInformer.Lister(),
|
||||
pSynced: pInformer.Informer().HasSynced,
|
||||
rbLister: rbInformer.Lister(),
|
||||
rLister: rInformer.Lister(),
|
||||
rbSynced: rbInformer.Informer().HasSynced,
|
||||
crbLister: crbInformer.Lister(),
|
||||
crLister: crInformer.Lister(),
|
||||
crbSynced: crbInformer.Informer().HasSynced,
|
||||
eventGen: eventGen,
|
||||
pCache: pCache,
|
||||
|
@ -366,27 +377,25 @@ func (ws *WebhookServer) resourceMutation(request *v1beta1.AdmissionRequest) *v1
|
|||
|
||||
func (ws *WebhookServer) resourceValidation(request *v1beta1.AdmissionRequest) *v1beta1.AdmissionResponse {
|
||||
logger := ws.log.WithName("resourceValidation").WithValues("uid", request.UID, "kind", request.Kind.Kind, "namespace", request.Namespace, "name", request.Name, "operation", request.Operation)
|
||||
logger.V(4).Info("DEBUG","request",request)
|
||||
checked, err := userinfo.IsRoleAuthorize(ws.rbLister, ws.crbLister,ws.rLister, ws.crLister, request)
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to get RBAC infromation for request")
|
||||
}
|
||||
|
||||
if request.Operation == v1beta1.Delete || request.Operation == v1beta1.Update {
|
||||
// convert RAW to unstructured
|
||||
resource, err := enginutils.ConvertToUnstructured(request.Object.Raw)
|
||||
if err != nil {
|
||||
//TODO: skip applying the admission control ?
|
||||
logger.Error(err, "failed to convert RAR resource to unstructured format")
|
||||
|
||||
return &v1beta1.AdmissionResponse{
|
||||
Allowed: false,
|
||||
Result: &metav1.Status{
|
||||
Status: "Failure",
|
||||
Message: err.Error(),
|
||||
},
|
||||
if !checked {
|
||||
if request.Operation == v1beta1.Delete || request.Operation == v1beta1.Update {
|
||||
// convert RAW to unstructured
|
||||
var resource *unstructured.Unstructured
|
||||
if request.Operation == v1beta1.Delete {
|
||||
resource, err = enginutils.ConvertToUnstructured(request.OldObject.Raw)
|
||||
}else{
|
||||
resource, err = enginutils.ConvertToUnstructured(request.Object.Raw)
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
//TODO: skip applying the admission control ?
|
||||
logger.Error(err, "failed to convert RAR resource to unstructured format")
|
||||
|
||||
oldResource, err := ws.client.GetResource(resource.GetKind(),resource.GetNamespace(),resource.GetName());
|
||||
if err != nil {
|
||||
if !apierrors.IsNotFound(err) {
|
||||
logger.Error(err, "failed to get resource")
|
||||
return &v1beta1.AdmissionResponse{
|
||||
Allowed: false,
|
||||
Result: &metav1.Status{
|
||||
|
@ -395,22 +404,35 @@ func (ws *WebhookServer) resourceValidation(request *v1beta1.AdmissionRequest) *
|
|||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
labels := oldResource.GetLabels()
|
||||
if labels != nil {
|
||||
if labels["app.kubernetes.io/managed-by"] == "kyverno" && labels["app.kubernetes.io/synchronize"] == "enable" {
|
||||
return &v1beta1.AdmissionResponse{
|
||||
Allowed: false,
|
||||
Result: &metav1.Status{
|
||||
Status: "Failure",
|
||||
Message: "You don't have permission to update resourses that is generated by kyverno",
|
||||
},
|
||||
|
||||
oldResource, err := ws.client.GetResource(resource.GetKind(),resource.GetNamespace(),resource.GetName());
|
||||
if err != nil {
|
||||
if !apierrors.IsNotFound(err) {
|
||||
logger.Error(err, "failed to get resource")
|
||||
return &v1beta1.AdmissionResponse{
|
||||
Allowed: false,
|
||||
Result: &metav1.Status{
|
||||
Status: "Failure",
|
||||
Message: err.Error(),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
labels := oldResource.GetLabels()
|
||||
if labels != nil {
|
||||
if labels["app.kubernetes.io/managed-by"] == "kyverno" && labels["app.kubernetes.io/synchronize"] == "enable" {
|
||||
return &v1beta1.AdmissionResponse{
|
||||
Allowed: false,
|
||||
Result: &metav1.Status{
|
||||
Status: "Failure",
|
||||
Message: "You don't have permission to update resourses that is generated by kyverno",
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if !ws.supportMudateValidate {
|
||||
logger.Info("mutate and validate rules are not supported prior to Kubernetes 1.14.0")
|
||||
return &v1beta1.AdmissionResponse{
|
||||
|
@ -437,7 +459,6 @@ func (ws *WebhookServer) resourceValidation(request *v1beta1.AdmissionRequest) *
|
|||
}
|
||||
|
||||
var roles, clusterRoles []string
|
||||
var err error
|
||||
// getRoleRef only if policy has roles/clusterroles defined
|
||||
if containRBACinfo(policies) {
|
||||
roles, clusterRoles, err = userinfo.GetRoleRef(ws.rbLister, ws.crbLister, request)
|
||||
|
|
Loading…
Add table
Reference in a new issue