From a814a9d9608b7c6fdeed6dafceb6ac6420cfb9d3 Mon Sep 17 00:00:00 2001 From: Adam Korczynski Date: Sat, 25 May 2024 17:04:51 +0100 Subject: [PATCH 1/5] Add fuzzer for github event parsers Signed-off-by: Adam Korczynski --- internal/controlplane/fuzz_test.go | 128 +++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 internal/controlplane/fuzz_test.go diff --git a/internal/controlplane/fuzz_test.go b/internal/controlplane/fuzz_test.go new file mode 100644 index 0000000000..fcd80423da --- /dev/null +++ b/internal/controlplane/fuzz_test.go @@ -0,0 +1,128 @@ +// +// Copyright 2024 Stacklok, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package controlplane + +import ( + "bytes" + "crypto/hmac" + "crypto/sha256" + "encoding/hex" + "fmt" + "net/http" + "os" + "testing" + + "github.com/ThreeDotsLabs/watermill/message" + "github.com/google/go-github/v61/github" + + "github.com/stacklok/minder/internal/config/server" + "github.com/stacklok/minder/internal/controlplane/metrics" + "github.com/stacklok/minder/internal/db" + "github.com/stacklok/minder/internal/events" +) + +var eventTypes = map[int]string{ + 0: "branch_protection_configuration", + 1: "branch_protection_rule", + 2: "code_scanning_alert", + 3: "create", + 4: "member", + 5: "meta", + 6: "repository_vulnerability_alert", + 7: "org_block", + 8: "organization", + 9: "public", + 10: "push", + 11: "repository", + 12: "repository_advisory", + 13: "repository_import", + 14: "repository_ruleset", + 15: "secret_scanning_alert", + 16: "secret_scanning_alert_location", + 17: "security_advisory", + 18: "security_and_analysis", + 19: "team", + 20: "team_add", + 21: "package", + 22: "pull_request", +} + +func FuzzGithubEventParsers(f *testing.F) { + f.Fuzz(func(t *testing.T, rawWHPayload []byte, target, entEnum int) { + mac := hmac.New(sha256.New, []byte("test")) + mac.Write(rawWHPayload) + expectedMAC := hex.EncodeToString(mac.Sum(nil)) + + req, err := http.NewRequest("POST", "/", bytes.NewBuffer(rawWHPayload)) + if err != nil { + t.Fatal(err) + } + + entType := eventTypes[entEnum%len(eventTypes)] + + req.Header.Add("X-GitHub-Event", entType) + req.Header.Add("X-GitHub-Delivery", "12345") + req.Header.Add("Content-Type", "application/json") + req.Header.Add("X-Hub-Signature-256", fmt.Sprintf("sha256=%s", expectedMAC)) + + wes := &metrics.WebhookEventState{ + Typ: "unknown", + Accepted: false, + Error: true, + } + + wes.Typ = github.WebHookType(req) + + m := message.NewMessage("", nil) + m.Metadata.Set(events.ProviderDeliveryIdKey, github.DeliveryID(req)) + m.Metadata.Set(events.ProviderTypeKey, string(db.ProviderTypeGithub)) + m.Metadata.Set(events.ProviderSourceKey, "") + m.Metadata.Set(events.GithubWebhookEventTypeKey, wes.Typ) + + // Create whConfig + whSecretFile, err := os.CreateTemp("", "webhooksecret*") + if err != nil { + t.Fatal(err) + } + secret := "test" + _, err = whSecretFile.WriteString(secret) + if err != nil { + t.Fatal(err) + } + defer os.Remove(whSecretFile.Name()) + + whConfig := &server.WebhookConfig{WebhookSecretFile: whSecretFile.Name()} + + s := &Server{} + + switch target % 2 { + case 0: + payload, err := validatePayloadSignature(req, whConfig) + if err != nil { + return + } + //nolint:gosec + s.parseGithubEventForProcessing(payload, m) + case 1: + payload, err := github.ValidatePayload(req, []byte(secret)) + if err != nil { + return + } + //nolint:gosec + s.parseGithubAppEventForProcessing(payload, m) + } + }) +} From a12cb64d8976fd74bffa5fb585cae1dce3eb598f Mon Sep 17 00:00:00 2001 From: Adam Korczynski Date: Tue, 28 May 2024 09:50:46 +0100 Subject: [PATCH 2/5] rename variable Signed-off-by: Adam Korczynski --- internal/controlplane/fuzz_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/controlplane/fuzz_test.go b/internal/controlplane/fuzz_test.go index fcd80423da..5c6c74656f 100644 --- a/internal/controlplane/fuzz_test.go +++ b/internal/controlplane/fuzz_test.go @@ -61,7 +61,7 @@ var eventTypes = map[int]string{ } func FuzzGithubEventParsers(f *testing.F) { - f.Fuzz(func(t *testing.T, rawWHPayload []byte, target, entEnum int) { + f.Fuzz(func(t *testing.T, rawWHPayload []byte, target, eventEnum int) { mac := hmac.New(sha256.New, []byte("test")) mac.Write(rawWHPayload) expectedMAC := hex.EncodeToString(mac.Sum(nil)) @@ -71,9 +71,9 @@ func FuzzGithubEventParsers(f *testing.F) { t.Fatal(err) } - entType := eventTypes[entEnum%len(eventTypes)] + eventType := eventTypes[eventEnum%len(eventTypes)] - req.Header.Add("X-GitHub-Event", entType) + req.Header.Add("X-GitHub-Event", eventType) req.Header.Add("X-GitHub-Delivery", "12345") req.Header.Add("Content-Type", "application/json") req.Header.Add("X-Hub-Signature-256", fmt.Sprintf("sha256=%s", expectedMAC)) From 9698be933abd9dd004568bb9756310a852d5579e Mon Sep 17 00:00:00 2001 From: Adam Korczynski Date: Tue, 28 May 2024 09:58:21 +0100 Subject: [PATCH 3/5] turn map into slice Signed-off-by: Adam Korczynski --- internal/controlplane/fuzz_test.go | 52 +++++++++++++++--------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/internal/controlplane/fuzz_test.go b/internal/controlplane/fuzz_test.go index 5c6c74656f..fe2f14ca05 100644 --- a/internal/controlplane/fuzz_test.go +++ b/internal/controlplane/fuzz_test.go @@ -34,34 +34,34 @@ import ( "github.com/stacklok/minder/internal/events" ) -var eventTypes = map[int]string{ - 0: "branch_protection_configuration", - 1: "branch_protection_rule", - 2: "code_scanning_alert", - 3: "create", - 4: "member", - 5: "meta", - 6: "repository_vulnerability_alert", - 7: "org_block", - 8: "organization", - 9: "public", - 10: "push", - 11: "repository", - 12: "repository_advisory", - 13: "repository_import", - 14: "repository_ruleset", - 15: "secret_scanning_alert", - 16: "secret_scanning_alert_location", - 17: "security_advisory", - 18: "security_and_analysis", - 19: "team", - 20: "team_add", - 21: "package", - 22: "pull_request", +var eventTypes = [23]string{ + "branch_protection_configuration", + "branch_protection_rule", + "code_scanning_alert", + "create", + "member", + "meta", + "repository_vulnerability_alert", + "org_block", + "organization", + "public", + "push", + "repository", + "repository_advisory", + "repository_import", + "repository_ruleset", + "secret_scanning_alert", + "secret_scanning_alert_location", + "security_advisory", + "security_and_analysis", + "team", + "team_add", + "package", + "pull_request", } func FuzzGithubEventParsers(f *testing.F) { - f.Fuzz(func(t *testing.T, rawWHPayload []byte, target, eventEnum int) { + f.Fuzz(func(t *testing.T, rawWHPayload []byte, target, eventEnum uint) { mac := hmac.New(sha256.New, []byte("test")) mac.Write(rawWHPayload) expectedMAC := hex.EncodeToString(mac.Sum(nil)) @@ -71,7 +71,7 @@ func FuzzGithubEventParsers(f *testing.F) { t.Fatal(err) } - eventType := eventTypes[eventEnum%len(eventTypes)] + eventType := eventTypes[eventEnum%uint(len(eventTypes))] req.Header.Add("X-GitHub-Event", eventType) req.Header.Add("X-GitHub-Delivery", "12345") From 3d35aa2b30b01335feca02b57b0369b5e66a2b58 Mon Sep 17 00:00:00 2001 From: Adam Korczynski Date: Tue, 28 May 2024 10:03:50 +0100 Subject: [PATCH 4/5] add documentation Signed-off-by: Adam Korczynski --- internal/controlplane/fuzz_test.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/internal/controlplane/fuzz_test.go b/internal/controlplane/fuzz_test.go index fe2f14ca05..75b2184743 100644 --- a/internal/controlplane/fuzz_test.go +++ b/internal/controlplane/fuzz_test.go @@ -60,6 +60,11 @@ var eventTypes = [23]string{ "pull_request", } +// FuzzGithubEventParsers tests Minders two GH event parsers: +// 1: parseGithubEventForProcessing +// 2: parseGithubAppEventForProcessing +// The fuzzer does not validate return values of the parsers. It tests if any +// input can cause code-level issues. func FuzzGithubEventParsers(f *testing.F) { f.Fuzz(func(t *testing.T, rawWHPayload []byte, target, eventEnum uint) { mac := hmac.New(sha256.New, []byte("test")) @@ -114,14 +119,14 @@ func FuzzGithubEventParsers(f *testing.F) { if err != nil { return } - //nolint:gosec + //nolint:gosec // The fuzzer does not validate the return values s.parseGithubEventForProcessing(payload, m) case 1: payload, err := github.ValidatePayload(req, []byte(secret)) if err != nil { return } - //nolint:gosec + //nolint:gosec // The fuzzer does not validate the return values s.parseGithubAppEventForProcessing(payload, m) } }) From 650122c385fdff15ede39c56425537719b1a8871 Mon Sep 17 00:00:00 2001 From: Adam Korczynski Date: Tue, 28 May 2024 10:12:05 +0100 Subject: [PATCH 5/5] fix linting issues Signed-off-by: Adam Korczynski --- internal/controlplane/fuzz_test.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/internal/controlplane/fuzz_test.go b/internal/controlplane/fuzz_test.go index 75b2184743..190b934fe4 100644 --- a/internal/controlplane/fuzz_test.go +++ b/internal/controlplane/fuzz_test.go @@ -61,8 +61,10 @@ var eventTypes = [23]string{ } // FuzzGithubEventParsers tests Minders two GH event parsers: -// 1: parseGithubEventForProcessing -// 2: parseGithubAppEventForProcessing +// +// 1: parseGithubEventForProcessing +// 2: parseGithubAppEventForProcessing +// // The fuzzer does not validate return values of the parsers. It tests if any // input can cause code-level issues. func FuzzGithubEventParsers(f *testing.F) {