1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2024-12-14 11:57:48 +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,16 +141,15 @@ func IsRoleAuthorize(rbLister rbaclister.RoleBindingLister, crbLister rbaclister
for _, e := range clusterRoles {
if strings.Contains(e, "kyverno:") {
return true, nil
} else {
role, err := crLister.Get(e)
if err != nil {
return false, err
}
labels := role.GetLabels()
}
role, err := crLister.Get(e)
if err != nil {
return false, err
}
labels := role.GetLabels()
if labels["kubernetes.io/bootstrapping"] == "rbac-defaults" {
return true, nil
}
if labels["kubernetes.io/bootstrapping"] == "rbac-defaults" {
return true, nil
}
}
for _, e := range roles {
@ -166,26 +165,25 @@ func IsRoleAuthorize(rbLister rbaclister.RoleBindingLister, crbLister rbaclister
}
}
}
} else {
// User or Group
excludeDevelopmentRole := []string{"minikube-user", "kubernetes-admin"}
for _, e := range excludeDevelopmentRole {
if strings.Contains(request.UserInfo.Username, e) {
return false, nil
}
// User or Group
excludeDevelopmentRole := []string{"minikube-user", "kubernetes-admin"}
for _, e := range excludeDevelopmentRole {
if strings.Contains(request.UserInfo.Username, e) {
return false, nil
}
}
var matchedRoles []bool
for _, e := range request.UserInfo.Groups {
for _, defaultSuffix := range defaultSuffixs {
if strings.Contains(e, defaultSuffix) {
matchedRoles = append(matchedRoles, true)
break
}
}
var matchedRoles []bool
for _, e := range request.UserInfo.Groups {
for _, defaultSuffix := range defaultSuffixs {
if strings.Contains(e, defaultSuffix) {
matchedRoles = append(matchedRoles, true)
break
}
}
}
if len(matchedRoles) == len(request.UserInfo.Groups) {
return true, nil
}
}
if len(matchedRoles) == len(request.UserInfo.Groups) {
return true, nil
}
return false, nil

View file

@ -10,13 +10,13 @@ import (
"net/http"
"time"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"github.com/go-logr/logr"
"github.com/julienschmidt/httprouter"
v1 "github.com/nirmata/kyverno/pkg/api/kyverno/v1"
"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"
kyvernoinformer "github.com/nirmata/kyverno/pkg/client/informers/externalversions/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
rbSynced cache.InformerSynced
// return true if role store has synced atleast once
rSynced cache.InformerSynced
// list/get cluster role binding resource
crbLister rbaclister.ClusterRoleBindingLister
// return true if cluster role binding store has synced atleast once
crbSynced cache.InformerSynced
// return true if cluster role store has synced atleast once
crSynced cache.InformerSynced
// generate events
eventGen event.Interface
@ -146,16 +152,19 @@ func NewWebhookServer(
tlsConfig.Certificates = []tls.Certificate{pair}
ws := &WebhookServer{
client: client,
kyvernoClient: kyvernoClient,
pLister: pInformer.Lister(),
pSynced: pInformer.Informer().HasSynced,
rbLister: rbInformer.Lister(),
rLister: rInformer.Lister(),
rbSynced: rbInformer.Informer().HasSynced,
client: client,
kyvernoClient: kyvernoClient,
pLister: pInformer.Lister(),
pSynced: pInformer.Informer().HasSynced,
rbLister: rbInformer.Lister(),
rbSynced: rbInformer.Informer().HasSynced,
rLister: rInformer.Lister(),
rSynced: rInformer.Informer().HasSynced,
crbLister: crbInformer.Lister(),
crLister: crInformer.Lister(),
crbSynced: crbInformer.Informer().HasSynced,
crSynced: crInformer.Informer().HasSynced,
eventGen: eventGen,
pCache: pCache,
webhookRegistrationClient: webhookRegistrationClient,
@ -374,61 +383,19 @@ 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)
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 {
// 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 request.Operation == v1beta1.Delete || request.Operation == v1beta1.Update {
if err := ws.excludeKyvernoResources(request); err != nil {
return &v1beta1.AdmissionResponse{
Allowed: false,
Result: &metav1.Status{
Status: "Failure",
Message: err.Error(),
},
}
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{
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{
@ -458,6 +425,7 @@ 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)
@ -517,7 +485,7 @@ func (ws *WebhookServer) resourceValidation(request *v1beta1.AdmissionRequest) *
// RunAsync TLS server in separate thread and returns control immediately
func (ws *WebhookServer) RunAsync(stopCh <-chan struct{}) {
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")
}
@ -584,3 +552,43 @@ func (ws *WebhookServer) bodyToAdmissionReview(request *http.Request, writer htt
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
}