@@ -18,6 +18,7 @@ import (
1818 "github.com/l3montree-dev/devguard/internal/core"
1919 "github.com/l3montree-dev/devguard/internal/core/normalize"
2020 "github.com/l3montree-dev/devguard/internal/core/risk"
21+ "github.com/l3montree-dev/devguard/internal/core/vuln"
2122 "github.com/l3montree-dev/devguard/internal/database"
2223 "github.com/openvex/go-vex/pkg/vex"
2324
@@ -36,12 +37,15 @@ type service struct {
3637 firstPartyVulnService core.FirstPartyVulnService
3738 assetVersionRepository core.AssetVersionRepository
3839 assetRepository core.AssetRepository
40+ projectRepository core.ProjectRepository
41+ orgRepository core.OrganizationRepository
3942 vulnEventRepository core.VulnEventRepository
4043 componentService core.ComponentService
4144 httpClient * http.Client
45+ thirdPartyIntegration core.ThirdPartyIntegration
4246}
4347
44- func NewService (assetVersionRepository core.AssetVersionRepository , componentRepository core.ComponentRepository , dependencyVulnRepository core.DependencyVulnRepository , firstPartyVulnRepository core.FirstPartyVulnRepository , dependencyVulnService core.DependencyVulnService , firstPartyVulnService core.FirstPartyVulnService , assetRepository core.AssetRepository , vulnEventRepository core.VulnEventRepository , componentService core.ComponentService ) * service {
48+ func NewService (assetVersionRepository core.AssetVersionRepository , componentRepository core.ComponentRepository , dependencyVulnRepository core.DependencyVulnRepository , firstPartyVulnRepository core.FirstPartyVulnRepository , dependencyVulnService core.DependencyVulnService , firstPartyVulnService core.FirstPartyVulnService , assetRepository core.AssetRepository , projectRepository core. ProjectRepository , orgRepository core. OrganizationRepository , vulnEventRepository core.VulnEventRepository , componentService core.ComponentService , thirdPartyIntegration core. ThirdPartyIntegration ) * service {
4549 return & service {
4650 assetVersionRepository : assetVersionRepository ,
4751 componentRepository : componentRepository ,
@@ -53,6 +57,9 @@ func NewService(assetVersionRepository core.AssetVersionRepository, componentRep
5357 componentService : componentService ,
5458 assetRepository : assetRepository ,
5559 httpClient : & http.Client {},
60+ thirdPartyIntegration : thirdPartyIntegration ,
61+ projectRepository : projectRepository ,
62+ orgRepository : orgRepository ,
5663 }
5764}
5865
@@ -196,6 +203,29 @@ func (s *service) handleFirstPartyVulnResult(userID string, scannerID string, as
196203 return vuln .State == models .VulnStateOpen
197204 })
198205
206+ go func () {
207+ pro , err := s .projectRepository .GetProjectByAssetID (asset .ID )
208+ if err != nil {
209+ slog .Error ("could not get project by asset ID" , "err" , err )
210+ return
211+ }
212+ org , err := s .orgRepository .Read (pro .OrganizationID )
213+ if err != nil {
214+ slog .Error ("could not get organization by ID" , "err" , err )
215+ return
216+ }
217+
218+ if err = s .thirdPartyIntegration .HandleEvent (core.FirstPartyVulnsDetectedEvent {
219+ AssetVersion : core .ToAssetVersionObject (* assetVersion ),
220+ Asset : core .ToAssetObject (asset ),
221+ Project : core .ToProjectObject (pro ),
222+ Org : core .ToOrgObject (org ),
223+ Vulns : utils .Map (newVulns , vuln .FirstPartyVulnToDto ),
224+ }); err != nil {
225+ slog .Error ("could not handle first party vulnerabilities detected event" , "err" , err )
226+ }
227+ }()
228+
199229 return len (newVulns ), len (fixedVulns ), append (newVulns , comparison .InBoth ... ), nil
200230}
201231
@@ -254,6 +284,32 @@ func (s *service) HandleScanResult(asset models.Asset, assetVersion *models.Asse
254284
255285 assetVersion .Metadata [scannerID ] = models.ScannerInformation {LastScan : utils .Ptr (time .Now ())}
256286
287+ go func () {
288+ pro , err := s .projectRepository .GetProjectByAssetID (asset .ID )
289+ if err != nil {
290+ slog .Error ("could not get project by asset ID" , "err" , err )
291+ return
292+ }
293+
294+ org , err := s .orgRepository .Read (pro .OrganizationID )
295+ if err != nil {
296+ slog .Error ("could not get organization by ID" , "err" , err )
297+ return
298+ }
299+
300+ if err = s .thirdPartyIntegration .HandleEvent (core.DependencyVulnsDetectedEvent {
301+ AssetVersion : core .ToAssetVersionObject (* assetVersion ),
302+ Asset : core .ToAssetObject (asset ),
303+ Project : core .ToProjectObject (pro ),
304+ Org : core .ToOrgObject (org ),
305+
306+ Vulns : utils .Map (opened , vuln .DependencyVulnToDto ),
307+ }); err != nil {
308+ slog .Error ("could not handle dependency vulnerabilities detected event" , "err" , err )
309+ }
310+
311+ }()
312+
257313 return opened , closed , newState , nil
258314}
259315
@@ -419,14 +475,14 @@ func buildBomRefMap(bom normalize.SBOM) map[string]cdx.Component {
419475 return res
420476}
421477
422- func (s * service ) UpdateSBOM (assetVersion models.AssetVersion , scannerID string , sbom normalize.SBOM ) ( bool , error ) {
478+ func (s * service ) UpdateSBOM (assetVersion models.AssetVersion , scannerID string , sbom normalize.SBOM ) error {
423479
424480 sbomUpdated := false
425481
426482 // load the asset components
427483 assetComponents , err := s .componentRepository .LoadComponents (nil , assetVersion .Name , assetVersion .AssetID , "" )
428484 if err != nil {
429- return sbomUpdated , errors .Wrap (err , "could not load asset components" )
485+ return errors .Wrap (err , "could not load asset components" )
430486 }
431487
432488 existingComponentPurls := make (map [string ]bool )
@@ -516,12 +572,12 @@ func (s *service) UpdateSBOM(assetVersion models.AssetVersion, scannerID string,
516572
517573 // make sure, that the components exist
518574 if err := s .componentRepository .CreateBatch (nil , componentsSlice ); err != nil {
519- return sbomUpdated , err
575+ return err
520576 }
521577
522578 sbomUpdated , err = s .componentRepository .HandleStateDiff (nil , assetVersion .Name , assetVersion .AssetID , assetComponents , dependencies , scannerID )
523579 if err != nil {
524- return sbomUpdated , err
580+ return err
525581 }
526582
527583 // update the license information in the background
@@ -536,7 +592,43 @@ func (s *service) UpdateSBOM(assetVersion models.AssetVersion, scannerID string,
536592 }
537593 }()
538594
539- return sbomUpdated , nil
595+ go func (sbomUpdated bool ) {
596+
597+ if sbomUpdated {
598+ asset , err := s .assetRepository .Read (assetVersion .AssetID )
599+ if err != nil {
600+ slog .Error ("could not read asset" , "assetID" , assetVersion .AssetID , "err" , err )
601+ return
602+ }
603+
604+ pro , err := s .projectRepository .GetProjectByAssetID (asset .ID )
605+ if err != nil {
606+ slog .Error ("could not get project by asset ID" , "err" , err )
607+ return
608+ }
609+
610+ org , err := s .orgRepository .Read (pro .OrganizationID )
611+ if err != nil {
612+ slog .Error ("could not get organization by ID" , "err" , err )
613+ return
614+ }
615+
616+ if err = s .thirdPartyIntegration .HandleEvent (core.SBOMCreatedEvent {
617+ AssetVersion : core .ToAssetVersionObject (assetVersion ),
618+ Asset : core .ToAssetObject (asset ),
619+ Project : core .ToProjectObject (pro ),
620+ Org : core .ToOrgObject (org ),
621+ SBOM : sbom .GetCdxBom (),
622+ }); err != nil {
623+ slog .Error ("could not handle SBOM updated event" , "err" , err )
624+ } else {
625+ slog .Info ("handled SBOM updated event" , "assetVersion" , assetVersion .Name , "assetID" , assetVersion .AssetID )
626+ }
627+ }
628+
629+ }(sbomUpdated )
630+
631+ return nil
540632}
541633
542634func (s * service ) BuildSBOM (assetVersion models.AssetVersion , version string , organizationName string , components []models.ComponentDependency ) * cdx.BOM {
0 commit comments