2019-05-13 21:33:01 +03:00
|
|
|
package webhooks
|
2019-02-07 19:22:04 +02:00
|
|
|
|
|
|
|
import (
|
2019-03-04 20:40:02 +02:00
|
|
|
"context"
|
|
|
|
"crypto/tls"
|
|
|
|
"net/http"
|
|
|
|
"time"
|
|
|
|
|
2020-03-17 11:05:20 -07:00
|
|
|
"github.com/go-logr/logr"
|
2020-04-27 18:38:03 +05:30
|
|
|
"github.com/julienschmidt/httprouter"
|
2020-10-07 11:12:31 -07:00
|
|
|
"github.com/kyverno/kyverno/pkg/config"
|
|
|
|
"github.com/kyverno/kyverno/pkg/webhookconfig"
|
2022-03-31 17:34:10 +02:00
|
|
|
"github.com/kyverno/kyverno/pkg/webhooks/handlers"
|
2022-04-06 22:43:07 +02:00
|
|
|
admissionv1 "k8s.io/api/admission/v1"
|
2019-02-07 19:22:04 +02:00
|
|
|
)
|
|
|
|
|
2022-05-16 16:36:21 +02:00
|
|
|
type Server interface {
|
|
|
|
// Run TLS server in separate thread and returns control immediately
|
|
|
|
Run(<-chan struct{})
|
|
|
|
// Stop TLS server and returns control after the server is shut down
|
|
|
|
Stop(context.Context)
|
|
|
|
}
|
|
|
|
|
2022-05-13 07:33:20 +02:00
|
|
|
type Handlers interface {
|
|
|
|
// Mutate performs the mutation of policy resources
|
|
|
|
Mutate(logr.Logger, *admissionv1.AdmissionRequest) *admissionv1.AdmissionResponse
|
|
|
|
// Validate performs the validation check on policy resources
|
|
|
|
Validate(logr.Logger, *admissionv1.AdmissionRequest) *admissionv1.AdmissionResponse
|
|
|
|
}
|
|
|
|
|
2022-05-16 16:36:21 +02:00
|
|
|
type server struct {
|
|
|
|
server *http.Server
|
2020-11-26 16:07:06 -08:00
|
|
|
webhookRegister *webhookconfig.Register
|
2022-05-16 16:36:21 +02:00
|
|
|
cleanUp chan<- struct{}
|
2019-03-04 20:40:02 +02:00
|
|
|
}
|
|
|
|
|
2022-05-16 16:36:21 +02:00
|
|
|
type TlsProvider func() ([]byte, []byte, error)
|
|
|
|
|
|
|
|
// NewServer creates new instance of server accordingly to given configuration
|
|
|
|
func NewServer(
|
2022-05-13 07:33:20 +02:00
|
|
|
policyHandlers Handlers,
|
2022-05-16 16:36:21 +02:00
|
|
|
resourceHandlers Handlers,
|
|
|
|
tlsProvider TlsProvider,
|
|
|
|
configuration config.Configuration,
|
|
|
|
register *webhookconfig.Register,
|
|
|
|
monitor *webhookconfig.Monitor,
|
2020-03-17 11:05:20 -07:00
|
|
|
cleanUp chan<- struct{},
|
2022-05-16 16:36:21 +02:00
|
|
|
) Server {
|
2020-04-27 18:38:03 +05:30
|
|
|
mux := httprouter.New()
|
2022-05-16 16:36:21 +02:00
|
|
|
resourceLogger := logger.WithName("resource")
|
|
|
|
policyLogger := logger.WithName("policy")
|
|
|
|
verifyLogger := logger.WithName("verify")
|
|
|
|
mux.HandlerFunc("POST", config.MutatingWebhookServicePath, admission(resourceLogger.WithName("mutate"), monitor, filter(configuration, resourceHandlers.Mutate)))
|
|
|
|
mux.HandlerFunc("POST", config.ValidatingWebhookServicePath, admission(resourceLogger.WithName("validate"), monitor, filter(configuration, resourceHandlers.Validate)))
|
|
|
|
mux.HandlerFunc("POST", config.PolicyMutatingWebhookServicePath, admission(policyLogger.WithName("mutate"), monitor, filter(configuration, policyHandlers.Mutate)))
|
|
|
|
mux.HandlerFunc("POST", config.PolicyValidatingWebhookServicePath, admission(policyLogger.WithName("validate"), monitor, filter(configuration, policyHandlers.Validate)))
|
|
|
|
mux.HandlerFunc("POST", config.VerifyMutatingWebhookServicePath, admission(verifyLogger.WithName("mutate"), monitor, handlers.Verify(monitor)))
|
|
|
|
mux.HandlerFunc("GET", config.LivenessServicePath, handlers.Probe(register.Check))
|
2022-03-31 17:34:10 +02:00
|
|
|
mux.HandlerFunc("GET", config.ReadinessServicePath, handlers.Probe(nil))
|
2022-05-16 16:36:21 +02:00
|
|
|
return &server{
|
|
|
|
server: &http.Server{
|
|
|
|
Addr: ":9443",
|
|
|
|
TLSConfig: &tls.Config{
|
|
|
|
GetCertificate: func(*tls.ClientHelloInfo) (*tls.Certificate, error) {
|
|
|
|
certPem, keyPem, err := tlsProvider()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
pair, err := tls.X509KeyPair(certPem, keyPem)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return &pair, nil
|
|
|
|
},
|
|
|
|
MinVersion: tls.VersionTLS12,
|
2022-05-10 11:55:39 +02:00
|
|
|
},
|
2022-05-16 16:36:21 +02:00
|
|
|
Handler: mux,
|
|
|
|
ReadTimeout: 30 * time.Second,
|
|
|
|
WriteTimeout: 30 * time.Second,
|
2022-05-10 11:55:39 +02:00
|
|
|
},
|
2022-05-16 16:36:21 +02:00
|
|
|
webhookRegister: register,
|
|
|
|
cleanUp: cleanUp,
|
2019-03-04 20:40:02 +02:00
|
|
|
}
|
2019-02-21 20:31:18 +02:00
|
|
|
}
|
|
|
|
|
2022-05-16 16:36:21 +02:00
|
|
|
func (s *server) Run(stopCh <-chan struct{}) {
|
|
|
|
go func() {
|
|
|
|
logger.V(3).Info("started serving requests", "addr", s.server.Addr)
|
|
|
|
if err := s.server.ListenAndServeTLS("", ""); err != http.ErrServerClosed {
|
|
|
|
logger.Error(err, "failed to listen to requests")
|
2022-05-05 14:06:18 -07:00
|
|
|
}
|
2022-05-16 16:36:21 +02:00
|
|
|
}()
|
|
|
|
logger.Info("starting service")
|
2021-07-09 18:01:46 -07:00
|
|
|
}
|
2021-03-23 10:34:03 -07:00
|
|
|
|
2022-05-16 16:36:21 +02:00
|
|
|
func (s *server) Stop(ctx context.Context) {
|
|
|
|
go s.webhookRegister.Remove(s.cleanUp)
|
|
|
|
err := s.server.Shutdown(ctx)
|
2022-05-05 14:06:18 -07:00
|
|
|
if err != nil {
|
2022-05-16 16:36:21 +02:00
|
|
|
logger.Error(err, "shutting down server")
|
|
|
|
err = s.server.Close()
|
2022-05-05 14:06:18 -07:00
|
|
|
if err != nil {
|
2022-05-16 16:36:21 +02:00
|
|
|
logger.Error(err, "server shut down failed")
|
2022-05-05 14:06:18 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-16 16:36:21 +02:00
|
|
|
func filter(configuration config.Configuration, inner handlers.AdmissionHandler) handlers.AdmissionHandler {
|
|
|
|
return handlers.Filter(configuration, inner)
|
2019-02-07 19:22:04 +02:00
|
|
|
}
|
|
|
|
|
2022-05-16 16:36:21 +02:00
|
|
|
func admission(logger logr.Logger, monitor *webhookconfig.Monitor, inner handlers.AdmissionHandler) http.HandlerFunc {
|
|
|
|
return handlers.Monitor(monitor, handlers.Admission(logger, inner))
|
2019-02-07 19:22:04 +02:00
|
|
|
}
|