diff --git a/artifacts/flagger/crd.yaml b/artifacts/flagger/crd.yaml index 99940df06..2db00bb55 100644 --- a/artifacts/flagger/crd.yaml +++ b/artifacts/flagger/crd.yaml @@ -1135,6 +1135,9 @@ spec: retries: description: Number of retries for this webhook type: number + disableTLS: + description: Disable TLS verification for this webhook + type: boolean metadata: description: Metadata (key-value pairs) for this webhook type: object diff --git a/charts/flagger/crds/crd.yaml b/charts/flagger/crds/crd.yaml index 99940df06..2db00bb55 100644 --- a/charts/flagger/crds/crd.yaml +++ b/charts/flagger/crds/crd.yaml @@ -1135,6 +1135,9 @@ spec: retries: description: Number of retries for this webhook type: number + disableTLS: + description: Disable TLS verification for this webhook + type: boolean metadata: description: Metadata (key-value pairs) for this webhook type: object diff --git a/docs/gitbook/usage/webhooks.md b/docs/gitbook/usage/webhooks.md index 994885b67..f37d549c6 100644 --- a/docs/gitbook/usage/webhooks.md +++ b/docs/gitbook/usage/webhooks.md @@ -124,7 +124,10 @@ Event payload (HTTP POST): The event receiver can create alerts based on the received phase (possible values: `Initialized`, `Waiting`, `Progressing`, `Promoting`, `Finalising`, `Succeeded` or `Failed`). -The webhook request can be retried by specifying a positive integer in the `retries` field. +Options: +* retries: The webhook request can be retried by specifying a positive integer in the `retries` field. This helps ensure reliability if the webhook fails due to transient network issues. + +* disable TLS: Set `disableTLS` to `true` in the webhook spec to bypass TLS verification. This is useful in cases where the target service uses self-signed certificates, or you need to connect to an insecure service for testing purposes. ## Load Testing diff --git a/kustomize/base/flagger/crd.yaml b/kustomize/base/flagger/crd.yaml index 99940df06..2db00bb55 100644 --- a/kustomize/base/flagger/crd.yaml +++ b/kustomize/base/flagger/crd.yaml @@ -1135,6 +1135,9 @@ spec: retries: description: Number of retries for this webhook type: number + disableTLS: + description: Disable TLS verification for this webhook + type: boolean metadata: description: Metadata (key-value pairs) for this webhook type: object diff --git a/pkg/apis/flagger/v1beta1/canary.go b/pkg/apis/flagger/v1beta1/canary.go index 93fe004ed..50b235f97 100644 --- a/pkg/apis/flagger/v1beta1/canary.go +++ b/pkg/apis/flagger/v1beta1/canary.go @@ -398,6 +398,10 @@ type CanaryWebhook struct { // Number of retries for this webhook // +optional Retries int `json:"retries,omitempty"` + + // Disable TLS verification for this webhook + // +optional + DisableTLS bool `json:"disableTls,omitempty"` } // CanaryWebhookPayload holds the deployment info and metadata sent to webhooks diff --git a/pkg/controller/webhook.go b/pkg/controller/webhook.go index 5b08bd85d..cf8dcd89b 100644 --- a/pkg/controller/webhook.go +++ b/pkg/controller/webhook.go @@ -18,10 +18,12 @@ package controller import ( "bytes" + "crypto/tls" "encoding/json" "errors" "fmt" "io" + "net/http" "net/url" "strconv" "time" @@ -32,28 +34,32 @@ import ( "github.com/fluxcd/flagger/pkg/canary" ) -func callWebhook(webhook string, payload interface{}, timeout string, retries int) error { - payloadBin, err := json.Marshal(payload) - if err != nil { - return err +func newHTTPClient(retries int, timeout time.Duration, disableTls bool) *retryablehttp.Client { + httpClient := retryablehttp.NewClient() + httpClient.RetryMax = retries + httpClient.Logger = nil + httpClient.HTTPClient.Timeout = timeout + + if disableTls { + httpClient.HTTPClient.Transport = &http.Transport{ + TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, + } } - hook, err := url.Parse(webhook) + return httpClient +} + +func callWebhook(webhook string, payload interface{}, timeout string, retries int, disableTls bool) error { + payloadBin, err := json.Marshal(payload) if err != nil { return err } - httpClient := retryablehttp.NewClient() - httpClient.RetryMax = retries - httpClient.Logger = nil - - req, err := retryablehttp.NewRequest("POST", hook.String(), bytes.NewBuffer(payloadBin)) + hook, err := url.Parse(webhook) if err != nil { return err } - req.Header.Set("Content-Type", "application/json") - if timeout == "" { timeout = "10s" } @@ -62,7 +68,13 @@ func callWebhook(webhook string, payload interface{}, timeout string, retries in return err } - httpClient.HTTPClient.Timeout = t + httpClient := newHTTPClient(retries, t, disableTls) + + req, err := retryablehttp.NewRequest("POST", hook.String(), bytes.NewBuffer(payloadBin)) + if err != nil { + return err + } + req.Header.Set("Content-Type", "application/json") r, err := httpClient.Do(req) if err != nil { @@ -100,7 +112,7 @@ func CallWebhook(canary flaggerv1.Canary, phase flaggerv1.CanaryPhase, w flagger w.Timeout = "10s" } - return callWebhook(w.URL, payload, w.Timeout, w.Retries) + return callWebhook(w.URL, payload, w.Timeout, w.Retries, w.DisableTLS) } func CallEventWebhook(r *flaggerv1.Canary, w flaggerv1.CanaryWebhook, message, eventtype string) error { @@ -126,7 +138,7 @@ func CallEventWebhook(r *flaggerv1.Canary, w flaggerv1.CanaryWebhook, message, e payload.Metadata[key] = value } } - return callWebhook(w.URL, payload, "5s", w.Retries) + return callWebhook(w.URL, payload, "5s", w.Retries, w.DisableTLS) } func canaryChecksum(c flaggerv1.Canary) string { diff --git a/pkg/controller/webhook_test.go b/pkg/controller/webhook_test.go index d651da006..9d0022e2f 100644 --- a/pkg/controller/webhook_test.go +++ b/pkg/controller/webhook_test.go @@ -289,3 +289,22 @@ func TestCallWebhook_Retries(t *testing.T) { flaggerv1.CanaryPhaseProgressing, hook) require.NoError(t, err) } + +func TestCallWebhook_DisableTLS(t *testing.T) { + ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusAccepted) + })) + defer ts.Close() + hook := flaggerv1.CanaryWebhook{ + Name: "validation", + URL: ts.URL, + DisableTLS: true, + } + + err := CallWebhook( + flaggerv1.Canary{ + ObjectMeta: metav1.ObjectMeta{ + Name: "podinfo", Namespace: corev1.NamespaceDefault}}, + flaggerv1.CanaryPhaseProgressing, hook) + require.NoError(t, err) +}