Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

api:fix - Error when not exists analysis in database #583

Merged
merged 1 commit into from
Mar 30, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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