|
1 | 1 | package remediation
|
2 | 2 |
|
3 | 3 | import (
|
4 |
| - "errors" |
5 | 4 | "fmt"
|
6 |
| - "slices" |
7 | 5 |
|
8 |
| - "github.com/snyk/go-application-framework/pkg/apiclients/testapi" |
9 |
| - |
10 |
| - "github.com/snyk/cli-extension-os-flows/internal/legacy/definitions" |
11 |
| - "github.com/snyk/cli-extension-os-flows/internal/semver/shared" |
| 6 | + "github.com/snyk/cli-extension-os-flows/internal/semver" |
12 | 7 | )
|
13 | 8 |
|
14 |
| -func FixesToRemediationSummary(findings []Finding, semver shared.Runtime) Summary { |
15 |
| - calculatePins(findings, semver) |
16 |
| - return Summary{} |
17 |
| -} |
18 |
| - |
19 |
| -func getDepedencyPathEvidence(finding testapi.FindingData) (*testapi.DependencyPathEvidence, error) { |
20 |
| - for _, ev := range finding.Attributes.Evidence { |
21 |
| - disc, err := ev.Discriminator() |
22 |
| - if err != nil { |
23 |
| - return nil, err |
24 |
| - } |
25 |
| - |
26 |
| - if disc != string(testapi.DependencyPath) { |
27 |
| - continue |
28 |
| - } |
29 |
| - |
30 |
| - depPath, err := ev.AsDependencyPathEvidence() |
31 |
| - if err != nil { |
32 |
| - return nil, err |
33 |
| - } |
34 |
| - |
35 |
| - return &depPath, nil |
| 9 | +func FixesToRemediationSummary(findings []Finding) (Summary, error) { |
| 10 | + pins, err := calculatePins(findings) |
| 11 | + if err != nil { |
| 12 | + return Summary{}, err |
36 | 13 | }
|
37 |
| - return nil, fmt.Errorf("no depedency path evidence was found for finding: %s", finding.Id) |
| 14 | + return Summary{Pins: pins}, err |
38 | 15 | }
|
39 | 16 |
|
40 |
| -func getSnykVuln(finding testapi.FindingData) (*testapi.SnykVulnProblem, error) { |
41 |
| - for _, prob := range finding.Attributes.Problems { |
42 |
| - disc, err := prob.Discriminator() |
43 |
| - if err != nil { |
44 |
| - return nil, err |
45 |
| - } |
| 17 | +type packageKey string |
46 | 18 |
|
47 |
| - if disc != string(testapi.SnykVuln) { |
48 |
| - continue |
49 |
| - } |
50 |
| - |
51 |
| - vuln, err := prob.AsSnykVulnProblem() |
52 |
| - if err != nil { |
53 |
| - return nil, err |
54 |
| - } |
55 |
| - |
56 |
| - return &vuln, nil |
57 |
| - } |
58 |
| - return nil, nil |
| 19 | +func NewPackageKey(p Package) packageKey { |
| 20 | + return packageKey(fmt.Sprintf("%s@%s", p.Name, p.Version)) |
59 | 21 | }
|
60 | 22 |
|
61 |
| -func calculatePins(findings []Finding, semver shared.Runtime) (map[string]definitions.PinRemediation, error) { |
62 |
| - pin := make(map[string]Upgrade) |
| 23 | +func calculatePins(findings []Finding) ([]Upgrade, error) { |
| 24 | + var output []Upgrade |
| 25 | + var pinMap = make(map[packageKey]Upgrade) |
63 | 26 | for _, finding := range findings {
|
64 |
| - if len(finding.DependencyPath) < 2 { |
65 |
| - continue |
66 |
| - } |
| 27 | + vulnerablePackage := finding.Package |
| 28 | + key := NewPackageKey(vulnerablePackage) |
67 | 29 |
|
68 |
| - // vuln, err := getSnykVuln(finding) |
69 |
| - // if err != nil { |
70 |
| - // return nil, err |
71 |
| - // } |
72 |
| - // |
73 |
| - // if vuln == nil { |
74 |
| - // continue |
75 |
| - // } |
76 |
| - |
77 |
| - key := fmt.Sprintf("%s@%s", finding.Package.Name, finding.Package.Version) |
78 |
| - |
79 |
| - var currentUpgradeToVersion string |
80 |
| - vulnPin, pinExistsForPkg := pin[key] |
81 |
| - if pinExistsForPkg { |
82 |
| - currentUpgradeToVersion = vulnPin.To.Version |
83 |
| - } |
84 |
| - |
85 |
| - if len(finding.InitiallyFixedInVersions) == 0 { |
86 |
| - continue |
87 |
| - } |
| 30 | + upgrade, upgradeExists := pinMap[key] |
88 | 31 |
|
89 |
| - var sortErr error |
90 |
| - slices.SortStableFunc(finding.InitiallyFixedInVersions, func(a, b string) int { |
91 |
| - comp, err := semver.Compare(a, b) |
92 |
| - if err != nil { |
93 |
| - sortErr = errors.Join(sortErr, err) |
94 |
| - } |
95 |
| - return comp |
96 |
| - }) |
97 |
| - if sortErr != nil { |
98 |
| - return nil, fmt.Errorf("failed to sort fixedIn values: %w", sortErr) |
| 32 | + vulnerabilityInPackage := VulnerabilityInPackage{ |
| 33 | + VulnerablePackage: vulnerablePackage, |
| 34 | + Vulnerability: finding.Vulnerability, |
| 35 | + IntroducedThrough: finding.DependencyPaths, |
99 | 36 | }
|
100 | 37 |
|
101 |
| - var newVersion string |
102 |
| - for _, fixVersion := range finding.InitiallyFixedInVersions { |
103 |
| - comp, err := semver.Compare(fixVersion, finding.Package.Version) |
| 38 | + if upgradeExists { |
| 39 | + highestVersion, err := getMaxVersion(finding.PackageManager, upgrade.To.Version, finding.Fix.(PinFix).PinAction.Package.Version) |
104 | 40 | if err != nil {
|
105 | 41 | return nil, err
|
106 | 42 | }
|
| 43 | + upgrade.To.Version = highestVersion |
| 44 | + upgrade.Fixes = append(upgrade.Fixes, vulnerabilityInPackage) |
107 | 45 |
|
108 |
| - if comp > 0 { |
109 |
| - newVersion = fixVersion |
110 |
| - break |
111 |
| - } |
112 |
| - } |
113 |
| - |
114 |
| - if newVersion == "" { |
115 |
| - continue |
116 |
| - } |
117 |
| - |
118 |
| - if !pinExistsForPkg { |
119 |
| - pin[key] = Upgrade{ |
120 |
| - From: finding.Package, |
121 |
| - To: Package{ |
122 |
| - Name: finding.Package.Name, |
123 |
| - Version: newVersion, |
124 |
| - }, |
125 |
| - Fixes: []*VulnerabilityInPackage{ |
126 |
| - { |
127 |
| - VulnerablePackage: finding.Package, |
128 |
| - Vulnerability: Vulnerability{ |
129 |
| - ID: finding.VulnId, |
130 |
| - Name: finding.Title, |
131 |
| - Severity: finding.Severity, |
132 |
| - }, |
133 |
| - IntroducedThrough: []DependencyPath{finding.DependencyPath}, |
134 |
| - }, |
135 |
| - }, |
136 |
| - } |
| 46 | + pinMap[key] = upgrade |
137 | 47 | } else {
|
138 |
| - var fixForVuln *VulnerabilityInPackage |
139 |
| - for _, vulnInPkg := range vulnPin.Fixes { |
140 |
| - if vulnInPkg.Vulnerability.ID == finding.VulnId { |
141 |
| - fixForVuln := vulnInPkg |
142 |
| - break |
143 |
| - } |
144 |
| - } |
145 |
| - if fixForVuln { |
146 |
| - fixForVuln.IntroducedThrough = append(fixForVuln.IntroducedThrough, fi) |
147 |
| - } |
148 |
| - vulnPin.Vulns = append(vulnPin.Vulns, vuln.Id) |
149 | 48 |
|
150 |
| - v, err := semver.Compare(newVersion, currentUpgradeToVersion) |
151 |
| - if err != nil { |
152 |
| - return nil, err |
153 |
| - } |
154 |
| - if v > 0 { |
155 |
| - vulnPin.UpgradeTo = fmt.Sprintf("%s@%s", vuln.PackageName, newVersion) |
| 49 | + pinMap[key] = Upgrade{ |
| 50 | + From: vulnerablePackage, |
| 51 | + To: finding.Fix.(PinFix).PinAction.Package, |
| 52 | + Fixes: []VulnerabilityInPackage{vulnerabilityInPackage}, |
156 | 53 | }
|
157 |
| - |
158 |
| - // vulnPin is a copy of the value from the map, |
159 |
| - // so we need to store it back after modifying it |
160 |
| - pin[key] = vulnPin |
161 | 54 | }
|
162 | 55 | }
|
163 |
| - return pin, nil |
| 56 | + |
| 57 | + for _, pin := range pinMap { |
| 58 | + output = append(output, pin) |
| 59 | + } |
| 60 | + return output, nil |
| 61 | + //pin := make(map[string]Upgrade) |
| 62 | + //for _, finding := range findings { |
| 63 | + // if len(finding.DependencyPath) < 2 { |
| 64 | + // continue |
| 65 | + // } |
| 66 | + // |
| 67 | + // key := fmt.Sprintf("%s@%s", finding.Package.Name, finding.Package.Version) |
| 68 | + // |
| 69 | + // var currentUpgradeToVersion string |
| 70 | + // vulnPin, pinExistsForPkg := pin[key] |
| 71 | + // if pinExistsForPkg { |
| 72 | + // currentUpgradeToVersion = vulnPin.To.Version |
| 73 | + // } |
| 74 | + // |
| 75 | + // if len(finding.InitiallyFixedInVersions) == 0 { |
| 76 | + // continue |
| 77 | + // } |
| 78 | + // |
| 79 | + // var sortErr error |
| 80 | + // slices.SortStableFunc(finding.InitiallyFixedInVersions, func(a, b string) int { |
| 81 | + // comp, err := semver.Compare(a, b) |
| 82 | + // if err != nil { |
| 83 | + // sortErr = errors.Join(sortErr, err) |
| 84 | + // } |
| 85 | + // return comp |
| 86 | + // }) |
| 87 | + // if sortErr != nil { |
| 88 | + // return nil, fmt.Errorf("failed to sort fixedIn values: %w", sortErr) |
| 89 | + // } |
| 90 | + // |
| 91 | + // var newVersion string |
| 92 | + // for _, fixVersion := range finding.InitiallyFixedInVersions { |
| 93 | + // comp, err := semver.Compare(fixVersion, finding.Package.Version) |
| 94 | + // if err != nil { |
| 95 | + // return nil, err |
| 96 | + // } |
| 97 | + // |
| 98 | + // if comp > 0 { |
| 99 | + // newVersion = fixVersion |
| 100 | + // break |
| 101 | + // } |
| 102 | + // } |
| 103 | + // |
| 104 | + // if newVersion == "" { |
| 105 | + // continue |
| 106 | + // } |
| 107 | + // |
| 108 | + // if !pinExistsForPkg { |
| 109 | + // pin[key] = Upgrade{ |
| 110 | + // From: finding.Package, |
| 111 | + // To: Package{ |
| 112 | + // Name: finding.Package.Name, |
| 113 | + // Version: newVersion, |
| 114 | + // }, |
| 115 | + // Fixes: []*VulnerabilityInPackage{ |
| 116 | + // { |
| 117 | + // VulnerablePackage: finding.Package, |
| 118 | + // Vulnerability: Vulnerability{ |
| 119 | + // ID: finding.VulnId, |
| 120 | + // Name: finding.Title, |
| 121 | + // Severity: finding.Severity, |
| 122 | + // }, |
| 123 | + // IntroducedThrough: []DependencyPath{finding.DependencyPath}, |
| 124 | + // }, |
| 125 | + // }, |
| 126 | + // } |
| 127 | + // } else { |
| 128 | + // var fixForVuln *VulnerabilityInPackage |
| 129 | + // for _, vulnInPkg := range vulnPin.Fixes { |
| 130 | + // if vulnInPkg.Vulnerability.ID == finding.VulnId { |
| 131 | + // fixForVuln := vulnInPkg |
| 132 | + // break |
| 133 | + // } |
| 134 | + // } |
| 135 | + // if fixForVuln { |
| 136 | + // fixForVuln.IntroducedThrough = append(fixForVuln.IntroducedThrough, fi) |
| 137 | + // } |
| 138 | + // vulnPin.Vulns = append(vulnPin.Vulns, vuln.Id) |
| 139 | + // |
| 140 | + // v, err := semver.Compare(newVersion, currentUpgradeToVersion) |
| 141 | + // if err != nil { |
| 142 | + // return nil, err |
| 143 | + // } |
| 144 | + // if v > 0 { |
| 145 | + // vulnPin.UpgradeTo = fmt.Sprintf("%s@%s", vuln.PackageName, newVersion) |
| 146 | + // } |
| 147 | + // |
| 148 | + // // vulnPin is a copy of the value from the map, |
| 149 | + // // so we need to store it back after modifying it |
| 150 | + // pin[key] = vulnPin |
| 151 | + // } |
| 152 | + //} |
| 153 | + //return pin, nil |
| 154 | +} |
| 155 | + |
| 156 | +func getMaxVersion(packageManager PackageManager, v1 string, v2 string) (string, error) { |
| 157 | + semverResolver, err := semver.GetSemver(string(packageManager)) |
| 158 | + if err != nil { |
| 159 | + return "", err |
| 160 | + } |
| 161 | + var version string |
| 162 | + compare, err := semverResolver.Compare(v1, v2) |
| 163 | + if err != nil { |
| 164 | + return "", err |
| 165 | + } |
| 166 | + if compare >= 0 { |
| 167 | + version = v1 |
| 168 | + } else { |
| 169 | + version = v2 |
| 170 | + } |
| 171 | + return version, nil |
164 | 172 | }
|
0 commit comments