webhook

package
v0.0.0-...-40afb7c Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 18, 2024 License: Apache-2.0 Imports: 34 Imported by: 216

README

Knative Webhooks

Knative provides infrastructure for authoring webhooks under knative.dev/pkg/webhook and has a few built-in helpers for certain common admission control scenarios. The built-in admission controllers are:

  1. Resource validation and defaulting (builds around apis.Validatable and apis.Defaultable under knative.dev/pkg/apis).
  2. ConfigMap validation, which builds around similar patterns from knative.dev/pkg/configmap (in particular the store concept)

To illustrate standing up the webhook, let's start with one of these built-in admission controllers and then talk about how you can write your own admission controller.

Standing up a Webhook from an Admission Controller

We provide facilities in knative.dev/pkg/injection/sharedmain to try and eliminate much of the boilerplate involved in standing up a webhook. For this example we will show how to stand up the webhook using the built-in admission controller for validating and defaulting resources.

The code to stand up such a webhook looks roughly like this:

// Create a function matching this signature to pass into sharedmain.
func NewResourceAdmissionController(ctx context.Context, cmw configmap.Watcher) *controller.Impl {
	return validation.NewAdmissionController(ctx,
		// Name of the resource webhook (created via yaml)
		fmt.Sprintf("resources.webhook.%s.knative.dev", system.Namespace()),

		// The path on which to serve the webhook.
		"/resource-validation",

		// The resources to validate and default.
		map[schema.GroupVersionKind]resourcesemantics.GenericCRD{
			// List the types to validate, this from knative.dev/sample-controller
			v1alpha1.SchemeGroupVersion.WithKind("AddressableService"): &v1alpha1.AddressableService{},
		},

		// A function that infuses the context passed to Validate/SetDefaults with custom metadata.
		func(ctx context.Context) context.Context {
			// Here is where you would infuse the context with state
			// (e.g. attach a store with configmap data, like knative.dev/serving attaches config-defaults)
			return ctx
		},

		// Whether to disallow unknown fields when parsing the resources' JSON.
		true,
	)
}

func main() {
	// Set up a signal context with our webhook options.
	ctx := webhook.WithOptions(signals.NewContext(), webhook.Options{
		// The name of the Kubernetes service selecting over this deployment's pods.
		ServiceName: "webhook",

		// The port on which to serve.
		Port:        8443,

		// The name of the secret containing certificate data.
		SecretName:  "webhook-certs",
	})

	sharedmain.MainWithContext(ctx, "webhook",
		// The certificate controller will ensure that the named secret (above) has
		// the appropriate shape for our webhook's admission controllers.
		certificates.NewController,

		// This invokes the method defined above to instantiate the resource admission
		// controller.
		NewResourceAdmissionController,
	)
}

There is also a config map validation admission controller built in under knative.dev/pkg/webhook/configmaps.

Writing new Admission Controllers

To implement your own admission controller akin to the resource defaulting and validation controller above, you implement a knative.dev/pkg/controller.Reconciler as with any you would with any other type of controller, but the Reconciler that gets embedded in the *controller.Impl should also implement:

// AdmissionController provides the interface for different admission controllers
type AdmissionController interface {
	// Path returns the path that this particular admission controller serves on.
	Path() string

	// Admit is the callback which is invoked when an HTTPS request comes in on Path().
	Admit(context.Context, *admissionv1beta1.AdmissionRequest) *admissionv1beta1.AdmissionResponse
}

The Reconciler part is responsible for the mutating or validating webhook configuration. The AdmissionController part is responsible for guiding request dispatch (Path()) and handling admission requests (Admit()).

Documentation

Index

Constants

