Skip to content

Commit

Permalink
api:fix - Error when not exists analysis in database (#583)
Browse files Browse the repository at this point in the history
When not exists analysis in database, I founded this problem.
And for solution it was necessary change this logic for check if
not exists hashes deprecated. Other problem resolved here was
about the responsability of the methods, them I change all code
with database logic to repositories layer and stay only business logic
into controllers layer.

Signed-off-by: Wilian Gabriel <[email protected]>
  • Loading branch information
wiliansilvazup committed Mar 30, 2022
1 parent 949a137 commit 46e61fc
Show file tree
Hide file tree
Showing 7 changed files with 274 additions and 136 deletions.
6 changes: 3 additions & 3 deletions api/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module github.com/ZupIT/horusec-platform/api
go 1.17

require (
github.com/ZupIT/horusec-devkit v1.0.23
github.com/ZupIT/horusec-devkit v1.0.24
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751
github.com/go-chi/chi v4.1.2+incompatible
github.com/go-chi/cors v1.2.0
Expand Down Expand Up @@ -64,6 +64,6 @@ require (
google.golang.org/protobuf v1.27.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
gorm.io/driver/postgres v1.2.3 // indirect
gorm.io/gorm v1.22.5 // indirect
gorm.io/driver/postgres v1.3.1 // indirect
gorm.io/gorm v1.23.2 // indirect
)
17 changes: 7 additions & 10 deletions api/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tN
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/ZupIT/horusec-devkit v1.0.23 h1:CBL5ya45zLMXYYgmdAtShAm3VC1F7KQGiRaIU3WGTow=
github.com/ZupIT/horusec-devkit v1.0.23/go.mod h1:01lg6tLZkqwJE/Nn8Prnq7bFjq9Agf4zwbuV47sxMno=
github.com/ZupIT/horusec-devkit v1.0.24 h1:GGW6LyyvVvmN2+2/miPjOZ6E6BhE9k7Tw0rVcS+CaFM=
github.com/ZupIT/horusec-devkit v1.0.24/go.mod h1:l1vuCb/lxyGZ8vIgW3EO5CS6aJUukGprD9UB6FwU16w=
github.com/agiledragon/gomonkey/v2 v2.3.1 h1:k+UnUY0EMNYUFUAQVETGY9uUTxjMdnUkP0ARyJS1zzs=
github.com/agiledragon/gomonkey/v2 v2.3.1/go.mod h1:ap1AmDzcVOAz1YpeJ3TCzIgstoaWLA6jbbgxfB4w2iY=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
Expand Down Expand Up @@ -244,14 +244,12 @@ github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01C
github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc=
github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw=
github.com/jackc/pgtype v1.8.1-0.20210724151600-32e20a603178/go.mod h1:C516IlIV9NKqfsMCXTdChteoXmwgUceqaLfjg2e3NlM=
github.com/jackc/pgtype v1.9.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4=
github.com/jackc/pgtype v1.9.1 h1:MJc2s0MFS8C3ok1wQTdQxWuXQcB6+HwAm5x1CzW7mf0=
github.com/jackc/pgtype v1.9.1/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4=
github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y=
github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM=
github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc=
github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs=
github.com/jackc/pgx/v4 v4.14.0/go.mod h1:jT3ibf/A0ZVCp89rtCIN0zCJxcE74ypROmHEZYsG/j8=
github.com/jackc/pgx/v4 v4.14.1 h1:71oo1KAGI6mXhLiTMn6iDFcp3e7+zon/capWjl2OEFU=
github.com/jackc/pgx/v4 v4.14.1/go.mod h1:RgDuE4Z34o7XE92RpLsvFiOEfrAUT0Xt2KxvX73W06M=
github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
Expand All @@ -260,7 +258,6 @@ github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dv
github.com/jackc/puddle v1.2.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.1.2/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/jinzhu/now v1.1.4 h1:tHnRBy1i5F2Dh8BAFxqFzxKqqvezXrL2OW1TnX+Mlas=
github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
Expand Down Expand Up @@ -744,11 +741,11 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gorm.io/driver/postgres v1.2.3 h1:f4t0TmNMy9gh3TU2PX+EppoA6YsgFnyq8Ojtddb42To=
gorm.io/driver/postgres v1.2.3/go.mod h1:pJV6RgYQPG47aM1f0QeOzFH9HxQc8JcmAgjRCgS0wjs=
gorm.io/gorm v1.22.3/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0=
gorm.io/gorm v1.22.5 h1:lYREBgc02Be/5lSCTuysZZDb6ffL2qrat6fg9CFbvXU=
gorm.io/gorm v1.22.5/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk=
gorm.io/driver/postgres v1.3.1 h1:Pyv+gg1Gq1IgsLYytj/S2k7ebII3CzEdpqQkPOdH24g=
gorm.io/driver/postgres v1.3.1/go.mod h1:WwvWOuR9unCLpGWCL6Y3JOeBWvbKi6JLhayiVclSZZU=
gorm.io/gorm v1.23.1/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk=
gorm.io/gorm v1.23.2 h1:xmq9QRMWL8HTJyhAUBXy8FqIIQCYESeKfJL4DoGKiWQ=
gorm.io/gorm v1.23.2/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
Expand Down
132 changes: 50 additions & 82 deletions api/internal/controllers/analysis/analysis.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,9 @@
package analysis

import (
"errors"
"time"

"github.com/ZupIT/horusec-devkit/pkg/services/database/response"
"github.com/ZupIT/horusec-devkit/pkg/entities/vulnerability"

"github.com/google/uuid"

Expand Down Expand Up @@ -66,23 +65,15 @@ func (c *Controller) GetAnalysis(analysisID uuid.UUID) (*analysis.Analysis, erro
return res.GetData().(*analysis.Analysis), nil
}

// nolint
func (c *Controller) SaveAnalysis(analysisEntity *analysis.Analysis) (uuid.UUID, error) {
analysisEntity, err := c.createRepositoryIfNotExists(analysisEntity)
if err != nil {
return uuid.Nil, err
}

//TODO: REMOVE treatCompatibility IN v2.10.0 VERSION
if err := c.treatCompatibility(analysisEntity); err != nil {
return uuid.Nil, err
}

analysisDecorated, err := c.decorateAnalysisEntityAndSaveOnDatabase(analysisEntity)
analysisDecorated, err := c.saveNewAnalysisInDatabase(analysisEntity)
if err != nil {
return uuid.Nil, err
}

if err := c.publishInBroker(analysisDecorated.ID); err != nil {
return uuid.Nil, err
}
Expand All @@ -105,10 +96,19 @@ func (c *Controller) createRepositoryIfNotExists(analysisEntity *analysis.Analys
return analysisEntity, nil
}

func (c *Controller) decorateAnalysisEntityAndSaveOnDatabase(
analysisEntity *analysis.Analysis) (*analysis.Analysis, error) {
analysisDecorated := c.decoratorAnalysisToSave(analysisEntity)
return analysisDecorated, c.createNewAnalysis(analysisDecorated)
func (c *Controller) saveNewAnalysisInDatabase(newAnalysis *analysis.Analysis) (*analysis.Analysis, error) {
//TODO: REMOVE treatHashCompatibility IN v2.10.0 VERSION
if err := c.treatHashCompatibility(newAnalysis); err != nil {
return nil, err
}

analysisDecorated := c.decoratorAnalysisToSave(newAnalysis)

if err := c.repoAnalysis.CreateFullAnalysis(analysisDecorated); err != nil {
return nil, err
}

return analysisDecorated, nil
}

func (c *Controller) decoratorAnalysisToSave(analysisEntity *analysis.Analysis) *analysis.Analysis {
Expand All @@ -128,10 +128,6 @@ func (c *Controller) decoratorAnalysisToSave(analysisEntity *analysis.Analysis)
return newAnalysis
}

func (c *Controller) createNewAnalysis(newAnalysis *analysis.Analysis) error {
return c.repoAnalysis.CreateFullAnalysis(newAnalysis)
}

func (c *Controller) extractBaseOfTheAnalysis(analysisEntity *analysis.Analysis) *analysis.Analysis {
return &analysis.Analysis{
ID: analysisEntity.ID,
Expand Down Expand Up @@ -168,88 +164,60 @@ func (c *Controller) publishInBroker(analysisID uuid.UUID) error {
}

// TODO:REMOVE ALL BELOW AFTER v2.10.0
// treatCompatibility checks if the field Analysis.AnalysisVulnerabilities[i].DeprecatedHashes exists
// treatHashCompatibility checks if the field Analysis.AnalysisVulnerabilities[i].DeprecatedHashes exists
// and if so, find them on database and updates it with the correct field Analysis.AnalysisVulnerabilities[i].VulnHash.
// this is only a temporary fix to maintain compatibility between versions,
// it will be deleted when v2.10.0 is released
// nolint
func (c *Controller) treatCompatibility(analysisEntity *analysis.Analysis) error {
// nolint:funlen,gocyclo // funlen and gocyclo is not necessary in this method deprecated
func (c *Controller) treatHashCompatibility(analysisEntity *analysis.Analysis) error {
if !c.existsDeprecatedHashesSlice(analysisEntity.AnalysisVulnerabilities) {
return nil
}
deprecatedHashes := make([]string, 0)

for i := range analysisEntity.AnalysisVulnerabilities {
deprecatedHashes = append(
deprecatedHashes,
analysisEntity.AnalysisVulnerabilities[i].Vulnerability.DeprecatedHashes...)
}

if err := c.saveUpdates(deprecatedHashes, analysisEntity); err != nil {
deprecatedHashes := []string{}
for index := range analysisEntity.AnalysisVulnerabilities {
manyToMany := analysisEntity.AnalysisVulnerabilities[index]
deprecatedHashes = append(deprecatedHashes, manyToMany.Vulnerability.DeprecatedHashes...)
}
mapHashToVulnerabilityID, err := c.getMapHashToVulnerabilityID(deprecatedHashes, analysisEntity)
if err != nil || len(mapHashToVulnerabilityID) == 0 {
// When the database cannot find data, it means that the user is using the new CLI version,
// but Horusec-Platform is new and has not yet received any analysis for this repository.
if err == enums.ErrorNotFoundRecords {
return nil
}
return err
}

return nil
return c.repoAnalysis.SaveTreatCompatibility(mapHashToVulnerabilityID, analysisEntity)
}

func (c *Controller) saveUpdates(hashSlice []string, analysisEntity *analysis.Analysis) error {
res := c.repoAnalysis.FindVulnerabilitiesByHashSliceInRepository(hashSlice, analysisEntity.RepositoryID)
if res.GetError() != nil {
return res.GetError()
}
mapHashToID, err := c.parseResIds(res)
if err != nil {
return err
// existsDeprecatedHashesSlice will get all vulnerabilities from database with deprecated hashes
// nolint:funlen // funlen is not necessary in this method deprecated
func (c *Controller) getMapHashToVulnerabilityID(deprecatedHashes []string,
analysisEntity *analysis.Analysis) (map[string]uuid.UUID, error) {
mapHashToVulnerabilityID := make(map[string]uuid.UUID, 0)
res := c.repoAnalysis.FindAllVulnerabilitiesByHashesAndRepository(deprecatedHashes, analysisEntity.RepositoryID)
if err := res.GetError(); err != nil {
return map[string]uuid.UUID{}, err
}
query, values := c.mountUpdateQuery(analysisEntity, mapHashToID)

if err := c.repoAnalysis.RawQuery(query, values); err != nil {
return err
if res.GetData() == nil {
return map[string]uuid.UUID{}, nil
}
return nil
}

// mountUpdateQuery iterates over rawAnalysis.AnalysisVulnerabilities and
// checks if some vuln.Vulnerability.DeprecatedHashes is present on
// mapHashToId then creates and update statement to update the
// deprecated Hash value to the new one (that is present in rawAnalysis.Vulnerability.VulnHash field)
func (c *Controller) mountUpdateQuery(
rawAnalysis *analysis.Analysis, mapHashToID map[string]uuid.UUID,
) (string, []string) {
query := ""
values := make([]string, 0)
for i := range rawAnalysis.AnalysisVulnerabilities {
vuln := rawAnalysis.AnalysisVulnerabilities[i]
for _, hash := range vuln.Vulnerability.DeprecatedHashes {
if mapHashToID[hash] != uuid.Nil {
query += "UPDATE vulnerabilities SET vuln_hash =? where vulnerability_id = ? ;\n"
values = append(values, vuln.Vulnerability.VulnHash, mapHashToID[hash].String())
}
}
vulnerabilities := *res.GetData().(*[]vulnerability.Vulnerability)
for index := range vulnerabilities {
vuln := vulnerabilities[index]
mapHashToVulnerabilityID[vuln.VulnHash] = vuln.VulnerabilityID
}
return query, values
return mapHashToVulnerabilityID, nil
}

// existsDeprecatedHashesSlice checks if []analysis.AnalysisVulnerabilities.Vulnerability
// has a field called DeprecatedHashes
func (c *Controller) existsDeprecatedHashesSlice(vulns []analysis.AnalysisVulnerabilities) bool {
if len(vulns) > 0 {
if vulns[0].Vulnerability.DeprecatedHashes != nil {
func (c *Controller) existsDeprecatedHashesSlice(sliceManyToMany []analysis.AnalysisVulnerabilities) bool {
for index := range sliceManyToMany {
manyToMany := sliceManyToMany[index]
if len(manyToMany.Vulnerability.DeprecatedHashes) > 0 {
return true
}
}
return false
}

// parseResIds makes a map[hash] id that already exists on database for further manipulation
func (c *Controller) parseResIds(res response.IResponse) (map[string]uuid.UUID, error) {
if res.GetData() == nil {
return nil, errors.New("nil response.GetData")
}
mapIds := res.GetData().(*[]map[string]interface{})
mapIDHash := make(map[string]uuid.UUID, len(*mapIds))
for _, id := range *mapIds {
mapIDHash[id["vuln_hash"].(string)] = uuid.MustParse(id["vulnerability_id"].(string))
}
return mapIDHash, nil
}
Loading

0 comments on commit 46e61fc

Please sign in to comment.