mirror of https://github.com/linkerd/linkerd2.git
110 lines
2.3 KiB
Go
110 lines
2.3 KiB
Go
package injector
|
|
|
|
import (
|
|
"context"
|
|
"crypto/tls"
|
|
"encoding/json"
|
|
"io/ioutil"
|
|
"net/http"
|
|
|
|
pem "github.com/linkerd/linkerd2/pkg/tls"
|
|
log "github.com/sirupsen/logrus"
|
|
"k8s.io/client-go/kubernetes"
|
|
)
|
|
|
|
// WebhookServer is the webhook's HTTP server. It has an embedded webhook which
|
|
// mutate all the requests.
|
|
type WebhookServer struct {
|
|
*http.Server
|
|
*Webhook
|
|
}
|
|
|
|
// NewWebhookServer returns a new instance of the WebhookServer.
|
|
func NewWebhookServer(client kubernetes.Interface, resources *WebhookResources, addr, controllerNamespace, certFile, keyFile string) (*WebhookServer, error) {
|
|
c, err := tlsConfig(certFile, keyFile)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
server := &http.Server{
|
|
Addr: addr,
|
|
TLSConfig: c,
|
|
}
|
|
|
|
webhook, err := NewWebhook(client, resources, controllerNamespace)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
ws := &WebhookServer{server, webhook}
|
|
ws.Handler = http.HandlerFunc(ws.serve)
|
|
return ws, nil
|
|
}
|
|
|
|
func (w *WebhookServer) serve(res http.ResponseWriter, req *http.Request) {
|
|
var (
|
|
data []byte
|
|
err error
|
|
)
|
|
if req.Body != nil {
|
|
data, err = ioutil.ReadAll(req.Body)
|
|
if err != nil {
|
|
http.Error(res, err.Error(), http.StatusInternalServerError)
|
|
return
|
|
}
|
|
}
|
|
|
|
if len(data) == 0 {
|
|
return
|
|
}
|
|
|
|
response := w.Mutate(data)
|
|
responseJSON, err := json.Marshal(response)
|
|
if err != nil {
|
|
http.Error(res, err.Error(), http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
if _, err := res.Write(responseJSON); err != nil {
|
|
http.Error(res, err.Error(), http.StatusInternalServerError)
|
|
return
|
|
}
|
|
}
|
|
|
|
// Shutdown initiates a graceful shutdown of the underlying HTTP server.
|
|
func (w *WebhookServer) Shutdown() error {
|
|
return w.Server.Shutdown(context.Background())
|
|
}
|
|
|
|
func tlsConfig(certFile, keyFile string) (*tls.Config, error) {
|
|
certBytes, err := ioutil.ReadFile(certFile)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
keyBytes, err := ioutil.ReadFile(keyFile)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
certPEM, err := pem.PEMEncodeCert(certBytes)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
log.Debugf("PEM-encoded certificate: %s\n", certPEM)
|
|
|
|
keyPEM, err := pem.PEMEncodeKey(keyBytes, pem.KeyTypeECDSA)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
cert, err := tls.X509KeyPair(certPEM, keyPEM)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &tls.Config{
|
|
Certificates: []tls.Certificate{cert},
|
|
}, nil
|
|
}
|