From 48dcc1bd919cb8aa92c3de96737045df63c8f3d5 Mon Sep 17 00:00:00 2001 From: NickBorgers Date: Tue, 26 Jul 2022 15:07:14 +0000 Subject: [PATCH 1/3] add count of compromises as returned value and containerize testing --- Makefile | 3 +++ hibp.go | 17 +++++++++-------- hibp_test.go | 24 ++++++++++++++++++++---- test.Dockerfile | 7 +++++++ 4 files changed, 39 insertions(+), 12 deletions(-) create mode 100644 Makefile create mode 100644 test.Dockerfile diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..bcb375d --- /dev/null +++ b/Makefile @@ -0,0 +1,3 @@ +test: + docker build -t test-pwned-passwords -f test.Dockerfile . + docker run --volume=$(CURDIR):/go/pwned-passwords/ test-pwned-passwords go test diff --git a/hibp.go b/hibp.go index 7a20ae1..4c018ca 100644 --- a/hibp.go +++ b/hibp.go @@ -102,9 +102,9 @@ func (c *Client) Do(req *http.Request) ([]string, error) { } // Compromised will build and execute a request to HIBP to check to see if the passed value is compromised or not. -func (c *Client) Compromised(value string) (bool, error) { +func (c *Client) Compromised(value string) (bool, int64, error) { if value == "" { - return false, errors.New("value for compromised check cannot be empty") + return false, 0, errors.New("value for compromised check cannot be empty") } hashedStr := hashString(value) @@ -113,12 +113,12 @@ func (c *Client) Compromised(value string) (bool, error) { request, err := c.NewRequest("GET", fmt.Sprintf("range/%s", prefix), nil) if err != nil { - return false, err + return false, 0, err } response, err := c.Do(request) if err != nil { - return false, err + return false, 0, err } for _, target := range response { @@ -127,15 +127,16 @@ func (c *Client) Compromised(value string) (bool, error) { } if target[:35] == suffix { - if _, err = strconv.ParseInt(target[36:], 10, 64); err != nil { - return false, err + var count int64 + if count, err = strconv.ParseInt(target[36:], 10, 64); err != nil { + return false, 0, err } - return true, err + return true, count, err } } - return false, err + return false, 0, err } // hashString will return a sha1 hash of the given value. diff --git a/hibp_test.go b/hibp_test.go index 4e92d8e..6e08bfa 100644 --- a/hibp_test.go +++ b/hibp_test.go @@ -19,7 +19,7 @@ func TestClientCustomHTTPClient(t *testing.T) { Timeout: 3 * time.Second, }) - compromised, err := client.Compromised("p@ssword") + compromised, count, err := client.Compromised("p@ssword") if err != nil { t.Fatalf("Unexpected error running client.Pwned.Compromised(): %s", err) } @@ -27,6 +27,10 @@ func TestClientCustomHTTPClient(t *testing.T) { if !compromised { t.Fatalf("Expected compromised hash (p@ssword) to be true but got: %v", compromised) } + + if count == 0 { + t.Fatalf("Expected compromised hash (p@ssword) to have been compromised at least once but got: %v", count) + } } // TestCompromisedHash will test a compromised value against the HIBP API. @@ -36,7 +40,7 @@ func TestCompromisedHash(t *testing.T) { client := NewClient() - compromised, err := client.Compromised("p@ssword") + compromised, count, err := client.Compromised("p@ssword") if err != nil { t.Fatalf("Unexpected error running client.Pwned.Compromised(): %s", err) } @@ -44,6 +48,10 @@ func TestCompromisedHash(t *testing.T) { if !compromised { t.Fatalf("Expected compromised hash (p@ssword) to be true but got: %v", compromised) } + + if count == 0 { + t.Fatalf("Expected compromised hash (p@ssword) to have been compromised at least once but got: %v", count) + } } // TestNonCompromisedHash will test a non-compromised value against the HIBP API. @@ -56,7 +64,7 @@ func TestNonCompromisedHash(t *testing.T) { // Check if input is compromised. value := fmt.Sprintf("SHOULD_NOT_BE_COMPROMISED_%s", time.Now().Format("2006-01-02 15:04:05")) - compromised, err := client.Compromised(value) + compromised, count, err := client.Compromised(value) if err != nil { t.Fatalf("Unexpected error running client.Pwned.Compromised(): %s", err) } @@ -64,6 +72,10 @@ func TestNonCompromisedHash(t *testing.T) { if compromised { t.Fatalf("Expected non-compromised hash to be false but got: %v", compromised) } + + if count != 0 { + t.Fatalf("Expected non-compromised hash to have been compromised exactly 0 times but got: %v", count) + } } func TestEmptyCompromisedHash(t *testing.T) { @@ -73,7 +85,7 @@ func TestEmptyCompromisedHash(t *testing.T) { client := NewClient() // Check if input is compromised. - compromised, err := client.Compromised("") + compromised, count, err := client.Compromised("") if err == nil { t.Fatal("Expected error when checking empty value, but got: nil") } @@ -85,4 +97,8 @@ func TestEmptyCompromisedHash(t *testing.T) { if compromised { t.Fatalf("Expected empty compromised hash to be false but got: %v", compromised) } + + if count != 0 { + t.Fatalf("Expected empty compromised hash to have been compromised exactly 0 times but got: %v", count) + } } diff --git a/test.Dockerfile b/test.Dockerfile new file mode 100644 index 0000000..c36fd85 --- /dev/null +++ b/test.Dockerfile @@ -0,0 +1,7 @@ +FROM golang:1.13-buster + +COPY go.* ./pwned-passwords/ + +WORKDIR ./pwned-passwords/ + +RUN go mod download From 6a72960215cdb97a9119c4d3feee9ed7450cc787 Mon Sep 17 00:00:00 2001 From: NickBorgers Date: Tue, 26 Jul 2022 15:08:02 +0000 Subject: [PATCH 2/3] make Docker linter happy by using absolute path for WORKDIR --- test.Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test.Dockerfile b/test.Dockerfile index c36fd85..0d71bcf 100644 --- a/test.Dockerfile +++ b/test.Dockerfile @@ -2,6 +2,6 @@ FROM golang:1.13-buster COPY go.* ./pwned-passwords/ -WORKDIR ./pwned-passwords/ +WORKDIR /go/pwned-passwords/ RUN go mod download From b84fa1dd964887e62ccea59792d31b89cb56d3e0 Mon Sep 17 00:00:00 2001 From: NickBorgers Date: Thu, 28 Jul 2022 14:18:45 +0000 Subject: [PATCH 3/3] make this a non-breaking change --- Makefile | 4 ++- hibp.go | 8 +++++- hibp_test.go | 70 ++++++++++++++++++++++++++++++++++++++++++++++------ 3 files changed, 72 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index bcb375d..1941a8f 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,5 @@ -test: +build: docker build -t test-pwned-passwords -f test.Dockerfile . + +test: docker run --volume=$(CURDIR):/go/pwned-passwords/ test-pwned-passwords go test diff --git a/hibp.go b/hibp.go index 4c018ca..12ede18 100644 --- a/hibp.go +++ b/hibp.go @@ -102,7 +102,13 @@ func (c *Client) Do(req *http.Request) ([]string, error) { } // Compromised will build and execute a request to HIBP to check to see if the passed value is compromised or not. -func (c *Client) Compromised(value string) (bool, int64, error) { +func (c *Client) Compromised(value string) (bool, error) { + compromised, _, error := c.CompromisedCount(value) + return compromised, error +} + +// Compromised will build and execute a request to HIBP to check to see if the passed value is compromised or not. +func (c *Client) CompromisedCount(value string) (bool, int64, error) { if value == "" { return false, 0, errors.New("value for compromised check cannot be empty") } diff --git a/hibp_test.go b/hibp_test.go index 6e08bfa..82ff3b9 100644 --- a/hibp_test.go +++ b/hibp_test.go @@ -19,7 +19,7 @@ func TestClientCustomHTTPClient(t *testing.T) { Timeout: 3 * time.Second, }) - compromised, count, err := client.Compromised("p@ssword") + compromised, err := client.Compromised("p@ssword") if err != nil { t.Fatalf("Unexpected error running client.Pwned.Compromised(): %s", err) } @@ -27,10 +27,6 @@ func TestClientCustomHTTPClient(t *testing.T) { if !compromised { t.Fatalf("Expected compromised hash (p@ssword) to be true but got: %v", compromised) } - - if count == 0 { - t.Fatalf("Expected compromised hash (p@ssword) to have been compromised at least once but got: %v", count) - } } // TestCompromisedHash will test a compromised value against the HIBP API. @@ -40,7 +36,24 @@ func TestCompromisedHash(t *testing.T) { client := NewClient() - compromised, count, err := client.Compromised("p@ssword") + compromised, err := client.Compromised("p@ssword") + if err != nil { + t.Fatalf("Unexpected error running client.Pwned.Compromised(): %s", err) + } + + if !compromised { + t.Fatalf("Expected compromised hash (p@ssword) to be true but got: %v", compromised) + } +} + +// TestCompromisedCountHash will test a compromised value against the HIBP API. +func TestCompromisedCountHash(t *testing.T) { + // Register the test. + RegisterTestingT(t) + + client := NewClient() + + compromised, count, err := client.CompromisedCount("p@ssword") if err != nil { t.Fatalf("Unexpected error running client.Pwned.Compromised(): %s", err) } @@ -64,7 +77,27 @@ func TestNonCompromisedHash(t *testing.T) { // Check if input is compromised. value := fmt.Sprintf("SHOULD_NOT_BE_COMPROMISED_%s", time.Now().Format("2006-01-02 15:04:05")) - compromised, count, err := client.Compromised(value) + compromised, err := client.Compromised(value) + if err != nil { + t.Fatalf("Unexpected error running client.Pwned.Compromised(): %s", err) + } + + if compromised { + t.Fatalf("Expected non-compromised hash to be false but got: %v", compromised) + } +} + +// TestNonCompromisedCountHash will test a non-compromised value against the HIBP API. +func TestNonCompromisedCountHash(t *testing.T) { + // Register the test. + RegisterTestingT(t) + + client := NewClient() + + // Check if input is compromised. + value := fmt.Sprintf("SHOULD_NOT_BE_COMPROMISED_%s", time.Now().Format("2006-01-02 15:04:05")) + + compromised, count, err := client.CompromisedCount(value) if err != nil { t.Fatalf("Unexpected error running client.Pwned.Compromised(): %s", err) } @@ -85,7 +118,28 @@ func TestEmptyCompromisedHash(t *testing.T) { client := NewClient() // Check if input is compromised. - compromised, count, err := client.Compromised("") + compromised, err := client.Compromised("") + if err == nil { + t.Fatal("Expected error when checking empty value, but got: nil") + } + + if err.Error() != "value for compromised check cannot be empty" { + t.Fatalf("Expected err to read 'value for compromised check cannot be empty' but got: '%v'", err) + } + + if compromised { + t.Fatalf("Expected empty compromised hash to be false but got: %v", compromised) + } +} + +func TestEmptyCompromisedCountHash(t *testing.T) { + // Register the test. + RegisterTestingT(t) + + client := NewClient() + + // Check if input is compromised. + compromised, count, err := client.CompromisedCount("") if err == nil { t.Fatal("Expected error when checking empty value, but got: nil") }