Skip to content

Commit

Permalink
feat: move basic auth for for Azure DevOps to webhooks lib (#19407)
Browse files Browse the repository at this point in the history
Signed-off-by: Robin Lieb <robin.j.lieb@gmail.com>
  • Loading branch information
robinlieb committed Aug 7, 2024
1 parent da1e95d commit 4f64f0f
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 59 deletions.
54 changes: 17 additions & 37 deletions applicationset/webhook/webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package webhook

import (
"context"
"errors"
"fmt"
"html"
"net/http"
Expand All @@ -29,18 +28,15 @@ import (

const payloadQueueSize = 50000

var errBasicAuthVerificationFailed = errors.New("basic auth verification failed")

type WebhookHandler struct {
sync.WaitGroup // for testing
namespace string
github *github.Webhook
gitlab *gitlab.Webhook
azuredevops *azuredevops.Webhook
azuredevopsAuthHandler func(r *http.Request) error
client client.Client
generators map[string]generators.Generator
queue chan interface{}
sync.WaitGroup // for testing
namespace string
github *github.Webhook
gitlab *gitlab.Webhook
azuredevops *azuredevops.Webhook
client client.Client
generators map[string]generators.Generator
queue chan interface{}
}

type gitGeneratorInfo struct {
Expand Down Expand Up @@ -85,29 +81,19 @@ func NewWebhookHandler(namespace string, webhookParallelism int, argocdSettingsM
if err != nil {
return nil, fmt.Errorf("Unable to init GitLab webhook: %w", err)
}
azuredevopsHandler, err := azuredevops.New()
azuredevopsHandler, err := azuredevops.New(azuredevops.Options.BasicAuth(argocdSettings.WebhookAzureDevOpsUsername, argocdSettings.WebhookAzureDevOpsPassword))
if err != nil {
return nil, fmt.Errorf("Unable to init Azure DevOps webhook: %w", err)
}
azuredevopsAuthHandler := func(r *http.Request) error {
if argocdSettings.WebhookAzureDevOpsUsername != "" && argocdSettings.WebhookAzureDevOpsPassword != "" {
username, password, ok := r.BasicAuth()
if !ok || username != argocdSettings.WebhookAzureDevOpsUsername || password != argocdSettings.WebhookAzureDevOpsPassword {
return errBasicAuthVerificationFailed
}
}
return nil
}

webhookHandler := &WebhookHandler{
namespace: namespace,
github: githubHandler,
gitlab: gitlabHandler,
azuredevops: azuredevopsHandler,
azuredevopsAuthHandler: azuredevopsAuthHandler,
client: client,
generators: generators,
queue: make(chan interface{}, payloadQueueSize),
namespace: namespace,
github: githubHandler,
gitlab: gitlabHandler,
azuredevops: azuredevopsHandler,
client: client,
generators: generators,
queue: make(chan interface{}, payloadQueueSize),
}

webhookHandler.startWorkerPool(webhookParallelism)
Expand Down Expand Up @@ -179,13 +165,7 @@ func (h *WebhookHandler) Handler(w http.ResponseWriter, r *http.Request) {
case r.Header.Get("X-Gitlab-Event") != "":
payload, err = h.gitlab.Parse(r, gitlab.PushEvents, gitlab.TagEvents, gitlab.MergeRequestEvents)
case r.Header.Get("X-Vss-Activityid") != "":
if err = h.azuredevopsAuthHandler(r); err != nil {
if errors.Is(err, errBasicAuthVerificationFailed) {
log.WithField(common.SecurityField, common.SecurityHigh).Infof("Azure DevOps webhook basic auth verification failed")
}
} else {
payload, err = h.azuredevops.Parse(r, azuredevops.GitPushEventType, azuredevops.GitPullRequestCreatedEventType, azuredevops.GitPullRequestUpdatedEventType, azuredevops.GitPullRequestMergedEventType)
}
payload, err = h.azuredevops.Parse(r, azuredevops.GitPushEventType, azuredevops.GitPullRequestCreatedEventType, azuredevops.GitPullRequestUpdatedEventType, azuredevops.GitPullRequestMergedEventType)
default:
log.Debug("Ignoring unknown webhook event")
http.Error(w, "Unknown webhook event", http.StatusBadRequest)
Expand Down
27 changes: 5 additions & 22 deletions util/webhook/webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,7 @@ const usernameRegex = `[a-zA-Z0-9_\.][a-zA-Z0-9_\.-]{0,30}[a-zA-Z0-9_\.\$-]?`

const payloadQueueSize = 50000

var (
_ settingsSource = &settings.SettingsManager{}
errBasicAuthVerificationFailed = errors.New("basic auth verification failed")
)
var _ settingsSource = &settings.SettingsManager{}

type ArgoCDWebhookHandler struct {
sync.WaitGroup // for testing
Expand All @@ -62,7 +59,6 @@ type ArgoCDWebhookHandler struct {
bitbucket *bitbucket.Webhook
bitbucketserver *bitbucketserver.Webhook
azuredevops *azuredevops.Webhook
azuredevopsAuthHandler func(r *http.Request) error
gogs *gogs.Webhook
settingsSrc settingsSource
queue chan interface{}
Expand Down Expand Up @@ -90,19 +86,10 @@ func NewHandler(namespace string, applicationNamespaces []string, webhookParalle
if err != nil {
log.Warnf("Unable to init the Gogs webhook")
}
azuredevopsWebhook, err := azuredevops.New()
azuredevopsWebhook, err := azuredevops.New(azuredevops.Options.BasicAuth(set.WebhookAzureDevOpsUsername, set.WebhookAzureDevOpsPassword))
if err != nil {
log.Warnf("Unable to init the Azure DevOps webhook")
}
azuredevopsAuthHandler := func(r *http.Request) error {
if set.WebhookAzureDevOpsUsername != "" && set.WebhookAzureDevOpsPassword != "" {
username, password, ok := r.BasicAuth()
if !ok || username != set.WebhookAzureDevOpsUsername || password != set.WebhookAzureDevOpsPassword {
return errBasicAuthVerificationFailed
}
}
return nil
}

acdWebhook := ArgoCDWebhookHandler{
ns: namespace,
Expand All @@ -113,7 +100,6 @@ func NewHandler(namespace string, applicationNamespaces []string, webhookParalle
bitbucket: bitbucketWebhook,
bitbucketserver: bitbucketserverWebhook,
azuredevops: azuredevopsWebhook,
azuredevopsAuthHandler: azuredevopsAuthHandler,
gogs: gogsWebhook,
settingsSrc: settingsSrc,
repoCache: repoCache,
Expand Down Expand Up @@ -423,12 +409,9 @@ func (a *ArgoCDWebhookHandler) Handler(w http.ResponseWriter, r *http.Request) {

switch {
case r.Header.Get("X-Vss-Activityid") != "":
if err = a.azuredevopsAuthHandler(r); err != nil {
if errors.Is(err, errBasicAuthVerificationFailed) {
log.WithField(common.SecurityField, common.SecurityHigh).Infof("Azure DevOps webhook basic auth verification failed")
}
} else {
payload, err = a.azuredevops.Parse(r, azuredevops.GitPushEventType)
payload, err = a.azuredevops.Parse(r, azuredevops.GitPushEventType)
if errors.Is(err, azuredevops.ErrBasicAuthVerificationFailed) {
log.WithField(common.SecurityField, common.SecurityHigh).Infof("Azure DevOps webhook basic auth verification failed")
}
// Gogs needs to be checked before GitHub since it carries both Gogs and (incompatible) GitHub headers
case r.Header.Get("X-Gogs-Event") != "":
Expand Down

0 comments on commit 4f64f0f

Please # to comment.