From 0b7df9e513f1364b158c102551913f6e16e10814 Mon Sep 17 00:00:00 2001 From: Maksim Paskal Date: Mon, 29 Jul 2024 16:01:49 +0100 Subject: [PATCH] Using HTTP Proxy for Webhooks Signed-off-by: Maksim Paskal --- README.md | 31 +++++++++++++++++++++++++++ internal/internal.go | 9 ++++++++ pkg/config/config.go | 4 ++++ pkg/events/events.go | 2 +- pkg/metrics/metrics.go | 42 +++++++++++++++++++++++++++++-------- pkg/metrics/metrics_test.go | 2 +- pkg/webhook/webhook.go | 9 ++++---- 7 files changed, 84 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 47fc286..323e595 100644 --- a/README.md +++ b/README.md @@ -184,6 +184,37 @@ aks-node-termination-handler/aks-node-termination-handler \ ``` +
+ Use HTTP Proxy for making webhook requests + +Use flag `-webhook.http-proxy=https://someproxy:3128` for making requests with PROXY + +```bash +cat < + ## Simulate eviction ### Using Azure CLI diff --git a/internal/internal.go b/internal/internal.go index 2e5cec7..d3dd580 100644 --- a/internal/internal.go +++ b/internal/internal.go @@ -14,6 +14,7 @@ package internal import ( "context" + "net/http" "github.com/maksim-paskal/aks-node-termination-handler/pkg/alert" "github.com/maksim-paskal/aks-node-termination-handler/pkg/api" @@ -21,6 +22,7 @@ import ( "github.com/maksim-paskal/aks-node-termination-handler/pkg/client" "github.com/maksim-paskal/aks-node-termination-handler/pkg/config" "github.com/maksim-paskal/aks-node-termination-handler/pkg/events" + "github.com/maksim-paskal/aks-node-termination-handler/pkg/metrics" "github.com/maksim-paskal/aks-node-termination-handler/pkg/template" "github.com/maksim-paskal/aks-node-termination-handler/pkg/types" "github.com/maksim-paskal/aks-node-termination-handler/pkg/web" @@ -42,6 +44,13 @@ func Run(ctx context.Context) error { log.Debugf("using config: %s", config.Get().String()) + webhook.SetHTTPClient(&http.Client{ + Transport: metrics.NewInstrumenter("webhook"). + WithProxy(*config.Get().WebhookProxy). + WithInsecureSkipVerify(*config.Get().WebhookInsecure). + InstrumentedRoundTripper(), + }) + err = alert.Init() if err != nil { return errors.Wrap(err, "error in init alerts") diff --git a/pkg/config/config.go b/pkg/config/config.go index a9bd6aa..49c75c5 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -66,6 +66,8 @@ type Type struct { WebHookTemplateFile *string WebHookMethod *string WebHookTimeout *time.Duration + WebhookInsecure *bool + WebhookProxy *string SentryDSN *string WebHTTPAddress *string TaintNode *bool @@ -96,6 +98,8 @@ var config = Type{ WebHookTimeout: flag.Duration("webhook.timeout", defaultWebHookTimeout, "request timeout"), WebHookTemplate: flag.String("webhook.template", os.Getenv("WEBHOOK_TEMPLATE"), "request body"), WebHookTemplateFile: flag.String("webhook.template-file", os.Getenv("WEBHOOK_TEMPLATE_FILE"), "path to request body template file"), + WebhookInsecure: flag.Bool("webhook.insecureSkip", true, "skip tls verification for webhook"), + WebhookProxy: flag.String("webhook.http-proxy", os.Getenv("WEBHOOK_HTTP_PROXY"), "use http proxy for webhook"), SentryDSN: flag.String("sentry.dsn", "", "sentry DSN"), WebHTTPAddress: flag.String("web.address", ":17923", ""), TaintNode: flag.Bool("taint.node", false, "Taint the node before cordon and draining"), diff --git a/pkg/events/events.go b/pkg/events/events.go index 4961fb3..a018ac5 100644 --- a/pkg/events/events.go +++ b/pkg/events/events.go @@ -34,7 +34,7 @@ const ( ) var httpClient = &http.Client{ - Transport: metrics.NewInstrumenter("events", false).InstrumentedRoundTripper(), + Transport: metrics.NewInstrumenter("events").InstrumentedRoundTripper(), } type Reader struct { diff --git a/pkg/metrics/metrics.go b/pkg/metrics/metrics.go index 67e7e94..f33c69b 100644 --- a/pkg/metrics/metrics.go +++ b/pkg/metrics/metrics.go @@ -26,6 +26,7 @@ import ( "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" "github.com/prometheus/client_golang/prometheus/promhttp" + log "github.com/sirupsen/logrus" ) const namespace = "aks_node_termination_handler" @@ -33,17 +34,29 @@ const namespace = "aks_node_termination_handler" type Instrumenter struct { subsystemIdentifier string insecureSkipVerify bool + proxyURL string } // New creates a new Instrumenter. The subsystemIdentifier will be used as part of // the metric names (e.g. http__requests_total). -func NewInstrumenter(subsystemIdentifier string, insecureSkipVerify bool) *Instrumenter { +func NewInstrumenter(subsystemIdentifier string) *Instrumenter { return &Instrumenter{ subsystemIdentifier: subsystemIdentifier, - insecureSkipVerify: insecureSkipVerify, } } +func (i *Instrumenter) WithProxy(proxyURL string) *Instrumenter { + i.proxyURL = proxyURL + + return i +} + +func (i *Instrumenter) WithInsecureSkipVerify(insecure bool) *Instrumenter { + i.insecureSkipVerify = insecure + + return i +} + // InstrumentedRoundTripper returns an instrumented round tripper. func (i *Instrumenter) InstrumentedRoundTripper() http.RoundTripper { inFlightRequestsGauge := promauto.NewGauge(prometheus.GaugeOpts{ @@ -71,15 +84,26 @@ func (i *Instrumenter) InstrumentedRoundTripper() http.RoundTripper { []string{"method"}, ) + defaultTransport := &http.Transport{ + TLSClientConfig: &tls.Config{ + InsecureSkipVerify: i.insecureSkipVerify, //nolint:gosec + }, + } + + if len(i.proxyURL) > 0 { + proxyURL, err := url.Parse(i.proxyURL) + if err != nil { + log.WithError(err).Errorf("error parsing proxy url %s for %s", i.proxyURL, i.subsystemIdentifier) + } else { + log.Infof("using http_proxy %s for %s", i.proxyURL, i.subsystemIdentifier) + + defaultTransport.Proxy = http.ProxyURL(proxyURL) + } + } + return promhttp.InstrumentRoundTripperInFlight(inFlightRequestsGauge, promhttp.InstrumentRoundTripperDuration(requestLatencyHistogram, - i.instrumentRoundTripperEndpoint(requestsPerEndpointCounter, - &http.Transport{ - TLSClientConfig: &tls.Config{ - InsecureSkipVerify: i.insecureSkipVerify, //nolint:gosec - }, - }, - ), + i.instrumentRoundTripperEndpoint(requestsPerEndpointCounter, defaultTransport), ), ) } diff --git a/pkg/metrics/metrics_test.go b/pkg/metrics/metrics_test.go index 8ccb385..7eb6178 100644 --- a/pkg/metrics/metrics_test.go +++ b/pkg/metrics/metrics_test.go @@ -77,7 +77,7 @@ func TestKubernetesMetrics(t *testing.T) { func TestInstrumenter(t *testing.T) { t.Parallel() - instrumenter := metrics.NewInstrumenter("test", false) + instrumenter := metrics.NewInstrumenter("test") r, err := instrumenter.InstrumentedRoundTripper().RoundTrip(httptest.NewRequest(http.MethodGet, ts.URL, nil)) if err != nil { diff --git a/pkg/webhook/webhook.go b/pkg/webhook/webhook.go index 75f3674..493f5b0 100644 --- a/pkg/webhook/webhook.go +++ b/pkg/webhook/webhook.go @@ -20,18 +20,19 @@ import ( "os" "github.com/maksim-paskal/aks-node-termination-handler/pkg/config" - "github.com/maksim-paskal/aks-node-termination-handler/pkg/metrics" "github.com/maksim-paskal/aks-node-termination-handler/pkg/template" "github.com/pkg/errors" log "github.com/sirupsen/logrus" ) -var client = &http.Client{ - Transport: metrics.NewInstrumenter("webhook", true).InstrumentedRoundTripper(), -} +var client = &http.Client{} var errHTTPNotOK = errors.New("http result not OK") +func SetHTTPClient(c *http.Client) { + client = c +} + func SendWebHook(ctx context.Context, obj *template.MessageType) error { ctx, cancel := context.WithTimeout(ctx, *config.Get().WebHookTimeout) defer cancel()