@@ -15,6 +15,7 @@ import (
1515 cdx "github.com/CycloneDX/cyclonedx-go"
1616 "github.com/l3montree-dev/devguard/internal/core"
1717 "github.com/l3montree-dev/devguard/internal/core/vuln"
18+ "github.com/l3montree-dev/devguard/internal/database/models"
1819)
1920
2021type WebhookStruct struct {
@@ -32,6 +33,16 @@ const (
3233 WebhookTypeSBOM WebhookType = "sbom"
3334 WebhookTypeFirstPartyVulnerabilities WebhookType = "firstPartyVulnerabilities"
3435 WebhookTypeDependencyVulnerabilities WebhookType = "dependencyVulnerabilities"
36+ WebhookTypeTest WebhookType = "test"
37+ )
38+
39+ type TestPayloadType string
40+
41+ const (
42+ TestPayloadTypeEmpty TestPayloadType = "empty"
43+ TestPayloadTypeSampleSBOM TestPayloadType = "sampleSbom"
44+ TestPayloadTypeSampleDependencyVulns TestPayloadType = "sampleDependencyVulns"
45+ TestPayloadTypeSampleFirstPartyVulns TestPayloadType = "sampleFirstPartyVulns"
3546)
3647
3748type webhookClient struct {
@@ -96,8 +107,9 @@ func (c *webhookClient) SendSBOM(SBOM cdx.BOM, org core.OrgObject, project core.
96107}
97108
98109func (c * webhookClient ) SendFirstPartyVulnerabilities (vuln []vuln.FirstPartyVulnDTO , org core.OrgObject , project core.ProjectObject , asset core.AssetObject , assetVersion core.AssetVersionObject ) error {
110+ return nil
99111
100- body := WebhookStruct {
112+ /* body := WebhookStruct{
101113 Organization: org,
102114 Project: project,
103115 Asset: asset,
@@ -121,7 +133,7 @@ func (c *webhookClient) SendFirstPartyVulnerabilities(vuln []vuln.FirstPartyVuln
121133 return fmt.Errorf("failed to send vulnerability, status: %s,", resp.Status)
122134 }
123135
124- return nil
136+ return nil*/
125137}
126138
127139func (c * webhookClient ) SendDependencyVulnerabilities (vuln []vuln.DependencyVulnDTO , org core.OrgObject , project core.ProjectObject , asset core.AssetObject , assetVersion core.AssetVersionObject ) error {
@@ -152,3 +164,183 @@ func (c *webhookClient) SendDependencyVulnerabilities(vuln []vuln.DependencyVuln
152164
153165 return nil
154166}
167+
168+ func (c * webhookClient ) SendTest (org core.OrgObject , project core.ProjectObject , asset core.AssetObject , assetVersion core.AssetVersionObject , payloadType TestPayloadType ) error {
169+
170+ var payload any
171+ var webhookType WebhookType
172+
173+ switch payloadType {
174+ case TestPayloadTypeEmpty :
175+ payload = map [string ]any {
176+ "message" : "This is a test webhook from DevGuard" ,
177+ "timestamp" : time .Now ().UTC ().Format (time .RFC3339 ),
178+ }
179+ webhookType = WebhookTypeTest
180+
181+ case TestPayloadTypeSampleSBOM :
182+ payload = createSampleSBOM ()
183+ webhookType = WebhookTypeSBOM
184+
185+ case TestPayloadTypeSampleDependencyVulns :
186+ payload = createSampleDependencyVulns ()
187+ webhookType = WebhookTypeDependencyVulnerabilities
188+
189+ case TestPayloadTypeSampleFirstPartyVulns :
190+ payload = createSampleFirstPartyVulns ()
191+ webhookType = WebhookTypeFirstPartyVulnerabilities
192+
193+ default :
194+ payload = map [string ]any {
195+ "message" : "This is a test webhook from DevGuard" ,
196+ "timestamp" : time .Now ().UTC ().Format (time .RFC3339 ),
197+ }
198+ webhookType = WebhookTypeTest
199+ }
200+
201+ body := WebhookStruct {
202+ Organization : org ,
203+ Project : project ,
204+ Asset : asset ,
205+ AssetVersion : assetVersion ,
206+ Payload : payload ,
207+ Type : webhookType ,
208+ }
209+
210+ var buf bytes.Buffer
211+ err := json .NewEncoder (& buf ).Encode (body )
212+ if err != nil {
213+ return err
214+ }
215+
216+ resp , err := c .CreateRequest ("POST" , c .URL , & buf )
217+ if err != nil {
218+ return err
219+ }
220+ defer resp .Body .Close ()
221+ if resp .StatusCode != http .StatusOK {
222+ return fmt .Errorf ("failed to send test webhook, status: %s" , resp .Status )
223+ }
224+
225+ return nil
226+ }
227+
228+ func createSampleSBOM () cdx.BOM {
229+ return cdx.BOM {
230+ BOMFormat : "CycloneDX" ,
231+ SpecVersion : cdx .SpecVersion1_4 ,
232+ SerialNumber : "urn:uuid:3e671687-395b-41f5-a30f-a58921a69b79" ,
233+ Version : 1 ,
234+ Metadata : & cdx.Metadata {
235+ Timestamp : time .Now ().UTC ().Format (time .RFC3339 ),
236+ Component : & cdx.Component {
237+ Type : cdx .ComponentTypeApplication ,
238+ Name : "example-web-app" ,
239+ Version : "1.2.3" ,
240+ PackageURL : "pkg:docker/example/web-app@1.2.3" ,
241+ },
242+ },
243+ Components : & []cdx.Component {
244+ {
245+ Type : cdx .ComponentTypeLibrary ,
246+ Name : "express" ,
247+ Version : "4.18.2" ,
248+ PackageURL : "pkg:npm/express@4.18.2" ,
249+ Licenses : & cdx.Licenses {
250+ {License : & cdx.License {ID : "MIT" }},
251+ },
252+ },
253+ {
254+ Type : cdx .ComponentTypeLibrary ,
255+ Name : "log4j-core" ,
256+ Version : "2.14.1" ,
257+ PackageURL : "pkg:maven/org.apache.logging.log4j/log4j-core@2.14.1" ,
258+ Licenses : & cdx.Licenses {
259+ {License : & cdx.License {ID : "Apache-2.0" }},
260+ },
261+ },
262+ },
263+ }
264+ }
265+
266+ func createSampleDependencyVulns () []vuln.DependencyVulnDTO {
267+ cve := "CVE-2021-44228"
268+ purl := "pkg:maven/org.apache.logging.log4j/log4j-core@2.14.1"
269+ fixedVersion := "2.15.0"
270+ depth := 2
271+ risk := 95
272+ rawRisk := 9.8
273+ priority := 1
274+ effort := 4
275+
276+ cveData := & models.CVE {
277+ CVE : "CVE-2021-44228" ,
278+ Description : "Apache Log4j2 <=2.14.1 JNDI features used in configuration, log messages, and parameters do not protect against attacker controlled LDAP and other JNDI related endpoints." ,
279+ CVSS : 10.0 ,
280+ Severity : models .SeverityCritical ,
281+ AttackVector : "Network" ,
282+ AttackComplexity : "Low" ,
283+ PrivilegesRequired : "None" ,
284+ UserInteraction : "None" ,
285+ Scope : "Changed" ,
286+ ConfidentialityImpact : "High" ,
287+ IntegrityImpact : "High" ,
288+ AvailabilityImpact : "High" ,
289+ Vector : "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H" ,
290+ }
291+
292+ return []vuln.DependencyVulnDTO {
293+ {
294+ ID : "dep-vuln-001" ,
295+ ScannerIDs : "trivy" ,
296+ AssetVersionName : "v1.2.3" ,
297+ AssetID : "asset-12345" ,
298+ State : models .VulnStateOpen ,
299+ CVEID : & cve ,
300+ CVE : cveData ,
301+ ComponentPurl : & purl ,
302+ ComponentDepth : & depth ,
303+ ComponentFixedVersion : & fixedVersion ,
304+ Effort : & effort ,
305+ RiskAssessment : & risk ,
306+ RawRiskAssessment : & rawRisk ,
307+ Priority : & priority ,
308+ LastDetected : time .Now (),
309+ CreatedAt : time .Now ().Add (- 24 * time .Hour ),
310+ RiskRecalculatedAt : time .Now (),
311+ },
312+ }
313+ }
314+
315+ func createSampleFirstPartyVulns () []vuln.FirstPartyVulnDTO {
316+ message := "SQL injection vulnerability detected"
317+
318+ return []vuln.FirstPartyVulnDTO {
319+ {
320+ ID : "fpv-001" ,
321+ ScannerIDs : "semgrep" ,
322+ Message : & message ,
323+ AssetVersionName : "v1.2.3" ,
324+ AssetID : "asset-12345" ,
325+ State : models .VulnStateOpen ,
326+ RuleID : "javascript.lang.security.audit.sqli" ,
327+ URI : "src/auth/login.js" ,
328+ SnippetContents : []models.SnippetContent {
329+ {
330+ StartLine : 42 ,
331+ EndLine : 45 ,
332+ Snippet : `const query = "SELECT * FROM users WHERE username = '" + username + "'";` ,
333+ },
334+ },
335+ CreatedAt : time .Now (),
336+ Commit : "abc123" ,
337+ Author : "Developer" ,
338+ RuleName : "SQL Injection Detection" ,
339+ RuleDescription : "Detects SQL injection vulnerabilities" ,
340+ RuleProperties : map [string ]any {
341+ "severity" : "HIGH" ,
342+ "cwe" : "CWE-89" ,
343+ },
344+ },
345+ }
346+ }
0 commit comments