From edcb6d0ca4d89408abb2ec298574825e42eeead3 Mon Sep 17 00:00:00 2001 From: Chris Cummer Date: Sun, 21 Jul 2019 14:45:10 -0700 Subject: [PATCH] WTF-508 HIBP now uses API v3 with authorization to fetch data --- modules/hibp/client.go | 29 ++++++++++++++++++++++++++--- modules/hibp/settings.go | 4 +++- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/modules/hibp/client.go b/modules/hibp/client.go index 70b7bff7..d1505dcb 100644 --- a/modules/hibp/client.go +++ b/modules/hibp/client.go @@ -2,6 +2,7 @@ package hibp import ( "encoding/json" + "errors" "fmt" "io/ioutil" "net/http" @@ -9,12 +10,16 @@ import ( ) const ( - apiURL = "https://haveibeenpwned.com/api/breachedaccount/" - apiVersion = "application/vnd.haveibeenpwned.v2+json" + apiURL = "https://haveibeenpwned.com/api/v3/breachedaccount/" clientTimeoutSecs = 2 userAgent = "WTFUtil" ) +type hibpError struct { + StatusCode int `json:"statusCode"` + Message string `json:"message"` +} + func (widget *Widget) fullURL(account string, truncated bool) string { truncStr := "false" if truncated == true { @@ -43,8 +48,8 @@ func (widget *Widget) fetchForAccount(account string, since string) (*Status, er return nil, err } - request.Header.Set("Accept", apiVersion) request.Header.Set("User-Agent", userAgent) + request.Header.Set("hibp-api-key", widget.settings.apiKey) response, getErr := hibpClient.Do(request) if getErr != nil { @@ -56,6 +61,11 @@ func (widget *Widget) fetchForAccount(account string, since string) (*Status, er return nil, err } + hibpErr := widget.validateHTTPResponse(response.StatusCode, body) + if hibpErr != nil { + return nil, errors.New(hibpErr.Message) + } + stat, err := widget.parseResponseBody(account, body) if err != nil { return nil, err @@ -115,3 +125,16 @@ func (widget *Widget) filterBreaches(breaches []Breach) []Breach { return latestBreaches } + +func (widget *Widget) validateHTTPResponse(responseCode int, body []byte) *hibpError { + hibpErr := &hibpError{} + + switch responseCode { + case 401, 402: + json.Unmarshal(body, hibpErr) + default: + hibpErr = nil + } + + return hibpErr +} diff --git a/modules/hibp/settings.go b/modules/hibp/settings.go index 49d1a26c..16f0005e 100644 --- a/modules/hibp/settings.go +++ b/modules/hibp/settings.go @@ -24,7 +24,8 @@ type Settings struct { common *cfg.Common accounts []string `help:"A list of the accounts to check the HIBP database for."` - since string `help:"Only check for breaches after this date. Set this if you’ve been breached in the past, have taken steps to mitigate that (changing passwords, cancelling accounts, etc.) and now only want to know about future breaches." values:"A date string in the format 'yyyy-mm-dd', ie: '2019-06-22'", optional:"true"` + apiKey string `help:"Your HIBP API v3 API key"` + since string `help:"Only check for breaches after this date. Set this if you’ve been breached in the past, have taken steps to mitigate that (changing passwords, cancelling accounts, etc.) and now only want to know about future breaches." values:"A date string in the format 'yyyy-mm-dd', ie. '2019-06-22'" optional:"true"` } // NewSettingsFromYAML creates a new settings instance from a YAML config block @@ -32,6 +33,7 @@ func NewSettingsFromYAML(name string, ymlConfig *config.Config, globalConfig *co settings := &Settings{ common: cfg.NewCommonSettingsFromModule(name, defaultTitle, ymlConfig, globalConfig), + apiKey: ymlConfig.UString("apiKey", ""), accounts: wtf.ToStrs(ymlConfig.UList("accounts")), since: ymlConfig.UString("since", ""), }