From f3cf34e50aa01a956b806b82a8ba5104a3068d17 Mon Sep 17 00:00:00 2001 From: Daniel Date: Mon, 2 May 2022 19:53:36 +0300 Subject: [PATCH] fix: Enforce webhook secret in BitbucketServer event source (#1917) * fix: Webhook secret to be optional field in bitbucketserver es Signed-off-by: Daniel Soifer --- eventsources/sources/bitbucketserver/start.go | 31 +++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/eventsources/sources/bitbucketserver/start.go b/eventsources/sources/bitbucketserver/start.go index 8efa30bf41..0ec837d952 100644 --- a/eventsources/sources/bitbucketserver/start.go +++ b/eventsources/sources/bitbucketserver/start.go @@ -17,6 +17,9 @@ package bitbucketserver import ( "context" + "crypto/hmac" + "crypto/sha256" + "encoding/hex" "encoding/json" "io/ioutil" "math/rand" @@ -80,9 +83,9 @@ func (router *Router) HandleRoute(writer http.ResponseWriter, request *http.Requ route.Metrics.EventProcessingDuration(route.EventSourceName, route.EventName, float64(time.Since(start)/time.Millisecond)) }(time.Now()) - body, err := ioutil.ReadAll(request.Body) + body, err := router.parseAndValidateBitbucketServerRequest(request) if err != nil { - logger.Errorw("failed to parse request body", zap.Error(err)) + logger.Errorw("failed to parse/validate request", zap.Error(err)) common.SendErrorResponse(writer, err.Error()) route.Metrics.EventProcessingFailed(route.EventSourceName, route.EventName) return @@ -387,3 +390,27 @@ func (router *Router) createRequestBodyFromWebhook(hook bitbucketv1.Webhook) ([] return requestBody, nil } + +func (router *Router) parseAndValidateBitbucketServerRequest(request *http.Request) ([]byte, error) { + body, err := ioutil.ReadAll(request.Body) + if err != nil { + return nil, errors.Wrap(err, "failed to parse request body") + } + + if len(router.hookSecret) != 0 { + signature := request.Header.Get("X-Hub-Signature") + if len(signature) == 0 { + return nil, errors.New("missing signature header") + } + + mac := hmac.New(sha256.New, []byte(router.hookSecret)) + _, _ = mac.Write(body) + expectedMAC := hex.EncodeToString(mac.Sum(nil)) + + if !hmac.Equal([]byte(signature[7:]), []byte(expectedMAC)) { + return nil, errors.New("hmac verification failed") + } + } + + return body, nil +}