1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-30 19:35:06 +00:00

create separate validate webhook for policy validation

This commit is contained in:
Shuting Zhao 2019-07-02 18:42:07 -07:00
parent ff10a6f6e7
commit c3d4dbf228
3 changed files with 93 additions and 12 deletions

View file

@ -15,6 +15,10 @@ const (
ValidatingWebhookConfigurationDebug = "kyverno-validating-webhook-cfg-debug"
ValidatingWebhookName = "nirmata.kyverno.validating-webhook"
PolicyValidatingWebhookConfigurationName = "kyverno-policy-validating-webhook-cfg"
PolicyValidatingWebhookConfigurationDebug = "kyverno-policy-validating-webhook-cfg-debug"
PolicyValidatingWebhookName = "nirmata.kyverno.policy-validating-webhook"
// Due to kubernetes issue, we must use next literal constants instead of deployment TypeMeta fields
// Issue: https://github.com/kubernetes/kubernetes/pull/63972
// When the issue is closed, we should use TypeMeta struct instead of this constants
@ -24,9 +28,10 @@ const (
)
var (
MutatingWebhookServicePath = "/mutate"
ValidatingWebhookServicePath = "/validate"
KubePolicyAppLabels = map[string]string{
MutatingWebhookServicePath = "/mutate"
ValidatingWebhookServicePath = "/validate"
PolicyValidatingWebhookServicePath = "/policyvalidate"
KubePolicyAppLabels = map[string]string{
"app": "kyverno",
}

View file

@ -4,6 +4,7 @@ import (
"errors"
"fmt"
"io/ioutil"
"strings"
"github.com/golang/glog"
"github.com/nirmata/kyverno/pkg/config"
@ -67,6 +68,16 @@ func (wrc *WebhookRegistrationClient) Register() error {
return err
}
policyValidationWebhookConfig, err := wrc.contructPolicyValidatingWebhookConfig()
if err != nil {
return err
}
_, err = wrc.registrationClient.ValidatingWebhookConfigurations().Create(policyValidationWebhookConfig)
if err != nil {
return err
}
return nil
}
@ -77,11 +88,13 @@ func (wrc *WebhookRegistrationClient) Deregister() {
if wrc.serverIP != "" {
wrc.registrationClient.MutatingWebhookConfigurations().Delete(config.MutatingWebhookConfigurationDebug, &meta.DeleteOptions{})
wrc.registrationClient.ValidatingWebhookConfigurations().Delete(config.ValidatingWebhookConfigurationDebug, &meta.DeleteOptions{})
wrc.registrationClient.ValidatingWebhookConfigurations().Delete(config.PolicyValidatingWebhookConfigurationDebug, &meta.DeleteOptions{})
return
}
wrc.registrationClient.MutatingWebhookConfigurations().Delete(config.MutatingWebhookConfigurationName, &meta.DeleteOptions{})
wrc.registrationClient.ValidatingWebhookConfigurations().Delete(config.ValidatingWebhookConfigurationName, &meta.DeleteOptions{})
wrc.registrationClient.ValidatingWebhookConfigurations().Delete(config.PolicyValidatingWebhookConfigurationName, &meta.DeleteOptions{})
}
func (wrc *WebhookRegistrationClient) constructMutatingWebhookConfig(configuration *rest.Config) (*admregapi.MutatingWebhookConfiguration, error) {
@ -175,7 +188,7 @@ func (wrc *WebhookRegistrationClient) contructDebugValidatingWebhookConfig(caDat
return &admregapi.ValidatingWebhookConfiguration{
ObjectMeta: meta.ObjectMeta{
Name: config.ValidatingWebhookConfigurationName,
Name: config.ValidatingWebhookConfigurationDebug,
Labels: config.KubePolicyAppLabels,
},
Webhooks: []admregapi.Webhook{
@ -187,7 +200,63 @@ func (wrc *WebhookRegistrationClient) contructDebugValidatingWebhookConfig(caDat
}
}
func (wrc *WebhookRegistrationClient) contructPolicyValidatingWebhookConfig() (*admregapi.ValidatingWebhookConfiguration, error) {
// Check if ca is defined in the secret tls-ca
// assume the key and signed cert have been defined in secret tls.kyverno
caData := wrc.client.ReadRootCASecret()
if len(caData) == 0 {
// load the CA from kubeconfig
caData = extractCA(wrc.clientConfig)
}
if len(caData) == 0 {
return nil, errors.New("Unable to extract CA data from configuration")
}
if wrc.serverIP != "" {
return wrc.contructDebugPolicyValidatingWebhookConfig(caData), nil
}
return &admregapi.ValidatingWebhookConfiguration{
ObjectMeta: meta.ObjectMeta{
Name: config.PolicyValidatingWebhookConfigurationName,
Labels: config.KubePolicyAppLabels,
OwnerReferences: []meta.OwnerReference{
wrc.constructOwner(),
},
},
Webhooks: []admregapi.Webhook{
constructWebhook(
config.PolicyValidatingWebhookName,
config.PolicyValidatingWebhookServicePath,
caData),
},
}, nil
}
func (wrc *WebhookRegistrationClient) contructDebugPolicyValidatingWebhookConfig(caData []byte) *admregapi.ValidatingWebhookConfiguration {
url := fmt.Sprintf("https://%s%s", wrc.serverIP, config.PolicyValidatingWebhookServicePath)
glog.V(3).Infof("Debug PolicyValidatingWebhookConfig is registered with url %s\n", url)
return &admregapi.ValidatingWebhookConfiguration{
ObjectMeta: meta.ObjectMeta{
Name: config.PolicyValidatingWebhookConfigurationDebug,
Labels: config.KubePolicyAppLabels,
},
Webhooks: []admregapi.Webhook{
constructDebugWebhook(
config.PolicyValidatingWebhookName,
url,
caData),
},
}
}
func constructWebhook(name, servicePath string, caData []byte) admregapi.Webhook {
resource := "*/*"
if servicePath == config.PolicyValidatingWebhookServicePath {
resource = "policies/*"
}
return admregapi.Webhook{
Name: name,
ClientConfig: admregapi.WebhookClientConfig{
@ -212,7 +281,7 @@ func constructWebhook(name, servicePath string, caData []byte) admregapi.Webhook
"*",
},
Resources: []string{
"*/*",
resource,
},
},
},
@ -221,6 +290,11 @@ func constructWebhook(name, servicePath string, caData []byte) admregapi.Webhook
}
func constructDebugWebhook(name, url string, caData []byte) admregapi.Webhook {
resource := "*/*"
if strings.Contains(url, config.PolicyValidatingWebhookServicePath) {
resource = "policies/*"
}
return admregapi.Webhook{
Name: name,
ClientConfig: admregapi.WebhookClientConfig{
@ -241,7 +315,7 @@ func constructDebugWebhook(name, url string, caData []byte) admregapi.Webhook {
"*",
},
Resources: []string{
"*/*",
resource,
},
},
},

View file

@ -67,6 +67,7 @@ func NewWebhookServer(
mux := http.NewServeMux()
mux.HandleFunc(config.MutatingWebhookServicePath, ws.serve)
mux.HandleFunc(config.ValidatingWebhookServicePath, ws.serve)
mux.HandleFunc(config.PolicyValidatingWebhookServicePath, ws.serve)
ws.server = http.Server{
Addr: ":443", // Listen on port for HTTPS requests
@ -98,15 +99,11 @@ func (ws *WebhookServer) serve(w http.ResponseWriter, r *http.Request) {
admissionReview.Response = ws.HandleMutation(admissionReview.Request)
case config.ValidatingWebhookServicePath:
admissionReview.Response = ws.HandleValidation(admissionReview.Request)
case config.PolicyValidatingWebhookServicePath:
admissionReview.Response = ws.HandlePolicyValidation(admissionReview.Request)
}
}
// validateUniqueRuleName MUST be called after admission webhook
// otherwise admissionReview.Response will be overwritten
if admissionReview.Request.Kind.Kind == policyKind {
admissionReview.Response = ws.validateUniqueRuleName(admissionReview.Request.Object.Raw)
}
admissionReview.Response.UID = admissionReview.Request.UID
responseJSON, err := json.Marshal(admissionReview)
@ -391,6 +388,10 @@ func (ws *WebhookServer) bodyToAdmissionReview(request *http.Request, writer htt
return admissionReview
}
func (ws *WebhookServer) HandlePolicyValidation(request *v1beta1.AdmissionRequest) *v1beta1.AdmissionResponse {
return ws.validateUniqueRuleName(request.Object.Raw)
}
func (ws *WebhookServer) validateUniqueRuleName(rawPolicy []byte) *v1beta1.AdmissionResponse {
var policy *policyv1.Policy
var ruleNames []string
@ -413,6 +414,7 @@ func (ws *WebhookServer) validateUniqueRuleName(rawPolicy []byte) *v1beta1.Admis
}
}
glog.V(3).Infof("Policy validation passed.")
return &v1beta1.AdmissionResponse{
Allowed: true,
}