diff --git a/output/webhook/options.go b/output/webhook/options.go index dc92824..a854a89 100644 --- a/output/webhook/options.go +++ b/output/webhook/options.go @@ -24,3 +24,11 @@ func WithUrl(url string) WebhookOptionFunc { o.url = url } } + +// WithBasicAuth specifies the username and password +func WithBasicAuth(username, password string) WebhookOptionFunc { + return func(o *WebhookOutput) { + o.username = username + o.password = password + } +} diff --git a/output/webhook/plugin.go b/output/webhook/plugin.go index fbb2ac3..0059849 100644 --- a/output/webhook/plugin.go +++ b/output/webhook/plugin.go @@ -19,7 +19,9 @@ import ( ) var cmdlineOptions struct { - url string + url string + username string + password string } func init() { @@ -37,6 +39,20 @@ func init() { DefaultValue: "http://localhost:3000", Dest: &(cmdlineOptions.url), }, + { + Name: "username", + Type: plugin.PluginOptionTypeString, + Description: "specifies the username for basic auth", + DefaultValue: "", + Dest: &(cmdlineOptions.username), + }, + { + Name: "password", + Type: plugin.PluginOptionTypeString, + Description: "specifies the password for basic auth", + DefaultValue: "", + Dest: &(cmdlineOptions.password), + }, }, }, ) @@ -45,6 +61,7 @@ func init() { func NewFromCmdlineOptions() plugin.Plugin { p := New( WithUrl(cmdlineOptions.url), + WithBasicAuth(cmdlineOptions.username, cmdlineOptions.password), ) return p } diff --git a/output/webhook/webhook.go b/output/webhook/webhook.go index 83e4240..de453c7 100644 --- a/output/webhook/webhook.go +++ b/output/webhook/webhook.go @@ -18,6 +18,7 @@ import ( "bytes" "context" "crypto/tls" + "encoding/base64" "encoding/json" "fmt" "io" @@ -34,6 +35,8 @@ type WebhookOutput struct { errorChan chan error eventChan chan event.Event url string + username string + password string } func New(options ...WebhookOptionFunc) *WebhookOutput { @@ -78,7 +81,7 @@ func (w *WebhookOutput) Start() error { return } // TODO: error handle - err := SendWebhook(&evt, w.url) + err := w.SendWebhook(&evt) if err != nil { logger.Errorf("ERROR: %s", err) } @@ -87,9 +90,14 @@ func (w *WebhookOutput) Start() error { return nil } -func SendWebhook(e *event.Event, url string) error { +func basicAuth(username, password string) string { + auth := username + ":" + password + return "Basic " + base64.StdEncoding.EncodeToString([]byte(auth)) +} + +func (w *WebhookOutput) SendWebhook(e *event.Event) error { logger := logging.GetLogger() - logger.Infof("sending event %s to %s", e.Type, url) + logger.Infof("sending event %s to %s", e.Type, w.url) data, err := json.Marshal(e) if err != nil { return fmt.Errorf("%s", err) @@ -97,22 +105,27 @@ func SendWebhook(e *event.Event, url string) error { // Setup request ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() - req, err := http.NewRequestWithContext(ctx, http.MethodPost, url, bytes.NewReader(data)) + req, err := http.NewRequestWithContext(ctx, http.MethodPost, w.url, bytes.NewReader(data)) if err != nil { return fmt.Errorf("%s", err) } req.Header.Add("Content-Type", "application/json") req.Header.Add("User-Agent", fmt.Sprintf("Snek/%s", version.GetVersionString())) + + // Setup authorization + if w.username != "" && w.password != "" { + req.Header.Add("Authorization", basicAuth(w.username, w.password)) + } // Setup custom transport to ignore self-signed SSL defaultTransport := http.DefaultTransport.(*http.Transport) customTransport := &http.Transport{ - Proxy: defaultTransport.Proxy, - DialContext: defaultTransport.DialContext, - MaxIdleConns: defaultTransport.MaxIdleConns, - IdleConnTimeout: defaultTransport.IdleConnTimeout, + Proxy: defaultTransport.Proxy, + DialContext: defaultTransport.DialContext, + MaxIdleConns: defaultTransport.MaxIdleConns, + IdleConnTimeout: defaultTransport.IdleConnTimeout, ExpectContinueTimeout: defaultTransport.ExpectContinueTimeout, - TLSHandshakeTimeout: defaultTransport.TLSHandshakeTimeout, - TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, + TLSHandshakeTimeout: defaultTransport.TLSHandshakeTimeout, + TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, } client := &http.Client{Transport: customTransport} // Send payload @@ -127,7 +140,7 @@ func SendWebhook(e *event.Event, url string) error { defer resp.Body.Close() logger.Infof("sent: %s, payload: %s, body: %s, response: %s, status: %d", - url, + w.url, string(data), string(respBody), resp.Status,