Refactor ingress validation in webhook

This commit is contained in:
Manuel Alejandro de Brito Fontes 2020-04-28 11:14:27 -04:00
parent c8eb914d8a
commit af910a16d4
7 changed files with 96 additions and 86 deletions

View file

@ -17,12 +17,15 @@ limitations under the License.
package controller
import (
"fmt"
"k8s.io/api/admission/v1beta1"
extensions "k8s.io/api/extensions/v1beta1"
networking "k8s.io/api/networking/v1beta1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/ingress-nginx/internal/ingress/annotations/parser"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/klog"
"k8s.io/ingress-nginx/internal/ingress/annotations/parser"
)
// Checker must return an error if the ingress provided as argument
@ -37,57 +40,82 @@ type IngressAdmission struct {
Checker Checker
}
var (
extensionsResource = metav1.GroupVersionResource{
Group: networking.GroupName,
Version: "v1beta1",
Resource: "ingresses",
}
networkingResource = metav1.GroupVersionResource{
Group: extensions.GroupName,
Version: "v1beta1",
Resource: "ingresses",
}
)
// HandleAdmission populates the admission Response
// with Allowed=false if the Object is an ingress that would prevent nginx to reload the configuration
// with Allowed=true otherwise
func (ia *IngressAdmission) HandleAdmission(ar *v1beta1.AdmissionReview) error {
func (ia *IngressAdmission) HandleAdmission(ar *v1beta1.AdmissionReview) {
if ar.Request == nil {
klog.Infof("rejecting nil request")
ar.Response = &v1beta1.AdmissionResponse{
Allowed: false,
}
return nil
return
}
klog.V(3).Infof("handling ingress admission webhook request for {%s} %s in namespace %s", ar.Request.Resource.String(), ar.Request.Name, ar.Request.Namespace)
ingressResource := v1.GroupVersionResource{Group: networking.SchemeGroupVersion.Group, Version: networking.SchemeGroupVersion.Version, Resource: "ingresses"}
oldIngressResource := v1.GroupVersionResource{Group: extensions.SchemeGroupVersion.Group, Version: extensions.SchemeGroupVersion.Version, Resource: "ingresses"}
if ar.Request.Resource == ingressResource || ar.Request.Resource == oldIngressResource {
if ar.Request.Resource != extensionsResource && ar.Request.Resource != networkingResource {
err := fmt.Errorf("rejecting admission review because the request does not contains an Ingress resource but %s with name %s in namespace %s",
ar.Request.Resource.String(), ar.Request.Name, ar.Request.Namespace)
ar.Response = &v1beta1.AdmissionResponse{
UID: ar.Request.UID,
Allowed: false,
}
ingress := networking.Ingress{}
deserializer := codecs.UniversalDeserializer()
if _, _, err := deserializer.Decode(ar.Request.Object.Raw, nil, &ingress); err != nil {
ar.Response.Result = &v1.Status{Message: err.Error()}
ar.Response.AuditAnnotations = map[string]string{
parser.GetAnnotationWithPrefix("error"): err.Error(),
}
klog.Errorf("failed to decode ingress %s in namespace %s: %s, refusing it", ar.Request.Name, ar.Request.Namespace, err.Error())
return err
Result: &metav1.Status{Message: err.Error()},
}
err := ia.Checker.CheckIngress(&ingress)
if err != nil {
ar.Response.Result = &v1.Status{Message: err.Error()}
ar.Response.AuditAnnotations = map[string]string{
parser.GetAnnotationWithPrefix("error"): err.Error(),
}
klog.Errorf("failed to generate configuration for ingress %s in namespace %s: %s, refusing it", ar.Request.Name, ar.Request.Namespace, err.Error())
return err
}
ar.Response.Allowed = true
klog.Infof("successfully validated configuration, accepting ingress %s in namespace %s", ar.Request.Name, ar.Request.Namespace)
return nil
return
}
klog.Infof("accepting non ingress %s in namespace %s %s", ar.Request.Name, ar.Request.Namespace, ar.Request.Resource.String())
ingress := networking.Ingress{}
deserializer := codecs.UniversalDeserializer()
if _, _, err := deserializer.Decode(ar.Request.Object.Raw, nil, &ingress); err != nil {
klog.Errorf("failed to decode ingress %s in namespace %s: %s, refusing it",
ar.Request.Name, ar.Request.Namespace, err.Error())
ar.Response = &v1beta1.AdmissionResponse{
UID: ar.Request.UID,
Allowed: false,
Result: &metav1.Status{Message: err.Error()},
AuditAnnotations: map[string]string{
parser.GetAnnotationWithPrefix("error"): err.Error(),
},
}
return
}
if err := ia.Checker.CheckIngress(&ingress); err != nil {
klog.Errorf("failed to generate configuration for ingress %s in namespace %s: %s, refusing it",
ar.Request.Name, ar.Request.Namespace, err.Error())
ar.Response = &v1beta1.AdmissionResponse{
UID: ar.Request.UID,
Allowed: false,
Result: &metav1.Status{Message: err.Error()},
AuditAnnotations: map[string]string{
parser.GetAnnotationWithPrefix("error"): err.Error(),
},
}
return
}
klog.Infof("successfully validated configuration, accepting ingress %s in namespace %s",
ar.Request.Name, ar.Request.Namespace)
ar.Response = &v1beta1.AdmissionResponse{
UID: ar.Request.UID,
Allowed: true,
}
return nil
}