View Source
const (
	// AdmissionReviewUID is the key used to represent the admission review
	// request/response UID in logs
	AdmissionReviewUID = "admissionreview/uid"

	// AdmissionReviewAllowed is the key used to represent whether or not
	// the admission request was permitted in logs
	AdmissionReviewAllowed = "admissionreview/allowed"

	// AdmissionReviewResult is the key used to represent extra details into
	// why an admission request was denied in logs
	AdmissionReviewResult = "admissionreview/result"

	// AdmissionReviewPatchType is the key used to represent the type of Patch in logs
	AdmissionReviewPatchType = "admissionreview/patchtype"
)

Variables

This section is empty.

Functions

func DisableNamespaceOwnershipFromEnv

func DisableNamespaceOwnershipFromEnv() *bool

func EnsureLabelSelectorExpressions

func EnsureLabelSelectorExpressions(
	current *metav1.LabelSelector,
	want *metav1.LabelSelector,
) *metav1.LabelSelector

EnsureLabelSelectorExpressions merges the current label selector's MatchExpressions with the ones wanted. It keeps all non-knative keys intact, removes all knative-keys no longer wanted and adds all knative-keys not yet there.

func MakeErrorStatus

func MakeErrorStatus(reason string, args ...interface{}) *admissionv1.AdmissionResponse

MakeErrorStatus creates an 'BadRequest' error AdmissionResponse

func NameFromEnv

func NameFromEnv() string

func PortFromEnv

func PortFromEnv(defaultPort int) int

PortFromEnv returns the webhook port set by portEnvKey, or default port if env var is not set.

func RegisterMetrics

func RegisterMetrics(opts ...StatsReporterOption)

func SecretNameFromEnv

func SecretNameFromEnv(defaultSecretName string) string

func TLSMinVersionFromEnv

func TLSMinVersionFromEnv(defaultTLSMinVersion uint16) uint16

func WithOptions

func WithOptions(ctx context.Context, opt Options) context.Context

WithOptions associates a set of webhook.Options with the returned context.

Types

type AdmissionController

type AdmissionController interface {
	// Path returns the path that this particular admission controller serves on.
	Path() string

	// Admit is the callback which is invoked when an HTTPS request comes in on Path().
	Admit(context.Context, *admissionv1.AdmissionRequest) *admissionv1.AdmissionResponse
}

AdmissionController provides the interface for different admission controllers

type ConversionController

type ConversionController interface {
	// Path returns the path that this particular conversion controller serves on.
	Path() string

	// Convert is the callback which is invoked when an HTTPS request comes in on Path().
	Convert(context.Context, *apixv1.ConversionRequest) *apixv1.ConversionResponse
}

ConversionController provides the interface for different conversion controllers

type Operation

type Operation = admissionv1.Operation

Operation is the verb being operated on it is aliased in Validation from the k8s admission package

Operation types

type Options

type Options struct {
	// TLSMinVersion contains the minimum TLS version that is acceptable to communicate with the API server.
	// TLS 1.3 is the minimum version if not specified otherwise.
	TLSMinVersion uint16

	// ServiceName is the service name of the webhook.
	ServiceName string

	// SecretName is the name of k8s secret that contains the webhook
	// server key/cert and corresponding CA cert that signed them. The
	// server key/cert are used to serve the webhook and the CA cert
	// is provided to k8s apiserver during admission controller
	// registration.
	// If no SecretName is provided, then the webhook serves without TLS.
	SecretName string

	// ServerPrivateKeyName is the name for the webhook secret's data key e.g. `tls.key`.
	// Default value is `server-key.pem` if no value is passed.
	ServerPrivateKeyName string

	// ServerCertificateName is the name for the webhook secret's ca data key e.g. `tls.crt`.
	// Default value is `server-cert.pem` if no value is passed.
	ServerCertificateName string

	// Port where the webhook is served. Per k8s admission
	// registration requirements this should be 443 unless there is
	// only a single port for the service.
	Port int

	// StatsReporterOptions are the options used to initialize the default StatsReporter
	StatsReporterOptions []StatsReporterOption

	// StatsReporter reports metrics about the webhook.
	// This will be automatically initialized by the constructor if left uninitialized.
	StatsReporter StatsReporter

	// GracePeriod is how long to wait after failing readiness probes
	// before shutting down.
	GracePeriod time.Duration

	// DisableNamespaceOwnership configures if the SYSTEM_NAMESPACE is added as an owner reference to the
	// webhook configuration resources. Overridden by the WEBHOOK_DISABLE_NAMESPACE_OWNERSHIP environment variable.
	// Disabling can be useful to avoid breaking systems that expect ownership to indicate a true controller
	// relationship: https://github.com/knative/serving/issues/15483
	DisableNamespaceOwnership bool

	// ControllerOptions encapsulates options for creating a new controller,
	// including throttling and stats behavior.
	ControllerOptions *controller.ControllerOptions

	// EnableHTTP2 enables HTTP2 for webhooks.
	// Mitigate CVE-2023-44487 by disabling HTTP2 by default until the Go
	// standard library and golang.org/x/net are fully fixed.
	// Right now, it is possible for authenticated and unauthenticated users to
	// hold open HTTP2 connections and consume huge amounts of memory.
	// See:
	// * https://github.com/kubernetes/kubernetes/pull/121120
	// * https://github.com/kubernetes/kubernetes/issues/121197
	// * https://github.com/golang/go/issues/63417#issuecomment-1758858612
	EnableHTTP2 bool
}

