1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-15 12:17:56 +00:00

code fixes

This commit is contained in:
evalsocket 2020-07-10 16:59:17 -07:00
parent 8cf5cd70fe
commit a64789c59d
2 changed files with 95 additions and 89 deletions

View file

@ -141,7 +141,7 @@ func IsRoleAuthorize(rbLister rbaclister.RoleBindingLister, crbLister rbaclister
for _, e := range clusterRoles { for _, e := range clusterRoles {
if strings.Contains(e, "kyverno:") { if strings.Contains(e, "kyverno:") {
return true, nil return true, nil
} else { }
role, err := crLister.Get(e) role, err := crLister.Get(e)
if err != nil { if err != nil {
return false, err return false, err
@ -152,7 +152,6 @@ func IsRoleAuthorize(rbLister rbaclister.RoleBindingLister, crbLister rbaclister
return true, nil return true, nil
} }
} }
}
for _, e := range roles { for _, e := range roles {
roleData := strings.Split(e, ":") roleData := strings.Split(e, ":")
role, err := rLister.Roles(roleData[0]).Get(roleData[1]) role, err := rLister.Roles(roleData[0]).Get(roleData[1])
@ -166,7 +165,7 @@ func IsRoleAuthorize(rbLister rbaclister.RoleBindingLister, crbLister rbaclister
} }
} }
} }
} else { }
// User or Group // User or Group
excludeDevelopmentRole := []string{"minikube-user", "kubernetes-admin"} excludeDevelopmentRole := []string{"minikube-user", "kubernetes-admin"}
for _, e := range excludeDevelopmentRole { for _, e := range excludeDevelopmentRole {
@ -186,7 +185,6 @@ func IsRoleAuthorize(rbLister rbaclister.RoleBindingLister, crbLister rbaclister
if len(matchedRoles) == len(request.UserInfo.Groups) { if len(matchedRoles) == len(request.UserInfo.Groups) {
return true, nil return true, nil
} }
}
return false, nil return false, nil
} }

View file

