Skip to content
This repository has been archived by the owner on Oct 12, 2022. It is now read-only.

Commit

Permalink
Replace changevalidator with webhook (#14)
Browse files Browse the repository at this point in the history
  • Loading branch information
adamwalach authored and mszostok committed Jun 11, 2019
1 parent 3e9a872 commit f6cda00
Show file tree
Hide file tree
Showing 16 changed files with 976 additions and 7 deletions.
8 changes: 7 additions & 1 deletion Gopkg.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

45 changes: 45 additions & 0 deletions charts/catalog/templates/rbac.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -152,3 +152,48 @@ items:
kind: Group
name: system:authenticated
{{end}}

### Webhook ###
- apiVersion: {{template "rbacApiVersion" . }}
kind: ClusterRole
metadata:
name: "servicecatalog.k8s.io:webhook"
rules:
# access to our service-catalog types
- apiGroups: ["servicecatalog.k8s.io"]
resources: ["clusterserviceclasses"]
verbs: ["get","list","watch"]
- apiGroups: ["servicecatalog.k8s.io"]
resources: ["clusterserviceplans"]
verbs: ["get","list","watch"]
- apiGroups: ["servicecatalog.k8s.io"]
resources: ["clusterservicebrokers"]
verbs: ["get","list","watch"]
- apiGroups: ["servicecatalog.k8s.io"]
resources: ["serviceinstances","servicebindings"]
verbs: ["get","list","watch"]
{{- if not .Values.namespacedServiceBrokerDisabled }}
- apiGroups: ["servicecatalog.k8s.io"]
resources: ["serviceclasses"]
verbs: ["get","list","watch"]
- apiGroups: ["servicecatalog.k8s.io"]
resources: ["serviceplans"]
verbs: ["get","list","watch"]
- apiGroups: ["servicecatalog.k8s.io"]
resources: ["servicebrokers"]
verbs: ["get","list","watch"]
{{- end }}
# give the webhook service account access to whats defined in its role.
- apiVersion: {{template "rbacApiVersion" . }}
kind: ClusterRoleBinding
metadata:
name: "servicecatalog.k8s.io:webhook"
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: "servicecatalog.k8s.io:webhook"
subjects:
- apiGroup: ""
kind: ServiceAccount
name: "{{ .Values.webhook.serviceAccount }}"
namespace: "{{ .Release.Namespace }}"
5 changes: 5 additions & 0 deletions charts/catalog/templates/serviceaccounts.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,8 @@ items:
kind: ServiceAccount
metadata:
name: "{{ .Values.controllerManager.serviceAccount }}"
# The SA for the webhook service
- apiVersion: v1
kind: ServiceAccount
metadata:
name: "{{ .Values.webhook.serviceAccount }}"
20 changes: 20 additions & 0 deletions charts/catalog/templates/webhook-register.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,26 @@ webhooks:
apiVersions: ["v1beta1"]
resources: ["serviceinstances"]
---
apiVersion: admissionregistration.k8s.io/v1beta1
kind: ValidatingWebhookConfiguration
metadata:
name: {{ template "fullname" . }}-validating-webhook
namespace: "{{ .Release.Namespace }}"
webhooks:
- name: validating.serviceinstances.servicecatalog.k8s.io
clientConfig:
caBundle: {{ b64enc $ca.Cert }}
service:
name: {{ template "fullname" . }}-webhook
namespace: "{{ .Release.Namespace }}"
path: "/validating-serviceinstances"
failurePolicy: Fail
rules:
- operations: [ "CREATE", "UPDATE" ]
apiGroups: ["servicecatalog.k8s.io"]
apiVersions: ["v1beta1"]
resources: ["serviceinstances"]
---
apiVersion: v1
kind: Secret
metadata:
Expand Down
1 change: 1 addition & 0 deletions charts/catalog/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ webhook:
securePort: 30443
# Log level; valid values are in the range 0 - 10
verbosity: 10
serviceAccount: service-catalog-webhook
# Webhook resource requests and limits
# Ref: http://kubernetes.io/docs/user-guide/compute-resources/
resources:
Expand Down
4 changes: 4 additions & 0 deletions cmd/webhook/server/webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ import (
simutation "github.com/kubernetes-incubator/service-catalog/pkg/webhook/servicecatalog/serviceinstance/mutation"
spmutation "github.com/kubernetes-incubator/service-catalog/pkg/webhook/servicecatalog/serviceplan/mutation"

sivalidation "github.com/kubernetes-incubator/service-catalog/pkg/webhook/servicecatalog/serviceinstance/validation"

"github.com/pkg/errors"
"k8s.io/apiserver/pkg/server/healthz"
"sigs.k8s.io/controller-runtime/pkg/client/config"
Expand Down Expand Up @@ -78,6 +80,8 @@ func run(opts *WebhookServerOptions, stopCh <-chan struct{}) error {
"/mutating-serviceclasses": &scmutation.CreateUpdateHandler{},
"/mutating-serviceinstances": &simutation.CreateUpdateHandler{},
"/mutating-serviceplans": &spmutation.CreateUpdateHandler{},

"/validating-serviceinstances": sivalidation.NewAdmissionHandler(),
}

for path, handler := range webhooks {
Expand Down
4 changes: 4 additions & 0 deletions pkg/apis/servicecatalog/v1beta1/register.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package v1beta1

import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/controller-runtime/pkg/scheme"

"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
Expand Down Expand Up @@ -46,6 +47,9 @@ var (
localSchemeBuilder = &SchemeBuilder
// AddToScheme is exposed for API installation
AddToScheme = SchemeBuilder.AddToScheme

//SchemeBuilderRuntime maps go types to Kubernetes GroupVersionKinds.
SchemeBuilderRuntime = &scheme.Builder{GroupVersion: SchemeGroupVersion}
)

func addKnownTypes(scheme *runtime.Scheme) error {
Expand Down
6 changes: 6 additions & 0 deletions pkg/apis/servicecatalog/v1beta1/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -1492,3 +1492,9 @@ type RemoveKeyTransform struct {
// The key to remove from the Secret
Key string `json:"key"`
}

func init() {
// SchemaBuilder is used to map go structs to GroupVersionKinds.
// Solution suggested by the Kubebuilder book: https://book.kubebuilder.io/basics/simple_resource.html - "Scaffolded Boilerplate" section
SchemeBuilderRuntime.Register(&ServiceBinding{}, &ServiceInstance{}, &ClusterServiceClass{})
}
128 changes: 128 additions & 0 deletions pkg/webhook/servicecatalog/serviceinstance/validation/handler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
/*
Copyright 2019 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package validation

import (
"context"
"net/http"

sc "github.com/kubernetes-incubator/service-catalog/pkg/apis/servicecatalog/v1beta1"
"github.com/kubernetes-incubator/service-catalog/pkg/webhookutil"

"github.com/hashicorp/go-multierror"
admissionTypes "k8s.io/api/admission/v1beta1"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/runtime/inject"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
)

// Validator is used to implement new validation logic
type Validator interface {
Validate(context.Context, admission.Request, *sc.ServiceInstance, *webhookutil.TracedLogger) error
}

// AdmissionHandler handles ServiceInstance validation
type AdmissionHandler struct {
decoder *admission.Decoder
client client.Client

CreateValidators []Validator
UpdateValidators []Validator
}

var _ admission.Handler = &AdmissionHandler{}
var _ admission.DecoderInjector = &AdmissionHandler{}
var _ inject.Client = &AdmissionHandler{}

// NewAdmissionHandler creates new AdmissionHandler and initializes validators list
func NewAdmissionHandler() *AdmissionHandler {
return &AdmissionHandler{
UpdateValidators: []Validator{&DenyPlanChangeIfNotUpdatable{}},
}
}

// Handle handles admission requests.
func (h *AdmissionHandler) Handle(ctx context.Context, req admission.Request) admission.Response {
traced := webhookutil.NewTracedLogger(req.UID)
traced.Infof("Start handling AdmissionHandler operation: %s for %s: %q", req.Operation, req.Kind.Kind, req.Name)

si := &sc.ServiceInstance{}
if err := webhookutil.MatchKinds(si, req.Kind); err != nil {
traced.Errorf("Error matching kinds: %v", err)
return admission.Errored(http.StatusBadRequest, err)
}

if err := h.decoder.Decode(req, si); err != nil {
traced.Errorf("Could not decode request object: %v", err)
return admission.Errored(http.StatusBadRequest, err)
}

var errs error

switch req.Operation {
case admissionTypes.Create:
for _, v := range h.CreateValidators {
if err := v.Validate(ctx, req, si, traced); err != nil {
errs = multierror.Append(errs, err)
}
}
case admissionTypes.Update:
for _, v := range h.UpdateValidators {
if err := v.Validate(ctx, req, si, traced); err != nil {
errs = multierror.Append(errs, err)
}
}
default:
traced.Infof("ServiceInstance AdmissionHandler wehbook does not support action %q", req.Operation)
return admission.Allowed("action not taken")
}

if errs != nil {
return admission.Denied(errs.Error())
}

traced.Infof("Completed successfully AdmissionHandler operation: %s for %s: %q", req.Operation, req.Kind.Kind, req.Name)
return admission.Allowed("ServiceInstance AdmissionHandler successful")
}

// InjectDecoder injects the decoder into the handlers
func (h *AdmissionHandler) InjectDecoder(d *admission.Decoder) error {
h.decoder = d

for _, v := range h.CreateValidators {
admission.InjectDecoderInto(d, v)
}
for _, v := range h.UpdateValidators {
admission.InjectDecoderInto(d, v)
}

return nil
}

// InjectClient injects the client into the handlers
func (h *AdmissionHandler) InjectClient(c client.Client) error {
h.client = c

for _, v := range h.CreateValidators {
inject.ClientInto(c, v)
}
for _, v := range h.UpdateValidators {
inject.ClientInto(c, v)
}

return nil
}
Loading

0 comments on commit f6cda00

Please sign in to comment.