Options contains the configuration for the webhook

func GetOptions

func GetOptions(ctx context.Context) *Options

GetOptions retrieves webhook.Options associated with the given context via WithOptions (above).

type StatelessAdmissionController

type StatelessAdmissionController interface {
	// A silly name that should avoid collisions.
	ThisTypeDoesNotDependOnInformerState()
}

StatelessAdmissionController is implemented by AdmissionControllers where Admit may be safely called before informers have finished syncing. This is implemented by inlining StatelessAdmissionImpl in your Go type.

type StatelessAdmissionImpl

type StatelessAdmissionImpl struct{}

StatelessAdmissionImpl marks a reconciler as stateless. Inline this type to implement StatelessAdmissionController.

func (StatelessAdmissionImpl) ThisTypeDoesNotDependOnInformerState

func (sai StatelessAdmissionImpl) ThisTypeDoesNotDependOnInformerState()

type StatsReporter

type StatsReporter interface {
	ReportAdmissionRequest(request *admissionv1.AdmissionRequest, response *admissionv1.AdmissionResponse, d time.Duration) error
	ReportConversionRequest(request *apixv1.ConversionRequest, response *apixv1.ConversionResponse, d time.Duration) error
}

StatsReporter reports webhook metrics

func NewStatsReporter

func NewStatsReporter(opts ...StatsReporterOption) (StatsReporter, error)

NewStatsReporter creates a reporter for webhook metrics

type StatsReporterOption

type StatsReporterOption func(_ *statsReporterOptions)

func WithoutTags

func WithoutTags(tags ...string) StatsReporterOption

type Webhook

type Webhook struct {
	Options Options
	Logger  *zap.SugaredLogger
	// contains filtered or unexported fields
}

Webhook implements the external webhook for validation of resources and configuration.

func New

func New(
	ctx context.Context,
	controllers []interface{},
) (webhook *Webhook, err error)

New constructs a Webhook

func (*Webhook) InformersHaveSynced

func (wh *Webhook) InformersHaveSynced()

InformersHaveSynced is called when the informers have all been synced, which allows any outstanding admission webhooks through.

func (*Webhook) Run

func (wh *Webhook) Run(stop <-chan struct{}) error

Run implements the admission controller run loop.

func (*Webhook) ServeHTTP

func (wh *Webhook) ServeHTTP(w http.ResponseWriter, r *http.Request)

Directories

Path Synopsis
Package psbinding provides facilities to make authoring Bindings that work with "Pod Spec"-able subjects easier.
Package psbinding provides facilities to make authoring Bindings that work with "Pod Spec"-able subjects easier.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL