1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.owasp.dependencycheck.analyzer;
19
20 import org.owasp.dependencycheck.Engine;
21 import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
22 import org.owasp.dependencycheck.data.artifactory.ArtifactorySearch;
23 import org.owasp.dependencycheck.data.nexus.MavenArtifact;
24 import org.owasp.dependencycheck.dependency.Confidence;
25 import org.owasp.dependencycheck.dependency.Dependency;
26 import org.owasp.dependencycheck.dependency.Evidence;
27 import org.owasp.dependencycheck.dependency.EvidenceType;
28 import org.owasp.dependencycheck.exception.InitializationException;
29 import org.owasp.dependencycheck.utils.DownloadFailedException;
30 import org.owasp.dependencycheck.utils.Downloader;
31 import org.owasp.dependencycheck.utils.FileFilterBuilder;
32 import org.owasp.dependencycheck.utils.FileUtils;
33 import org.owasp.dependencycheck.utils.InvalidSettingException;
34 import org.owasp.dependencycheck.utils.ResourceNotFoundException;
35 import org.owasp.dependencycheck.utils.Settings;
36 import org.owasp.dependencycheck.utils.TooManyRequestsException;
37 import org.owasp.dependencycheck.xml.pom.PomUtils;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
40
41 import javax.annotation.concurrent.ThreadSafe;
42 import java.io.File;
43 import java.io.FileFilter;
44 import java.io.FileNotFoundException;
45 import java.io.IOException;
46 import java.net.URL;
47 import java.nio.file.Files;
48 import java.util.List;
49
50
51
52
53
54
55
56 @ThreadSafe
57 public class ArtifactoryAnalyzer extends AbstractFileTypeAnalyzer {
58
59
60
61
62 private static final Logger LOGGER = LoggerFactory.getLogger(ArtifactoryAnalyzer.class);
63
64
65
66
67 private static final String ANALYZER_NAME = "Artifactory Analyzer";
68
69
70
71
72 private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INFORMATION_COLLECTION;
73
74
75
76
77 private static final String SUPPORTED_EXTENSIONS = "jar";
78
79
80
81
82 private static final FileFilter FILTER = FileFilterBuilder.newInstance().addExtensions(SUPPORTED_EXTENSIONS).build();
83
84
85
86
87 private ArtifactorySearch searcher;
88
89
90
91
92
93
94 @Override
95 public synchronized void initialize(Settings settings) {
96 super.initialize(settings);
97 setEnabled(checkEnabled());
98 }
99
100
101
102
103
104
105
106 @Override
107 public boolean supportsParallelProcessing() {
108 return getSettings().getBoolean(Settings.KEYS.ANALYZER_ARTIFACTORY_PARALLEL_ANALYSIS, true);
109 }
110
111
112
113
114
115
116
117 private boolean checkEnabled() {
118 try {
119 return getSettings().getBoolean(Settings.KEYS.ANALYZER_ARTIFACTORY_ENABLED);
120 } catch (InvalidSettingException ise) {
121 LOGGER.warn("Invalid setting. Disabling the Artifactory analyzer");
122 }
123 return false;
124 }
125
126
127
128
129
130
131
132
133 @Override
134 public void prepareFileTypeAnalyzer(Engine engine) throws InitializationException {
135 LOGGER.debug("Initializing Artifactory analyzer");
136 final boolean enabled = isEnabled();
137 LOGGER.debug("Artifactory analyzer enabled: {}", enabled);
138 if (enabled) {
139 searcher = new ArtifactorySearch(getSettings());
140 final boolean preflightRequest = searcher.preflightRequest();
141 if (!preflightRequest) {
142 setEnabled(false);
143 throw new InitializationException("There was an issue connecting to Artifactory . Disabling analyzer.");
144 }
145 }
146 }
147
148
149
150
151
152
153 @Override
154 public String getName() {
155 return ANALYZER_NAME;
156 }
157
158
159
160
161
162
163
164 @Override
165 protected String getAnalyzerEnabledSettingKey() {
166 return Settings.KEYS.ANALYZER_ARTIFACTORY_ENABLED;
167 }
168
169
170
171
172
173
174 @Override
175 public AnalysisPhase getAnalysisPhase() {
176 return ANALYSIS_PHASE;
177 }
178
179 @Override
180 protected FileFilter getFileFilter() {
181 return FILTER;
182 }
183
184
185
186
187
188
189
190
191 @Override
192 public void analyzeDependency(Dependency dependency, Engine engine) throws AnalysisException {
193 for (Evidence e : dependency.getEvidence(EvidenceType.VENDOR)) {
194 if ("pom".equals(e.getSource())) {
195 return;
196 }
197 }
198 try {
199 final List<MavenArtifact> mas = searcher.search(dependency);
200 final Confidence confidence = mas.size() > 1 ? Confidence.HIGH : Confidence.HIGHEST;
201 for (MavenArtifact ma : mas) {
202 LOGGER.debug("Artifactory analyzer found artifact ({}) for dependency ({})", ma, dependency.getFileName());
203 dependency.addAsEvidence("artifactory", ma, confidence);
204
205 if (ma.getPomUrl() != null) {
206 processPom(dependency, ma);
207 }
208 }
209 } catch (IllegalArgumentException iae) {
210 LOGGER.info("invalid sha1-hash on {}", dependency.getFileName());
211 } catch (FileNotFoundException fnfe) {
212 LOGGER.debug("Artifact not found in repository: '{}", dependency.getFileName());
213 } catch (IOException ioe) {
214 final String message = "Could not connect to Artifactory search. Analysis failed.";
215 LOGGER.error(message, ioe);
216 throw new AnalysisException(message, ioe);
217 }
218 }
219
220
221
222
223
224
225
226
227
228
229 private void processPom(Dependency dependency, MavenArtifact ma) throws IOException, AnalysisException {
230 File pomFile = null;
231 try {
232 final File baseDir = getSettings().getTempDirectory();
233 pomFile = File.createTempFile("pom", ".xml", baseDir);
234 Files.delete(pomFile.toPath());
235 LOGGER.debug("Downloading {}", ma.getPomUrl());
236
237 Downloader.getInstance().fetchFile(new URL(ma.getPomUrl()), pomFile, true,
238 Settings.KEYS.ANALYZER_ARTIFACTORY_API_USERNAME,
239 Settings.KEYS.ANALYZER_ARTIFACTORY_API_TOKEN);
240 PomUtils.analyzePOM(dependency, pomFile);
241
242 } catch (DownloadFailedException ex) {
243 LOGGER.warn("Unable to download pom.xml for {} from Artifactory; "
244 + "this could result in undetected CPE/CVEs.", dependency.getFileName());
245 } catch (TooManyRequestsException ex) {
246 this.setEnabled(false);
247 throw new AnalysisException("Received a 429 - too many requests from Artifactory; "
248 + "the artifactory analyzer is being disabled.", ex);
249 } catch (ResourceNotFoundException ex) {
250 LOGGER.warn("pom.xml not found for {} from Artifactory; "
251 + "this could result in undetected CPE/CVEs.", dependency.getFileName());
252 } finally {
253 if (pomFile != null && pomFile.exists() && !FileUtils.delete(pomFile)) {
254 LOGGER.debug("Failed to delete temporary pom file {}", pomFile);
255 pomFile.deleteOnExit();
256 }
257 }
258 }
259
260 }