diff --git a/core/src/main/java/io/snyk/plugins/artifactory/SnykPlugin.java b/core/src/main/java/io/snyk/plugins/artifactory/SnykPlugin.java index 39a8f0a..be49cad 100644 --- a/core/src/main/java/io/snyk/plugins/artifactory/SnykPlugin.java +++ b/core/src/main/java/io/snyk/plugins/artifactory/SnykPlugin.java @@ -4,10 +4,11 @@ import io.snyk.plugins.artifactory.configuration.UserAgent; import io.snyk.plugins.artifactory.configuration.properties.ArtifactProperty; import io.snyk.plugins.artifactory.configuration.ConfigurationModule; +import io.snyk.plugins.artifactory.ecosystem.Ecosystem; import io.snyk.plugins.artifactory.exception.CannotScanException; import io.snyk.plugins.artifactory.exception.SnykAPIFailureException; import io.snyk.plugins.artifactory.exception.SnykRuntimeException; -import io.snyk.plugins.artifactory.scanner.ScannerModule; +import io.snyk.plugins.artifactory.scanner.*; import io.snyk.sdk.SnykConfig; import io.snyk.sdk.api.v1.SnykClient; import io.snyk.sdk.api.v1.SnykResult; @@ -63,7 +64,8 @@ public SnykPlugin(@Nonnull Repositories repositories, File pluginsDirectory) { final SnykClient snykClient = createSnykClient(configurationModule, pluginVersion); auditModule = new AuditModule(); - scannerModule = new ScannerModule(configurationModule, repositories, snykClient); + ScannerResolver scannerResolver = ScannerResolver.setup(configurationModule, snykClient); + scannerModule = new ScannerModule(configurationModule, repositories, scannerResolver); LOG.info("Plugin version: {}", pluginVersion); } catch (Exception ex) { diff --git a/core/src/main/java/io/snyk/plugins/artifactory/scanner/Ecosystem.java b/core/src/main/java/io/snyk/plugins/artifactory/ecosystem/Ecosystem.java similarity index 52% rename from core/src/main/java/io/snyk/plugins/artifactory/scanner/Ecosystem.java rename to core/src/main/java/io/snyk/plugins/artifactory/ecosystem/Ecosystem.java index c488106..2f9a4c8 100644 --- a/core/src/main/java/io/snyk/plugins/artifactory/scanner/Ecosystem.java +++ b/core/src/main/java/io/snyk/plugins/artifactory/ecosystem/Ecosystem.java @@ -1,16 +1,21 @@ -package io.snyk.plugins.artifactory.scanner; +package io.snyk.plugins.artifactory.ecosystem; import io.snyk.plugins.artifactory.configuration.PluginConfiguration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.Optional; public enum Ecosystem { + MAVEN(PluginConfiguration.SCANNER_PACKAGE_TYPE_MAVEN), NPM(PluginConfiguration.SCANNER_PACKAGE_TYPE_NPM), PYPI(PluginConfiguration.SCANNER_PACKAGE_TYPE_PYPI), ; + private static final Logger LOG = LoggerFactory.getLogger(Ecosystem.class); + private final PluginConfiguration configProperty; Ecosystem(PluginConfiguration configProperty) { @@ -21,19 +26,14 @@ public PluginConfiguration getConfigProperty() { return configProperty; } - static Optional fromPackagePath(String path) { - if (path.endsWith(".jar")) { - return Optional.of(MAVEN); - } - - if (path.endsWith(".tgz")) { - return Optional.of(NPM); - } - - if (path.endsWith(".whl") || path.endsWith(".tar.gz") || path.endsWith(".zip") || path.endsWith(".egg")) { - return Optional.of(PYPI); + public static Optional fromPackageType(String artifactoryPackageType) { + switch (artifactoryPackageType.toLowerCase()) { + case "maven": return Optional.of(MAVEN); + case "npm": return Optional.of(NPM); + case "pypi": return Optional.of(PYPI); } + LOG.error("Unknown package type: {}", artifactoryPackageType); return Optional.empty(); } } diff --git a/core/src/main/java/io/snyk/plugins/artifactory/ecosystem/EcosystemResolver.java b/core/src/main/java/io/snyk/plugins/artifactory/ecosystem/EcosystemResolver.java new file mode 100644 index 0000000..37a53cc --- /dev/null +++ b/core/src/main/java/io/snyk/plugins/artifactory/ecosystem/EcosystemResolver.java @@ -0,0 +1,10 @@ +package io.snyk.plugins.artifactory.ecosystem; + +import org.artifactory.repo.RepoPath; + +import java.util.Optional; + +public interface EcosystemResolver { + + Optional getFor(RepoPath repoPath); +} diff --git a/core/src/main/java/io/snyk/plugins/artifactory/ecosystem/RepositoryMetadataEcosystemResolver.java b/core/src/main/java/io/snyk/plugins/artifactory/ecosystem/RepositoryMetadataEcosystemResolver.java new file mode 100644 index 0000000..89cb9e1 --- /dev/null +++ b/core/src/main/java/io/snyk/plugins/artifactory/ecosystem/RepositoryMetadataEcosystemResolver.java @@ -0,0 +1,37 @@ +package io.snyk.plugins.artifactory.ecosystem; + +import org.artifactory.repo.RepoPath; +import org.artifactory.repo.Repositories; +import org.artifactory.repo.RepositoryConfiguration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Optional; + +public class RepositoryMetadataEcosystemResolver implements EcosystemResolver { + + private static final Logger LOG = LoggerFactory.getLogger(RepositoryMetadataEcosystemResolver.class); + + private final Repositories repositories; + + public RepositoryMetadataEcosystemResolver(Repositories repositories) { + this.repositories = repositories; + } + + @Override + public Optional getFor(RepoPath repoPath) { + RepositoryConfiguration repositoryConfiguration = repositories.getRepositoryConfiguration(repoPath.getRepoKey()); + if(repositoryConfiguration == null) { + LOG.error("No repository configuration for {}", repoPath); + return Optional.empty(); + } + + String packageType = repositoryConfiguration.getPackageType(); + if(packageType == null) { + LOG.error("No package type for {}", repoPath); + return Optional.empty(); + } + + return Ecosystem.fromPackageType(packageType); + } +} diff --git a/core/src/main/java/io/snyk/plugins/artifactory/scanner/PackageScanner.java b/core/src/main/java/io/snyk/plugins/artifactory/scanner/PackageScanner.java index 4d2c0d1..55ac0d4 100644 --- a/core/src/main/java/io/snyk/plugins/artifactory/scanner/PackageScanner.java +++ b/core/src/main/java/io/snyk/plugins/artifactory/scanner/PackageScanner.java @@ -4,6 +4,6 @@ import org.artifactory.fs.FileLayoutInfo; import org.artifactory.repo.RepoPath; -interface PackageScanner { +public interface PackageScanner { TestResult scan(FileLayoutInfo fileLayoutInfo, RepoPath repoPath); } diff --git a/core/src/main/java/io/snyk/plugins/artifactory/scanner/ScannerModule.java b/core/src/main/java/io/snyk/plugins/artifactory/scanner/ScannerModule.java index 3930dfb..69e85c2 100644 --- a/core/src/main/java/io/snyk/plugins/artifactory/scanner/ScannerModule.java +++ b/core/src/main/java/io/snyk/plugins/artifactory/scanner/ScannerModule.java @@ -4,12 +4,12 @@ import io.snyk.plugins.artifactory.configuration.PluginConfiguration; import io.snyk.plugins.artifactory.configuration.properties.ArtifactProperties; import io.snyk.plugins.artifactory.configuration.properties.RepositoryArtifactProperties; -import io.snyk.plugins.artifactory.exception.CannotScanException; +import io.snyk.plugins.artifactory.ecosystem.EcosystemResolver; +import io.snyk.plugins.artifactory.ecosystem.RepositoryMetadataEcosystemResolver; import io.snyk.plugins.artifactory.model.Ignores; import io.snyk.plugins.artifactory.model.MonitoredArtifact; import io.snyk.plugins.artifactory.model.TestResult; import io.snyk.plugins.artifactory.model.ValidationSettings; -import io.snyk.sdk.api.v1.SnykClient; import org.artifactory.fs.FileLayoutInfo; import org.artifactory.repo.RepoPath; import org.artifactory.repo.Repositories; @@ -21,25 +21,23 @@ import java.time.Duration; import java.util.Optional; -import static java.lang.String.format; import static java.util.Objects.requireNonNull; public class ScannerModule { private static final Logger LOG = LoggerFactory.getLogger(ScannerModule.class); private final ConfigurationModule configurationModule; private final Repositories repositories; - private final MavenScanner mavenScanner; - private final NpmScanner npmScanner; - private final PythonScanner pythonScanner; + private final EcosystemResolver ecosystemResolver; + private final ScannerResolver scannerResolver; private final ArtifactResolver artifactResolver; - public ScannerModule(@Nonnull ConfigurationModule configurationModule, @Nonnull Repositories repositories, @Nonnull SnykClient snykClient) { + public ScannerModule(ConfigurationModule configurationModule, @Nonnull Repositories repositories, ScannerResolver scannerResolver) { this.configurationModule = requireNonNull(configurationModule); this.repositories = requireNonNull(repositories); - mavenScanner = new MavenScanner(configurationModule, snykClient); - npmScanner = new NpmScanner(configurationModule, snykClient); - pythonScanner = new PythonScanner(configurationModule, snykClient); + ecosystemResolver = new RepositoryMetadataEcosystemResolver(repositories); + + this.scannerResolver = scannerResolver; artifactResolver = shouldTestContinuously() ? new ArtifactCache( durationHoursProperty(PluginConfiguration.TEST_FREQUENCY_HOURS, configurationModule), @@ -68,7 +66,9 @@ private ArtifactProperties properties(RepoPath repoPath) { } private @NotNull Optional runTest(RepoPath repoPath) { - return getScannerForPackageType(repoPath).map(scanner -> runTestWith(scanner, repoPath)); + return ecosystemResolver.getFor(repoPath) + .flatMap(ecosystem -> scannerResolver.getFor(ecosystem)) + .map(scanner -> runTestWith(scanner, repoPath)); } private MonitoredArtifact runTestWith(PackageScanner scanner, RepoPath repoPath) { @@ -88,33 +88,6 @@ private void filter(MonitoredArtifact artifact) { return new MonitoredArtifact(repoPath.toString(), testResult, ignores); } - protected Optional getScannerForPackageType(RepoPath repoPath) { - String path = Optional.ofNullable(repoPath.getPath()) - .orElseThrow(() -> new CannotScanException("Path not provided.")); - return getScannerForPackageType(path); - } - - protected Optional getScannerForPackageType(String path) { - return Ecosystem.fromPackagePath(path).map(this::getScanner); - } - - private PackageScanner getScanner(Ecosystem ecosystem) { - if (!configurationModule.getPropertyOrDefault(ecosystem.getConfigProperty()).equals("true")) { - throw new CannotScanException(format("Plugin Property \"%s\" is not \"true\".", ecosystem.getConfigProperty().propertyKey())); - } - - switch (ecosystem) { - case MAVEN: - return mavenScanner; - case NPM: - return npmScanner; - case PYPI: - return pythonScanner; - default: - throw new IllegalStateException("Unsupported ecosystem: " + ecosystem.name()); - } - } - private boolean shouldTestContinuously() { return configurationModule.getPropertyOrDefault(PluginConfiguration.TEST_CONTINUOUSLY).equals("true"); } diff --git a/core/src/main/java/io/snyk/plugins/artifactory/scanner/ScannerResolver.java b/core/src/main/java/io/snyk/plugins/artifactory/scanner/ScannerResolver.java new file mode 100644 index 0000000..682d626 --- /dev/null +++ b/core/src/main/java/io/snyk/plugins/artifactory/scanner/ScannerResolver.java @@ -0,0 +1,52 @@ +package io.snyk.plugins.artifactory.scanner; + +import io.snyk.plugins.artifactory.configuration.ConfigurationModule; +import io.snyk.plugins.artifactory.configuration.PluginConfiguration; +import io.snyk.plugins.artifactory.ecosystem.Ecosystem; +import io.snyk.sdk.api.v1.SnykClient; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import java.util.function.Function; + +public class ScannerResolver { + private static final Logger LOG = LoggerFactory.getLogger(ScannerResolver.class); + private final Function getConfig; + private final Map scannerByEcosystem = new HashMap<>(); + + public ScannerResolver(Function getConfig) { + this.getConfig = getConfig; + } + + public ScannerResolver register(Ecosystem ecosystem, PackageScanner scanner) { + scannerByEcosystem.put(ecosystem, scanner); + return this; + } + + public Optional getFor(Ecosystem ecosystem) { + PluginConfiguration configKey = ecosystem.getConfigProperty(); + String configValue = getConfig.apply(configKey); + if (!"true".equals(configValue)) { + LOG.info("Snyk scanner disabled for {}. Config: {} = {}", ecosystem.name(), configKey.propertyKey(), configValue); + return Optional.empty(); + } + + PackageScanner scanner = scannerByEcosystem.get(ecosystem); + + if (scanner == null) { + LOG.error("No scanner registered for {}", ecosystem.name()); + } + + return Optional.ofNullable(scanner); + } + + public static ScannerResolver setup(ConfigurationModule configurationModule, SnykClient snykClient) { + return new ScannerResolver(configurationModule::getPropertyOrDefault) + .register(Ecosystem.MAVEN, new MavenScanner(configurationModule, snykClient)) + .register(Ecosystem.NPM, new NpmScanner(configurationModule, snykClient)) + .register(Ecosystem.PYPI, new PythonScanner(configurationModule, snykClient)); + } +} diff --git a/core/src/test/java/io/snyk/plugins/artifactory/ecosystem/EcosystemTest.java b/core/src/test/java/io/snyk/plugins/artifactory/ecosystem/EcosystemTest.java new file mode 100644 index 0000000..1c51873 --- /dev/null +++ b/core/src/test/java/io/snyk/plugins/artifactory/ecosystem/EcosystemTest.java @@ -0,0 +1,16 @@ +package io.snyk.plugins.artifactory.ecosystem; + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +class EcosystemTest { + + @Test + void ecosystemByPackageType() { + assertThat(Ecosystem.fromPackageType("maven")).contains(Ecosystem.MAVEN); + assertThat(Ecosystem.fromPackageType("npm")).contains(Ecosystem.NPM); + assertThat(Ecosystem.fromPackageType("pypi")).contains(Ecosystem.PYPI); + assertThat(Ecosystem.fromPackageType("nuget")).isEmpty(); + } +} diff --git a/core/src/test/java/io/snyk/plugins/artifactory/scanner/EcosystemTest.java b/core/src/test/java/io/snyk/plugins/artifactory/scanner/EcosystemTest.java deleted file mode 100644 index 775771e..0000000 --- a/core/src/test/java/io/snyk/plugins/artifactory/scanner/EcosystemTest.java +++ /dev/null @@ -1,19 +0,0 @@ -package io.snyk.plugins.artifactory.scanner; - -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.*; - -class EcosystemTest { - - @Test - void testGetScannerForPackageType() { - assertEquals(Ecosystem.MAVEN, Ecosystem.fromPackagePath("myArtifact.jar").orElse(null)); - assertEquals(Ecosystem.NPM, Ecosystem.fromPackagePath("myArtifact.tgz").orElse(null)); - assertEquals(Ecosystem.PYPI, Ecosystem.fromPackagePath("myArtifact.whl").orElse(null)); - assertEquals(Ecosystem.PYPI, Ecosystem.fromPackagePath("myArtifact.tar.gz").orElse(null)); - assertEquals(Ecosystem.PYPI, Ecosystem.fromPackagePath("myArtifact.zip").orElse(null)); - assertEquals(Ecosystem.PYPI, Ecosystem.fromPackagePath("myArtifact.egg").orElse(null)); - assertNull(Ecosystem.fromPackagePath("file.txt").orElse(null)); - } -} diff --git a/core/src/test/java/io/snyk/plugins/artifactory/scanner/ScannerModuleTest.java b/core/src/test/java/io/snyk/plugins/artifactory/scanner/ScannerModuleTest.java deleted file mode 100644 index a13569f..0000000 --- a/core/src/test/java/io/snyk/plugins/artifactory/scanner/ScannerModuleTest.java +++ /dev/null @@ -1,214 +0,0 @@ -package io.snyk.plugins.artifactory.scanner; - -import io.snyk.plugins.artifactory.configuration.ConfigurationModule; -import io.snyk.plugins.artifactory.exception.CannotScanException; -import io.snyk.plugins.artifactory.exception.SnykAPIFailureException; -import io.snyk.plugins.artifactory.model.MonitoredArtifact; -import io.snyk.plugins.artifactory.util.SnykConfigForTests; -import io.snyk.sdk.SnykConfig; -import io.snyk.sdk.api.v1.SnykClient; -import org.artifactory.fs.FileLayoutInfo; -import org.artifactory.repo.RepoPath; -import org.artifactory.repo.Repositories; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.mockito.Mockito; - -import javax.annotation.Nonnull; -import java.net.http.HttpConnectTimeoutException; -import java.time.Duration; -import java.util.Properties; -import java.util.function.Function; - -import static io.snyk.plugins.artifactory.configuration.PluginConfiguration.*; -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -public class ScannerModuleTest { - - @Test - void testGetScannerForPackageType_cannotScanPathsWithDisabledScanners() { - Properties properties = new Properties(); - properties.put(SCANNER_PACKAGE_TYPE_MAVEN.propertyKey(), "false"); - properties.put(SCANNER_PACKAGE_TYPE_NPM.propertyKey(), "false"); - properties.put(SCANNER_PACKAGE_TYPE_PYPI.propertyKey(), "false"); - ConfigurationModule configurationModule = new ConfigurationModule(properties); - - ScannerModule sm = new ScannerModule( - configurationModule, - mock(Repositories.class), - mock(SnykClient.class) - ); - - assertThrows(CannotScanException.class, () -> sm.getScannerForPackageType("myArtifact.jar")); - assertThrows(CannotScanException.class, () -> sm.getScannerForPackageType("myArtifact.tgz")); - assertThrows(CannotScanException.class, () -> sm.getScannerForPackageType("myArtifact.whl")); - } - - ScanTestSetup createScannerSpyModuleForTest(FileLayoutInfo fileLayoutInfo) throws Exception { - return createScannerSpyModuleForTest(fileLayoutInfo, Function.identity()); - } - - ScanTestSetup createScannerSpyModuleForTest( - FileLayoutInfo fileLayoutInfo, - Function customiseBuilder - ) throws Exception { - SnykConfig config = customiseBuilder.apply(SnykConfigForTests.newBuilder()).build(); - Properties properties = new Properties(); - properties.put(SCANNER_PACKAGE_TYPE_MAVEN.propertyKey(), "true"); - properties.put(SCANNER_PACKAGE_TYPE_NPM.propertyKey(), "true"); - properties.put(SCANNER_PACKAGE_TYPE_PYPI.propertyKey(), "true"); - - @Nonnull String org = System.getenv("TEST_SNYK_ORG"); - Assertions.assertNotNull(org, "must not be null for test"); - - properties.put(API_ORGANIZATION.propertyKey(), org); - ConfigurationModule configurationModule = new ConfigurationModule(properties); - - SnykClient snykClient = new SnykClient(config); - - RepoPath repoPath = mock(RepoPath.class); - - Repositories repositories = mock(Repositories.class); - when(repositories.getLayoutInfo(repoPath)).thenReturn(fileLayoutInfo); - - ScannerModule scanner = new ScannerModule( - configurationModule, - repositories, - snykClient); - - ScannerModule scannerSpy = Mockito.spy(scanner); - return new ScanTestSetup(scannerSpy, repoPath, org); - } - - class ScanTestSetup { - ScannerModule scannerModule; - RepoPath repoPath; - String org; - - public ScanTestSetup(ScannerModule scannerModule, RepoPath repoPath, String org) { - this.scannerModule = scannerModule; - this.repoPath = repoPath; - this.org = org; - } - } - - @Test - void shouldUseConfiguredTimeoutForAPIRequests() throws Exception { - FileLayoutInfo fileLayoutInfo = mock(FileLayoutInfo.class); - when(fileLayoutInfo.getModule()).thenReturn("minimist"); - when(fileLayoutInfo.getBaseRevision()).thenReturn("1.2.6"); - - ScanTestSetup testSetup = createScannerSpyModuleForTest(fileLayoutInfo, config -> config.setTimeout(Duration.ofMillis(1))); - ScannerModule spyScanner = testSetup.scannerModule; - RepoPath repoPath = testSetup.repoPath; - when(repoPath.getPath()).thenReturn("myArtifact.tgz"); - when(repoPath.toString()).thenReturn("npm:minimist/-/minimist-1.2.6.tgz"); - - // Using try-catch as assertThrows does not let us check the cause. - try { - spyScanner.testArtifact(repoPath); - fail("Expected SnykAPIFailureException for timeout but no exception was thrown."); - } catch (SnykAPIFailureException e) { - Throwable cause = e.getCause(); - assertEquals(HttpConnectTimeoutException.class, cause.getClass()); - assertEquals("HTTP connect timed out", cause.getMessage()); - } - } - - @Test - void testScanNpmItem_noVulns() throws Exception { - FileLayoutInfo fileLayoutInfo = mock(FileLayoutInfo.class); - when(fileLayoutInfo.getModule()).thenReturn("minimist"); - when(fileLayoutInfo.getBaseRevision()).thenReturn("1.2.6"); - - ScanTestSetup testSetup = createScannerSpyModuleForTest(fileLayoutInfo); - ScannerModule spyScanner = testSetup.scannerModule; - RepoPath repoPath = testSetup.repoPath; - when(repoPath.getPath()).thenReturn("myArtifact.tgz"); - when(repoPath.toString()).thenReturn("npm:minimist/-/minimist-1.2.6.tgz"); - - MonitoredArtifact result = spyScanner.testArtifact(repoPath).get(); - - assertEquals(0, result.getTestResult().getVulnSummary().getTotalCount()); - } - - @Test - void testScanNpmItem_withVulns() throws Exception { - FileLayoutInfo fileLayoutInfo = mock(FileLayoutInfo.class); - when(fileLayoutInfo.getModule()).thenReturn("lodash"); - when(fileLayoutInfo.getBaseRevision()).thenReturn("4.17.15"); - - ScanTestSetup testSetup = createScannerSpyModuleForTest(fileLayoutInfo); - ScannerModule spyScanner = testSetup.scannerModule; - RepoPath repoPath = testSetup.repoPath; - when(repoPath.getPath()).thenReturn("myArtifact.tgz"); - when(repoPath.toString()).thenReturn("npm:lodash/-/lodash-4.17.15.tgz"); - - MonitoredArtifact result = spyScanner.testArtifact(repoPath).get(); - assertTrue(result.getTestResult().getVulnSummary().getTotalCount() > 0); - } - - @Test - void testScanMavenItem_noVulns() throws Exception { - FileLayoutInfo fileLayoutInfo = mock(FileLayoutInfo.class); - when(fileLayoutInfo.getOrganization()).thenReturn("org.apache.commons"); // corresponds to groupId - when(fileLayoutInfo.getModule()).thenReturn("commons-lang3"); // corresponds to artifactId - when(fileLayoutInfo.getBaseRevision()).thenReturn("3.12.0"); - - ScanTestSetup testSetup = createScannerSpyModuleForTest(fileLayoutInfo); - ScannerModule spyScanner = testSetup.scannerModule; - RepoPath repoPath = testSetup.repoPath; - when(repoPath.getPath()).thenReturn("myArtifact.jar"); - - MonitoredArtifact result = spyScanner.testArtifact(repoPath).get(); - assertEquals(0, result.getTestResult().getVulnSummary().getTotalCount()); - } - - @Test - void testScanMavenItem_withVulns() throws Exception { - FileLayoutInfo fileLayoutInfo = mock(FileLayoutInfo.class); - when(fileLayoutInfo.getOrganization()).thenReturn("com.fasterxml.jackson.core"); // corresponds to groupId - when(fileLayoutInfo.getModule()).thenReturn("jackson-databind"); // corresponds to artifactId - when(fileLayoutInfo.getBaseRevision()).thenReturn("2.9.8"); - - ScanTestSetup testSetup = createScannerSpyModuleForTest(fileLayoutInfo); - ScannerModule spyScanner = testSetup.scannerModule; - RepoPath repoPath = testSetup.repoPath; - when(repoPath.getPath()).thenReturn("myArtifact.jar"); - - MonitoredArtifact result = spyScanner.testArtifact(repoPath).get(); - assertTrue(result.getTestResult().getVulnSummary().getTotalCount() > 0); - } - - @Test - void testScanPythonItem_noVulns() throws Exception { - FileLayoutInfo fileLayoutInfo = mock(FileLayoutInfo.class); - when(fileLayoutInfo.getModule()).thenReturn("numpy"); - when(fileLayoutInfo.getBaseRevision()).thenReturn("1.22.2"); - - ScanTestSetup testSetup = createScannerSpyModuleForTest(fileLayoutInfo); - ScannerModule spyScanner = testSetup.scannerModule; - RepoPath repoPath = testSetup.repoPath; - when(repoPath.getPath()).thenReturn("myArtifact.whl"); - - MonitoredArtifact result = spyScanner.testArtifact(repoPath).get(); - assertEquals(0, result.getTestResult().getVulnSummary().getTotalCount()); - } - - @Test - void testScanPythonItem_withVulns() throws Exception { - FileLayoutInfo fileLayoutInfo = mock(FileLayoutInfo.class); - when(fileLayoutInfo.getModule()).thenReturn("urllib3"); - when(fileLayoutInfo.getBaseRevision()).thenReturn("1.25.7"); - - ScanTestSetup testSetup = createScannerSpyModuleForTest(fileLayoutInfo); - ScannerModule spyScanner = testSetup.scannerModule; - RepoPath repoPath = testSetup.repoPath; - when(repoPath.getPath()).thenReturn("myArtifact.whl"); - - MonitoredArtifact result = spyScanner.testArtifact(repoPath).get(); - assertEquals(6, result.getTestResult().getVulnSummary().getTotalCount()); - } -} diff --git a/core/src/test/java/io/snyk/plugins/artifactory/scanner/ScannerResolverTest.java b/core/src/test/java/io/snyk/plugins/artifactory/scanner/ScannerResolverTest.java new file mode 100644 index 0000000..6e50d8a --- /dev/null +++ b/core/src/test/java/io/snyk/plugins/artifactory/scanner/ScannerResolverTest.java @@ -0,0 +1,51 @@ +package io.snyk.plugins.artifactory.scanner; + +import io.snyk.plugins.artifactory.model.IssueSummary; +import io.snyk.plugins.artifactory.model.TestResult; +import org.artifactory.fs.FileLayoutInfo; +import org.artifactory.repo.RepoPath; +import org.junit.jupiter.api.Test; + +import java.net.URI; +import java.util.stream.Stream; + +import static io.snyk.plugins.artifactory.ecosystem.Ecosystem.MAVEN; +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +class ScannerResolverTest { + + @Test + void scannerEnabled() { + ScannerResolver resolver = new ScannerResolver((param) -> "true") + .register(MAVEN, new DummyScanner()); + + assertThat(resolver.getFor(MAVEN)).isPresent(); + } + + @Test + void scannerDisabled() { + ScannerResolver resolver = new ScannerResolver((param) -> "false") + .register(MAVEN, new DummyScanner()); + + assertThat(resolver.getFor(MAVEN)).isEmpty(); + } + + @Test + void scannerNotRegistered() { + ScannerResolver resolver = new ScannerResolver((param) -> "true"); + + assertThat(resolver.getFor(MAVEN)).isEmpty(); + } + + static class DummyScanner implements PackageScanner { + + @Override + public TestResult scan(FileLayoutInfo fileLayoutInfo, RepoPath repoPath) { + return new TestResult( + IssueSummary.from(Stream.empty()), + IssueSummary.from(Stream.empty()), + URI.create("https://snyk.io") + ); + } + } +}