Skip to content

Commit

Permalink
Using HTTP Proxy for Webhooks
Browse files Browse the repository at this point in the history
Signed-off-by: Maksim Paskal <[email protected]>
  • Loading branch information
maksim-paskal committed Jul 29, 2024
1 parent cde1c54 commit 0b7df9e
Show file tree
Hide file tree
Showing 7 changed files with 84 additions and 15 deletions.
31 changes: 31 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,37 @@ aks-node-termination-handler/aks-node-termination-handler \
```
</details>

<details>
<summary>Use HTTP Proxy for making webhook requests</summary>

Use flag `-webhook.http-proxy=https://someproxy:3128` for making requests with PROXY

```bash
cat <<EOF | tee values.yaml
priorityClassName: system-node-critical
args:
- -webhook.url=https://someserver/somepath
- -webhook.template-file=/files/payload.json
- -webhook.contentType=text/plain
- -webhook.method=POST
- -webhook.timeout=30s
- -webhook.http-proxy=https://someproxy:3128
configMap:
data:
payload.json: "This is message for {{ .NodeName }}, {{ .InstanceType }} from {{ .NodeRegion }}"
EOF

# install/upgrade helm chart
helm upgrade aks-node-termination-handler \
--install \
--namespace kube-system \
aks-node-termination-handler/aks-node-termination-handler \
--values values.yaml
```
</details>

## Simulate eviction

### Using Azure CLI
Expand Down
9 changes: 9 additions & 0 deletions internal/internal.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,15 @@ 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"
"github.com/maksim-paskal/aks-node-termination-handler/pkg/cache"
"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"
Expand All @@ -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")
Expand Down
4 changes: 4 additions & 0 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ type Type struct {
WebHookTemplateFile *string
WebHookMethod *string
WebHookTimeout *time.Duration
WebhookInsecure *bool
WebhookProxy *string
SentryDSN *string
WebHTTPAddress *string
TaintNode *bool
Expand Down Expand Up @@ -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"),
Expand Down
2 changes: 1 addition & 1 deletion pkg/events/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ const (
)

var httpClient = &http.Client{
Transport: metrics.NewInstrumenter("events", false).InstrumentedRoundTripper(),
Transport: metrics.NewInstrumenter("events").InstrumentedRoundTripper(),
}

type Reader struct {
Expand Down
42 changes: 33 additions & 9 deletions pkg/metrics/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,24 +26,37 @@ 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"

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_<identifier>_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{
Expand Down Expand Up @@ -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),
),
)
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/metrics/metrics_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
9 changes: 5 additions & 4 deletions pkg/webhook/webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down

0 comments on commit 0b7df9e

Please sign in to comment.