...

Source file src/sigs.k8s.io/controller-runtime/pkg/webhook/authentication/webhook.go

Documentation: sigs.k8s.io/controller-runtime/pkg/webhook/authentication

     1  /*
     2  Copyright 2021 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8     http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package authentication
    18  
    19  import (
    20  	"context"
    21  	"errors"
    22  	"net/http"
    23  	"sync"
    24  
    25  	"github.com/go-logr/logr"
    26  	authenticationv1 "k8s.io/api/authentication/v1"
    27  	"k8s.io/klog/v2"
    28  
    29  	logf "sigs.k8s.io/controller-runtime/pkg/log"
    30  )
    31  
    32  var (
    33  	errUnableToEncodeResponse = errors.New("unable to encode response")
    34  )
    35  
    36  // Request defines the input for an authentication handler.
    37  // It contains information to identify the object in
    38  // question (group, version, kind, resource, subresource,
    39  // name, namespace), as well as the operation in question
    40  // (e.g. Get, Create, etc), and the object itself.
    41  type Request struct {
    42  	authenticationv1.TokenReview
    43  }
    44  
    45  // Response is the output of an authentication handler.
    46  // It contains a response indicating if a given
    47  // operation is allowed.
    48  type Response struct {
    49  	authenticationv1.TokenReview
    50  }
    51  
    52  // Complete populates any fields that are yet to be set in
    53  // the underlying TokenResponse, It mutates the response.
    54  func (r *Response) Complete(req Request) error {
    55  	r.UID = req.UID
    56  
    57  	return nil
    58  }
    59  
    60  // Handler can handle an TokenReview.
    61  type Handler interface {
    62  	// Handle yields a response to an TokenReview.
    63  	//
    64  	// The supplied context is extracted from the received http.Request, allowing wrapping
    65  	// http.Handlers to inject values into and control cancelation of downstream request processing.
    66  	Handle(context.Context, Request) Response
    67  }
    68  
    69  // HandlerFunc implements Handler interface using a single function.
    70  type HandlerFunc func(context.Context, Request) Response
    71  
    72  var _ Handler = HandlerFunc(nil)
    73  
    74  // Handle process the TokenReview by invoking the underlying function.
    75  func (f HandlerFunc) Handle(ctx context.Context, req Request) Response {
    76  	return f(ctx, req)
    77  }
    78  
    79  // Webhook represents each individual webhook.
    80  type Webhook struct {
    81  	// Handler actually processes an authentication request returning whether it was authenticated or unauthenticated,
    82  	// and potentially patches to apply to the handler.
    83  	Handler Handler
    84  
    85  	// WithContextFunc will allow you to take the http.Request.Context() and
    86  	// add any additional information such as passing the request path or
    87  	// headers thus allowing you to read them from within the handler
    88  	WithContextFunc func(context.Context, *http.Request) context.Context
    89  
    90  	setupLogOnce sync.Once
    91  	log          logr.Logger
    92  }
    93  
    94  // Handle processes TokenReview.
    95  func (wh *Webhook) Handle(ctx context.Context, req Request) Response {
    96  	resp := wh.Handler.Handle(ctx, req)
    97  	if err := resp.Complete(req); err != nil {
    98  		wh.getLogger(&req).Error(err, "unable to encode response")
    99  		return Errored(errUnableToEncodeResponse)
   100  	}
   101  
   102  	return resp
   103  }
   104  
   105  // getLogger constructs a logger from the injected log and LogConstructor.
   106  func (wh *Webhook) getLogger(req *Request) logr.Logger {
   107  	wh.setupLogOnce.Do(func() {
   108  		if wh.log.GetSink() == nil {
   109  			wh.log = logf.Log.WithName("authentication")
   110  		}
   111  	})
   112  
   113  	return logConstructor(wh.log, req)
   114  }
   115  
   116  // logConstructor adds some commonly interesting fields to the given logger.
   117  func logConstructor(base logr.Logger, req *Request) logr.Logger {
   118  	if req != nil {
   119  		return base.WithValues("object", klog.KRef(req.Namespace, req.Name),
   120  			"namespace", req.Namespace, "name", req.Name,
   121  			"user", req.Status.User.Username,
   122  			"requestID", req.UID,
   123  		)
   124  	}
   125  	return base
   126  }
   127  

View as plain text