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

NK-51: Added Deployment as owner of MutatingWebhookConfiguration. This allows kubernetes to delete webhook config, when deployment deletes.

This commit is contained in:
belyshevdenis 2019-03-25 15:44:53 +02:00
parent 736bd2efcf
commit 670881c71d
6 changed files with 69 additions and 42 deletions

View file

@ -2,16 +2,22 @@ package config
const (
// These constants MUST be equal to the corresponding names in service definition in definitions/install.yaml
WebhookServiceNamespace = "kube-system"
KubePolicyDeploymentName = "kube-policy-deployment"
KubePolicyNamespace = "kube-system"
WebhookServiceName = "kube-policy-svc"
WebhookConfigName = "nirmata-kube-policy-webhook-cfg"
MutationWebhookName = "webhook.nirmata.kube-policy"
// Due to kubernetes issue, we must use next literal constants instead of deployment TypeMeta fields
// Pull request: https://github.com/kubernetes/kubernetes/pull/63972
// When pull request is closed, we should use TypeMeta struct instead of this constants
DeploymentKind = "Deployment"
DeploymentAPIVersion = "extensions/v1beta1"
)
var (
WebhookServicePath = "/mutate"
WebhookConfigLabels = map[string]string {
WebhookConfigLabels = map[string]string{
"app": "kube-policy",
}
)

View file

@ -76,7 +76,7 @@ func tlsPairFromCluster(configuration *rest.Config, client *kubeclient.KubeClien
}
certProps := utils.TlsCertificateProps{
Service: config.WebhookServiceName,
Namespace: config.WebhookServiceNamespace,
Namespace: config.KubePolicyNamespace,
ApiServerHost: apiServerUrl.Hostname(),
}

View file

@ -36,6 +36,10 @@ func NewKubeClient(config *rest.Config, logger *log.Logger) (*KubeClient, error)
}, nil
}
func (kc *KubeClient) GetClient() *kubernetes.Clientset {
return kc.client
}
// Generates new ConfigMap in given namespace. If the namespace does not exists yet,
// waits until it is created for maximum namespaceCreationMaxWaitTime (see below)
func (kc *KubeClient) GenerateConfigMap(generator types.PolicyConfigGenerator, namespace string) error {

View file

@ -59,12 +59,8 @@ func main() {
log.Println("Policy Controller has started")
<-stopCh
server.Stop()
err = mutationWebhook.Deregister()
if err != nil {
log.Printf("Unable to deregister mutation webhook: %v", err)
}
server.Stop()
log.Println("Policy Controller has stopped")
}

View file

@ -29,7 +29,12 @@ func CreateMutationWebhook(clientConfig *rest.Config, kubeclient *kubeclient.Kub
return nil, errors.New("Some parameters are not set")
}
registration, err := NewMutationWebhookRegistration(clientConfig)
registration, err := NewMutationWebhookRegistration(clientConfig, kubeclient)
if err != nil {
return nil, err
}
err = registration.Register()
if err != nil {
return nil, err
}
@ -45,10 +50,6 @@ func CreateMutationWebhook(clientConfig *rest.Config, kubeclient *kubeclient.Kub
}, nil
}
func (mw *MutationWebhook) Deregister() error {
return mw.registration.Deregister()
}
// Mutate applies admission to request
func (mw *MutationWebhook) Mutate(request *v1beta1.AdmissionRequest) *v1beta1.AdmissionResponse {
mw.logger.Printf("AdmissionReview for Kind=%v, Namespace=%v Name=%v UID=%v patchOperation=%v UserInfo=%v",

View file

@ -2,10 +2,10 @@ package webhooks
import (
"errors"
"fmt"
"io/ioutil"
"github.com/nirmata/kube-policy/config"
kubeclient "github.com/nirmata/kube-policy/kubeclient"
admregapi "k8s.io/api/admissionregistration/v1beta1"
meta "k8s.io/apimachinery/pkg/apis/meta/v1"
@ -15,60 +15,80 @@ import (
type MutationWebhookRegistration struct {
registrationClient *admregclient.AdmissionregistrationV1beta1Client
kubeclient *kubeclient.KubeClient
clientConfig *rest.Config
}
func NewMutationWebhookRegistration(clientConfig *rest.Config) (*MutationWebhookRegistration, error) {
func NewMutationWebhookRegistration(clientConfig *rest.Config, kubeclient *kubeclient.KubeClient) (*MutationWebhookRegistration, error) {
registrationClient, err := admregclient.NewForConfig(clientConfig)
if err != nil {
return nil, err
}
webhookConfig, err := constructWebhookConfig(clientConfig)
if err != nil {
return nil, err
}
oldConfig, err := registrationClient.MutatingWebhookConfigurations().Get(config.WebhookConfigName, meta.GetOptions{})
if oldConfig != nil && oldConfig.ObjectMeta.UID != "" {
// Normally webhook configuration should be deleted from cluster when controller end his work.
// But if old configuration is detected in cluster, it should be replaced by new one.
err = registrationClient.MutatingWebhookConfigurations().Delete(config.WebhookConfigName, &meta.DeleteOptions{})
if err != nil {
return nil, errors.New(fmt.Sprintf("Failed to delete old webhook configuration: %v", err))
}
}
_, err = registrationClient.MutatingWebhookConfigurations().Create(webhookConfig)
if err != nil {
return nil, err
}
return &MutationWebhookRegistration{
registrationClient: registrationClient,
kubeclient: kubeclient,
clientConfig: clientConfig,
}, nil
}
func (mwr *MutationWebhookRegistration) Register() error {
webhookConfig, err := mwr.constructWebhookConfig(mwr.clientConfig)
if err != nil {
return err
}
_, err = mwr.registrationClient.MutatingWebhookConfigurations().Create(webhookConfig)
if err != nil {
return err
}
return nil
}
func (mwr *MutationWebhookRegistration) Deregister() error {
return mwr.registrationClient.MutatingWebhookConfigurations().Delete(config.MutationWebhookName, &meta.DeleteOptions{})
}
func constructWebhookConfig(configuration *rest.Config) (*admregapi.MutatingWebhookConfiguration, error) {
func (mwr *MutationWebhookRegistration) constructWebhookConfig(configuration *rest.Config) (*admregapi.MutatingWebhookConfiguration, error) {
caData := ExtractCA(configuration)
if len(caData) == 0 {
return nil, errors.New("Unable to extract CA data from configuration")
}
// Here we must know our Deployment UID
kubePolicyDeployment, err := mwr.kubeclient.
GetClient().
Apps().
Deployments(config.KubePolicyNamespace).
Get(config.KubePolicyDeploymentName, meta.GetOptions{
ResourceVersion: "1",
IncludeUninitialized: true,
})
if err != nil {
return nil, err
}
return &admregapi.MutatingWebhookConfiguration{
ObjectMeta: meta.ObjectMeta{
Name: config.WebhookConfigName,
Labels: config.WebhookConfigLabels,
OwnerReferences: []meta.OwnerReference{
meta.OwnerReference{
APIVersion: config.DeploymentAPIVersion,
Kind: config.DeploymentKind,
Name: kubePolicyDeployment.ObjectMeta.Name,
UID: kubePolicyDeployment.ObjectMeta.UID,
},
},
},
Webhooks: []admregapi.Webhook{
admregapi.Webhook{
Name: config.MutationWebhookName,
ClientConfig: admregapi.WebhookClientConfig{
Service: &admregapi.ServiceReference{
Namespace: config.WebhookServiceNamespace,
Namespace: config.KubePolicyNamespace,
Name: config.WebhookServiceName,
Path: &config.WebhookServicePath,
},