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:
parent
ff10a6f6e7
commit
c3d4dbf228
3 changed files with 93 additions and 12 deletions
|
@ -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",
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue