Skip to content

Commit

Permalink
vulnHash:feature - add treatment to vuln.deprecatedHashes slice (#569)
Browse files Browse the repository at this point in the history
Signed-off-by: Ian Cardoso <ian.cardoso@zup.com.br>
Signed-off-by: Wilian Gabriel <wilian.silva@zup.com.br>
  • Loading branch information
iancardosozup authored Mar 22, 2022
1 parent 75b7d49 commit 949a137
Show file tree
Hide file tree
Showing 7 changed files with 500 additions and 75 deletions.
30 changes: 15 additions & 15 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.21
github.com/ZupIT/horusec-devkit v1.0.23
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 All @@ -12,8 +12,8 @@ require (
github.com/google/wire v0.5.0
github.com/lib/pq v1.10.4
github.com/stretchr/testify v1.7.0
github.com/swaggo/swag v1.7.8
google.golang.org/grpc v1.43.0
github.com/swaggo/swag v1.7.9
google.golang.org/grpc v1.44.0
)

require (
Expand All @@ -37,33 +37,33 @@ require (
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgproto3/v2 v2.2.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b // indirect
github.com/jackc/pgtype v1.9.0 // indirect
github.com/jackc/pgx/v4 v4.14.0 // indirect
github.com/jackc/pgtype v1.9.1 // indirect
github.com/jackc/pgx/v4 v4.14.1 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.3 // indirect
github.com/jinzhu/now v1.1.4 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_golang v1.11.0 // indirect
github.com/prometheus/client_golang v1.12.1 // indirect
github.com/prometheus/client_model v0.2.0 // indirect
github.com/prometheus/common v0.31.1 // indirect
github.com/prometheus/common v0.32.1 // indirect
github.com/prometheus/procfs v0.7.3 // indirect
github.com/sirupsen/logrus v1.8.1 // indirect
github.com/streadway/amqp v1.0.0 // indirect
github.com/stretchr/objx v0.3.0 // indirect
github.com/swaggo/files v0.0.0-20210815190702-a29dd2bc99b2 // indirect
github.com/swaggo/http-swagger v1.1.2 // indirect
golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871 // indirect
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 // indirect
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e // indirect
github.com/swaggo/http-swagger v1.2.5 // indirect
golang.org/x/crypto v0.0.0-20220214200702-86341886e292 // indirect
golang.org/x/net v0.0.0-20220114011407-0dd24b26b47d // indirect
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 // indirect
golang.org/x/text v0.3.7 // indirect
golang.org/x/tools v0.1.7 // indirect
google.golang.org/genproto v0.0.0-20211007155348-82e027067bd4 // indirect
golang.org/x/tools v0.1.8 // indirect
google.golang.org/genproto v0.0.0-20220114231437-d2e6a121cae0 // indirect
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.4 // indirect
gorm.io/gorm v1.22.5 // indirect
)
93 changes: 40 additions & 53 deletions api/go.sum

Large diffs are not rendered by default.

112 changes: 105 additions & 7 deletions api/internal/controllers/analysis/analysis.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,11 @@
package analysis

import (
"errors"
"time"

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

"github.com/google/uuid"

"github.com/ZupIT/horusec-devkit/pkg/entities/analysis"
Expand Down Expand Up @@ -52,26 +55,34 @@ func NewAnalysisController(broker brokerService.IBroker, appConfig appConfigurat
}

func (c *Controller) GetAnalysis(analysisID uuid.UUID) (*analysis.Analysis, error) {
response := c.repoAnalysis.FindAnalysisByID(analysisID)
if response.GetError() != nil {
return nil, response.GetError()
res := c.repoAnalysis.FindAnalysisByID(analysisID)
if res.GetError() != nil {
return nil, res.GetError()
}
if response.GetData() == nil {
if res.GetData() == nil {
return nil, enums.ErrorNotFoundRecords
}

return response.GetData().(*analysis.Analysis), nil
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)
if err != nil {
return uuid.Nil, err
}

if err := c.publishInBroker(analysisDecorated.ID); err != nil {
return uuid.Nil, err
}
Expand Down Expand Up @@ -147,11 +158,98 @@ func (c *Controller) hasDuplicatedHash(
}

func (c *Controller) publishInBroker(analysisID uuid.UUID) error {
response, err := c.GetAnalysis(analysisID)
res, err := c.GetAnalysis(analysisID)
if err != nil {
return err
}

return c.broker.Publish("", exchange.NewAnalysis,
exchange.Fanout, response.ToBytes())
exchange.Fanout, res.ToBytes())
}

// TODO:REMOVE ALL BELOW AFTER v2.10.0
// treatCompatibility 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 {
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 {
return err
}

return nil
}

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
}
query, values := c.mountUpdateQuery(analysisEntity, mapHashToID)

if err := c.repoAnalysis.RawQuery(query, values); err != nil {
return err
}
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())
}
}
}
return query, values
}

// 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 {
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 949a137

Please sign in to comment.