@ -10,13 +10,13 @@ import (
"net/http" "net/http"
"time" "time"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"github.com/go-logr/logr" "github.com/go-logr/logr"
"github.com/julienschmidt/httprouter" "github.com/julienschmidt/httprouter"
v1 "github.com/nirmata/kyverno/pkg/api/kyverno/v1" v1 "github.com/nirmata/kyverno/pkg/api/kyverno/v1"
"github.com/nirmata/kyverno/pkg/checker" "github.com/nirmata/kyverno/pkg/checker"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
kyvernoclient "github.com/nirmata/kyverno/pkg/client/clientset/versioned" kyvernoclient "github.com/nirmata/kyverno/pkg/client/clientset/versioned"
kyvernoinformer "github.com/nirmata/kyverno/pkg/client/informers/externalversions/kyverno/v1" kyvernoinformer "github.com/nirmata/kyverno/pkg/client/informers/externalversions/kyverno/v1"
kyvernolister "github.com/nirmata/kyverno/pkg/client/listers/kyverno/v1" kyvernolister "github.com/nirmata/kyverno/pkg/client/listers/kyverno/v1"
@ -65,12 +65,18 @@ type WebhookServer struct {
// return true if role bining store has synced atleast once // return true if role bining store has synced atleast once
rbSynced cache.InformerSynced rbSynced cache.InformerSynced
// return true if role store has synced atleast once
rSynced cache.InformerSynced
// list/get cluster role binding resource // list/get cluster role binding resource
crbLister rbaclister.ClusterRoleBindingLister crbLister rbaclister.ClusterRoleBindingLister
// return true if cluster role binding store has synced atleast once // return true if cluster role binding store has synced atleast once
crbSynced cache.InformerSynced crbSynced cache.InformerSynced
// return true if cluster role store has synced atleast once
crSynced cache.InformerSynced
// generate events // generate events
eventGen event.Interface eventGen event.Interface
@ -151,11 +157,14 @@ func NewWebhookServer(
pLister: pInformer.Lister(), pLister: pInformer.Lister(),
pSynced: pInformer.Informer().HasSynced, pSynced: pInformer.Informer().HasSynced,
rbLister: rbInformer.Lister(), rbLister: rbInformer.Lister(),
rLister: rInformer.Lister(),
rbSynced: rbInformer.Informer().HasSynced, rbSynced: rbInformer.Informer().HasSynced,
rLister: rInformer.Lister(),
rSynced: rInformer.Informer().HasSynced,
crbLister: crbInformer.Lister(), crbLister: crbInformer.Lister(),
crLister: crInformer.Lister(), crLister: crInformer.Lister(),
crbSynced: crbInformer.Informer().HasSynced, crbSynced: crbInformer.Informer().HasSynced,
crSynced: crInformer.Informer().HasSynced,
eventGen: eventGen, eventGen: eventGen,
pCache: pCache, pCache: pCache,
webhookRegistrationClient: webhookRegistrationClient, webhookRegistrationClient: webhookRegistrationClient,
@ -374,37 +383,9 @@ func (ws *WebhookServer) resourceMutation(request *v1beta1.AdmissionRequest) *v1
func (ws *WebhookServer) resourceValidation(request *v1beta1.AdmissionRequest) *v1beta1.AdmissionResponse { 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 := ws.log.WithName("resourceValidation").WithValues("uid", request.UID, "kind", request.Kind.Kind, "namespace", request.Namespace, "name", request.Name, "operation", request.Operation)
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 !checked {
if request.Operation == v1beta1.Delete || request.Operation == v1beta1.Update { if request.Operation == v1beta1.Delete || request.Operation == v1beta1.Update {
// convert RAW to unstructured if err := ws.excludeKyvernoResources(request); err != nil {
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")
return &v1beta1.AdmissionResponse{
Allowed: false,
Result: &metav1.Status{
Status: "Failure",
Message: err.Error(),
},
}
}
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{ return &v1beta1.AdmissionResponse{
Allowed: false, Allowed: false,
Result: &metav1.Status{ Result: &metav1.Status{
@ -414,21 +395,7 @@ 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",
},
}
}
}
}
}
if !ws.supportMudateValidate { if !ws.supportMudateValidate {
logger.Info("mutate and validate rules are not supported prior to Kubernetes 1.14.0") logger.Info("mutate and validate rules are not supported prior to Kubernetes 1.14.0")
return &v1beta1.AdmissionResponse{ return &v1beta1.AdmissionResponse{
@ -458,6 +425,7 @@ func (ws *WebhookServer) resourceValidation(request *v1beta1.AdmissionRequest) *
} }
var roles, clusterRoles []string var roles, clusterRoles []string
var err error
// getRoleRef only if policy has roles/clusterroles defined // getRoleRef only if policy has roles/clusterroles defined
if containRBACinfo(policies) { if containRBACinfo(policies) {
roles, clusterRoles, err = userinfo.GetRoleRef(ws.rbLister, ws.crbLister, request) roles, clusterRoles, err = userinfo.GetRoleRef(ws.rbLister, ws.crbLister, request)
@ -517,7 +485,7 @@ func (ws *WebhookServer) resourceValidation(request *v1beta1.AdmissionRequest) *
// RunAsync TLS server in separate thread and returns control immediately // RunAsync TLS server in separate thread and returns control immediately
func (ws *WebhookServer) RunAsync(stopCh <-chan struct{}) { func (ws *WebhookServer) RunAsync(stopCh <-chan struct{}) {
logger := ws.log logger := ws.log
if !cache.WaitForCacheSync(stopCh, ws.pSynced, ws.rbSynced, ws.crbSynced) { if !cache.WaitForCacheSync(stopCh, ws.pSynced, ws.rbSynced, ws.crbSynced, ws.rSynced, ws.crSynced) {
logger.Info("failed to sync informer cache") logger.Info("failed to sync informer cache")
} }
@ -584,3 +552,43 @@ func (ws *WebhookServer) bodyToAdmissionReview(request *http.Request, writer htt
return admissionReview return admissionReview
} }
// excludeKyvernoResources will check resource can have acces or not
func (ws *WebhookServer) excludeKyvernoResources(request *v1beta1.AdmissionRequest) error {
logger := ws.log.WithName("resourceValidation").WithValues("uid", request.UID, "kind", request.Kind.Kind, "namespace", request.Namespace, "name", request.Name, "operation", request.Operation)
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 !checked {
// 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 {
logger.Error(err, "failed to convert RAR resource to unstructured format")
return err
}
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 err
}
}
labels := oldResource.GetLabels()
if labels != nil {
if labels["app.kubernetes.io/managed-by"] == "kyverno" && labels["app.kubernetes.io/synchronize"] == "enable" {
return fmt.Errorf("Resource is managed by Kyverno, can't be changed manually. You can edit generate policy to update this resource")
}
}
}
return nil
}